diff --git a/lib/ansible/modules/extras/network/f5/bigip_pool.py b/lib/ansible/modules/extras/network/f5/bigip_pool.py index 1f4a0ed7746..3966742fd3e 100644 --- a/lib/ansible/modules/extras/network/f5/bigip_pool.py +++ b/lib/ansible/modules/extras/network/f5/bigip_pool.py @@ -23,235 +23,245 @@ DOCUMENTATION = ''' module: bigip_pool short_description: "Manages F5 BIG-IP LTM pools" description: - - "Manages F5 BIG-IP LTM pools via iControl SOAP API" -version_added: "1.2" + - Manages F5 BIG-IP LTM pools via iControl SOAP API +version_added: 1.2 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/pool member state - required: false - default: present - choices: ['present', 'absent'] - aliases: [] - name: - description: - - Pool name - required: true - default: null - choices: [] - aliases: ['pool'] - partition: - description: - - Partition of pool/pool member - required: false - default: 'Common' - choices: [] - aliases: [] - lb_method: - description: - - Load balancing method - version_added: "1.3" - required: False - default: 'round_robin' - choices: ['round_robin', 'ratio_member', 'least_connection_member', - 'observed_member', 'predictive_member', 'ratio_node_address', - 'least_connection_node_address', 'fastest_node_address', - 'observed_node_address', 'predictive_node_address', - 'dynamic_ratio', 'fastest_app_response', 'least_sessions', - 'dynamic_ratio_member', 'l3_addr', - 'weighted_least_connection_member', - 'weighted_least_connection_node_address', - 'ratio_session', 'ratio_least_connection_member', - 'ratio_least_connection_node_address'] - aliases: [] - monitor_type: - description: - - Monitor rule type when monitors > 1 - version_added: "1.3" - 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: "1.3" - required: False - default: null - choices: [] - aliases: [] - monitors: - description: - - Monitor template name list. Always use the full path to the monitor. - version_added: "1.3" - required: False - default: null - choices: [] - aliases: [] - slow_ramp_time: - description: - - Sets the ramp-up time (in seconds) to gradually ramp up the load on newly added or freshly detected up pool members - version_added: "1.3" - required: False - default: null - choices: [] - aliases: [] - reselect_tries: - description: - - Sets the number of times the system tries to contact a pool member after a passive failure - version_added: "2.2" - required: False - default: null - choices: [] - aliases: [] - service_down_action: - description: - - Sets the action to take when node goes down in pool - version_added: "1.3" - required: False - default: null - choices: ['none', 'reset', 'drop', 'reselect'] - aliases: [] - host: - description: - - "Pool member IP" - required: False - default: null - choices: [] - aliases: ['address'] - port: - description: - - "Pool member port" - required: False - default: null - choices: [] - aliases: [] + 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/pool member state + required: false + default: present + choices: + - present + - absent + aliases: [] + name: + description: + - Pool name + required: true + default: null + choices: [] + aliases: + - pool + partition: + description: + - Partition of pool/pool member + required: false + default: 'Common' + choices: [] + aliases: [] + lb_method: + description: + - Load balancing method + version_added: "1.3" + required: False + default: 'round_robin' + choices: + - round_robin + - ratio_member + - least_connection_member + - observed_member + - predictive_member + - ratio_node_address + - least_connection_node_address + - fastest_node_address + - observed_node_address + - predictive_node_address + - dynamic_ratio + - fastest_app_response + - least_sessions + - dynamic_ratio_member + - l3_addr + - weighted_least_connection_member + - weighted_least_connection_node_address + - ratio_session + - ratio_least_connection_member + - ratio_least_connection_node_address + aliases: [] + monitor_type: + description: + - Monitor rule type when monitors > 1 + version_added: "1.3" + 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: "1.3" + required: False + default: null + choices: [] + aliases: [] + monitors: + description: + - Monitor template name list. Always use the full path to the monitor. + version_added: "1.3" + required: False + default: null + choices: [] + aliases: [] + slow_ramp_time: + description: + - Sets the ramp-up time (in seconds) to gradually ramp up the load on + newly added or freshly detected up pool members + version_added: "1.3" + required: False + default: null + choices: [] + aliases: [] + reselect_tries: + description: + - Sets the number of times the system tries to contact a pool member + after a passive failure + version_added: "2.2" + required: False + default: null + choices: [] + aliases: [] + service_down_action: + description: + - Sets the action to take when node goes down in pool + version_added: "1.3" + required: False + default: null + choices: + - none + - reset + - drop + - reselect + aliases: [] + host: + description: + - "Pool member IP" + required: False + default: null + choices: [] + aliases: + - address + port: + description: + - Pool member port + required: False + default: null + choices: [] + aliases: [] ''' EXAMPLES = ''' +- name: Create pool + bigip_pool: + server: "lb.mydomain.com" + user: "admin" + password: "secret" + state: "present" + name: "my-pool" + partition: "Common" + lb_method: "least_connection_member" + slow_ramp_time: 120 + delegate_to: localhost + +- name: Modify load balancer method + bigip_pool: + server: "lb.mydomain.com" + user: "admin" + password: "secret" + state: "present" + name: "my-pool" + partition: "Common" + lb_method: "round_robin" + +- name: Add pool member + bigip_pool: + server: "lb.mydomain.com" + user: "admin" + password: "secret" + state: "present" + name: "my-pool" + partition: "Common" + host: "{{ ansible_default_ipv4["address"] }}" + port: 80 + +- name: Remove pool member from pool + bigip_pool: + server: "lb.mydomain.com" + user: "admin" + password: "secret" + state: "absent" + name: "my-pool" + partition: "Common" + host: "{{ ansible_default_ipv4["address"] }}" + port: 80 + +- name: Delete pool + bigip_pool: + server: "lb.mydomain.com" + user: "admin" + password: "secret" + state: "absent" + name: "my-pool" + partition: "Common" +''' -## playbook task examples: - ---- -# file bigip-test.yml -# ... -- hosts: localhost - tasks: - - name: Create pool - local_action: > - bigip_pool - server=lb.mydomain.com - user=admin - password=mysecret - state=present - name=matthite-pool - partition=matthite - lb_method=least_connection_member - slow_ramp_time=120 - - - name: Modify load balancer method - local_action: > - bigip_pool - server=lb.mydomain.com - user=admin - password=mysecret - state=present - name=matthite-pool - partition=matthite - lb_method=round_robin - -- hosts: bigip-test - tasks: - - name: Add pool member - local_action: > - bigip_pool - server=lb.mydomain.com - user=admin - password=mysecret - state=present - name=matthite-pool - partition=matthite - host="{{ ansible_default_ipv4["address"] }}" - port=80 - - - name: Remove pool member from pool - local_action: > - bigip_pool - server=lb.mydomain.com - user=admin - password=mysecret - state=absent - name=matthite-pool - partition=matthite - host="{{ ansible_default_ipv4["address"] }}" - port=80 - -- hosts: localhost - tasks: - - name: Delete pool - local_action: > - bigip_pool - server=lb.mydomain.com - user=admin - password=mysecret - state=absent - name=matthite-pool - partition=matthite - +RETURN = ''' ''' + def pool_exists(api, pool): # hack to determine if pool exists result = False try: api.LocalLB.Pool.get_object_status(pool_names=[pool]) result = True - except bigsuds.OperationFailed, e: + except bigsuds.OperationFailed as e: if "was not found" in str(e): result = False else: @@ -259,6 +269,7 @@ def pool_exists(api, pool): raise return result + def create_pool(api, pool, lb_method): # create requires lb_method but we don't want to default # to a value on subsequent runs @@ -268,18 +279,22 @@ def create_pool(api, pool, lb_method): api.LocalLB.Pool.create_v2(pool_names=[pool], lb_methods=[lb_method], members=[[]]) + def remove_pool(api, pool): api.LocalLB.Pool.delete_pool(pool_names=[pool]) + def get_lb_method(api, pool): lb_method = api.LocalLB.Pool.get_lb_method(pool_names=[pool])[0] lb_method = lb_method.strip().replace('LB_METHOD_', '').lower() return lb_method + def set_lb_method(api, pool, lb_method): lb_method = "LB_METHOD_%s" % lb_method.strip().upper() api.LocalLB.Pool.set_lb_method(pool_names=[pool], lb_methods=[lb_method]) + def get_monitors(api, pool): result = api.LocalLB.Pool.get_monitor_association(pool_names=[pool])[0]['monitor_rule'] monitor_type = result['type'].split("MONITOR_RULE_TYPE_")[-1].lower() @@ -287,35 +302,43 @@ def get_monitors(api, pool): monitor_templates = result['monitor_templates'] return (monitor_type, quorum, monitor_templates) + def set_monitors(api, pool, 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} monitor_association = {'pool_name': pool, 'monitor_rule': monitor_rule} api.LocalLB.Pool.set_monitor_association(monitor_associations=[monitor_association]) + def get_slow_ramp_time(api, pool): result = api.LocalLB.Pool.get_slow_ramp_time(pool_names=[pool])[0] return result + def set_slow_ramp_time(api, pool, seconds): api.LocalLB.Pool.set_slow_ramp_time(pool_names=[pool], values=[seconds]) + def get_reselect_tries(api, pool): result = api.LocalLB.Pool.get_reselect_tries(pool_names=[pool])[0] return result + def set_reselect_tries(api, pool, tries): api.LocalLB.Pool.set_reselect_tries(pool_names=[pool], values=[tries]) + def get_action_on_service_down(api, pool): result = api.LocalLB.Pool.get_action_on_service_down(pool_names=[pool])[0] result = result.split("SERVICE_DOWN_ACTION_")[-1].lower() return result + def set_action_on_service_down(api, pool, action): action = "SERVICE_DOWN_ACTION_%s" % action.strip().upper() api.LocalLB.Pool.set_action_on_service_down(pool_names=[pool], actions=[action]) + def member_exists(api, pool, address, port): # hack to determine if member exists result = False @@ -324,7 +347,7 @@ def member_exists(api, pool, address, port): api.LocalLB.Pool.get_member_object_status(pool_names=[pool], members=[members]) result = True - except bigsuds.OperationFailed, e: + except bigsuds.OperationFailed as e: if "was not found" in str(e): result = False else: @@ -332,12 +355,13 @@ def member_exists(api, pool, address, port): raise return result + def delete_node_address(api, address): result = False try: api.LocalLB.NodeAddressV2.delete_node_address(nodes=[address]) result = True - except bigsuds.OperationFailed, e: + except bigsuds.OperationFailed as e: if "is referenced by a member of pool" in str(e): result = False else: @@ -345,14 +369,17 @@ def delete_node_address(api, address): raise return result + def remove_pool_member(api, pool, address, port): members = [{'address': address, 'port': port}] api.LocalLB.Pool.remove_member_v2(pool_names=[pool], members=[members]) + def add_pool_member(api, pool, address, port): members = [{'address': address, 'port': port}] api.LocalLB.Pool.add_member_v2(pool_names=[pool], members=[members]) + def main(): lb_method_choices = ['round_robin', 'ratio_member', 'least_connection_member', 'observed_member', @@ -371,23 +398,24 @@ def main(): service_down_choices = ['none', 'reset', 'drop', 'reselect'] - argument_spec=f5_argument_spec(); - argument_spec.update(dict( - name = dict(type='str', required=True, aliases=['pool']), - lb_method = dict(type='str', choices=lb_method_choices), - monitor_type = dict(type='str', choices=monitor_type_choices), - quorum = dict(type='int'), - monitors = dict(type='list'), - slow_ramp_time = dict(type='int'), - reselect_tries = dict(type='int'), - service_down_action = dict(type='str', choices=service_down_choices), - host = dict(type='str', aliases=['address']), - port = dict(type='int') - ) + argument_spec = f5_argument_spec() + + meta_args = dict( + name=dict(type='str', required=True, aliases=['pool']), + lb_method=dict(type='str', choices=lb_method_choices), + monitor_type=dict(type='str', choices=monitor_type_choices), + quorum=dict(type='int'), + monitors=dict(type='list'), + slow_ramp_time=dict(type='int'), + reselect_tries=dict(type='int'), + service_down_action=dict(type='str', choices=service_down_choices), + host=dict(type='str', aliases=['address']), + port=dict(type='int') ) + argument_spec.update(meta_args) module = AnsibleModule( - argument_spec = argument_spec, + argument_spec=argument_spec, supports_check_mode=True ) @@ -408,7 +436,7 @@ def main(): validate_certs = module.params['validate_certs'] name = module.params['name'] - pool = fq_name(partition,name) + pool = fq_name(partition, name) lb_method = module.params['lb_method'] if lb_method: lb_method = lb_method.lower() @@ -427,7 +455,7 @@ def main(): if service_down_action: service_down_action = service_down_action.lower() host = module.params['host'] - address = fq_name(partition,host) + address = fq_name(partition, host) port = module.params['port'] # sanity check user supplied values @@ -479,7 +507,7 @@ def main(): try: remove_pool(api, pool) result = {'changed': True} - except bigsuds.OperationFailed, e: + except bigsuds.OperationFailed as e: if "was not found" in str(e): result = {'changed': False} else: @@ -502,7 +530,7 @@ def main(): try: create_pool(api, pool, lb_method) result = {'changed': True} - except bigsuds.OperationFailed, e: + except bigsuds.OperationFailed as e: if "already exists" in str(e): update = True else: @@ -558,12 +586,11 @@ def main(): add_pool_member(api, pool, address, port) 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 *