├── .gitignore ├── README.md ├── cli-deploy.py ├── push-fixed-nat-table.py ├── member-prio.py ├── member-disable-with.py ├── hm-vip-down-min-active.py ├── reset-config.py ├── a10_server ├── a10_service_group └── a10_virtual /.gitignore: -------------------------------------------------------------------------------- 1 | commands.txt* 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # A10 Networks aXAPI Collection 2 | 3 | Here you can find a collection of A10 Networks related aXAPI scripts. 4 | 5 | For a python API client, please look here: https://github.com/a10networks/acos-client 6 | 7 | ## Ansible Modules 8 | * a10_server -- Ansible module for “slb server” 9 | * a10_service_group -- Ansible module for “slb service-group” 10 | * a10_virtual_server -- Ansible module for “slb virtual” 11 | 12 | ## aXAPI Scripts 13 | * cli-deploy.py - Use for quick cli.deploy runs 14 | * member-disable-with.py -- Use 2.7.2-P2 feature “disable-with-health-check” to gracefully shutdown members via aXAPI. 15 | * member-prio.py -- Use member priority to gracefully shutdown members via aXAPI 16 | * push-fixed-nat-table.py -- Get the Fixed-NAT table from ACOS 17 | * reset-config.py -- Reset the Lab config 18 | 19 | ## Health Monitors 20 | * hm-vip-down-min-active.py - If service-group has less than min_active_member then it returns 0, marking VIP down. 21 | -------------------------------------------------------------------------------- /cli-deploy.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2014, Mischa Peters , A10 Networks. 4 | # Version 1.0 - 20140713 5 | # Version 1.1 - 20140810 - PEP8 Compliant 6 | # 7 | # Quick cli.deploy 8 | # 9 | # Requiers: 10 | # - Python 2.7.x 11 | # - aXAPI V2.1 12 | # - ACOS 2.7.1-Px or higher 13 | # 14 | 15 | import json 16 | import urllib2 17 | import argparse 18 | 19 | parser = argparse.ArgumentParser(description="Script to run cli.deploy") 20 | parser.add_argument("-d", "--device", required=True, 21 | help="A10 device IP address") 22 | parser.add_argument("-l", "--login", default='admin', 23 | help="A10 admin (default: admin)") 24 | parser.add_argument("-p", "--password", required=True, 25 | help="A10 password") 26 | # 27 | parser.add_argument("-f", "--file", default='commands.txt', 28 | help="A10 commands file") 29 | 30 | print "DEBUG ==> " + str(parser.parse_args()) + "\n" 31 | 32 | try: 33 | args = parser.parse_args() 34 | a10_host = args.device 35 | a10_admin = args.login 36 | a10_pwd = args.password 37 | a10_commands_file = args.file 38 | 39 | except IOError, msg: 40 | parser.error(str(msg)) 41 | 42 | 43 | def axapi_call(url, data=None): 44 | result = urllib2.urlopen(url, data).read() 45 | return result 46 | 47 | 48 | def axapi_authenticate(base_url, user, pwd): 49 | url = base_url + '&method=authenticate&username=' + user + \ 50 | '&password=' + pwd 51 | sessid = json.loads(axapi_call(url))['session_id'] 52 | result = base_url + '&session_id=' + sessid 53 | return result 54 | 55 | 56 | def axapi_result(result): 57 | status = str(json.loads(response)['response']['status']) 58 | if status == 'fail': 59 | return result 60 | else: 61 | return status 62 | 63 | try: 64 | print "===> Start for host: " + a10_host 65 | 66 | f = open(a10_commands_file, 'r') 67 | commands = f.read() 68 | print "===> Commands: \n" + commands 69 | 70 | axapi_base_url = 'https://' + a10_host + '/services/rest/V2.1/?format=json' 71 | session_url = axapi_authenticate(axapi_base_url, a10_admin, a10_pwd) 72 | 73 | print "===> CLI Deploy" 74 | response = axapi_call(session_url + '&method=cli.deploy', commands) 75 | print "<=== Status: " + axapi_result(response) 76 | 77 | closed = axapi_call(session_url + '&method=session.close') 78 | 79 | except Exception, e: 80 | print e 81 | -------------------------------------------------------------------------------- /push-fixed-nat-table.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2014, Mischa Peters , A10 Networks. 4 | # Version 1.0 - 20140701 5 | # Version 1.1 - 20140810 - PEP8 Compliant 6 | # 7 | # Push the Fixed-NAT table from ACOS 2.8.x to an FTP 8 | # server. 9 | # 10 | # Requiers: 11 | # - Python 2.7.x 12 | # - aXAPI V2.8 13 | # 14 | 15 | import json 16 | import urllib2 17 | import argparse 18 | 19 | parser = argparse.ArgumentParser(description="Push the Fixed-NAT table \ 20 | from an A10 device") 21 | parser.add_argument("-d", "--device", required=True, 22 | help="A10 device IP address") 23 | parser.add_argument("-l", "--login", default='admin', 24 | help="A10 admin (default: admin)") 25 | parser.add_argument("-p", "--password", required=True, 26 | help="A10 password") 27 | # 28 | parser.add_argument("--ftp-server", required=True, 29 | help="Set the FTP server") 30 | parser.add_argument("--ftp-account", required=True, 31 | help="Set the FTP account") 32 | parser.add_argument("--ftp-password", required=True, 33 | help="Set the FTP password") 34 | parser.add_argument("--ftp-folder", default='/', 35 | help="Set the FTP directory to upload to (default: /)") 36 | parser.add_argument("--table", required=True, 37 | help="The Fixed-NAT table to push") 38 | 39 | print "DEBUG ==> " + str(parser.parse_args()) + "\n" 40 | 41 | try: 42 | args = parser.parse_args() 43 | a10_host = args.device 44 | a10_admin = args.login 45 | a10_pwd = args.password 46 | ftp_server = args.ftp_server 47 | ftp_upload_account = args.ftp_account 48 | ftp_upload_pwd = args.ftp_password 49 | ftp_upload_folder = args.ftp_folder 50 | fixed_nat_table = args.table 51 | 52 | except IOError, msg: 53 | parser.error(str(msg)) 54 | 55 | 56 | def axapi_call(url, data=None): 57 | result = urllib2.urlopen(url, data).read() 58 | return result 59 | 60 | 61 | def axapi_authenticate(base_url, user, pwd): 62 | url = base_url + "&method=authenticate&username=" + user + \ 63 | "&password=" + pwd 64 | sessid = json.loads(axapi_call(url))['session_id'] 65 | result = base_url + '&session_id=' + sessid 66 | return result 67 | 68 | try: 69 | axapi_base_url = 'https://' + a10_host + '/services/rest/V2.8/?format=json' 70 | session_url = axapi_authenticate(axapi_base_url, a10_admin, a10_pwd) 71 | 72 | response = axapi_call(session_url + '&method=cli.deploy', 73 | 'export fixed-nat ' + fixed_nat_table + 74 | ' ftp://' + ftp_upload_account + ':' + 75 | ftp_upload_pwd + '@' + ftp_server + 76 | ftp_upload_folder + fixed_nat_table) 77 | 78 | closed = axapi_call(session_url + '&method=session.close') 79 | 80 | except Exception, e: 81 | print e 82 | 83 | print "Download of " + fixed_nat_table + " succesfull!" 84 | -------------------------------------------------------------------------------- /member-prio.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2014, Mischa Peters , A10 Networks. 4 | # Version 1.0 - 20140701 5 | # Version 1.1 - 20140810 - PEP8 Compliant 6 | # 7 | # Change the member priority in a service-group 8 | # to gracefully shutdown a member. 9 | # 10 | # Requiers: 11 | # - Python 2.7.x 12 | # - aXAPI V2.1 13 | # 14 | 15 | import json 16 | import urllib2 17 | import argparse 18 | 19 | parser = argparse.ArgumentParser(description="Script to change a member \ 20 | priority in a service-group") 21 | parser.add_argument("-d", "--device", required=True, 22 | help="A10 device IP address") 23 | parser.add_argument("-l", "--login", default='admin', 24 | help="A10 admin (default: admin)") 25 | parser.add_argument("-p", "--password", required=True, 26 | help="A10 password") 27 | # 28 | parser.add_argument("-s", "--service-group", required=True, 29 | help="Select the service-group") 30 | parser.add_argument("-m", "--member", required=True, 31 | help="Select the member") 32 | parser.add_argument("--priority", default='8', 33 | help="Set the member prioriry (default: 8)") 34 | parser.add_argument("--port", default='80', 35 | help="Set the member port (default: 80)") 36 | parser.add_argument("--status", default='enable', 37 | choices=['enable', 'disable'], 38 | help="Set the member port (default: 80)") 39 | 40 | print "DEBUG ==> " + str(parser.parse_args()) + "\n" 41 | 42 | try: 43 | args = parser.parse_args() 44 | a10_host = args.device 45 | a10_admin = args.login 46 | a10_pwd = args.password 47 | service_group = args.service_group 48 | service_group_member = args.member 49 | service_group_member_priority = args.priority 50 | service_group_member_port = args.port 51 | if args.status == 'enable': 52 | service_group_member_status = '1' 53 | else: 54 | service_group_member_status = '0' 55 | 56 | except IOError, msg: 57 | parser.error(str(msg)) 58 | 59 | 60 | def axapi_call(url, data=None): 61 | result = urllib2.urlopen(url, data).read() 62 | return result 63 | 64 | 65 | def axapi_authenticate(base_url, user, pwd): 66 | url = base_url + "&method=authenticate&username=" + user + \ 67 | "&password=" + pwd 68 | sessid = json.loads(axapi_call(url))['session_id'] 69 | result = base_url + '&session_id=' + sessid 70 | return result 71 | 72 | try: 73 | axapi_base_url = 'https://' + a10_host + '/services/rest/V2.1/?format=json' 74 | session_url = axapi_authenticate(axapi_base_url, a10_admin, a10_pwd) 75 | 76 | print "===> Set service-group member priority" 77 | json_post = {'member': {'server': service_group_member, 78 | 'port': service_group_member_port, 79 | 'status': service_group_member_status, 80 | 'priority': service_group_member_priority}, 81 | 'name': service_group} 82 | response = axapi_call(session_url + 83 | '&method=slb.service_group.member.update', 84 | json.dumps(json_post)) 85 | print response 86 | print "<=== Status: " + str(json.loads(response)['response']['status']) 87 | 88 | print "\n===> Collect current connections" 89 | json_post = {'name': service_group_member} 90 | response = axapi_call(session_url + '&method=slb.server.fetchStatistics', 91 | json.dumps(json_post)) 92 | print response 93 | print "<=== Current Connections: " + \ 94 | str(json.loads(response)['server_stat']['cur_conns']) 95 | 96 | closed = axapi_call(session_url + '&method=session.close') 97 | 98 | except Exception, e: 99 | print e 100 | -------------------------------------------------------------------------------- /member-disable-with.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2014, Mischa Peters , A10 Networks. 4 | # Version 1.0 - 20140701 5 | # Version 1.1 - 20140810 - PEP8 Complaint 6 | # Version 1.1b - 20151201 - enable password 7 | # 8 | # Change status of a member with "disable-with-health-check" 9 | # in 2.7.2-P2 to gracefully shutdown a member. 10 | # 11 | # Requiers: 12 | # - Python 2.7.x 13 | # - aXAPI V2.1 14 | # - ACOS 2.7.2-P2 15 | # 16 | 17 | import json 18 | import urllib2 19 | import argparse 20 | 21 | 22 | parser = argparse.ArgumentParser(description="Script to change the status \ 23 | of a member in a service-group") 24 | parser.add_argument("-d", "--device", required=True, 25 | help="A10 device IP address") 26 | parser.add_argument("-l", "--login", default='admin', 27 | help="A10 admin (default: admin)") 28 | parser.add_argument("-p", "--password", required=True, 29 | help="A10 password") 30 | # 31 | parser.add_argument("-s", "--service-group", required=True, 32 | help="Select the service-group") 33 | parser.add_argument("-m", "--member", required=True, 34 | help="Select the member") 35 | parser.add_argument("--priority", default='8', 36 | help="Set the member prioriry (default: 8)") 37 | parser.add_argument("--port", default='80', 38 | help="Set the member port (default: 80)") 39 | parser.add_argument("--enable_password", default='', 40 | help="Set the enable-password required to make changes") 41 | parser.add_argument("--status", default='disable-with-health-check', 42 | choices=['enable', 'disable', 'disable-with-health-check'], 43 | help="Set the member status \ 44 | (default: disable-with-health-check)") 45 | 46 | print "DEBUG ==> " + str(parser.parse_args()) + "\n" 47 | 48 | try: 49 | args = parser.parse_args() 50 | a10_host = args.device 51 | a10_admin = args.login 52 | a10_pwd = args.password 53 | a10_enable = args.enable_password 54 | service_group = args.service_group 55 | service_group_member = args.member 56 | service_group_member_priority = args.priority 57 | service_group_member_port = args.port 58 | service_group_member_status = args.status 59 | 60 | except IOError, msg: 61 | parser.error(str(msg)) 62 | 63 | 64 | def axapi_call(url, data=None): 65 | result = urllib2.urlopen(url, data).read() 66 | return result 67 | 68 | 69 | def axapi_authenticate(base_url, user, pwd): 70 | url = base_url + "&method=authenticate&username=" + user + \ 71 | "&password=" + pwd 72 | sessid = json.loads(axapi_call(url))['session_id'] 73 | result = base_url + '&session_id=' + sessid 74 | return result 75 | 76 | try: 77 | axapi_base_url = 'https://' + a10_host + '/services/rest/V2.1/?format=json' 78 | session_url = axapi_authenticate(axapi_base_url, a10_admin, a10_pwd) 79 | 80 | command = ("slb service-group " + service_group + " tcp\n" 81 | "member " + service_group_member + ":" + 82 | service_group_member_port + " " + service_group_member_status) 83 | 84 | print "===> Set service-group member disable-with-health-check" 85 | response = axapi_call(session_url + '&method=cli.deploy&enable_password='+a10_enable, command) 86 | print response 87 | print "<=== Status: " + str(json.loads(response)['response']['status']) 88 | 89 | print "\n===> Collect current connections" 90 | json_post = {'name': service_group_member} 91 | response = axapi_call(session_url + '&method=slb.server.fetchStatistics', 92 | json.dumps(json_post)) 93 | print response 94 | print "<=== Current Connections: " + \ 95 | str(json.loads(response)['server_stat']['cur_conns']) 96 | 97 | closed = axapi_call(session_url + '&method=session.close') 98 | 99 | except Exception, e: 100 | print e 101 | -------------------------------------------------------------------------------- /hm-vip-down-min-active.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2014, Fadi Hafez , A10 Networks. 4 | # Version 1.0 - 20140729 5 | # Version 1.1 - 20140810 - PEP8 Compliant (-3 exceptions) 6 | # 7 | # Reference: AX_aXAPI_Ref_v2-20120211.pdf 8 | # 9 | # RETURNS: 10 | # 0: Success 11 | # 1: Failed 12 | # 13 | import sys 14 | import json 15 | import urllib 16 | import urllib2 17 | 18 | from xml.dom import minidom 19 | 20 | SG_NAME = "sg" 21 | host = "192.168.91.103" 22 | username = "admin" 23 | password = "a10" 24 | 25 | FAIL = 1 26 | SUCCESS = 0 27 | 28 | 29 | class path: 30 | @classmethod 31 | def v1(cls): 32 | return "/services/rest/V1/" 33 | 34 | @classmethod 35 | def v2(cls): 36 | return "/services/rest/V2/" 37 | 38 | @classmethod 39 | def sessionID(cls): 40 | return "?session_id=" 41 | 42 | 43 | class auth: 44 | @classmethod 45 | def sessionID(cls, host, username, password): 46 | services_path = path.v2() 47 | sid_url = "http://" + host + services_path 48 | method = 'authenticate' 49 | authparams = urllib.urlencode({'method': method, 50 | 'username': username, 51 | 'password': password 52 | }) 53 | 54 | request = urllib2.Request(sid_url, authparams) 55 | request.add_header('Connection', 'Keep-Alive') 56 | response = urllib2.urlopen(request) 57 | 58 | sessionID = minidom.parse(response).getElementsByTagName('session_id')[0].childNodes[0].nodeValue 59 | return sessionID 60 | 61 | @classmethod 62 | def sessionClose(cls, host, sid): 63 | method = "method=session.close" 64 | response = req.get(host, method, sid) 65 | return response 66 | 67 | 68 | class req: 69 | @classmethod 70 | def get(cls, host, method, sid): 71 | url = "https://" + host + path.v2() + path.sessionID() + sid + "&" + \ 72 | method.__str__() + "&format=json" 73 | # print url 74 | data = urllib.urlopen(url.__str__()).read() 75 | return data 76 | 77 | @classmethod 78 | def post(cls, host, method, sid, config): 79 | url = "https://" + host + path.v2() + path.sessionID() + sid + "&" + \ 80 | method.__str__() + "&format=json" 81 | # print url 82 | # print config 83 | data = urllib.urlopen(url.__str__(), config).read() 84 | return data 85 | 86 | # Authenticate and get session ID 87 | sid = auth.sessionID(host, username, password) 88 | 89 | # Get the Service Group details 90 | result = req.get(host, "method=slb.service_group.search&name=" + SG_NAME, sid) 91 | 92 | # Extract the min_active_servers value 93 | result_list = json.loads(result) 94 | min_active_server_status = result_list["service_group"]["min_active_member"]["status"] 95 | min_active_server_num = result_list["service_group"]["min_active_member"]["number"] 96 | 97 | # if the minimum_active_servers is disabled then 98 | # just quit with SUCCESS return code 99 | if min_active_server_status == 0: 100 | # disconnect from the API 101 | result = auth.sessionClose(host, sid) 102 | sys.exit(SUCCESS) 103 | 104 | 105 | # Get the Service Group statistics 106 | result = req.get(host, "method=slb.service_group.fetchStatistics&name=" + 107 | SG_NAME, sid) 108 | result_list = json.loads(result) 109 | 110 | up_port_count = 0 111 | for member in result_list["service_group_stat"]["member_stat_list"]: 112 | server_name = member["server"] 113 | server_port = member["port"] 114 | 115 | # Get the status of the server port from the server statistics 116 | result = req.get(host, "method=slb.server.fetchStatistics&name=" + 117 | server_name, sid) 118 | result_server_list = json.loads(result) 119 | for port in result_server_list["server_stat"]["port_stat_list"]: 120 | if port["port_num"] == server_port: 121 | if port["status"] == 1: 122 | up_port_count += 1 123 | break 124 | 125 | # disconnect from the API 126 | result = auth.sessionClose(host, sid) 127 | 128 | if up_port_count < min_active_server_num: 129 | sys.exit(FAIL) 130 | else: 131 | sys.exit(SUCCESS) 132 | -------------------------------------------------------------------------------- /reset-config.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2014, Mischa Peters , A10 Networks. 4 | # Version 1.0 - 20140710 5 | # Version 1.1 - 20140711 - added upgrade 6 | # Version 1.2 - 20140712 - moved to aXAPI V2.1 7 | # Version 1.3 - 20140713 - moved result to function 8 | # Version 1.4 - 20140810 - PEP8 Compliant 9 | # 10 | # Reset a training lab to default config 11 | # 12 | # Requiers: 13 | # - Python 2.7.x 14 | # - aXAPI V2.1 15 | # - ACOS 2.7.1-Px or higher 16 | # 17 | 18 | import json 19 | import urllib2 20 | import argparse 21 | 22 | ################################################# 23 | # Set specific defaults 24 | ################################################# 25 | FTP = '' 26 | ACOS = '' 27 | 28 | tftp_lab1 = "tftp://172.31.81.10/sx" 29 | devices_lab1 = {'172.31.81.11': '1', '172.31.81.21': '2', '172.31.81.31': '3', 30 | '172.31.81.41': '4', '172.31.81.51': '5', '172.31.81.61': '6', 31 | '172.31.81.71': '7', '172.31.81.81': '8', '172.31.81.91': '9', 32 | '172.31.81.91': '9', '172.31.81.101': '10', 33 | '172.31.81.111': '11', '172.31.81.121': '12'} 34 | tftp_lab2 = "tftp://172.31.82.10/sx" 35 | devices_lab2 = {'172.31.82.11': '1', '172.31.82.21': '2', '172.31.82.31': '3', 36 | '172.31.82.41': '4', '172.31.82.51': '5', '172.31.82.61': '6', 37 | '172.31.82.71': '7', '172.31.82.81': '8', '172.31.82.91': '9', 38 | '172.31.82.91': '9', '172.31.82.101': '10', 39 | '172.31.82.111': '11', '172.31.82.121': '12'} 40 | ################################################# 41 | 42 | parser = argparse.ArgumentParser(description="Script to clear out config") 43 | parser.add_argument("-d", "--device", required=True, choices=['lab1', 'lab2'], 44 | help="Training Lab") 45 | parser.add_argument("-l", "--login", default='admin', 46 | help="A10 admin (default: admin)") 47 | parser.add_argument("-p", "--password", required=True, 48 | help="A10 password") 49 | # 50 | parser.add_argument("-a", "--action", required=True, 51 | choices=['restore', 'backup', 'reboot', 52 | 'clear-log', 'upgrade'], 53 | help="Action to perform") 54 | parser.add_argument("--partition", default='primary', 55 | help="Boot Partition to use (default: primary)") 56 | parser.add_argument("--file", default=ACOS, 57 | help="ACOS Version (default: " + ACOS + ")") 58 | parser.add_argument("--ftpserver", default=FTP, 59 | help="FTP Server (default: " + FTP + ")") 60 | parser.add_argument("--ftpuser", default='annonymous', 61 | help="FTP Username (default: anonymous)") 62 | parser.add_argument("--ftppass", default='ftp@ftp.com', 63 | help="FTP Pass (default: ftp@ftp.com)") 64 | 65 | print "DEBUG ==> " + str(parser.parse_args()) + "\n" 66 | 67 | try: 68 | args = parser.parse_args() 69 | a10_host = args.device 70 | a10_admin = args.login 71 | a10_pwd = args.password 72 | action = args.action 73 | a10_partition = args.partition 74 | ftp_file = args.file 75 | ftp_host = args.ftpserver 76 | ftp_user = args.ftpuser 77 | ftp_pass = args.ftppass 78 | 79 | except IOError, msg: 80 | parser.error(str(msg)) 81 | 82 | 83 | def axapi_call(url, data=None): 84 | result = urllib2.urlopen(url, data).read() 85 | return result 86 | 87 | 88 | def axapi_authenticate(base_url, user, pwd): 89 | url = base_url + "&method=authenticate&username=" + \ 90 | user + "&password=" + pwd 91 | sessid = json.loads(axapi_call(url))['session_id'] 92 | result = base_url + '&session_id=' + sessid 93 | return result 94 | 95 | 96 | def axapi_result(result): 97 | status = str(json.loads(response)['response']['status']) 98 | if status == 'fail': 99 | return result 100 | else: 101 | return status 102 | 103 | try: 104 | if a10_host == 'lab1': 105 | devices = devices_lab1.items() 106 | tftp = tftp_lab1 107 | if a10_host == 'lab2': 108 | devices = devices_lab2.items() 109 | tftp = tftp_lab2 110 | if a10_partition == 'primary': 111 | destination = '0' 112 | else: 113 | destination = '1' 114 | 115 | for item in devices: 116 | a10_host = item[0] 117 | tftp_file = item[1] 118 | 119 | print "===> Start for host: " + a10_host 120 | 121 | axapi_base_url = 'https://' + a10_host + \ 122 | '/services/rest/V2.1/?format=json' 123 | session_url = axapi_authenticate(axapi_base_url, a10_admin, a10_pwd) 124 | 125 | if action == 'restore': 126 | print "===> Restore Config" 127 | response = axapi_call(session_url + '&method=cli.deploy', 128 | 'restore ' + tftp + tftp_file) 129 | print "<=== Status: " + axapi_result(response) 130 | 131 | if action == 'backup': 132 | print "===> Backup Config" 133 | response = axapi_call(session_url + '&method=cli.deploy', 134 | 'backup system ' + tftp + tftp_file) 135 | print "<=== Status: " + axapi_result(response) 136 | 137 | if action == 'reboot': 138 | print "===> Reboot Instance" 139 | response = axapi_call(session_url + 140 | '&method=system.action.reboot&\ 141 | write_memory=1') 142 | print "<=== Status: " + axapi_result(response) 143 | 144 | if action == 'clear-log': 145 | print "===> Clear Log" 146 | response = axapi_call(session_url + '&method=system.log.clear') 147 | print "<=== Status: " + axapi_result(response) 148 | 149 | if action == 'upgrade': 150 | print "===> Upgrade" 151 | json_post = {'sys_maintain': {'media': '0', 152 | 'destination': destination, 153 | 'reboot': '0', 154 | 'remote': {'protocol': '1', 155 | 'host': ftp_host, 156 | 'location': ftp_file, 157 | 'username': ftp_user, 158 | 'password': ftp_pass}}} 159 | response = axapi_call(session_url + 160 | '&method=system.maintain.upgrade', 161 | json.dumps(json_post)) 162 | print "<=== Status: " + axapi_result(response) 163 | 164 | closed = axapi_call(session_url + '&method=session.close') 165 | 166 | except Exception, e: 167 | print e 168 | -------------------------------------------------------------------------------- /a10_server: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | Ansible module to manage A10 Networks slb server objects 6 | (c) 2014, Mischa Peters 7 | 8 | This file is part of Ansible 9 | 10 | Ansible is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | Ansible is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with Ansible. If not, see . 22 | """ 23 | 24 | DOCUMENTATION = ''' 25 | --- 26 | module: a10_server 27 | version_added: 1.0 28 | short_description: Manage A10 Networks AX/SoftAX/Thunder/vThunder devices 29 | description: 30 | - Manage slb server objects on A10 Networks devices via aXAPI 31 | author: Mischa Peters 32 | notes: 33 | - Requires A10 Networks aXAPI 2.1 34 | requirements: 35 | - urllib2 36 | - re 37 | options: 38 | host: 39 | description: 40 | - hostname or ip of your A10 Networks device 41 | required: true 42 | default: null 43 | aliases: [] 44 | choices: [] 45 | username: 46 | description: 47 | - admin account of your A10 Networks device 48 | required: true 49 | default: null 50 | aliases: ['user', 'admin'] 51 | choices: [] 52 | password: 53 | description: 54 | - admin password of your A10 Networks device 55 | required: true 56 | default: null 57 | aliases: ['pass', 'pwd'] 58 | choices: [] 59 | server_name: 60 | description: 61 | - slb server name 62 | required: true 63 | default: null 64 | aliases: ['server'] 65 | choices: [] 66 | server_ip: 67 | description: 68 | - slb server IP address 69 | required: false 70 | default: null 71 | aliases: ['ip', 'address'] 72 | choices: [] 73 | server_port: 74 | description: 75 | - slb server port 76 | required: false 77 | default: null 78 | aliases: ['port'] 79 | choices: [] 80 | server_protocol: 81 | description: 82 | - slb server protocol 83 | required: false 84 | default: null 85 | aliases: ['proto', 'protocol'] 86 | choices: ['tcp', 'udp'] 87 | server_status: 88 | description: 89 | - slb server status 90 | required: false 91 | default: enabled 92 | aliases: ['status'] 93 | choices: ['enable', 'disable'] 94 | state: 95 | description: 96 | - create, update or remove slb server 97 | required: false 98 | default: present 99 | aliases: [] 100 | choices: ['present', 'absent'] 101 | ''' 102 | 103 | EXAMPLES = ''' 104 | # Create a new server 105 | ansible host -m a10_server -a "host=a10adc.example.com username=axapiuser password=axapipass server_name=realserver1 server_ip=192.168.1.23" 106 | 107 | # Add a port 108 | ansible host -m a10_server -a "host=a10adc.example.com username=axapiuser password=axapipass server_name=realserver1 server_port=80 server_protocol=tcp" 109 | 110 | # Disable a server 111 | ansible host -m a10_server -a "host=a10adc.example.com username=axapiuser password=axapipass server_name=realserver1 server_status=disable" 112 | ''' 113 | 114 | import urllib2 115 | 116 | 117 | def axapi_call(url, post=None): 118 | result = urllib2.urlopen(url, post).read() 119 | return result 120 | 121 | 122 | def axapi_authenticate(base_url, user, pwd): 123 | url = base_url + '&method=authenticate&username=' + user + \ 124 | '&password=' + pwd 125 | result = json.loads(axapi_call(url)) 126 | if 'response' in result: 127 | return module.fail_json(msg=result['response']['err']['msg']) 128 | sessid = result['session_id'] 129 | return base_url + '&session_id=' + sessid 130 | 131 | 132 | def main(): 133 | global module 134 | module = AnsibleModule( 135 | argument_spec=dict( 136 | host=dict(type='str', required=True), 137 | username=dict(type='str', aliases=['user', 'admin'], 138 | required=True), 139 | password=dict(type='str', aliases=['pass', 'pwd'], required=True), 140 | server_name=dict(type='str', aliases=['server'], required=True), 141 | server_ip=dict(type='str', aliases=['ip', 'address']), 142 | server_port=dict(type='int', aliases=['port']), 143 | server_protocol=dict(type='str', aliases=['proto', 'protocol'], 144 | choices=['tcp', 'udp']), 145 | server_status=dict(type='str', default='enable', 146 | aliases=['status'], 147 | choices=['enable', 'disable']), 148 | state=dict(type='str', default='present', 149 | choices=['present', 'absent']), 150 | ), 151 | supports_check_mode=False 152 | ) 153 | 154 | host = module.params['host'] 155 | user = module.params['username'] 156 | pwd = module.params['password'] 157 | slb_server = module.params['server_name'] 158 | slb_server_ip = module.params['server_ip'] 159 | slb_server_port = module.params['server_port'] 160 | slb_server_proto = module.params['server_protocol'] 161 | slb_server_status = module.params['server_status'] 162 | state = module.params['state'] 163 | 164 | axapi_base_url = 'https://' + host + '/services/rest/V2.1/?format=json' 165 | 166 | if slb_server_proto == 'tcp' or slb_server_proto == 'TCP' or \ 167 | slb_server_proto is None: 168 | protocol = '2' 169 | else: 170 | protocol = '3' 171 | 172 | if slb_server_status == 'enable': 173 | status = '1' 174 | else: 175 | status = '0' 176 | 177 | if slb_server is None: 178 | module.fail_json(msg='server_name is required') 179 | 180 | if slb_server_port is None: 181 | json_post = {'server': {'name': slb_server, 182 | 'host': slb_server_ip, 'status': status}} 183 | else: 184 | json_post = {'server': {'name': slb_server, 'host': slb_server_ip, 185 | 'status': status, 'port_list': 186 | [{'port_num': slb_server_port, 187 | 'protocol': protocol}]}} 188 | 189 | try: 190 | session_url = axapi_authenticate(axapi_base_url, user, pwd) 191 | 192 | if state == 'present': 193 | response = axapi_call(session_url + '&method=slb.server.search', 194 | json.dumps({'name': slb_server})) 195 | slb_server_exist = re.search(slb_server, response, re.I) 196 | 197 | if slb_server_exist is None: 198 | if slb_server_ip is None: 199 | module.fail_json(msg='IP address is required') 200 | response = axapi_call(session_url + 201 | '&method=slb.server.create', 202 | json.dumps(json_post)) 203 | else: 204 | response = axapi_call(session_url + 205 | '&method=slb.server.update', 206 | json.dumps(json_post)) 207 | 208 | if state == 'absent': 209 | response = axapi_call(session_url + 210 | '&method=slb.server.delete', 211 | json.dumps({'name': slb_server})) 212 | 213 | result = json.loads(response) 214 | axapi_call(session_url + '&method=session.close') 215 | 216 | except Exception, e: 217 | return module.fail_json(msg='received exception: %s' % e) 218 | 219 | if 'respone' in result and 'err' in result['response']: 220 | return module.fail_json(msg=result['response']['err']['msg']) 221 | 222 | module.exit_json(changed=True, content=result) 223 | 224 | from ansible.module_utils.basic import * 225 | main() 226 | -------------------------------------------------------------------------------- /a10_service_group: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | Ansible module to manage A10 Networks slb service-group objects 6 | (c) 2014, Mischa Peters 7 | 8 | This file is part of Ansible 9 | 10 | Ansible is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | Ansible is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with Ansible. If not, see . 22 | """ 23 | 24 | DOCUMENTATION = ''' 25 | --- 26 | module: a10_service_group 27 | version_added: 1.0 28 | short_description: Manage A10 Networks AX/SoftAX/Thunder/vThunder devices 29 | description: 30 | - Manage slb service-group objects on A10 Networks devices via aXAPI 31 | author: Mischa Peters 32 | notes: 33 | - Requires A10 Networks aXAPI 2.1 34 | - When a server doesn't exist and is added to the service-group the server will be created 35 | requirements: 36 | - urllib2 37 | - re 38 | options: 39 | host: 40 | description: 41 | - hostname or ip of your A10 Networks device 42 | required: true 43 | default: null 44 | aliases: [] 45 | choices: [] 46 | username: 47 | description: 48 | - admin account of your A10 Networks device 49 | required: true 50 | default: null 51 | aliases: ['user', 'admin'] 52 | choices: [] 53 | password: 54 | description: 55 | - admin password of your A10 Networks device 56 | required: true 57 | default: null 58 | aliases: ['pass', 'pwd'] 59 | choices: [] 60 | service_group: 61 | description: 62 | - slb service-group name 63 | required: true 64 | default: null 65 | aliases: ['service', 'pool', 'group'] 66 | choices: [] 67 | service_group_protocol: 68 | description: 69 | - slb service-group protocol 70 | required: false 71 | default: tcp 72 | aliases: ['proto', 'protocol'] 73 | choices: ['tcp', 'udp'] 74 | service_group_method: 75 | description: 76 | - slb service-group loadbalancing method 77 | required: false 78 | default: round-robin 79 | aliases: ['method'] 80 | 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'] 81 | server_name: 82 | description: 83 | - slb server name 84 | required: false 85 | default: null 86 | aliases: ['server', 'member'] 87 | choices: [] 88 | server_port: 89 | description: 90 | - slb server port 91 | required: false 92 | default: null 93 | aliases: ['port'] 94 | choices: [] 95 | server_status: 96 | description: 97 | - slb server status 98 | required: false 99 | default: enabled 100 | aliases: ['status'] 101 | choices: ['enable', 'disable'] 102 | state: 103 | description: 104 | - create, remove or update slb service-group 105 | required: false 106 | default: present 107 | aliases: [] 108 | choices: ['present', 'absent'] 109 | ''' 110 | 111 | EXAMPLES = ''' 112 | # Create a new service-group 113 | ansible host -m a10_service_group -a "host=a10adc.example.com username=axapiuser password=axapipass service_group=sg-80-tcp" 114 | 115 | # Add a server 116 | 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" 117 | 118 | # Disable a server 119 | 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" 120 | ''' 121 | 122 | import urllib2 123 | 124 | 125 | def axapi_call(url, post=None): 126 | result = urllib2.urlopen(url, post).read() 127 | return result 128 | 129 | 130 | def axapi_authenticate(base_url, user, pwd): 131 | url = base_url + '&method=authenticate&username=' + user + \ 132 | '&password=' + pwd 133 | result = json.loads(axapi_call(url)) 134 | if 'response' in result: 135 | return module.fail_json(msg=result['response']['err']['msg']) 136 | sessid = result['session_id'] 137 | return base_url + '&session_id=' + sessid 138 | 139 | 140 | def main(): 141 | global module 142 | module = AnsibleModule( 143 | argument_spec=dict( 144 | host=dict(type='str', required=True), 145 | username=dict(type='str', aliases=['user', 'admin'], 146 | required=True), 147 | password=dict(type='str', aliases=['pass', 'pwd'], required=True), 148 | service_group=dict(type='str', 149 | aliases=['service', 'pool', 'group'], 150 | required=True), 151 | service_group_protocol=dict(type='str', default='tcp', 152 | aliases=['proto', 'protocol'], 153 | choices=['tcp', 'udp']), 154 | service_group_method=dict(type='str', default='round-robin', 155 | aliases=['method'], 156 | choices=['round-robin', 157 | 'weighted-rr', 158 | 'least-connection', 159 | 'weighted-least-connection', 160 | 'service-least-connection', 161 | 'service-weighted-least-connection', 162 | 'fastest-response', 163 | 'least-request', 164 | 'round-robin-strict', 165 | 'src-ip-only-hash', 166 | 'src-ip-hash']), 167 | server_name=dict(type='str', aliases=['server', 'member']), 168 | server_port=dict(type='int', aliases=['port']), 169 | server_status=dict(type='str', default='enable', 170 | aliases=['status'], 171 | choices=['enable', 'disable']), 172 | state=dict(type='str', default='present', 173 | choices=['present', 'absent']), 174 | ), 175 | supports_check_mode=False 176 | ) 177 | 178 | host = module.params['host'] 179 | user = module.params['username'] 180 | pwd = module.params['password'] 181 | slb_service_group = module.params['service_group'] 182 | slb_service_group_proto = module.params['service_group_protocol'] 183 | slb_service_group_method = module.params['service_group_method'] 184 | slb_server = module.params['server_name'] 185 | slb_server_port = module.params['server_port'] 186 | slb_server_status = module.params['server_status'] 187 | state = module.params['state'] 188 | 189 | axapi_base_url = 'https://' + host + '/services/rest/V2.1/?format=json' 190 | load_balancing_methods = {'round-robin': 0, 191 | 'weighted-rr': 1, 192 | 'least-connection': 2, 193 | 'weighted-least-connection': 3, 194 | 'service-least-connection': 4, 195 | 'service-weighted-least-connection': 5, 196 | 'fastest-response': 6, 197 | 'least-request': 7, 198 | 'round-robin-strict': 8, 199 | 'src-ip-only-hash': 14, 200 | 'src-ip-hash': 15} 201 | 202 | if slb_service_group_proto == 'tcp' or slb_service_group_proto == 'TCP': 203 | protocol = '2' 204 | else: 205 | protocol = '3' 206 | 207 | if slb_server_status == 'enable': 208 | status = '1' 209 | else: 210 | status = '0' 211 | 212 | if slb_service_group is None: 213 | module.fail_json(msg='service_group is required') 214 | 215 | if slb_server is None and slb_server_port is None: 216 | json_post = {'service_group': {'name': slb_service_group, 217 | 'protocol': protocol, 218 | 'lb_method': load_balancing_methods[slb_service_group_method]}} 219 | elif slb_server is not None and slb_server_port is not None: 220 | json_post = {'service_group': {'name': slb_service_group, 221 | 'protocol': protocol, 222 | 'lb_method': load_balancing_methods[slb_service_group_method], 223 | 'member_list': 224 | [{'server': slb_server, 225 | 'port': slb_server_port, 226 | 'status': status}]}} 227 | else: 228 | module.fail_json(msg='server_name and server_name_port are \ 229 | required to add to the service-group') 230 | 231 | try: 232 | session_url = axapi_authenticate(axapi_base_url, user, pwd) 233 | 234 | if state == 'present': 235 | response = axapi_call(session_url + 236 | '&method=slb.service_group.search', 237 | json.dumps({'name': slb_service_group})) 238 | slb_service_group_exist = re.search(slb_service_group, 239 | response, re.I) 240 | 241 | if slb_service_group_exist is None: 242 | response = axapi_call(session_url + 243 | '&method=slb.service_group.create', 244 | json.dumps(json_post)) 245 | else: 246 | response = axapi_call(session_url + 247 | '&method=slb.service_group.update', 248 | json.dumps(json_post)) 249 | 250 | if state == 'absent': 251 | response = axapi_call(session_url + 252 | '&method=slb.service_group.delete', 253 | json.dumps({'name': slb_service_group})) 254 | 255 | result = json.loads(response) 256 | axapi_call(session_url + '&method=session.close') 257 | 258 | except Exception, e: 259 | return module.fail_json(msg='received exception: %s' % e) 260 | 261 | if 'respone' in result and 'err' in result['response']: 262 | return module.fail_json(msg=result['response']['err']['msg']) 263 | 264 | module.exit_json(changed=True, content=result) 265 | 266 | from ansible.module_utils.basic import * 267 | main() 268 | -------------------------------------------------------------------------------- /a10_virtual: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | Ansible module to manage A10 Networks slb virtual server objects 6 | (c) 2014, Mischa Peters 7 | 8 | This file is part of Ansible 9 | 10 | Ansible is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | Ansible is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with Ansible. If not, see . 22 | """ 23 | 24 | DOCUMENTATION = ''' 25 | --- 26 | module: a10_virtual_server 27 | version_added: 1.0 28 | short_description: Manage A10 Networks AX/SoftAX/Thunder/vThunder devices 29 | description: 30 | - Manage slb virtual server objects on A10 Networks devices via aXAPI 31 | author: Mischa Peters 32 | notes: 33 | - Requires A10 Networks aXAPI 2.1 34 | requirements: 35 | - urllib2 36 | - re 37 | options: 38 | host: 39 | description: 40 | - hostname or ip of your A10 Networks device 41 | required: true 42 | default: null 43 | aliases: [] 44 | choices: [] 45 | username: 46 | description: 47 | - admin account of your A10 Networks device 48 | required: true 49 | default: null 50 | aliases: ['user', 'admin'] 51 | choices: [] 52 | password: 53 | description: 54 | - admin password of your A10 Networks device 55 | required: true 56 | default: null 57 | aliases: ['pass', 'pwd'] 58 | choices: [] 59 | virtual_server: 60 | description: 61 | - slb virtual server name 62 | required: true 63 | default: null 64 | aliases: ['vip', 'virtual'] 65 | choices: [] 66 | virtual_server_ip: 67 | description: 68 | - slb virtual server ip address 69 | required: false 70 | default: null 71 | aliases: ['ip', 'address'] 72 | choices: [] 73 | virtual_server_status: 74 | description: 75 | - slb virtual server status 76 | required: false 77 | default: enable 78 | aliases: ['status'] 79 | choices: ['enabled', 'disabled'] 80 | virtual_server_port: 81 | description: 82 | - slb virtual server port 83 | required: false 84 | default: round-robin 85 | aliases: ['port', 'vport'] 86 | choices: [] 87 | virtual_server_type: 88 | description: 89 | - slb virtual server port type 90 | required: false 91 | default: null 92 | aliases: ['proto', 'protocol'] 93 | choices: ['tcp', 'udp', 'fast-http', 'http', 'https'] 94 | virtual_server_port_status: 95 | description: 96 | - slb virtual server port status 97 | required: false 98 | default: enable 99 | aliases: ['status'] 100 | choices: ['enabled', 'disabled'] 101 | service_group: 102 | description: 103 | - slb virtual server service-group 104 | required: false 105 | default: enabled 106 | aliases: ['pool', 'group'] 107 | choices: [] 108 | state: 109 | description: 110 | - create, update or remove slb virtual server 111 | required: false 112 | default: present 113 | aliases: [] 114 | choices: ['present', 'absent'] 115 | ''' 116 | 117 | EXAMPLES = ''' 118 | # Create a new virtual server 119 | ansible host -m a10_virtual -a "host=a10adc.example.com username=axapiuser password=axapipass virtual_server=vip1 virtual_server_ip=192.168.1.20" 120 | 121 | # Add a virtual port 122 | 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" 123 | 124 | # Disable a virtual server 125 | ansible host -m a10_virtual -a "host=a10adc.example.com username=axapiuser password=axapipass virtual_server=vip1 status=disable" 126 | 127 | # Disable a virtual server port 128 | 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" 129 | ''' 130 | 131 | import urllib2 132 | 133 | 134 | def axapi_call(url, post=None): 135 | result = urllib2.urlopen(url, post).read() 136 | return result 137 | 138 | 139 | def axapi_authenticate(base_url, user, pwd): 140 | url = base_url + '&method=authenticate&username=' + user + \ 141 | '&password=' + pwd 142 | result = json.loads(axapi_call(url)) 143 | if 'response' in result: 144 | return module.fail_json(msg=result['response']['err']['msg']) 145 | sessid = result['session_id'] 146 | return base_url + '&session_id=' + sessid 147 | 148 | 149 | def main(): 150 | global module 151 | module = AnsibleModule( 152 | argument_spec=dict( 153 | host=dict(type='str', required=True), 154 | username=dict(type='str', aliases=['user', 'admin'], 155 | required=True), 156 | password=dict(type='str', aliases=['pass', 'pwd'], 157 | required=True), 158 | virtual_server=dict(type='str', aliases=['vip', 'virtual'], 159 | required=True), 160 | virtual_server_ip=dict(type='str', 161 | aliases=['ip', 'address']), 162 | virtual_server_status=dict(type='str', default='enabled', 163 | aliases=['status'], 164 | choices=['enabled', 'disabled']), 165 | virtual_server_port=dict(type='int', 166 | aliases=['port', 'vport']), 167 | virtual_server_port_type=dict(type='str', 168 | aliases=['proto', 'protocol'], 169 | choices=['tcp', 'udp', 'fast-http', 170 | 'http', 'https']), 171 | virtual_server_port_status=dict(type='str', default='enabled', 172 | aliases=['portstatus', 173 | 'port_status'], 174 | choices=['enabled', 'disabled']), 175 | service_group=dict(type='str', aliases=['pool', 'group']), 176 | state=dict(type='str', default='present', 177 | choices=['present', 'absent']), 178 | ), 179 | supports_check_mode=False 180 | ) 181 | 182 | host = module.params['host'] 183 | user = module.params['username'] 184 | pwd = module.params['password'] 185 | slb_virtual = module.params['virtual_server'] 186 | slb_virtual_ip = module.params['virtual_server_ip'] 187 | slb_virtual_status = module.params['virtual_server_status'] 188 | slb_virtual_port = module.params['virtual_server_port'] 189 | slb_virtual_port_type = module.params['virtual_server_port_type'] 190 | slb_virtual_port_status = module.params['virtual_server_port_status'] 191 | slb_service_group = module.params['service_group'] 192 | state = module.params['state'] 193 | 194 | axapi_base_url = 'https://' + host + '/services/rest/V2.1/?format=json' 195 | vport_types = {'tcp': 2, 196 | 'udp': 3, 197 | 'fast-http': 9, 198 | 'http': 11, 199 | 'https': 12} 200 | 201 | if slb_virtual_status == 'enabled': 202 | status = '1' 203 | else: 204 | status = '0' 205 | 206 | if slb_virtual_port_status == 'enabled': 207 | port_status = '1' 208 | else: 209 | port_status = '0' 210 | 211 | if slb_virtual is None: 212 | module.fail_json(msg='virtual_server is required') 213 | 214 | try: 215 | session_url = axapi_authenticate(axapi_base_url, user, pwd) 216 | 217 | if state == 'present': 218 | find_slb_virtual = axapi_call(session_url + 219 | '&method=slb.virtual_server.search', 220 | json.dumps({'name': slb_virtual})) 221 | slb_virtual_fail = re.search('status": "fail', 222 | find_slb_virtual, re.I) 223 | 224 | if slb_virtual_fail: 225 | if slb_virtual_port is None and slb_virtual_port_type is None \ 226 | and slb_service_group is None: 227 | json_post = {'virtual_server': {'name': slb_virtual, 228 | 'address': slb_virtual_ip, 229 | 'status': status}} 230 | elif slb_virtual_port is not None and \ 231 | slb_virtual_port_type is not None and \ 232 | slb_service_group is None: 233 | json_post = {'virtual_server': 234 | {'name': slb_virtual, 235 | 'address': slb_virtual_ip, 236 | 'status': status, 237 | 'vport_list': 238 | [{'protocol': 239 | vport_types[slb_virtual_port_type], 240 | 'port': slb_virtual_port}]}} 241 | elif slb_virtual_port is not None and \ 242 | slb_virtual_port_type is not None and \ 243 | slb_service_group is not None: 244 | json_post = {'virtual_server': 245 | {'name': slb_virtual, 246 | 'address': slb_virtual_ip, 247 | 'status': status, 'vport_list': 248 | [{'protocol': 249 | vport_types[slb_virtual_port_type], 250 | 'port': slb_virtual_port, 251 | 'service_group': slb_service_group}]}} 252 | else: 253 | module.fail_json(msg='virtual_server_port and 254 | virtual_server_type are required to 255 | create the virtual port') 256 | 257 | response = axapi_call(session_url + 258 | '&method=slb.virtual_server.create', 259 | json.dumps(json_post)) 260 | else: 261 | response = axapi_call(session_url + 262 | '&method=slb.virtual_server.search', 263 | json.dumps({'name': slb_virtual})) 264 | slb_virtual_port_exist = re.search('"port":' + 265 | str(slb_virtual_port) 266 | response, re.I) 267 | current_status = json.loads(response)['virtual_server']['status'] 268 | current_port_status = 1 269 | 270 | if slb_virtual_port_exist: 271 | vport_list = json.loads(response)['virtual_server']['vport_list'] 272 | if vport_list: 273 | for port in range(len(vport_list)): 274 | if slb_virtual_port == str(vport_list[port]['port']): 275 | current_port_status = vport_list[port]['port'] 276 | 277 | json_post = {'address': slb_virtual_ip, 278 | 'vport': 279 | {'protocol': 280 | vport_types[slb_virtual_port_type], 281 | 'port': slb_virtual_port, 282 | 'service_group': slb_service_group}, 283 | 'status': port_status} 284 | response = axapi_call(session_url + 285 | '&method=slb.virtual_server.\ 286 | vport.update', json.dumps(json_post)) 287 | else: 288 | if slb_service_group is None: 289 | module.fail_json(msg='service_group is required') 290 | json_post = {'name': slb_virtual, 291 | 'vport': 292 | {'protocol': 293 | vport_types[slb_virtual_port_type], 294 | 'port': slb_virtual_port, 295 | 'service_group': slb_service_group}, 296 | 'status': port_status} 297 | response = axapi_call(session_url + 298 | '&method=slb.virtual_server.\ 299 | vport.create', json.dumps(json_post)) 300 | 301 | if current_status != status: 302 | json_post = {'virtual_server': 303 | {'name': slb_virtual, 304 | 'address': slb_virtual_ip, 305 | 'status': status}} 306 | response = axapi_call(session_url + 307 | '&method=slb.virtual_server.update', 308 | json.dumps(json_post)) 309 | 310 | if current_port_status != port_status: 311 | json_post = {'address': slb_virtual_ip, 'vport': 312 | {'protocol': 313 | vport_types[slb_virtual_port_type], 314 | 'port': slb_virtual_port}, 315 | 'status': port_status} 316 | response = axapi_call(session_url + 317 | '&method=slb.virtual_server.\ 318 | vport.update', json.dumps(json_post)) 319 | 320 | if state == 'absent': 321 | if slb_virtual_port is not None and \ 322 | slb_virtual_port_type is not None: 323 | response = axapi_call(session_url + 324 | '&method=slb.virtual_server.\ 325 | vport.delete', 326 | json.dumps({'name': slb_virtual, 327 | 'vport': 328 | {'protocol': 329 | vport_types[slb_virtual_port_type], 330 | 'port': slb_virtual_port}})) 331 | elif slb_virtual_port is None and slb_virtual_port_type is None: 332 | response = axapi_call(session_url + 333 | '&method=slb.virtual_server.delete', 334 | json.dumps({'name': slb_virtual})) 335 | else: 336 | module.fail_json(msg='virtual_server_port and \ 337 | virtual_server_type are required to remove \ 338 | the virtual port') 339 | 340 | result = json.loads(response) 341 | axapi_call(session_url + '&method=session.close') 342 | 343 | except Exception, e: 344 | return module.fail_json(msg='received exception: %s' % e) 345 | 346 | if 'respone' in result and 'err' in result['response']: 347 | return module.fail_json(msg=result['response']['err']['msg']) 348 | 349 | module.exit_json(changed=True, content=result) 350 | 351 | from ansible.module_utils.basic import * 352 | main() 353 | --------------------------------------------------------------------------------