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