From d6069d6471efd6c2527c4115c7787596245fa556 Mon Sep 17 00:00:00 2001 From: Mischa Peters Date: Thu, 29 May 2014 12:16:04 +0200 Subject: [PATCH 1/2] Adding support for A10 Networks slb server, slb service-group, slb virtual-server --- net_infrastructure/a10_server | 199 +++++++++++++++++++++ net_infrastructure/a10_service_group | 220 +++++++++++++++++++++++ net_infrastructure/a10_virtual | 258 +++++++++++++++++++++++++++ 3 files changed, 677 insertions(+) create mode 100644 net_infrastructure/a10_server create mode 100644 net_infrastructure/a10_service_group create mode 100644 net_infrastructure/a10_virtual diff --git a/net_infrastructure/a10_server b/net_infrastructure/a10_server new file mode 100644 index 00000000000..7a89abb3ba3 --- /dev/null +++ b/net_infrastructure/a10_server @@ -0,0 +1,199 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +""" +Ansible module to manage A10 Networks slb server objects +(c) 2014, Mischa Peters + +This file is part of Ansible + +Ansible is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Ansible is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Ansible. If not, see . +""" + +DOCUMENTATION = ''' +--- +module: a10_server +version_added: 1.0 +short_description: Manage A10 Networks AX/SoftAX/Thunder/vThunder devices +description: + - Manage slb server objects on A10 Networks devices via aXAPI +author: Mischa Peters +notes: + - Requires A10 Networks aXAPI 2.1 +requirements: + - urllib2 + - re +options: + host: + description: + - hostname or ip of your A10 Networks device + required: true + default: null + aliases: [] + choices: [] + username: + description: + - admin account of your A10 Networks device + required: true + default: null + aliases: ['user', 'admin'] + choices: [] + password: + description: + - admin password of your A10 Networks device + required: true + default: null + aliases: ['pass', 'pwd'] + choices: [] + server_name: + description: + - slb server name + required: true + default: null + aliases: ['server'] + choices: [] + server_ip: + description: + - slb server IP address + required: false + default: null + aliases: ['ip', 'address'] + choices: [] + server_port: + description: + - slb server port + required: false + default: null + aliases: ['port'] + choices: [] + server_protocol: + description: + - slb server protocol + required: false + default: null + aliases: ['proto', 'protocol'] + choices: ['tcp', 'udp'] + server_status: + description: + - slb server status + required: false + default: enabled + aliases: ['status'] + choices: ['enable', 'disable'] + state: + description: + - create, update or remove slb server + required: false + default: present + aliases: [] + choices: ['present', 'absent'] +''' + +EXAMPLES = ''' +# Create a new server +ansible host -m a10_server -a "host=a10adc.example.com username=axapiuser password=axapipass server_name=realserver1 server_ip=192.168.1.23" + +# Add a port +ansible host -m a10_server -a "host=a10adc.example.com username=axapiuser password=axapipass server_name=realserver1 server_port=80 server_protocol=tcp" + +# Disable a server +ansible host -m a10_server -a "host=a10adc.example.com username=axapiuser password=axapipass server_name=realserver1 server_status=disable" +''' + +import urllib2 + +def axapi_call(url, post=None): + result = urllib2.urlopen(url, post).read() + return result + +def axapi_authenticate(base_url, user, pwd): + url = base_url + '&method=authenticate&username=' + user + '&password=' + pwd + sessid = json.loads(axapi_call(url))['session_id'] + result = base_url + '&session_id=' + sessid + return result + +def main(): + global module + module = AnsibleModule( + argument_spec=dict( + host = dict(type='str', required=True), + username = dict(type='str', aliases=['user', 'admin'], required=True), + password = dict(type='str', aliases=['pass', 'pwd'], required=True), + server_name = dict(type='str', aliases=['server'], required=True), + server_ip = dict(type='str', aliases=['ip', 'address']), + server_port = dict(type='int', aliases=['port']), + server_protocol = dict(type='str', aliases=['proto', 'protocol'], choices=['tcp', 'udp']), + server_status = dict(type='str', default='enable', aliases=['status'], choices=['enable', 'disable']), + state = dict(type='str', default='present', choices=['present', 'absent']), + ), + supports_check_mode=False + ) + + host = module.params['host'] + user = module.params['username'] + pwd = module.params['password'] + slb_server = module.params['server_name'] + slb_server_ip = module.params['server_ip'] + slb_server_port = module.params['server_port'] + slb_server_proto = module.params['server_protocol'] + slb_server_status = module.params['server_status'] + state = module.params['state'] + + axapi_base_url = 'https://' + host + '/services/rest/V2.1/?format=json' + + if slb_server_proto == 'tcp' or slb_server_proto == 'TCP' or slb_server_proto is None: + protocol = '2' + else: + protocol = '3' + + if slb_server_status == 'enable': + status = '1' + else: + status = '0' + + if slb_server is None: + module.fail_json(msg='server_name is required') + + if slb_server_port is None: + json_post = {'server': { 'name': slb_server, 'host': slb_server_ip, 'status': status }} + else: + json_post = {'server': { 'name': slb_server, 'host': slb_server_ip, 'status': status, 'port_list': [{ 'port_num': slb_server_port, 'protocol': protocol }]}} + + try: + session_url = axapi_authenticate(axapi_base_url, user, pwd) + + if state == 'present': + response = axapi_call(session_url + '&method=slb.server.search', json.dumps({ 'name': slb_server })) + slb_server_exist = re.search(slb_server, response, re.I) + + if slb_server_exist is None: + if slb_server_ip is None: + module.fail_json(msg='IP address is required') + response = axapi_call(session_url + '&method=slb.server.create', json.dumps(json_post)) + else: + response = axapi_call(session_url + '&method=slb.server.update', json.dumps(json_post)) + + if state == 'absent': + response = axapi_call(session_url + '&method=slb.server.delete', json.dumps({ 'name': slb_server })) + + result = json.loads(response) + axapi_call(session_url + '&method=session.close') + + except Exception, e: + return module.fail_json(msg='received exception: %s' % e) + + module.exit_json(changed=True, content=result) + +from ansible.module_utils.basic import * +main() diff --git a/net_infrastructure/a10_service_group b/net_infrastructure/a10_service_group new file mode 100644 index 00000000000..4cd5cc303f4 --- /dev/null +++ b/net_infrastructure/a10_service_group @@ -0,0 +1,220 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +""" +Ansible module to manage A10 Networks slb service-group objects +(c) 2014, Mischa Peters + +This file is part of Ansible + +Ansible is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Ansible is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Ansible. If not, see . +""" + +DOCUMENTATION = ''' +--- +module: a10_service_group +version_added: 1.0 +short_description: Manage A10 Networks AX/SoftAX/Thunder/vThunder devices +description: + - Manage slb service-group objects on A10 Networks devices via aXAPI +author: Mischa Peters +notes: + - Requires A10 Networks aXAPI 2.1 + - When a server doesn't exist and is added to the service-group the server will be created +requirements: + - urllib2 + - re +options: + host: + description: + - hostname or ip of your A10 Networks device + required: true + default: null + aliases: [] + choices: [] + username: + description: + - admin account of your A10 Networks device + required: true + default: null + aliases: ['user', 'admin'] + choices: [] + password: + description: + - admin password of your A10 Networks device + required: true + default: null + aliases: ['pass', 'pwd'] + choices: [] + service_group: + description: + - slb service-group name + required: true + default: null + aliases: ['service', 'pool', 'group'] + choices: [] + service_group_protocol: + description: + - slb service-group protocol + required: false + default: tcp + aliases: ['proto', 'protocol'] + choices: ['tcp', 'udp'] + service_group_method: + description: + - slb service-group loadbalancing method + required: false + default: round-robin + aliases: ['method'] + choices: ['round-robin', 'weighted-rr', 'least-connection', 'weighted-least-connection', 'service-least-connection', 'service-weighted-least-connection', 'fastest-response', 'least-request', 'round-robin-strict', 'src-ip-only-hash', 'src-ip-hash'] + server_name: + description: + - slb server name + required: false + default: null + aliases: ['server', 'member'] + choices: [] + server_port: + description: + - slb server port + required: false + default: null + aliases: ['port'] + choices: [] + server_status: + description: + - slb server status + required: false + default: enabled + aliases: ['status'] + choices: ['enable', 'disable'] + state: + description: + - create, remove or update slb service-group + required: false + default: present + aliases: [] + choices: ['present', 'absent'] +''' + +EXAMPLES = ''' +# Create a new service-group +ansible host -m a10_service_group -a "host=a10adc.example.com username=axapiuser password=axapipass service_group=sg-80-tcp" + +# Add a server +ansible host -m a10_service_group -a "host=a10adc.example.com username=axapiuser password=axapipass service_group=sg-80-tcp server_name=realserver1 server_port=80" + +# Disable a server +ansible host -m a10_service_group -a "host=a10adc.example.com username=axapiuser password=axapipass service_group=sg-80-tcp server_name=realserver1 server_port=80 status=disable" +''' + +import urllib2 + +def axapi_call(url, post=None): + result = urllib2.urlopen(url, post).read() + return result + +def axapi_authenticate(base_url, user, pwd): + url = base_url + '&method=authenticate&username=' + user + '&password=' + pwd + sessid = json.loads(axapi_call(url))['session_id'] + result = base_url + '&session_id=' + sessid + return result + +def main(): + global module + module = AnsibleModule( + argument_spec=dict( + host = dict(type='str', required=True), + username = dict(type='str', aliases=['user', 'admin'], required=True), + password = dict(type='str', aliases=['pass', 'pwd'], required=True), + service_group = dict(type='str', aliases=['service', 'pool', 'group'], required=True), + service_group_protocol = dict(type='str', default='tcp', aliases=['proto', 'protocol'], choices=['tcp', 'udp']), + service_group_method = dict(type='str', default='round-robin', aliases=['method'], choices=['round-robin', 'weighted-rr', 'least-connection', 'weighted-least-connection', 'service-least-connection', 'service-weighted-least-connection', 'fastest-response', 'least-request', 'round-robin-strict', 'src-ip-only-hash', 'src-ip-hash']), + server_name = dict(type='str', aliases=['server', 'member']), + server_port = dict(type='int', aliases=['port']), + server_status = dict(type='str', default='enable', aliases=['status'], choices=['enable', 'disable']), + state = dict(type='str', default='present', choices=['present', 'absent']), + ), + supports_check_mode=False + ) + + host = module.params['host'] + user = module.params['username'] + pwd = module.params['password'] + slb_service_group = module.params['service_group'] + slb_service_group_proto = module.params['service_group_protocol'] + slb_service_group_method = module.params['service_group_method'] + slb_server = module.params['server_name'] + slb_server_port = module.params['server_port'] + slb_server_status = module.params['server_status'] + state = module.params['state'] + + axapi_base_url = 'https://' + host + '/services/rest/V2.1/?format=json' + load_balancing_methods = { 'round-robin': 0, + 'weighted-rr': 1, + 'least-connection': 2, + 'weighted-least-connection': 3, + 'service-least-connection': 4, + 'service-weighted-least-connection': 5, + 'fastest-response': 6, + 'least-request': 7, + 'round-robin-strict': 8, + 'src-ip-only-hash': 14, + 'src-ip-hash': 15} + + if slb_service_group_proto == 'tcp' or slb_service_group_proto == 'TCP': + protocol = '2' + else: + protocol = '3' + + if slb_server_status == 'enable': + status = '1' + else: + status = '0' + + if slb_service_group is None: + module.fail_json(msg='service_group is required') + + if slb_server is None and slb_server_port is None: + json_post = {'service_group': { 'name': slb_service_group, 'protocol': protocol, 'lb_method': load_balancing_methods[slb_service_group_method] }} + elif slb_server is not None and slb_server_port is not None: + json_post = {'service_group': { 'name': slb_service_group, 'protocol': protocol, 'lb_method': load_balancing_methods[slb_service_group_method], 'member_list': [{ 'server': slb_server, 'port': slb_server_port, 'status': status }]}} + else: + module.fail_json(msg='server_name and server_name_port are required to add to the service-group') + + try: + session_url = axapi_authenticate(axapi_base_url, user, pwd) + + if state == 'present': + response = axapi_call(session_url + '&method=slb.service_group.search', json.dumps({ 'name': slb_service_group })) + slb_service_group_exist = re.search(slb_service_group, response, re.I) + + if slb_service_group_exist is None: + response = axapi_call(session_url + '&method=slb.service_group.create', json.dumps(json_post)) + else: + response = axapi_call(session_url + '&method=slb.service_group.update', json.dumps(json_post)) + + if state == 'absent': + response = axapi_call(session_url + '&method=slb.service_group.delete', json.dumps({ 'name': slb_service_group })) + + result = json.loads(response) + axapi_call(session_url + '&method=session.close') + + except Exception, e: + return module.fail_json(msg='received exception: %s' % e) + + module.exit_json(changed=True, content=result) + +from ansible.module_utils.basic import * +main() diff --git a/net_infrastructure/a10_virtual b/net_infrastructure/a10_virtual new file mode 100644 index 00000000000..a731ae3d611 --- /dev/null +++ b/net_infrastructure/a10_virtual @@ -0,0 +1,258 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +""" +Ansible module to manage A10 Networks slb virtual server objects +(c) 2014, Mischa Peters + +This file is part of Ansible + +Ansible is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Ansible is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Ansible. If not, see . +""" + +DOCUMENTATION = ''' +--- +module: a10_virtual_server +version_added: 1.0 +short_description: Manage A10 Networks AX/SoftAX/Thunder/vThunder devices +description: + - Manage slb virtual server objects on A10 Networks devices via aXAPI +author: Mischa Peters +notes: + - Requires A10 Networks aXAPI 2.1 +requirements: + - urllib2 + - re +options: + host: + description: + - hostname or ip of your A10 Networks device + required: true + default: null + aliases: [] + choices: [] + username: + description: + - admin account of your A10 Networks device + required: true + default: null + aliases: ['user', 'admin'] + choices: [] + password: + description: + - admin password of your A10 Networks device + required: true + default: null + aliases: ['pass', 'pwd'] + choices: [] + virtual_server: + description: + - slb virtual server name + required: true + default: null + aliases: ['vip', 'virtual'] + choices: [] + virtual_server_ip: + description: + - slb virtual server ip address + required: false + default: null + aliases: ['ip', 'address'] + choices: [] + virtual_server_status: + description: + - slb virtual server status + required: false + default: enable + aliases: ['status'] + choices: ['enabled', 'disabled'] + virtual_server_port: + description: + - slb virtual server port + required: false + default: round-robin + aliases: ['port', 'vport'] + choices: [] + virtual_server_type: + description: + - slb virtual server port type + required: false + default: null + aliases: ['proto', 'protocol'] + choices: ['tcp', 'udp', 'fast-http', 'http', 'https'] + virtual_server_port_status: + description: + - slb virtual server port status + required: false + default: enable + aliases: ['status'] + choices: ['enabled', 'disabled'] + service_group: + description: + - slb virtual server service-group + required: false + default: enabled + aliases: ['pool', 'group'] + choices: [] + state: + description: + - create, update or remove slb virtual server + required: false + default: present + aliases: [] + choices: ['present', 'absent'] +''' + +EXAMPLES = ''' +# Create a new virtual server +ansible host -m a10_virtual -a "host=a10adc.example.com username=axapiuser password=axapipass virtual_server=vip1 virtual_server_ip=192.168.1.20" + +# Add a virtual port +ansible host -m a10_virtual -a "host=a10adc.example.com username=axapiuser password=axapipass virtual_server=vip1 virtual_server_ip=192.168.1.20 virtual_server_port=80 virtual_server_port_type=http service_group=sg-80-tcp" + +# Disable a virtual server +ansible host -m a10_virtual -a "host=a10adc.example.com username=axapiuser password=axapipass virtual_server=vip1 status=disable" + +# Disable a virtual server port +ansible host -m a10_virtual -a "host=a10adc.example.com username=axapiuser password=axapipass virtual_server=vip1 virtual_server_port=80 virtual_server_port_type=http virtual_server_port_status=disable" +''' + +import urllib2 + +def axapi_call(url, post=None): + result = urllib2.urlopen(url, post).read() + return result + +def axapi_authenticate(base_url, user, pwd): + url = base_url + '&method=authenticate&username=' + user + '&password=' + pwd + sessid = json.loads(axapi_call(url))['session_id'] + result = base_url + '&session_id=' + sessid + return result + +def main(): + global module + module = AnsibleModule( + argument_spec=dict( + host = dict(type='str', required=True), + username = dict(type='str', aliases=['user', 'admin'], required=True), + password = dict(type='str', aliases=['pass', 'pwd'], required=True), + virtual_server = dict(type='str', aliases=['vip', 'virtual'], required=True), + virtual_server_ip = dict(type='str', aliases=['ip', 'address']), + virtual_server_status = dict(type='str', default='enabled', aliases=['status'], choices=['enabled', 'disabled']), + virtual_server_port = dict(type='int', aliases=['port', 'vport']), + virtual_server_port_type = dict(type='str', aliases=['proto', 'protocol'], choices=['tcp', 'udp', 'fast-http', 'http', 'https']), + virtual_server_port_status = dict(type='str', default='enabled', aliases=['portstatus', 'port_status'], choices=['enabled', 'disabled']), + service_group = dict(type='str', aliases=['pool', 'group']), + state = dict(type='str', default='present', choices=['present', 'absent']), + ), + supports_check_mode=False + ) + + host = module.params['host'] + user = module.params['username'] + pwd = module.params['password'] + slb_virtual = module.params['virtual_server'] + slb_virtual_ip = module.params['virtual_server_ip'] + slb_virtual_status = module.params['virtual_server_status'] + slb_virtual_port = module.params['virtual_server_port'] + slb_virtual_port_type = module.params['virtual_server_port_type'] + slb_virtual_port_status = module.params['virtual_server_port_status'] + slb_service_group = module.params['service_group'] + state = module.params['state'] + + axapi_base_url = 'https://' + host + '/services/rest/V2.1/?format=json' + vport_types = { 'tcp': 2, + 'udp': 3, + 'fast-http': 9, + 'http': 11, + 'https': 12} + + if slb_virtual_status == 'enabled': + status = '1' + else: + status = '0' + + if slb_virtual_port_status == 'enabled': + port_status = '1' + else: + port_status = '0' + + if slb_virtual is None: + module.fail_json(msg='virtual_server is required') + + try: + session_url = axapi_authenticate(axapi_base_url, user, pwd) + + if state == 'present': + find_slb_virtual = axapi_call(session_url + '&method=slb.virtual_server.search', json.dumps({ 'name': slb_virtual })) + slb_virtual_fail = re.search('status": "fail', find_slb_virtual, re.I) + + if slb_virtual_fail: + if slb_virtual_port is None and slb_virtual_port_type is None and slb_service_group is None: + json_post = { 'virtual_server': { 'name': slb_virtual, 'address': slb_virtual_ip, 'status': status }} + elif slb_virtual_port is not None and slb_virtual_port_type is not None and slb_service_group is None: + json_post = { 'virtual_server': { 'name': slb_virtual, 'address': slb_virtual_ip, 'status': status, 'vport_list': [{ 'protocol': vport_types[slb_virtual_port_type], 'port': slb_virtual_port }]}} + elif slb_virtual_port is not None and slb_virtual_port_type is not None and slb_service_group is not None: + json_post = { 'virtual_server': { 'name': slb_virtual, 'address': slb_virtual_ip, 'status': status, 'vport_list': [{ 'protocol': vport_types[slb_virtual_port_type], 'port': slb_virtual_port, 'service_group': slb_service_group }]}} + else: + module.fail_json(msg='virtual_server_port and virtual_server_type are required to create the virtual port') + + response = axapi_call(session_url + '&method=slb.virtual_server.create', json.dumps(json_post)) + else: + response = axapi_call(session_url + '&method=slb.virtual_server.search', json.dumps({ 'name': slb_virtual })) + slb_virtual_port_exist = re.search('"port":' + str(slb_virtual_port), response, re.I) + current_status = json.loads(response)['virtual_server']['status'] + current_port_status = 1 + + if slb_virtual_port_exist: + vport_list = json.loads(response)['virtual_server']['vport_list'] + if vport_list: + for port in range(len(vport_list)): + if slb_virtual_port == str(vport_list[port]['port']): + current_port_status = vport_list[port]['port'] + + json_post = { 'address': slb_virtual_ip, 'vport': { 'protocol': vport_types[slb_virtual_port_type], 'port': slb_virtual_port, 'service_group': slb_service_group }, 'status': port_status } + response = axapi_call(session_url + '&method=slb.virtual_server.vport.update', json.dumps(json_post)) + else: + if slb_service_group is None: + module.fail_json(msg='service_group is required') + json_post = { 'name': slb_virtual, 'vport': { 'protocol': vport_types[slb_virtual_port_type], 'port': slb_virtual_port, 'service_group': slb_service_group }, 'status': port_status } + response = axapi_call(session_url + '&method=slb.virtual_server.vport.create', json.dumps(json_post)) + + if current_status != status: + json_post = { 'virtual_server': { 'name': slb_virtual, 'address': slb_virtual_ip, 'status': status }} + response = axapi_call(session_url + '&method=slb.virtual_server.update', json.dumps(json_post)) + + if current_port_status != port_status: + json_post = { 'address': slb_virtual_ip, 'vport': { 'protocol': vport_types[slb_virtual_port_type], 'port': slb_virtual_port }, 'status': port_status } + response = axapi_call(session_url + '&method=slb.virtual_server.vport.update', json.dumps(json_post)) + + if state == 'absent': + if slb_virtual_port is not None and slb_virtual_port_type is not None: + response = axapi_call(session_url + '&method=slb.virtual_server.vport.delete', json.dumps({ 'name': slb_virtual, 'vport': { 'protocol': vport_types[slb_virtual_port_type], 'port': slb_virtual_port }})) + elif slb_virtual_port is None and slb_virtual_port_type is None: + response = axapi_call(session_url + '&method=slb.virtual_server.delete', json.dumps({ 'name': slb_virtual })) + else: + module.fail_json(msg='virtual_server_port and virtual_server_type are required to remove the virtual port') + + result = json.loads(response) + axapi_call(session_url + '&method=session.close') + + except Exception, e: + return module.fail_json(msg='received exception: %s' % e) + + module.exit_json(changed=True, content=result) + +from ansible.module_utils.basic import * +main() From 02236d30ca2f7b671a4bd0b3b20fc0bfda3e7dcb Mon Sep 17 00:00:00 2001 From: Mischa Peters Date: Sun, 10 Aug 2014 11:25:19 +0200 Subject: [PATCH 2/2] PEP8 Compliant except needed long lines and better exception handling --- net_infrastructure/a10_server | 66 +++++++--- net_infrastructure/a10_service_group | 113 ++++++++++++----- net_infrastructure/a10_virtual | 182 ++++++++++++++++++++------- 3 files changed, 264 insertions(+), 97 deletions(-) diff --git a/net_infrastructure/a10_server b/net_infrastructure/a10_server index 7a89abb3ba3..993ca7e8ce3 100644 --- a/net_infrastructure/a10_server +++ b/net_infrastructure/a10_server @@ -113,29 +113,40 @@ ansible host -m a10_server -a "host=a10adc.example.com username=axapiuser passwo import urllib2 + def axapi_call(url, post=None): result = urllib2.urlopen(url, post).read() return result + def axapi_authenticate(base_url, user, pwd): - url = base_url + '&method=authenticate&username=' + user + '&password=' + pwd - sessid = json.loads(axapi_call(url))['session_id'] - result = base_url + '&session_id=' + sessid - return result + url = base_url + '&method=authenticate&username=' + user + \ + '&password=' + pwd + result = json.loads(axapi_call(url)) + if 'response' in result: + return module.fail_json(msg=result['response']['err']['msg']) + sessid = result['session_id'] + return base_url + '&session_id=' + sessid + def main(): global module module = AnsibleModule( argument_spec=dict( - host = dict(type='str', required=True), - username = dict(type='str', aliases=['user', 'admin'], required=True), - password = dict(type='str', aliases=['pass', 'pwd'], required=True), - server_name = dict(type='str', aliases=['server'], required=True), - server_ip = dict(type='str', aliases=['ip', 'address']), - server_port = dict(type='int', aliases=['port']), - server_protocol = dict(type='str', aliases=['proto', 'protocol'], choices=['tcp', 'udp']), - server_status = dict(type='str', default='enable', aliases=['status'], choices=['enable', 'disable']), - state = dict(type='str', default='present', choices=['present', 'absent']), + host=dict(type='str', required=True), + username=dict(type='str', aliases=['user', 'admin'], + required=True), + password=dict(type='str', aliases=['pass', 'pwd'], required=True), + server_name=dict(type='str', aliases=['server'], required=True), + server_ip=dict(type='str', aliases=['ip', 'address']), + server_port=dict(type='int', aliases=['port']), + server_protocol=dict(type='str', aliases=['proto', 'protocol'], + choices=['tcp', 'udp']), + server_status=dict(type='str', default='enable', + aliases=['status'], + choices=['enable', 'disable']), + state=dict(type='str', default='present', + choices=['present', 'absent']), ), supports_check_mode=False ) @@ -152,7 +163,8 @@ def main(): axapi_base_url = 'https://' + host + '/services/rest/V2.1/?format=json' - if slb_server_proto == 'tcp' or slb_server_proto == 'TCP' or slb_server_proto is None: + if slb_server_proto == 'tcp' or slb_server_proto == 'TCP' or \ + slb_server_proto is None: protocol = '2' else: protocol = '3' @@ -166,26 +178,37 @@ def main(): module.fail_json(msg='server_name is required') if slb_server_port is None: - json_post = {'server': { 'name': slb_server, 'host': slb_server_ip, 'status': status }} + json_post = {'server': {'name': slb_server, + 'host': slb_server_ip, 'status': status}} else: - json_post = {'server': { 'name': slb_server, 'host': slb_server_ip, 'status': status, 'port_list': [{ 'port_num': slb_server_port, 'protocol': protocol }]}} + json_post = {'server': {'name': slb_server, 'host': slb_server_ip, + 'status': status, 'port_list': + [{'port_num': slb_server_port, + 'protocol': protocol}]}} try: session_url = axapi_authenticate(axapi_base_url, user, pwd) if state == 'present': - response = axapi_call(session_url + '&method=slb.server.search', json.dumps({ 'name': slb_server })) + response = axapi_call(session_url + '&method=slb.server.search', + json.dumps({'name': slb_server})) slb_server_exist = re.search(slb_server, response, re.I) if slb_server_exist is None: if slb_server_ip is None: module.fail_json(msg='IP address is required') - response = axapi_call(session_url + '&method=slb.server.create', json.dumps(json_post)) + response = axapi_call(session_url + + '&method=slb.server.create', + json.dumps(json_post)) else: - response = axapi_call(session_url + '&method=slb.server.update', json.dumps(json_post)) + response = axapi_call(session_url + + '&method=slb.server.update', + json.dumps(json_post)) if state == 'absent': - response = axapi_call(session_url + '&method=slb.server.delete', json.dumps({ 'name': slb_server })) + response = axapi_call(session_url + + '&method=slb.server.delete', + json.dumps({'name': slb_server})) result = json.loads(response) axapi_call(session_url + '&method=session.close') @@ -193,6 +216,9 @@ def main(): except Exception, e: return module.fail_json(msg='received exception: %s' % e) + if 'respone' in result and 'err' in result['response']: + return module.fail_json(msg=result['response']['err']['msg']) + module.exit_json(changed=True, content=result) from ansible.module_utils.basic import * diff --git a/net_infrastructure/a10_service_group b/net_infrastructure/a10_service_group index 4cd5cc303f4..0a9f02f76a1 100644 --- a/net_infrastructure/a10_service_group +++ b/net_infrastructure/a10_service_group @@ -121,30 +121,56 @@ ansible host -m a10_service_group -a "host=a10adc.example.com username=axapiuser import urllib2 + def axapi_call(url, post=None): result = urllib2.urlopen(url, post).read() return result + def axapi_authenticate(base_url, user, pwd): - url = base_url + '&method=authenticate&username=' + user + '&password=' + pwd - sessid = json.loads(axapi_call(url))['session_id'] - result = base_url + '&session_id=' + sessid - return result + url = base_url + '&method=authenticate&username=' + user + \ + '&password=' + pwd + result = json.loads(axapi_call(url)) + if 'response' in result: + return module.fail_json(msg=result['response']['err']['msg']) + sessid = result['session_id'] + return base_url + '&session_id=' + sessid + def main(): global module module = AnsibleModule( argument_spec=dict( - host = dict(type='str', required=True), - username = dict(type='str', aliases=['user', 'admin'], required=True), - password = dict(type='str', aliases=['pass', 'pwd'], required=True), - service_group = dict(type='str', aliases=['service', 'pool', 'group'], required=True), - service_group_protocol = dict(type='str', default='tcp', aliases=['proto', 'protocol'], choices=['tcp', 'udp']), - service_group_method = dict(type='str', default='round-robin', aliases=['method'], choices=['round-robin', 'weighted-rr', 'least-connection', 'weighted-least-connection', 'service-least-connection', 'service-weighted-least-connection', 'fastest-response', 'least-request', 'round-robin-strict', 'src-ip-only-hash', 'src-ip-hash']), - server_name = dict(type='str', aliases=['server', 'member']), - server_port = dict(type='int', aliases=['port']), - server_status = dict(type='str', default='enable', aliases=['status'], choices=['enable', 'disable']), - state = dict(type='str', default='present', choices=['present', 'absent']), + host=dict(type='str', required=True), + username=dict(type='str', aliases=['user', 'admin'], + required=True), + password=dict(type='str', aliases=['pass', 'pwd'], required=True), + service_group=dict(type='str', + aliases=['service', 'pool', 'group'], + required=True), + service_group_protocol=dict(type='str', default='tcp', + aliases=['proto', 'protocol'], + choices=['tcp', 'udp']), + service_group_method=dict(type='str', default='round-robin', + aliases=['method'], + choices=['round-robin', + 'weighted-rr', + 'least-connection', + 'weighted-least-connection', + 'service-least-connection', + 'service-weighted-least-connection', + 'fastest-response', + 'least-request', + 'round-robin-strict', + 'src-ip-only-hash', + 'src-ip-hash']), + server_name=dict(type='str', aliases=['server', 'member']), + server_port=dict(type='int', aliases=['port']), + server_status=dict(type='str', default='enable', + aliases=['status'], + choices=['enable', 'disable']), + state=dict(type='str', default='present', + choices=['present', 'absent']), ), supports_check_mode=False ) @@ -161,17 +187,17 @@ def main(): state = module.params['state'] axapi_base_url = 'https://' + host + '/services/rest/V2.1/?format=json' - load_balancing_methods = { 'round-robin': 0, - 'weighted-rr': 1, - 'least-connection': 2, - 'weighted-least-connection': 3, - 'service-least-connection': 4, - 'service-weighted-least-connection': 5, - 'fastest-response': 6, - 'least-request': 7, - 'round-robin-strict': 8, - 'src-ip-only-hash': 14, - 'src-ip-hash': 15} + load_balancing_methods = {'round-robin': 0, + 'weighted-rr': 1, + 'least-connection': 2, + 'weighted-least-connection': 3, + 'service-least-connection': 4, + 'service-weighted-least-connection': 5, + 'fastest-response': 6, + 'least-request': 7, + 'round-robin-strict': 8, + 'src-ip-only-hash': 14, + 'src-ip-hash': 15} if slb_service_group_proto == 'tcp' or slb_service_group_proto == 'TCP': protocol = '2' @@ -187,26 +213,44 @@ def main(): module.fail_json(msg='service_group is required') if slb_server is None and slb_server_port is None: - json_post = {'service_group': { 'name': slb_service_group, 'protocol': protocol, 'lb_method': load_balancing_methods[slb_service_group_method] }} + json_post = {'service_group': {'name': slb_service_group, + 'protocol': protocol, + 'lb_method': load_balancing_methods[slb_service_group_method]}} elif slb_server is not None and slb_server_port is not None: - json_post = {'service_group': { 'name': slb_service_group, 'protocol': protocol, 'lb_method': load_balancing_methods[slb_service_group_method], 'member_list': [{ 'server': slb_server, 'port': slb_server_port, 'status': status }]}} + json_post = {'service_group': {'name': slb_service_group, + 'protocol': protocol, + 'lb_method': load_balancing_methods[slb_service_group_method], + 'member_list': + [{'server': slb_server, + 'port': slb_server_port, + 'status': status}]}} else: - module.fail_json(msg='server_name and server_name_port are required to add to the service-group') + module.fail_json(msg='server_name and server_name_port are \ + required to add to the service-group') try: session_url = axapi_authenticate(axapi_base_url, user, pwd) if state == 'present': - response = axapi_call(session_url + '&method=slb.service_group.search', json.dumps({ 'name': slb_service_group })) - slb_service_group_exist = re.search(slb_service_group, response, re.I) + response = axapi_call(session_url + + '&method=slb.service_group.search', + json.dumps({'name': slb_service_group})) + slb_service_group_exist = re.search(slb_service_group, + response, re.I) if slb_service_group_exist is None: - response = axapi_call(session_url + '&method=slb.service_group.create', json.dumps(json_post)) + response = axapi_call(session_url + + '&method=slb.service_group.create', + json.dumps(json_post)) else: - response = axapi_call(session_url + '&method=slb.service_group.update', json.dumps(json_post)) + response = axapi_call(session_url + + '&method=slb.service_group.update', + json.dumps(json_post)) if state == 'absent': - response = axapi_call(session_url + '&method=slb.service_group.delete', json.dumps({ 'name': slb_service_group })) + response = axapi_call(session_url + + '&method=slb.service_group.delete', + json.dumps({'name': slb_service_group})) result = json.loads(response) axapi_call(session_url + '&method=session.close') @@ -214,6 +258,9 @@ def main(): except Exception, e: return module.fail_json(msg='received exception: %s' % e) + if 'respone' in result and 'err' in result['response']: + return module.fail_json(msg=result['response']['err']['msg']) + module.exit_json(changed=True, content=result) from ansible.module_utils.basic import * diff --git a/net_infrastructure/a10_virtual b/net_infrastructure/a10_virtual index a731ae3d611..aed49ce3ea5 100644 --- a/net_infrastructure/a10_virtual +++ b/net_infrastructure/a10_virtual @@ -130,31 +130,51 @@ ansible host -m a10_virtual -a "host=a10adc.example.com username=axapiuser passw import urllib2 + def axapi_call(url, post=None): result = urllib2.urlopen(url, post).read() return result + def axapi_authenticate(base_url, user, pwd): - url = base_url + '&method=authenticate&username=' + user + '&password=' + pwd - sessid = json.loads(axapi_call(url))['session_id'] - result = base_url + '&session_id=' + sessid - return result + url = base_url + '&method=authenticate&username=' + user + \ + '&password=' + pwd + result = json.loads(axapi_call(url)) + if 'response' in result: + return module.fail_json(msg=result['response']['err']['msg']) + sessid = result['session_id'] + return base_url + '&session_id=' + sessid + def main(): global module module = AnsibleModule( argument_spec=dict( - host = dict(type='str', required=True), - username = dict(type='str', aliases=['user', 'admin'], required=True), - password = dict(type='str', aliases=['pass', 'pwd'], required=True), - virtual_server = dict(type='str', aliases=['vip', 'virtual'], required=True), - virtual_server_ip = dict(type='str', aliases=['ip', 'address']), - virtual_server_status = dict(type='str', default='enabled', aliases=['status'], choices=['enabled', 'disabled']), - virtual_server_port = dict(type='int', aliases=['port', 'vport']), - virtual_server_port_type = dict(type='str', aliases=['proto', 'protocol'], choices=['tcp', 'udp', 'fast-http', 'http', 'https']), - virtual_server_port_status = dict(type='str', default='enabled', aliases=['portstatus', 'port_status'], choices=['enabled', 'disabled']), - service_group = dict(type='str', aliases=['pool', 'group']), - state = dict(type='str', default='present', choices=['present', 'absent']), + host=dict(type='str', required=True), + username=dict(type='str', aliases=['user', 'admin'], + required=True), + password=dict(type='str', aliases=['pass', 'pwd'], + required=True), + virtual_server=dict(type='str', aliases=['vip', 'virtual'], + required=True), + virtual_server_ip=dict(type='str', + aliases=['ip', 'address']), + virtual_server_status=dict(type='str', default='enabled', + aliases=['status'], + choices=['enabled', 'disabled']), + virtual_server_port=dict(type='int', + aliases=['port', 'vport']), + virtual_server_port_type=dict(type='str', + aliases=['proto', 'protocol'], + choices=['tcp', 'udp', 'fast-http', + 'http', 'https']), + virtual_server_port_status=dict(type='str', default='enabled', + aliases=['portstatus', + 'port_status'], + choices=['enabled', 'disabled']), + service_group=dict(type='str', aliases=['pool', 'group']), + state=dict(type='str', default='present', + choices=['present', 'absent']), ), supports_check_mode=False ) @@ -172,11 +192,11 @@ def main(): state = module.params['state'] axapi_base_url = 'https://' + host + '/services/rest/V2.1/?format=json' - vport_types = { 'tcp': 2, - 'udp': 3, - 'fast-http': 9, - 'http': 11, - 'https': 12} + vport_types = {'tcp': 2, + 'udp': 3, + 'fast-http': 9, + 'http': 11, + 'https': 12} if slb_virtual_status == 'enabled': status = '1' @@ -195,23 +215,55 @@ def main(): session_url = axapi_authenticate(axapi_base_url, user, pwd) if state == 'present': - find_slb_virtual = axapi_call(session_url + '&method=slb.virtual_server.search', json.dumps({ 'name': slb_virtual })) - slb_virtual_fail = re.search('status": "fail', find_slb_virtual, re.I) + find_slb_virtual = axapi_call(session_url + + '&method=slb.virtual_server.search', + json.dumps({'name': slb_virtual})) + slb_virtual_fail = re.search('status": "fail', + find_slb_virtual, re.I) if slb_virtual_fail: - if slb_virtual_port is None and slb_virtual_port_type is None and slb_service_group is None: - json_post = { 'virtual_server': { 'name': slb_virtual, 'address': slb_virtual_ip, 'status': status }} - elif slb_virtual_port is not None and slb_virtual_port_type is not None and slb_service_group is None: - json_post = { 'virtual_server': { 'name': slb_virtual, 'address': slb_virtual_ip, 'status': status, 'vport_list': [{ 'protocol': vport_types[slb_virtual_port_type], 'port': slb_virtual_port }]}} - elif slb_virtual_port is not None and slb_virtual_port_type is not None and slb_service_group is not None: - json_post = { 'virtual_server': { 'name': slb_virtual, 'address': slb_virtual_ip, 'status': status, 'vport_list': [{ 'protocol': vport_types[slb_virtual_port_type], 'port': slb_virtual_port, 'service_group': slb_service_group }]}} + if slb_virtual_port is None and slb_virtual_port_type is None \ + and slb_service_group is None: + json_post = {'virtual_server': {'name': slb_virtual, + 'address': slb_virtual_ip, + 'status': status}} + elif slb_virtual_port is not None and \ + slb_virtual_port_type is not None and \ + slb_service_group is None: + json_post = {'virtual_server': + {'name': slb_virtual, + 'address': slb_virtual_ip, + 'status': status, + 'vport_list': + [{'protocol': + vport_types[slb_virtual_port_type], + 'port': slb_virtual_port}]}} + elif slb_virtual_port is not None and \ + slb_virtual_port_type is not None and \ + slb_service_group is not None: + json_post = {'virtual_server': + {'name': slb_virtual, + 'address': slb_virtual_ip, + 'status': status, 'vport_list': + [{'protocol': + vport_types[slb_virtual_port_type], + 'port': slb_virtual_port, + 'service_group': slb_service_group}]}} else: - module.fail_json(msg='virtual_server_port and virtual_server_type are required to create the virtual port') + module.fail_json(msg='virtual_server_port and + virtual_server_type are required to + create the virtual port') - response = axapi_call(session_url + '&method=slb.virtual_server.create', json.dumps(json_post)) + response = axapi_call(session_url + + '&method=slb.virtual_server.create', + json.dumps(json_post)) else: - response = axapi_call(session_url + '&method=slb.virtual_server.search', json.dumps({ 'name': slb_virtual })) - slb_virtual_port_exist = re.search('"port":' + str(slb_virtual_port), response, re.I) + response = axapi_call(session_url + + '&method=slb.virtual_server.search', + json.dumps({'name': slb_virtual})) + slb_virtual_port_exist = re.search('"port":' + + str(slb_virtual_port) + response, re.I) current_status = json.loads(response)['virtual_server']['status'] current_port_status = 1 @@ -222,29 +274,68 @@ def main(): if slb_virtual_port == str(vport_list[port]['port']): current_port_status = vport_list[port]['port'] - json_post = { 'address': slb_virtual_ip, 'vport': { 'protocol': vport_types[slb_virtual_port_type], 'port': slb_virtual_port, 'service_group': slb_service_group }, 'status': port_status } - response = axapi_call(session_url + '&method=slb.virtual_server.vport.update', json.dumps(json_post)) + json_post = {'address': slb_virtual_ip, + 'vport': + {'protocol': + vport_types[slb_virtual_port_type], + 'port': slb_virtual_port, + 'service_group': slb_service_group}, + 'status': port_status} + response = axapi_call(session_url + + '&method=slb.virtual_server.\ + vport.update', json.dumps(json_post)) else: if slb_service_group is None: module.fail_json(msg='service_group is required') - json_post = { 'name': slb_virtual, 'vport': { 'protocol': vport_types[slb_virtual_port_type], 'port': slb_virtual_port, 'service_group': slb_service_group }, 'status': port_status } - response = axapi_call(session_url + '&method=slb.virtual_server.vport.create', json.dumps(json_post)) + json_post = {'name': slb_virtual, + 'vport': + {'protocol': + vport_types[slb_virtual_port_type], + 'port': slb_virtual_port, + 'service_group': slb_service_group}, + 'status': port_status} + response = axapi_call(session_url + + '&method=slb.virtual_server.\ + vport.create', json.dumps(json_post)) if current_status != status: - json_post = { 'virtual_server': { 'name': slb_virtual, 'address': slb_virtual_ip, 'status': status }} - response = axapi_call(session_url + '&method=slb.virtual_server.update', json.dumps(json_post)) + json_post = {'virtual_server': + {'name': slb_virtual, + 'address': slb_virtual_ip, + 'status': status}} + response = axapi_call(session_url + + '&method=slb.virtual_server.update', + json.dumps(json_post)) if current_port_status != port_status: - json_post = { 'address': slb_virtual_ip, 'vport': { 'protocol': vport_types[slb_virtual_port_type], 'port': slb_virtual_port }, 'status': port_status } - response = axapi_call(session_url + '&method=slb.virtual_server.vport.update', json.dumps(json_post)) + json_post = {'address': slb_virtual_ip, 'vport': + {'protocol': + vport_types[slb_virtual_port_type], + 'port': slb_virtual_port}, + 'status': port_status} + response = axapi_call(session_url + + '&method=slb.virtual_server.\ + vport.update', json.dumps(json_post)) if state == 'absent': - if slb_virtual_port is not None and slb_virtual_port_type is not None: - response = axapi_call(session_url + '&method=slb.virtual_server.vport.delete', json.dumps({ 'name': slb_virtual, 'vport': { 'protocol': vport_types[slb_virtual_port_type], 'port': slb_virtual_port }})) + if slb_virtual_port is not None and \ + slb_virtual_port_type is not None: + response = axapi_call(session_url + + '&method=slb.virtual_server.\ + vport.delete', + json.dumps({'name': slb_virtual, + 'vport': + {'protocol': + vport_types[slb_virtual_port_type], + 'port': slb_virtual_port}})) elif slb_virtual_port is None and slb_virtual_port_type is None: - response = axapi_call(session_url + '&method=slb.virtual_server.delete', json.dumps({ 'name': slb_virtual })) + response = axapi_call(session_url + + '&method=slb.virtual_server.delete', + json.dumps({'name': slb_virtual})) else: - module.fail_json(msg='virtual_server_port and virtual_server_type are required to remove the virtual port') + module.fail_json(msg='virtual_server_port and \ + virtual_server_type are required to remove \ + the virtual port') result = json.loads(response) axapi_call(session_url + '&method=session.close') @@ -252,6 +343,9 @@ def main(): except Exception, e: return module.fail_json(msg='received exception: %s' % e) + if 'respone' in result and 'err' in result['response']: + return module.fail_json(msg=result['response']['err']['msg']) + module.exit_json(changed=True, content=result) from ansible.module_utils.basic import *