|
|
|
@ -17,13 +17,15 @@ module: bigip_gtm_wide_ip
|
|
|
|
|
short_description: Manages F5 BIG-IP GTM wide ip
|
|
|
|
|
description:
|
|
|
|
|
- Manages F5 BIG-IP GTM wide ip.
|
|
|
|
|
version_added: "2.0"
|
|
|
|
|
version_added: 2.0
|
|
|
|
|
options:
|
|
|
|
|
pool_lb_method:
|
|
|
|
|
description:
|
|
|
|
|
- Specifies the load balancing method used to select a pool in this wide
|
|
|
|
|
IP. This setting is relevant only when multiple pools are configured
|
|
|
|
|
for a wide IP.
|
|
|
|
|
- The C(round_robin) value is deprecated and will be removed in Ansible 2.9.
|
|
|
|
|
- The C(global_availability) value is deprecated and will be removed in Ansible 2.9.
|
|
|
|
|
required: True
|
|
|
|
|
aliases: ['lb_method']
|
|
|
|
|
choices:
|
|
|
|
@ -31,6 +33,8 @@ options:
|
|
|
|
|
- ratio
|
|
|
|
|
- topology
|
|
|
|
|
- global-availability
|
|
|
|
|
- global_availability
|
|
|
|
|
- round_robin
|
|
|
|
|
version_added: 2.5
|
|
|
|
|
name:
|
|
|
|
|
description:
|
|
|
|
@ -80,13 +84,19 @@ options:
|
|
|
|
|
suboptions:
|
|
|
|
|
name:
|
|
|
|
|
description:
|
|
|
|
|
- The name of the pool to include
|
|
|
|
|
required: true
|
|
|
|
|
- The name of the pool to include.
|
|
|
|
|
required: True
|
|
|
|
|
ratio:
|
|
|
|
|
description:
|
|
|
|
|
- Ratio for the pool.
|
|
|
|
|
- The system uses this number with the Ratio load balancing method.
|
|
|
|
|
version_added: 2.5
|
|
|
|
|
irules:
|
|
|
|
|
version_added: 2.6
|
|
|
|
|
description:
|
|
|
|
|
- List of rules to be applied.
|
|
|
|
|
- If you want to remove all existing iRules, specify a single empty value; C("").
|
|
|
|
|
See the documentation for an example.
|
|
|
|
|
extends_documentation_fragment: f5
|
|
|
|
|
author:
|
|
|
|
|
- Tim Rupp (@caphrim007)
|
|
|
|
@ -98,8 +108,53 @@ EXAMPLES = r'''
|
|
|
|
|
server: lb.mydomain.com
|
|
|
|
|
user: admin
|
|
|
|
|
password: secret
|
|
|
|
|
lb_method: round-robin
|
|
|
|
|
pool_lb_method: round-robin
|
|
|
|
|
name: my-wide-ip.example.com
|
|
|
|
|
delegate_to: localhost
|
|
|
|
|
|
|
|
|
|
- name: Add iRules to the Wide IP
|
|
|
|
|
bigip_gtm_wide_ip:
|
|
|
|
|
server: lb.mydomain.com
|
|
|
|
|
user: admin
|
|
|
|
|
password: secret
|
|
|
|
|
pool_lb_method: round-robin
|
|
|
|
|
name: my-wide-ip.example.com
|
|
|
|
|
irules:
|
|
|
|
|
- irule1
|
|
|
|
|
- irule2
|
|
|
|
|
delegate_to: localhost
|
|
|
|
|
|
|
|
|
|
- name: Remove one iRule from the Virtual Server
|
|
|
|
|
bigip_gtm_wide_ip:
|
|
|
|
|
server: lb.mydomain.com
|
|
|
|
|
user: admin
|
|
|
|
|
password: secret
|
|
|
|
|
pool_lb_method: round-robin
|
|
|
|
|
name: my-wide-ip.example.com
|
|
|
|
|
irules:
|
|
|
|
|
- irule1
|
|
|
|
|
delegate_to: localhost
|
|
|
|
|
|
|
|
|
|
- name: Remove all iRules from the Virtual Server
|
|
|
|
|
bigip_gtm_wide_ip:
|
|
|
|
|
server: lb.mydomain.com
|
|
|
|
|
user: admin
|
|
|
|
|
password: secret
|
|
|
|
|
pool_lb_method: round-robin
|
|
|
|
|
name: my-wide-ip.example.com
|
|
|
|
|
irules: ""
|
|
|
|
|
delegate_to: localhost
|
|
|
|
|
|
|
|
|
|
- name: Assign a pool with ratio to the Wide IP
|
|
|
|
|
bigip_gtm_wide_ip:
|
|
|
|
|
server: lb.mydomain.com
|
|
|
|
|
user: admin
|
|
|
|
|
password: secret
|
|
|
|
|
pool_lb_method: round-robin
|
|
|
|
|
name: my-wide-ip.example.com
|
|
|
|
|
pools:
|
|
|
|
|
- name: pool1
|
|
|
|
|
ratio: 100
|
|
|
|
|
delegate_to: localhost
|
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
@ -114,40 +169,40 @@ state:
|
|
|
|
|
returned: changed
|
|
|
|
|
type: string
|
|
|
|
|
sample: disabled
|
|
|
|
|
irules:
|
|
|
|
|
description: iRules set on the Wide IP.
|
|
|
|
|
returned: changed
|
|
|
|
|
type: list
|
|
|
|
|
sample: ['/Common/irule1', '/Common/irule2']
|
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
import re
|
|
|
|
|
|
|
|
|
|
from ansible.module_utils.six import iteritems
|
|
|
|
|
from distutils.version import LooseVersion
|
|
|
|
|
|
|
|
|
|
from ansible.module_utils.basic import AnsibleModule
|
|
|
|
|
from ansible.module_utils.basic import env_fallback
|
|
|
|
|
|
|
|
|
|
HAS_DEVEL_IMPORTS = False
|
|
|
|
|
from ansible.module_utils.six import iteritems
|
|
|
|
|
from distutils.version import LooseVersion
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
# Sideband repository used for dev
|
|
|
|
|
from library.module_utils.network.f5.bigip import HAS_F5SDK
|
|
|
|
|
from library.module_utils.network.f5.bigip import F5Client
|
|
|
|
|
from library.module_utils.network.f5.common import F5ModuleError
|
|
|
|
|
from library.module_utils.network.f5.common import AnsibleF5Parameters
|
|
|
|
|
from library.module_utils.network.f5.common import cleanup_tokens
|
|
|
|
|
from library.module_utils.network.f5.common import fqdn_name
|
|
|
|
|
from library.module_utils.network.f5.common import fq_name
|
|
|
|
|
from library.module_utils.network.f5.common import is_valid_fqdn
|
|
|
|
|
from library.module_utils.network.f5.common import f5_argument_spec
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
|
|
|
|
|
except ImportError:
|
|
|
|
|
HAS_F5SDK = False
|
|
|
|
|
HAS_DEVEL_IMPORTS = True
|
|
|
|
|
except ImportError:
|
|
|
|
|
# Upstream Ansible
|
|
|
|
|
from ansible.module_utils.network.f5.bigip import HAS_F5SDK
|
|
|
|
|
from ansible.module_utils.network.f5.bigip import F5Client
|
|
|
|
|
from ansible.module_utils.network.f5.common import F5ModuleError
|
|
|
|
|
from ansible.module_utils.network.f5.common import AnsibleF5Parameters
|
|
|
|
|
from ansible.module_utils.network.f5.common import cleanup_tokens
|
|
|
|
|
from ansible.module_utils.network.f5.common import fqdn_name
|
|
|
|
|
from ansible.module_utils.network.f5.common import fq_name
|
|
|
|
|
from ansible.module_utils.network.f5.common import is_valid_fqdn
|
|
|
|
|
from ansible.module_utils.network.f5.common import f5_argument_spec
|
|
|
|
|
try:
|
|
|
|
|
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
|
|
|
|
@ -157,16 +212,21 @@ except ImportError:
|
|
|
|
|
|
|
|
|
|
class Parameters(AnsibleF5Parameters):
|
|
|
|
|
api_map = {
|
|
|
|
|
'poolLbMode': 'pool_lb_method'
|
|
|
|
|
'poolLbMode': 'pool_lb_method',
|
|
|
|
|
'rules': 'irules',
|
|
|
|
|
}
|
|
|
|
|
updatables = ['pool_lb_method', 'state', 'pools']
|
|
|
|
|
returnables = ['name', 'pool_lb_method', 'state', 'pools']
|
|
|
|
|
api_attributes = ['poolLbMode', 'enabled', 'disabled', 'pools']
|
|
|
|
|
|
|
|
|
|
def _fqdn_name(self, value):
|
|
|
|
|
if value is not None and not value.startswith('/'):
|
|
|
|
|
return '/{0}/{1}'.format(self.partition, value)
|
|
|
|
|
return value
|
|
|
|
|
updatables = [
|
|
|
|
|
'pool_lb_method', 'state', 'pools', 'irules', 'enabled', 'disabled'
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
returnables = [
|
|
|
|
|
'name', 'pool_lb_method', 'state', 'pools', 'irules'
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
api_attributes = [
|
|
|
|
|
'poolLbMode', 'enabled', 'disabled', 'pools', 'rules'
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ApiParameters(Parameters):
|
|
|
|
@ -204,25 +264,15 @@ class ApiParameters(Parameters):
|
|
|
|
|
class ModuleParameters(Parameters):
|
|
|
|
|
@property
|
|
|
|
|
def pool_lb_method(self):
|
|
|
|
|
deprecated = [
|
|
|
|
|
'return_to_dns', 'null', 'static_persist', 'vs_capacity',
|
|
|
|
|
'least_conn', 'lowest_rtt', 'lowest_hops', 'packet_rate', 'cpu',
|
|
|
|
|
'hit_ratio', 'qos', 'bps', 'drop_packet', 'explicit_ip',
|
|
|
|
|
'connection_rate', 'vs_score'
|
|
|
|
|
]
|
|
|
|
|
if self._values['lb_method'] is None:
|
|
|
|
|
if self._values['pool_lb_method'] is None:
|
|
|
|
|
return None
|
|
|
|
|
lb_method = str(self._values['lb_method'])
|
|
|
|
|
if lb_method in deprecated:
|
|
|
|
|
raise F5ModuleError(
|
|
|
|
|
"The provided lb_method is not supported"
|
|
|
|
|
)
|
|
|
|
|
elif lb_method == 'global_availability':
|
|
|
|
|
lb_method = str(self._values['pool_lb_method'])
|
|
|
|
|
if lb_method == 'global_availability':
|
|
|
|
|
if self._values['__warnings'] is None:
|
|
|
|
|
self._values['__warnings'] = []
|
|
|
|
|
self._values['__warnings'].append(
|
|
|
|
|
dict(
|
|
|
|
|
msg='The provided lb_method is deprecated',
|
|
|
|
|
msg='The provided pool_lb_method is deprecated',
|
|
|
|
|
version='2.4'
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
@ -232,7 +282,7 @@ class ModuleParameters(Parameters):
|
|
|
|
|
self._values['__warnings'] = []
|
|
|
|
|
self._values['__warnings'].append(
|
|
|
|
|
dict(
|
|
|
|
|
msg='The provided lb_method is deprecated',
|
|
|
|
|
msg='The provided pool_lb_method is deprecated',
|
|
|
|
|
version='2.4'
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
@ -249,7 +299,7 @@ class ModuleParameters(Parameters):
|
|
|
|
|
def name(self):
|
|
|
|
|
if self._values['name'] is None:
|
|
|
|
|
return None
|
|
|
|
|
if not re.search(r'.*\..*\..*', self._values['name']):
|
|
|
|
|
if not is_valid_fqdn(self._values['name']):
|
|
|
|
|
raise F5ModuleError(
|
|
|
|
|
"The provided name must be a valid FQDN"
|
|
|
|
|
)
|
|
|
|
@ -286,12 +336,28 @@ class ModuleParameters(Parameters):
|
|
|
|
|
return None
|
|
|
|
|
for item in self._values['pools']:
|
|
|
|
|
pool = dict()
|
|
|
|
|
if 'name' not in item:
|
|
|
|
|
raise F5ModuleError(
|
|
|
|
|
"'name' is a required key for items in the list of pools."
|
|
|
|
|
)
|
|
|
|
|
if 'ratio' in item:
|
|
|
|
|
pool['ratio'] = item['ratio']
|
|
|
|
|
pool['name'] = self._fqdn_name(item['name'])
|
|
|
|
|
pool['name'] = fq_name(self.partition, item['name'])
|
|
|
|
|
result.append(pool)
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def irules(self):
|
|
|
|
|
results = []
|
|
|
|
|
if self._values['irules'] is None:
|
|
|
|
|
return None
|
|
|
|
|
if len(self._values['irules']) == 1 and self._values['irules'][0] == '':
|
|
|
|
|
return ''
|
|
|
|
|
for irule in self._values['irules']:
|
|
|
|
|
result = fq_name(self.partition, irule)
|
|
|
|
|
results.append(result)
|
|
|
|
|
return results
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Changes(Parameters):
|
|
|
|
|
def to_return(self):
|
|
|
|
@ -310,7 +376,13 @@ class Changes(Parameters):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class UsableChanges(Changes):
|
|
|
|
|
pass
|
|
|
|
|
@property
|
|
|
|
|
def irules(self):
|
|
|
|
|
if self._values['irules'] is None:
|
|
|
|
|
return None
|
|
|
|
|
if self._values['irules'] == '':
|
|
|
|
|
return []
|
|
|
|
|
return self._values['irules']
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ReportableChanges(Changes):
|
|
|
|
@ -375,6 +447,17 @@ class Difference(object):
|
|
|
|
|
result = self._diff_complex_items(self.want.pools, self.have.pools)
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def irules(self):
|
|
|
|
|
if self.want.irules is None:
|
|
|
|
|
return None
|
|
|
|
|
if self.want.irules == '' and self.have.irules is None:
|
|
|
|
|
return None
|
|
|
|
|
if self.want.irules == '' and len(self.have.irules) > 0:
|
|
|
|
|
return []
|
|
|
|
|
if sorted(set(self.want.irules)) != sorted(set(self.have.irules)):
|
|
|
|
|
return self.want.irules
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ModuleManager(object):
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
@ -466,16 +549,16 @@ class BaseManager(object):
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def present(self):
|
|
|
|
|
if self.want.lb_method is None:
|
|
|
|
|
raise F5ModuleError(
|
|
|
|
|
"The 'lb_method' option is required when state is 'present'"
|
|
|
|
|
)
|
|
|
|
|
if self.exists():
|
|
|
|
|
return self.update()
|
|
|
|
|
else:
|
|
|
|
|
return self.create()
|
|
|
|
|
|
|
|
|
|
def create(self):
|
|
|
|
|
if self.want.pool_lb_method is None:
|
|
|
|
|
raise F5ModuleError(
|
|
|
|
|
"The 'pool_lb_method' option is required when state is 'present'"
|
|
|
|
|
)
|
|
|
|
|
self._set_changed_options()
|
|
|
|
|
if self.module.check_mode:
|
|
|
|
|
return True
|
|
|
|
@ -519,7 +602,7 @@ class UntypedManager(BaseManager):
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def update_on_device(self):
|
|
|
|
|
params = self.want.api_params()
|
|
|
|
|
params = self.changes.api_params()
|
|
|
|
|
result = self.client.api.tm.gtm.wideips.wipeip.load(
|
|
|
|
|
name=self.want.name,
|
|
|
|
|
partition=self.want.partition
|
|
|
|
@ -535,7 +618,7 @@ class UntypedManager(BaseManager):
|
|
|
|
|
return ApiParameters(params=result)
|
|
|
|
|
|
|
|
|
|
def create_on_device(self):
|
|
|
|
|
params = self.want.api_params()
|
|
|
|
|
params = self.changes.api_params()
|
|
|
|
|
self.client.api.tm.gtm.wideips.wideip.create(
|
|
|
|
|
name=self.want.name,
|
|
|
|
|
partition=self.want.partition,
|
|
|
|
@ -580,7 +663,7 @@ class TypedManager(BaseManager):
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
def update_on_device(self):
|
|
|
|
|
params = self.want.api_params()
|
|
|
|
|
params = self.changes.api_params()
|
|
|
|
|
wideips = self.client.api.tm.gtm.wideips
|
|
|
|
|
collection = getattr(wideips, self.collection)
|
|
|
|
|
resource = getattr(collection, self.want.type)
|
|
|
|
@ -602,7 +685,7 @@ class TypedManager(BaseManager):
|
|
|
|
|
return ApiParameters(params=result)
|
|
|
|
|
|
|
|
|
|
def create_on_device(self):
|
|
|
|
|
params = self.want.api_params()
|
|
|
|
|
params = self.changes.api_params()
|
|
|
|
|
wideips = self.client.api.tm.gtm.wideips
|
|
|
|
|
collection = getattr(wideips, self.collection)
|
|
|
|
|
resource = getattr(collection, self.want.type)
|
|
|
|
@ -626,16 +709,12 @@ class TypedManager(BaseManager):
|
|
|
|
|
|
|
|
|
|
class ArgumentSpec(object):
|
|
|
|
|
def __init__(self):
|
|
|
|
|
deprecated = [
|
|
|
|
|
'return_to_dns', 'null', 'round_robin', 'static_persist',
|
|
|
|
|
'global_availability', 'vs_capacity', 'least_conn', 'lowest_rtt',
|
|
|
|
|
'lowest_hops', 'packet_rate', 'cpu', 'hit_ratio', 'qos', 'bps',
|
|
|
|
|
'drop_packet', 'explicit_ip', 'connection_rate', 'vs_score'
|
|
|
|
|
]
|
|
|
|
|
supported = [
|
|
|
|
|
'round-robin', 'topology', 'ratio', 'global-availability'
|
|
|
|
|
lb_method_choices = [
|
|
|
|
|
'round-robin', 'topology', 'ratio', 'global-availability',
|
|
|
|
|
|
|
|
|
|
# TODO(Remove in Ansible 2.9)
|
|
|
|
|
'round_robin', 'global_availability'
|
|
|
|
|
]
|
|
|
|
|
lb_method_choices = deprecated + supported
|
|
|
|
|
self.supports_check_mode = True
|
|
|
|
|
argument_spec = dict(
|
|
|
|
|
pool_lb_method=dict(
|
|
|
|
@ -665,7 +744,10 @@ class ArgumentSpec(object):
|
|
|
|
|
partition=dict(
|
|
|
|
|
default='Common',
|
|
|
|
|
fallback=(env_fallback, ['F5_PARTITION'])
|
|
|
|
|
)
|
|
|
|
|
),
|
|
|
|
|
irules=dict(
|
|
|
|
|
type='list',
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
self.argument_spec = {}
|
|
|
|
|
self.argument_spec.update(f5_argument_spec)
|
|
|
|
|