Adds style conventions for bigip_node (#2697)

A number of coding conventions have been adopted for new F5 modules
that are in development. To ensure common usage across the modules,
this module needed to be updated to reflect those conventions.

No functional code changes were made.
pull/18777/head
Tim Rupp 8 years ago committed by Matt Clay
parent 081e6ec032
commit a367a9ac01

@ -1,6 +1,6 @@
#!/usr/bin/python #!/usr/bin/python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
#
# (c) 2013, Matt Hite <mhite@hotmail.com> # (c) 2013, Matt Hite <mhite@hotmail.com>
# #
# This file is part of Ansible # This file is part of Ansible
@ -23,148 +23,139 @@ DOCUMENTATION = '''
module: bigip_node module: bigip_node
short_description: "Manages F5 BIG-IP LTM nodes" short_description: "Manages F5 BIG-IP LTM nodes"
description: description:
- "Manages F5 BIG-IP LTM nodes via iControl SOAP API" - "Manages F5 BIG-IP LTM nodes via iControl SOAP API"
version_added: "1.4" version_added: "1.4"
author: author:
- Matt Hite (@mhite) - Matt Hite (@mhite)
- Tim Rupp (@caphrim007) - Tim Rupp (@caphrim007)
notes: notes:
- "Requires BIG-IP software version >= 11" - "Requires BIG-IP software version >= 11"
- "F5 developed module 'bigsuds' required (see http://devcentral.f5.com)" - "F5 developed module 'bigsuds' required (see http://devcentral.f5.com)"
- "Best run as a local_action in your playbook" - "Best run as a local_action in your playbook"
requirements: requirements:
- bigsuds - bigsuds
options: options:
server: server:
description: description:
- BIG-IP host - BIG-IP host
required: true required: true
default: null default: null
choices: [] choices: []
aliases: [] aliases: []
server_port: server_port:
description: description:
- BIG-IP server port - BIG-IP server port
required: false required: false
default: 443 default: 443
version_added: "2.2" version_added: "2.2"
user: user:
description: description:
- BIG-IP username - BIG-IP username
required: true required: true
default: null default: null
choices: [] choices: []
aliases: [] aliases: []
password: password:
description: description:
- BIG-IP password - BIG-IP password
required: true required: true
default: null default: null
choices: [] choices: []
aliases: [] aliases: []
validate_certs: validate_certs:
description: description:
- If C(no), SSL certificates will not be validated. This should only be used - If C(no), SSL certificates will not be validated. This should only be used
on personally controlled sites. Prior to 2.0, this module would always on personally controlled sites. Prior to 2.0, this module would always
validate on python >= 2.7.9 and never validate on python <= 2.7.8 validate on python >= 2.7.9 and never validate on python <= 2.7.8
required: false required: false
default: 'yes' default: 'yes'
choices: ['yes', 'no'] choices: ['yes', 'no']
version_added: 1.9.1 version_added: 2.0
state: state:
description: description:
- Pool member state - Pool member state
required: true required: true
default: present default: present
choices: ['present', 'absent'] choices: ['present', 'absent']
aliases: [] aliases: []
session_state: session_state:
description: description:
- Set new session availability status for node - Set new session availability status for node
version_added: "1.9" version_added: "1.9"
required: false required: false
default: null default: null
choices: ['enabled', 'disabled'] choices: ['enabled', 'disabled']
aliases: [] aliases: []
monitor_state: monitor_state:
description: description:
- Set monitor availability status for node - Set monitor availability status for node
version_added: "1.9" version_added: "1.9"
required: false required: false
default: null default: null
choices: ['enabled', 'disabled'] choices: ['enabled', 'disabled']
aliases: [] aliases: []
partition: partition:
description:
- Partition
required: false
default: 'Common'
choices: []
aliases: []
name:
description:
- "Node name"
required: false
default: null
choices: []
monitor_type:
description:
- Monitor rule type when monitors > 1
version_added: "2.2"
required: False
default: null
choices: ['and_list', 'm_of_n']
aliases: []
quorum:
description:
- Monitor quorum value when monitor_type is m_of_n
version_added: "2.2"
required: False
default: null
choices: []
aliases: []
monitors:
description:
- Monitor template name list. Always use the full path to the monitor.
version_added: "2.2"
required: False
default: null
choices: []
aliases: []
host:
description:
- "Node IP. Required when state=present and node does not exist. Error when state=absent."
required: true
default: null
choices: []
aliases: ['address', 'ip']
description: description:
description: - Partition
- "Node description." required: false
required: false default: 'Common'
default: null choices: []
choices: [] aliases: []
name:
description:
- "Node name"
required: false
default: null
choices: []
monitor_type:
description:
- Monitor rule type when monitors > 1
version_added: "2.2"
required: False
default: null
choices: ['and_list', 'm_of_n']
aliases: []
quorum:
description:
- Monitor quorum value when monitor_type is m_of_n
version_added: "2.2"
required: False
default: null
choices: []
aliases: []
monitors:
description:
- Monitor template name list. Always use the full path to the monitor.
version_added: "2.2"
required: False
default: null
choices: []
aliases: []
host:
description:
- "Node IP. Required when state=present and node does not exist. Error when state=absent."
required: true
default: null
choices: []
aliases: ['address', 'ip']
description:
description:
- "Node description."
required: false
default: null
choices: []
''' '''
EXAMPLES = ''' EXAMPLES = '''
- name: Add node
## playbook task examples: bigip_node:
server: "lb.mydomain.com"
--- user: "admin"
# file bigip-test.yml password: "secret"
# ... state: "present"
- hosts: bigip-test partition: "Common"
tasks: host: "10.20.30.40"
- name: Add node name: "10.20.30.40"
local_action: >
bigip_node
server=lb.mydomain.com
user=admin
password=mysecret
state=present
partition=matthite
host="{{ ansible_default_ipv4["address"] }}"
name="{{ ansible_default_ipv4["address"] }}"
# Note that the BIG-IP automatically names the node using the # Note that the BIG-IP automatically names the node using the
# IP address specified in previous play's host parameter. # IP address specified in previous play's host parameter.
@ -173,38 +164,38 @@ EXAMPLES = '''
# Alternatively, you could have specified a name with the # Alternatively, you could have specified a name with the
# name parameter when state=present. # name parameter when state=present.
- name: Add node with a single 'ping' monitor - name: Add node with a single 'ping' monitor
bigip_node: bigip_node:
server: lb.mydomain.com server: "lb.mydomain.com"
user: admin user: "admin"
password: mysecret password: "secret"
state: present state: "present"
partition: Common partition: "Common"
host: "{{ ansible_default_ipv4["address"] }}" host: "10.20.30.40"
name: mytestserver name: "mytestserver"
monitors: monitors:
- /Common/icmp - /Common/icmp
delegate_to: localhost
- name: Modify node description
local_action: > - name: Modify node description
bigip_node bigip_node:
server=lb.mydomain.com server: "lb.mydomain.com"
user=admin user: "admin"
password=mysecret password: "secret"
state=present state: "present"
partition=matthite partition: "Common"
name="{{ ansible_default_ipv4["address"] }}" name: "10.20.30.40"
description="Our best server yet" description: "Our best server yet"
delegate_to: localhost
- name: Delete node
local_action: > - name: Delete node
bigip_node bigip_node:
server=lb.mydomain.com server: "lb.mydomain.com"
user=admin user: "admin"
password=mysecret password: "secret"
state=absent state: "absent"
partition=matthite partition: "Common"
name="{{ ansible_default_ipv4["address"] }}" name: "10.20.30.40"
# The BIG-IP GUI doesn't map directly to the API calls for "Node -> # The BIG-IP GUI doesn't map directly to the API calls for "Node ->
# General Properties -> State". The following states map to API monitor # General Properties -> State". The following states map to API monitor
@ -219,27 +210,26 @@ EXAMPLES = '''
# #
# See https://devcentral.f5.com/questions/icontrol-equivalent-call-for-b-node-down # See https://devcentral.f5.com/questions/icontrol-equivalent-call-for-b-node-down
- name: Force node offline - name: Force node offline
local_action: > bigip_node:
bigip_node server: "lb.mydomain.com"
server=lb.mydomain.com user: "admin"
user=admin password: "mysecret"
password=mysecret state: "present"
state=present session_state: "disabled"
session_state=disabled monitor_state: "disabled"
monitor_state=disabled partition: "Common"
partition=matthite name: "10.20.30.40"
name="{{ ansible_default_ipv4["address"] }}"
''' '''
def node_exists(api, address): def node_exists(api, address):
# hack to determine if node exists # hack to determine if node exists
result = False result = False
try: try:
api.LocalLB.NodeAddressV2.get_object_status(nodes=[address]) api.LocalLB.NodeAddressV2.get_object_status(nodes=[address])
result = True result = True
except bigsuds.OperationFailed, e: except bigsuds.OperationFailed as e:
if "was not found" in str(e): if "was not found" in str(e):
result = False result = False
else: else:
@ -247,12 +237,17 @@ def node_exists(api, address):
raise raise
return result return result
def create_node_address(api, address, name): def create_node_address(api, address, name):
try: try:
api.LocalLB.NodeAddressV2.create(nodes=[name], addresses=[address], limits=[0]) api.LocalLB.NodeAddressV2.create(
nodes=[name],
addresses=[address],
limits=[0]
)
result = True result = True
desc = "" desc = ""
except bigsuds.OperationFailed, e: except bigsuds.OperationFailed as e:
if "already exists" in str(e): if "already exists" in str(e):
result = False result = False
desc = "referenced name or IP already in use" desc = "referenced name or IP already in use"
@ -261,15 +256,17 @@ def create_node_address(api, address, name):
raise raise
return (result, desc) return (result, desc)
def get_node_address(api, name): def get_node_address(api, name):
return api.LocalLB.NodeAddressV2.get_address(nodes=[name])[0] return api.LocalLB.NodeAddressV2.get_address(nodes=[name])[0]
def delete_node_address(api, address): def delete_node_address(api, address):
try: try:
api.LocalLB.NodeAddressV2.delete_node_address(nodes=[address]) api.LocalLB.NodeAddressV2.delete_node_address(nodes=[address])
result = True result = True
desc = "" desc = ""
except bigsuds.OperationFailed, e: except bigsuds.OperationFailed as e:
if "is referenced by a member of pool" in str(e): if "is referenced by a member of pool" in str(e):
result = False result = False
desc = "node referenced by pool" desc = "node referenced by pool"
@ -278,33 +275,40 @@ def delete_node_address(api, address):
raise raise
return (result, desc) return (result, desc)
def set_node_description(api, name, description): def set_node_description(api, name, description):
api.LocalLB.NodeAddressV2.set_description(nodes=[name], api.LocalLB.NodeAddressV2.set_description(nodes=[name],
descriptions=[description]) descriptions=[description])
def get_node_description(api, name): def get_node_description(api, name):
return api.LocalLB.NodeAddressV2.get_description(nodes=[name])[0] return api.LocalLB.NodeAddressV2.get_description(nodes=[name])[0]
def set_node_session_enabled_state(api, name, session_state): def set_node_session_enabled_state(api, name, session_state):
session_state = "STATE_%s" % session_state.strip().upper() session_state = "STATE_%s" % session_state.strip().upper()
api.LocalLB.NodeAddressV2.set_session_enabled_state(nodes=[name], api.LocalLB.NodeAddressV2.set_session_enabled_state(nodes=[name],
states=[session_state]) states=[session_state])
def get_node_session_status(api, name): def get_node_session_status(api, name):
result = api.LocalLB.NodeAddressV2.get_session_status(nodes=[name])[0] result = api.LocalLB.NodeAddressV2.get_session_status(nodes=[name])[0]
result = result.split("SESSION_STATUS_")[-1].lower() result = result.split("SESSION_STATUS_")[-1].lower()
return result return result
def set_node_monitor_state(api, name, monitor_state): def set_node_monitor_state(api, name, monitor_state):
monitor_state = "STATE_%s" % monitor_state.strip().upper() monitor_state = "STATE_%s" % monitor_state.strip().upper()
api.LocalLB.NodeAddressV2.set_monitor_state(nodes=[name], api.LocalLB.NodeAddressV2.set_monitor_state(nodes=[name],
states=[monitor_state]) states=[monitor_state])
def get_node_monitor_status(api, name): def get_node_monitor_status(api, name):
result = api.LocalLB.NodeAddressV2.get_monitor_status(nodes=[name])[0] result = api.LocalLB.NodeAddressV2.get_monitor_status(nodes=[name])[0]
result = result.split("MONITOR_STATUS_")[-1].lower() result = result.split("MONITOR_STATUS_")[-1].lower()
return result return result
def get_monitors(api, name): def get_monitors(api, name):
result = api.LocalLB.NodeAddressV2.get_monitor_rule(nodes=[name])[0] result = api.LocalLB.NodeAddressV2.get_monitor_rule(nodes=[name])[0]
monitor_type = result['type'].split("MONITOR_RULE_TYPE_")[-1].lower() monitor_type = result['type'].split("MONITOR_RULE_TYPE_")[-1].lower()
@ -312,37 +316,36 @@ def get_monitors(api, name):
monitor_templates = result['monitor_templates'] monitor_templates = result['monitor_templates']
return (monitor_type, quorum, monitor_templates) return (monitor_type, quorum, monitor_templates)
def set_monitors(api, name, monitor_type, quorum, monitor_templates): def set_monitors(api, name, monitor_type, quorum, monitor_templates):
monitor_type = "MONITOR_RULE_TYPE_%s" % monitor_type.strip().upper() monitor_type = "MONITOR_RULE_TYPE_%s" % monitor_type.strip().upper()
monitor_rule = {'type': monitor_type, 'quorum': quorum, 'monitor_templates': monitor_templates} monitor_rule = {'type': monitor_type, 'quorum': quorum, 'monitor_templates': monitor_templates}
api.LocalLB.NodeAddressV2.set_monitor_rule(nodes=[name], api.LocalLB.NodeAddressV2.set_monitor_rule(nodes=[name],
monitor_rules=[monitor_rule]) monitor_rules=[monitor_rule])
def main(): def main():
monitor_type_choices = ['and_list', 'm_of_n'] monitor_type_choices = ['and_list', 'm_of_n']
argument_spec = f5_argument_spec() argument_spec = f5_argument_spec()
argument_spec.update(dict( meta_args = dict(
session_state = dict(type='str', choices=['enabled', 'disabled']), session_state=dict(type='str', choices=['enabled', 'disabled']),
monitor_state = dict(type='str', choices=['enabled', 'disabled']), monitor_state=dict(type='str', choices=['enabled', 'disabled']),
name = dict(type='str', required=True), name=dict(type='str', required=True),
host = dict(type='str', aliases=['address', 'ip']), host=dict(type='str', aliases=['address', 'ip']),
description = dict(type='str'), description=dict(type='str'),
monitor_type = dict(type='str', choices=monitor_type_choices), monitor_type=dict(type='str', choices=monitor_type_choices),
quorum = dict(type='int'), quorum=dict(type='int'),
monitors = dict(type='list') monitors=dict(type='list')
)
) )
argument_spec.update(meta_args)
module = AnsibleModule( module = AnsibleModule(
argument_spec = argument_spec, argument_spec=argument_spec,
supports_check_mode=True supports_check_mode=True
) )
if not bigsuds_found:
module.fail_json(msg="the python bigsuds module is required")
if module.params['validate_certs']: if module.params['validate_certs']:
import ssl import ssl
if not hasattr(ssl, 'SSLContext'): if not hasattr(ssl, 'SSLContext'):
@ -373,7 +376,6 @@ def main():
monitors.append(fq_name(partition, monitor)) monitors.append(fq_name(partition, monitor))
# sanity check user supplied values # sanity check user supplied values
if state == 'absent' and host is not None: if state == 'absent' and host is not None:
module.fail_json(msg="host parameter invalid when state=absent") module.fail_json(msg="host parameter invalid when state=absent")
@ -415,7 +417,7 @@ def main():
elif state == 'present': elif state == 'present':
if not node_exists(api, address): if not node_exists(api, address):
if host is None: if host is None:
module.fail_json(msg="host parameter required when " \ module.fail_json(msg="host parameter required when "
"state=present and node does not exist") "state=present and node does not exist")
if not module.check_mode: if not module.check_mode:
created, desc = create_node_address(api, address=host, name=address) created, desc = create_node_address(api, address=host, name=address)
@ -442,8 +444,8 @@ def main():
# node exists -- potentially modify attributes # node exists -- potentially modify attributes
if host is not None: if host is not None:
if get_node_address(api, address) != host: if get_node_address(api, address) != host:
module.fail_json(msg="Changing the node address is " \ module.fail_json(msg="Changing the node address is "
"not supported by the API; " \ "not supported by the API; "
"delete and recreate the node.") "delete and recreate the node.")
if session_state is not None: if session_state is not None:
session_status = get_node_session_status(api, address) session_status = get_node_session_status(api, address)
@ -454,7 +456,7 @@ def main():
session_state) session_state)
result = {'changed': True} result = {'changed': True}
elif session_state == 'disabled' and \ elif session_state == 'disabled' and \
session_status != 'force_disabled': session_status != 'force_disabled':
if not module.check_mode: if not module.check_mode:
set_node_session_enabled_state(api, address, set_node_session_enabled_state(api, address,
session_state) session_state)
@ -468,7 +470,7 @@ def main():
monitor_state) monitor_state)
result = {'changed': True} result = {'changed': True}
elif monitor_state == 'disabled' and \ elif monitor_state == 'disabled' and \
monitor_status != 'forced_down': monitor_status != 'forced_down':
if not module.check_mode: if not module.check_mode:
set_node_monitor_state(api, address, set_node_monitor_state(api, address,
monitor_state) monitor_state)
@ -484,13 +486,11 @@ def main():
if not module.check_mode: if not module.check_mode:
set_monitors(api, address, monitor_type, quorum, monitors) set_monitors(api, address, monitor_type, quorum, monitors)
result = {'changed': True} result = {'changed': True}
except Exception as e:
except Exception, e:
module.fail_json(msg="received exception: %s" % e) module.fail_json(msg="received exception: %s" % e)
module.exit_json(**result) module.exit_json(**result)
# import module snippets
from ansible.module_utils.basic import * from ansible.module_utils.basic import *
from ansible.module_utils.f5 import * from ansible.module_utils.f5 import *

Loading…
Cancel
Save