1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02:00
community.general/plugins/modules/network/netscaler/netscaler_gslb_vserver.py
Ansible Core Team aebc1b03fd Initial commit
2020-03-09 09:11:07 +00:00

955 lines
33 KiB
Python

#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright (c) 2017 Citrix Systems
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: netscaler_gslb_vserver
short_description: Configure gslb vserver entities in Netscaler.
description:
- Configure gslb vserver entities in Netscaler.
author: George Nikolopoulos (@giorgos-nikolopoulos)
options:
name:
description:
- >-
Name for the GSLB virtual server. Must begin with an ASCII alphanumeric or underscore C(_) character,
and must contain only ASCII alphanumeric, underscore C(_), hash C(#), period C(.), space, colon C(:), at C(@),
equals C(=), and hyphen C(-) characters. Can be changed after the virtual server is created.
- "Minimum length = 1"
servicetype:
choices:
- 'HTTP'
- 'FTP'
- 'TCP'
- 'UDP'
- 'SSL'
- 'SSL_BRIDGE'
- 'SSL_TCP'
- 'NNTP'
- 'ANY'
- 'SIP_UDP'
- 'SIP_TCP'
- 'SIP_SSL'
- 'RADIUS'
- 'RDP'
- 'RTSP'
- 'MYSQL'
- 'MSSQL'
- 'ORACLE'
description:
- "Protocol used by services bound to the virtual server."
- >-
dnsrecordtype:
choices:
- 'A'
- 'AAAA'
- 'CNAME'
- 'NAPTR'
description:
- "DNS record type to associate with the GSLB virtual server's domain name."
- "Default value: A"
- "Possible values = A, AAAA, CNAME, NAPTR"
lbmethod:
choices:
- 'ROUNDROBIN'
- 'LEASTCONNECTION'
- 'LEASTRESPONSETIME'
- 'SOURCEIPHASH'
- 'LEASTBANDWIDTH'
- 'LEASTPACKETS'
- 'STATICPROXIMITY'
- 'RTT'
- 'CUSTOMLOAD'
description:
- "Load balancing method for the GSLB virtual server."
- "Default value: LEASTCONNECTION"
- >-
Possible values = ROUNDROBIN, LEASTCONNECTION, LEASTRESPONSETIME, SOURCEIPHASH, LEASTBANDWIDTH,
LEASTPACKETS, STATICPROXIMITY, RTT, CUSTOMLOAD
backuplbmethod:
choices:
- 'ROUNDROBIN'
- 'LEASTCONNECTION'
- 'LEASTRESPONSETIME'
- 'SOURCEIPHASH'
- 'LEASTBANDWIDTH'
- 'LEASTPACKETS'
- 'STATICPROXIMITY'
- 'RTT'
- 'CUSTOMLOAD'
description:
- >-
Backup load balancing method. Becomes operational if the primary load balancing method fails or
cannot be used. Valid only if the primary method is based on either round-trip time (RTT) or static
proximity.
netmask:
description:
- "IPv4 network mask for use in the SOURCEIPHASH load balancing method."
- "Minimum length = 1"
v6netmasklen:
description:
- >-
Number of bits to consider, in an IPv6 source IP address, for creating the hash that is required by
the C(SOURCEIPHASH) load balancing method.
- "Default value: C(128)"
- "Minimum value = C(1)"
- "Maximum value = C(128)"
tolerance:
description:
- >-
Site selection tolerance, in milliseconds, for implementing the RTT load balancing method. If a
site's RTT deviates from the lowest RTT by more than the specified tolerance, the site is not
considered when the NetScaler appliance makes a GSLB decision. The appliance implements the round
robin method of global server load balancing between sites whose RTT values are within the specified
tolerance. If the tolerance is 0 (zero), the appliance always sends clients the IP address of the
site with the lowest RTT.
- "Minimum value = C(0)"
- "Maximum value = C(100)"
persistencetype:
choices:
- 'SOURCEIP'
- 'NONE'
description:
- "Use source IP address based persistence for the virtual server."
- >-
After the load balancing method selects a service for the first packet, the IP address received in
response to the DNS query is used for subsequent requests from the same client.
persistenceid:
description:
- >-
The persistence ID for the GSLB virtual server. The ID is a positive integer that enables GSLB sites
to identify the GSLB virtual server, and is required if source IP address based or spill over based
persistence is enabled on the virtual server.
- "Minimum value = C(0)"
- "Maximum value = C(65535)"
persistmask:
description:
- >-
The optional IPv4 network mask applied to IPv4 addresses to establish source IP address based
persistence.
- "Minimum length = 1"
v6persistmasklen:
description:
- >-
Number of bits to consider in an IPv6 source IP address when creating source IP address based
persistence sessions.
- "Default value: C(128)"
- "Minimum value = C(1)"
- "Maximum value = C(128)"
timeout:
description:
- "Idle time, in minutes, after which a persistence entry is cleared."
- "Default value: C(2)"
- "Minimum value = C(2)"
- "Maximum value = C(1440)"
mir:
choices:
- 'enabled'
- 'disabled'
description:
- "Include multiple IP addresses in the DNS responses sent to clients."
disableprimaryondown:
choices:
- 'enabled'
- 'disabled'
description:
- >-
Continue to direct traffic to the backup chain even after the primary GSLB virtual server returns to
the UP state. Used when spillover is configured for the virtual server.
dynamicweight:
choices:
- 'SERVICECOUNT'
- 'SERVICEWEIGHT'
- 'DISABLED'
description:
- >-
Specify if the appliance should consider the service count, service weights, or ignore both when
using weight-based load balancing methods. The state of the number of services bound to the virtual
server help the appliance to select the service.
considereffectivestate:
choices:
- 'NONE'
- 'STATE_ONLY'
description:
- >-
If the primary state of all bound GSLB services is DOWN, consider the effective states of all the
GSLB services, obtained through the Metrics Exchange Protocol (MEP), when determining the state of
the GSLB virtual server. To consider the effective state, set the parameter to STATE_ONLY. To
disregard the effective state, set the parameter to NONE.
- >-
The effective state of a GSLB service is the ability of the corresponding virtual server to serve
traffic. The effective state of the load balancing virtual server, which is transferred to the GSLB
service, is UP even if only one virtual server in the backup chain of virtual servers is in the UP
state.
comment:
description:
- "Any comments that you might want to associate with the GSLB virtual server."
somethod:
choices:
- 'CONNECTION'
- 'DYNAMICCONNECTION'
- 'BANDWIDTH'
- 'HEALTH'
- 'NONE'
description:
- "Type of threshold that, when exceeded, triggers spillover. Available settings function as follows:"
- "* C(CONNECTION) - Spillover occurs when the number of client connections exceeds the threshold."
- >-
* C(DYNAMICCONNECTION) - Spillover occurs when the number of client connections at the GSLB virtual
server exceeds the sum of the maximum client (Max Clients) settings for bound GSLB services. Do not
specify a spillover threshold for this setting, because the threshold is implied by the Max Clients
settings of the bound GSLB services.
- >-
* C(BANDWIDTH) - Spillover occurs when the bandwidth consumed by the GSLB virtual server's incoming and
outgoing traffic exceeds the threshold.
- >-
* C(HEALTH) - Spillover occurs when the percentage of weights of the GSLB services that are UP drops
below the threshold. For example, if services gslbSvc1, gslbSvc2, and gslbSvc3 are bound to a virtual
server, with weights 1, 2, and 3, and the spillover threshold is 50%, spillover occurs if gslbSvc1
and gslbSvc3 or gslbSvc2 and gslbSvc3 transition to DOWN.
- "* C(NONE) - Spillover does not occur."
sopersistence:
choices:
- 'enabled'
- 'disabled'
description:
- >-
If spillover occurs, maintain source IP address based persistence for both primary and backup GSLB
virtual servers.
sopersistencetimeout:
description:
- "Timeout for spillover persistence, in minutes."
- "Default value: C(2)"
- "Minimum value = C(2)"
- "Maximum value = C(1440)"
sothreshold:
description:
- >-
Threshold at which spillover occurs. Specify an integer for the CONNECTION spillover method, a
bandwidth value in kilobits per second for the BANDWIDTH method (do not enter the units), or a
percentage for the HEALTH method (do not enter the percentage symbol).
- "Minimum value = C(1)"
- "Maximum value = C(4294967287)"
sobackupaction:
choices:
- 'DROP'
- 'ACCEPT'
- 'REDIRECT'
description:
- >-
Action to be performed if spillover is to take effect, but no backup chain to spillover is usable or
exists.
appflowlog:
choices:
- 'enabled'
- 'disabled'
description:
- "Enable logging appflow flow information."
domain_bindings:
description:
- >-
List of bindings for domains for this glsb vserver.
suboptions:
cookietimeout:
description:
- Timeout, in minutes, for the GSLB site cookie.
domainname:
description:
- Domain name for which to change the time to live (TTL) and/or backup service IP address.
ttl:
description:
- Time to live (TTL) for the domain.
sitedomainttl:
description:
- >-
TTL, in seconds, for all internally created site domains (created when a site prefix is
configured on a GSLB service) that are associated with this virtual server.
- Minimum value = C(1)
service_bindings:
description:
- List of bindings for gslb services bound to this gslb virtual server.
suboptions:
servicename:
description:
- Name of the GSLB service for which to change the weight.
weight:
description:
- Weight to assign to the GSLB service.
disabled:
description:
- When set to C(yes) the GSLB Vserver state will be set to C(disabled).
- When set to C(no) the GSLB Vserver state will be set to C(enabled).
- >-
Note that due to limitations of the underlying NITRO API a C(disabled) state change alone
does not cause the module result to report a changed status.
type: bool
default: false
extends_documentation_fragment:
- community.general.netscaler
requirements:
- nitro python sdk
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import copy
try:
from nssrc.com.citrix.netscaler.nitro.resource.config.gslb.gslbvserver import gslbvserver
from nssrc.com.citrix.netscaler.nitro.resource.config.gslb.gslbvserver_gslbservice_binding import gslbvserver_gslbservice_binding
from nssrc.com.citrix.netscaler.nitro.resource.config.gslb.gslbvserver_domain_binding import gslbvserver_domain_binding
from nssrc.com.citrix.netscaler.nitro.exception.nitro_exception import nitro_exception
PYTHON_SDK_IMPORTED = True
except ImportError as e:
PYTHON_SDK_IMPORTED = False
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.community.general.plugins.module_utils.network.netscaler.netscaler import (
ConfigProxy,
get_nitro_client,
netscaler_common_arguments,
log,
loglines,
ensure_feature_is_enabled,
get_immutables_intersection,
complete_missing_attributes
)
gslbvserver_domain_binding_rw_attrs = [
'name',
'domainname',
'backupipflag',
'cookietimeout',
'backupip',
'ttl',
'sitedomainttl',
'cookie_domainflag',
]
gslbvserver_gslbservice_binding_rw_attrs = [
'name',
'servicename',
'weight',
]
def get_actual_domain_bindings(client, module):
log('get_actual_domain_bindings')
# Get actual domain bindings and index them by domainname
actual_domain_bindings = {}
if gslbvserver_domain_binding.count(client, name=module.params['name']) != 0:
# Get all domain bindings associated with the named gslb vserver
fetched_domain_bindings = gslbvserver_domain_binding.get(client, name=module.params['name'])
# index by domainname
for binding in fetched_domain_bindings:
complete_missing_attributes(binding, gslbvserver_domain_binding_rw_attrs, fill_value=None)
actual_domain_bindings[binding.domainname] = binding
return actual_domain_bindings
def get_configured_domain_bindings_proxys(client, module):
log('get_configured_domain_bindings_proxys')
configured_domain_proxys = {}
# Get configured domain bindings and index them by domainname
if module.params['domain_bindings'] is not None:
for configured_domain_binding in module.params['domain_bindings']:
binding_values = copy.deepcopy(configured_domain_binding)
binding_values['name'] = module.params['name']
gslbvserver_domain_binding_proxy = ConfigProxy(
actual=gslbvserver_domain_binding(),
client=client,
attribute_values_dict=binding_values,
readwrite_attrs=gslbvserver_domain_binding_rw_attrs,
readonly_attrs=[],
)
configured_domain_proxys[configured_domain_binding['domainname']] = gslbvserver_domain_binding_proxy
return configured_domain_proxys
def sync_domain_bindings(client, module):
log('sync_domain_bindings')
actual_domain_bindings = get_actual_domain_bindings(client, module)
configured_domain_proxys = get_configured_domain_bindings_proxys(client, module)
# Delete actual bindings not in configured bindings
for domainname, actual_domain_binding in actual_domain_bindings.items():
if domainname not in configured_domain_proxys.keys():
log('Deleting absent binding for domain %s' % domainname)
gslbvserver_domain_binding.delete(client, actual_domain_binding)
# Delete actual bindings that differ from configured
for proxy_key, binding_proxy in configured_domain_proxys.items():
if proxy_key in actual_domain_bindings:
actual_binding = actual_domain_bindings[proxy_key]
if not binding_proxy.has_equal_attributes(actual_binding):
log('Deleting differing binding for domain %s' % binding_proxy.domainname)
gslbvserver_domain_binding.delete(client, actual_binding)
log('Adding anew binding for domain %s' % binding_proxy.domainname)
binding_proxy.add()
# Add configured domains that are missing from actual
for proxy_key, binding_proxy in configured_domain_proxys.items():
if proxy_key not in actual_domain_bindings.keys():
log('Adding domain binding for domain %s' % binding_proxy.domainname)
binding_proxy.add()
def domain_bindings_identical(client, module):
log('domain_bindings_identical')
actual_domain_bindings = get_actual_domain_bindings(client, module)
configured_domain_proxys = get_configured_domain_bindings_proxys(client, module)
actual_keyset = set(actual_domain_bindings.keys())
configured_keyset = set(configured_domain_proxys.keys())
symmetric_difference = actual_keyset ^ configured_keyset
log('symmetric difference %s' % symmetric_difference)
if len(symmetric_difference) != 0:
return False
# Item for item equality test
for key, proxy in configured_domain_proxys.items():
diff = proxy.diff_object(actual_domain_bindings[key])
if 'backupipflag' in diff:
del diff['backupipflag']
if not len(diff) == 0:
return False
# Fallthrough to True result
return True
def get_actual_service_bindings(client, module):
log('get_actual_service_bindings')
# Get actual domain bindings and index them by domainname
actual_bindings = {}
if gslbvserver_gslbservice_binding.count(client, name=module.params['name']) != 0:
# Get all service bindings associated with the named gslb vserver
fetched_bindings = gslbvserver_gslbservice_binding.get(client, name=module.params['name'])
# index by servicename
for binding in fetched_bindings:
complete_missing_attributes(binding, gslbvserver_gslbservice_binding_rw_attrs, fill_value=None)
actual_bindings[binding.servicename] = binding
return actual_bindings
def get_configured_service_bindings(client, module):
log('get_configured_service_bindings_proxys')
configured_proxys = {}
# Get configured domain bindings and index them by domainname
if module.params['service_bindings'] is not None:
for configured_binding in module.params['service_bindings']:
binding_values = copy.deepcopy(configured_binding)
binding_values['name'] = module.params['name']
gslbvserver_service_binding_proxy = ConfigProxy(
actual=gslbvserver_gslbservice_binding(),
client=client,
attribute_values_dict=binding_values,
readwrite_attrs=gslbvserver_gslbservice_binding_rw_attrs,
readonly_attrs=[],
)
configured_proxys[configured_binding['servicename']] = gslbvserver_service_binding_proxy
return configured_proxys
def sync_service_bindings(client, module):
actual = get_actual_service_bindings(client, module)
configured = get_configured_service_bindings(client, module)
# Delete extraneous
extraneous_service_bindings = list(set(actual.keys()) - set(configured.keys()))
for servicename in extraneous_service_bindings:
log('Deleting missing binding from service %s' % servicename)
binding = actual[servicename]
binding.name = module.params['name']
gslbvserver_gslbservice_binding.delete(client, binding)
# Recreate different
common_service_bindings = list(set(actual.keys()) & set(configured.keys()))
for servicename in common_service_bindings:
proxy = configured[servicename]
binding = actual[servicename]
if not proxy.has_equal_attributes(actual):
log('Recreating differing service binding %s' % servicename)
gslbvserver_gslbservice_binding.delete(client, binding)
proxy.add()
# Add missing
missing_service_bindings = list(set(configured.keys()) - set(actual.keys()))
for servicename in missing_service_bindings:
proxy = configured[servicename]
log('Adding missing service binding %s' % servicename)
proxy.add()
def service_bindings_identical(client, module):
actual_bindings = get_actual_service_bindings(client, module)
configured_proxys = get_configured_service_bindings(client, module)
actual_keyset = set(actual_bindings.keys())
configured_keyset = set(configured_proxys.keys())
symmetric_difference = actual_keyset ^ configured_keyset
if len(symmetric_difference) != 0:
return False
# Item for item equality test
for key, proxy in configured_proxys.items():
if key in actual_bindings.keys():
if not proxy.has_equal_attributes(actual_bindings[key]):
return False
# Fallthrough to True result
return True
def gslb_vserver_exists(client, module):
if gslbvserver.count_filtered(client, 'name:%s' % module.params['name']) > 0:
return True
else:
return False
def gslb_vserver_identical(client, module, gslb_vserver_proxy):
gslb_vserver_list = gslbvserver.get_filtered(client, 'name:%s' % module.params['name'])
diff_dict = gslb_vserver_proxy.diff_object(gslb_vserver_list[0])
if len(diff_dict) != 0:
return False
else:
return True
def all_identical(client, module, gslb_vserver_proxy):
return (
gslb_vserver_identical(client, module, gslb_vserver_proxy) and
domain_bindings_identical(client, module) and
service_bindings_identical(client, module)
)
def diff_list(client, module, gslb_vserver_proxy):
gslb_vserver_list = gslbvserver.get_filtered(client, 'name:%s' % module.params['name'])
return gslb_vserver_proxy.diff_object(gslb_vserver_list[0])
def do_state_change(client, module, gslb_vserver_proxy):
if module.params['disabled']:
log('Disabling glsb_vserver')
result = gslbvserver.disable(client, gslb_vserver_proxy.actual)
else:
log('Enabling gslbvserver')
result = gslbvserver.enable(client, gslb_vserver_proxy.actual)
return result
def main():
module_specific_arguments = dict(
name=dict(type='str'),
servicetype=dict(
type='str',
choices=[
'HTTP',
'FTP',
'TCP',
'UDP',
'SSL',
'SSL_BRIDGE',
'SSL_TCP',
'NNTP',
'ANY',
'SIP_UDP',
'SIP_TCP',
'SIP_SSL',
'RADIUS',
'RDP',
'RTSP',
'MYSQL',
'MSSQL',
'ORACLE',
]
),
dnsrecordtype=dict(
type='str',
choices=[
'A',
'AAAA',
'CNAME',
'NAPTR',
]
),
lbmethod=dict(
type='str',
choices=[
'ROUNDROBIN',
'LEASTCONNECTION',
'LEASTRESPONSETIME',
'SOURCEIPHASH',
'LEASTBANDWIDTH',
'LEASTPACKETS',
'STATICPROXIMITY',
'RTT',
'CUSTOMLOAD',
]
),
backuplbmethod=dict(
type='str',
choices=[
'ROUNDROBIN',
'LEASTCONNECTION',
'LEASTRESPONSETIME',
'SOURCEIPHASH',
'LEASTBANDWIDTH',
'LEASTPACKETS',
'STATICPROXIMITY',
'RTT',
'CUSTOMLOAD',
]
),
netmask=dict(type='str'),
v6netmasklen=dict(type='float'),
tolerance=dict(type='float'),
persistencetype=dict(
type='str',
choices=[
'SOURCEIP',
'NONE',
]
),
persistenceid=dict(type='float'),
persistmask=dict(type='str'),
v6persistmasklen=dict(type='float'),
timeout=dict(type='float'),
mir=dict(
type='str',
choices=[
'enabled',
'disabled',
]
),
disableprimaryondown=dict(
type='str',
choices=[
'enabled',
'disabled',
]
),
dynamicweight=dict(
type='str',
choices=[
'SERVICECOUNT',
'SERVICEWEIGHT',
'DISABLED',
]
),
considereffectivestate=dict(
type='str',
choices=[
'NONE',
'STATE_ONLY',
]
),
comment=dict(type='str'),
somethod=dict(
type='str',
choices=[
'CONNECTION',
'DYNAMICCONNECTION',
'BANDWIDTH',
'HEALTH',
'NONE',
]
),
sopersistence=dict(
type='str',
choices=[
'enabled',
'disabled',
]
),
sopersistencetimeout=dict(type='float'),
sothreshold=dict(type='float'),
sobackupaction=dict(
type='str',
choices=[
'DROP',
'ACCEPT',
'REDIRECT',
]
),
appflowlog=dict(
type='str',
choices=[
'enabled',
'disabled',
]
),
domainname=dict(type='str'),
cookie_domain=dict(type='str'),
)
hand_inserted_arguments = dict(
domain_bindings=dict(type='list'),
service_bindings=dict(type='list'),
disabled=dict(
type='bool',
default=False,
),
)
argument_spec = dict()
argument_spec.update(netscaler_common_arguments)
argument_spec.update(module_specific_arguments)
argument_spec.update(hand_inserted_arguments)
module = AnsibleModule(
argument_spec=argument_spec,
supports_check_mode=True,
)
module_result = dict(
changed=False,
failed=False,
loglines=loglines,
)
# Fail the module if imports failed
if not PYTHON_SDK_IMPORTED:
module.fail_json(msg='Could not load nitro python sdk')
# Fallthrough to rest of execution
client = get_nitro_client(module)
try:
client.login()
except nitro_exception as e:
msg = "nitro exception during login. errorcode=%s, message=%s" % (str(e.errorcode), e.message)
module.fail_json(msg=msg)
except Exception as e:
if str(type(e)) == "<class 'requests.exceptions.ConnectionError'>":
module.fail_json(msg='Connection error %s' % str(e))
elif str(type(e)) == "<class 'requests.exceptions.SSLError'>":
module.fail_json(msg='SSL Error %s' % str(e))
else:
module.fail_json(msg='Unexpected error during login %s' % str(e))
readwrite_attrs = [
'name',
'servicetype',
'dnsrecordtype',
'lbmethod',
'backuplbmethod',
'netmask',
'v6netmasklen',
'tolerance',
'persistencetype',
'persistenceid',
'persistmask',
'v6persistmasklen',
'timeout',
'mir',
'disableprimaryondown',
'dynamicweight',
'considereffectivestate',
'comment',
'somethod',
'sopersistence',
'sopersistencetimeout',
'sothreshold',
'sobackupaction',
'appflowlog',
'cookie_domain',
]
readonly_attrs = [
'curstate',
'status',
'lbrrreason',
'iscname',
'sitepersistence',
'totalservices',
'activeservices',
'statechangetimesec',
'statechangetimemsec',
'tickssincelaststatechange',
'health',
'policyname',
'priority',
'gotopriorityexpression',
'type',
'vsvrbindsvcip',
'vsvrbindsvcport',
'__count',
]
immutable_attrs = [
'name',
'servicetype',
]
transforms = {
'mir': [lambda v: v.upper()],
'disableprimaryondown': [lambda v: v.upper()],
'sopersistence': [lambda v: v.upper()],
'appflowlog': [lambda v: v.upper()],
}
# Instantiate config proxy
gslb_vserver_proxy = ConfigProxy(
actual=gslbvserver(),
client=client,
attribute_values_dict=module.params,
readwrite_attrs=readwrite_attrs,
readonly_attrs=readonly_attrs,
immutable_attrs=immutable_attrs,
transforms=transforms,
)
try:
ensure_feature_is_enabled(client, 'GSLB')
# Apply appropriate state
if module.params['state'] == 'present':
log('Applying state present')
if not gslb_vserver_exists(client, module):
log('Creating object')
if not module.check_mode:
gslb_vserver_proxy.add()
sync_domain_bindings(client, module)
sync_service_bindings(client, module)
if module.params['save_config']:
client.save_config()
module_result['changed'] = True
elif not all_identical(client, module, gslb_vserver_proxy):
log('Entering update actions')
# Check if we try to change value of immutable attributes
if not gslb_vserver_identical(client, module, gslb_vserver_proxy):
log('Updating gslb vserver')
immutables_changed = get_immutables_intersection(gslb_vserver_proxy, diff_list(client, module, gslb_vserver_proxy).keys())
if immutables_changed != []:
module.fail_json(
msg='Cannot update immutable attributes %s' % (immutables_changed,),
diff=diff_list(client, module, gslb_vserver_proxy),
**module_result
)
if not module.check_mode:
gslb_vserver_proxy.update()
# Update domain bindings
if not domain_bindings_identical(client, module):
if not module.check_mode:
sync_domain_bindings(client, module)
# Update service bindings
if not service_bindings_identical(client, module):
if not module.check_mode:
sync_service_bindings(client, module)
module_result['changed'] = True
if not module.check_mode:
if module.params['save_config']:
client.save_config()
else:
module_result['changed'] = False
if not module.check_mode:
res = do_state_change(client, module, gslb_vserver_proxy)
if res.errorcode != 0:
msg = 'Error when setting disabled state. errorcode: %s message: %s' % (res.errorcode, res.message)
module.fail_json(msg=msg, **module_result)
# Sanity check for state
if not module.check_mode:
if not gslb_vserver_exists(client, module):
module.fail_json(msg='GSLB Vserver does not exist', **module_result)
if not gslb_vserver_identical(client, module, gslb_vserver_proxy):
module.fail_json(msg='GSLB Vserver differs from configured', diff=diff_list(client, module, gslb_vserver_proxy), **module_result)
if not domain_bindings_identical(client, module):
module.fail_json(msg='Domain bindings differ from configured', diff=diff_list(client, module, gslb_vserver_proxy), **module_result)
if not service_bindings_identical(client, module):
module.fail_json(msg='Service bindings differ from configured', diff=diff_list(client, module, gslb_vserver_proxy), **module_result)
elif module.params['state'] == 'absent':
if gslb_vserver_exists(client, module):
if not module.check_mode:
gslb_vserver_proxy.delete()
if module.params['save_config']:
client.save_config()
module_result['changed'] = True
else:
module_result['changed'] = False
# Sanity check for state
if not module.check_mode:
if gslb_vserver_exists(client, module):
module.fail_json(msg='GSLB Vserver still exists', **module_result)
except nitro_exception as e:
msg = "nitro exception errorcode=%s, message=%s" % (str(e.errorcode), e.message)
module.fail_json(msg=msg, **module_result)
client.logout()
module.exit_json(**module_result)
if __name__ == "__main__":
main()