def main(): argument_spec = a10_argument_spec() argument_spec.update(url_argument_spec()) argument_spec.update( dict( state=dict(type='str', default='present', choices=['present', 'absent']), virtual_server=dict(type='str', aliases=['vip', 'virtual'], required=True), virtual_server_ip=dict(type='str', aliases=['ip', 'address'], required=True), virtual_server_status=dict(type='str', default='enabled', aliases=['status'], choices=['enabled', 'disabled']), virtual_server_ports=dict(type='list', required=True), partition=dict(type='str', default=[]), )) module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False) host = module.params['host'] username = module.params['username'] password = module.params['password'] partition = module.params['partition'] state = module.params['state'] write_config = module.params['write_config'] slb_virtual = module.params['virtual_server'] slb_virtual_ip = module.params['virtual_server_ip'] slb_virtual_status = module.params['virtual_server_status'] slb_virtual_ports = module.params['virtual_server_ports'] if slb_virtual is None: module.fail_json(msg='virtual_server is required') validate_ports(module, slb_virtual_ports) axapi_base_url = 'https://%s/services/rest/V2.1/?format=json' % host session_url = axapi_authenticate(module, axapi_base_url, username, password) axapi_call(module, session_url + '&method=system.partition.active', json.dumps({'name': partition})) slb_virtual_data = axapi_call( module, session_url + '&method=slb.virtual_server.search', json.dumps({'name': slb_virtual})) slb_virtual_exists = not axapi_failure(slb_virtual_data) changed = False if state == 'present': json_post = { 'virtual_server': { 'name': slb_virtual, 'address': slb_virtual_ip, 'status': axapi_enabled_disabled(slb_virtual_status), 'vport_list': slb_virtual_ports, } } # before creating/updating we need to validate that any # service groups defined in the ports list exist since # since the API will still create port definitions for # them while indicating a failure occurred checked_service_groups = [] for port in slb_virtual_ports: if 'service_group' in port and port[ 'service_group'] not in checked_service_groups: # skip blank service group entries if port['service_group'] == '': continue result = axapi_call( module, session_url + '&method=slb.service_group.search', json.dumps({'name': port['service_group']})) if axapi_failure(result): module.fail_json( msg= "the service group %s specified in the ports list does not exist" % port['service_group']) checked_service_groups.append(port['service_group']) if not slb_virtual_exists: result = axapi_call( module, session_url + '&method=slb.virtual_server.create', json.dumps(json_post)) if axapi_failure(result): module.fail_json( msg="failed to create the virtual server: %s" % result['response']['err']['msg']) changed = True else: def needs_update(src_ports, dst_ports): ''' Checks to determine if the port definitions of the src_ports array are in or different from those in dst_ports. If there is a difference, this function returns true, otherwise false. ''' for src_port in src_ports: found = False different = False for dst_port in dst_ports: if src_port['port'] == dst_port['port']: found = True for valid_field in VALID_PORT_FIELDS: if src_port[valid_field] != dst_port[ valid_field]: different = True break if found or different: break if not found or different: return True # every port from the src exists in the dst, and none of them were different return False defined_ports = slb_virtual_data.get('virtual_server', {}).get('vport_list', []) # we check for a needed update both ways, in case ports # are missing from either the ones specified by the user # or from those on the device if needs_update(defined_ports, slb_virtual_ports) or needs_update( slb_virtual_ports, defined_ports): result = axapi_call( module, session_url + '&method=slb.virtual_server.update', json.dumps(json_post)) if axapi_failure(result): module.fail_json( msg="failed to create the virtual server: %s" % result['response']['err']['msg']) changed = True # if we changed things, get the full info regarding # the service group for the return data below if changed: result = axapi_call( module, session_url + '&method=slb.virtual_server.search', json.dumps({'name': slb_virtual})) else: result = slb_virtual_data elif state == 'absent': if slb_virtual_exists: result = axapi_call( module, session_url + '&method=slb.virtual_server.delete', json.dumps({'name': slb_virtual})) changed = True else: result = dict(msg="the virtual server was not present") # if the config has changed, save the config unless otherwise requested if changed and write_config: write_result = axapi_call( module, session_url + '&method=system.action.write_memory') if axapi_failure(write_result): module.fail_json(msg="failed to save the configuration: %s" % write_result['response']['err']['msg']) # log out of the session nicely and exit axapi_call(module, session_url + '&method=session.close') module.exit_json(changed=changed, content=result)
def main(): argument_spec = a10_argument_spec() argument_spec.update(url_argument_spec()) argument_spec.update( dict( operation=dict(type='str', default='create', choices=['create', 'update', 'delete']), server_name=dict(type='str', aliases=['server'], required=True), server_ip=dict(type='str', aliases=['ip', 'address'], required=True), server_status=dict(type='str', default='enable', aliases=['action'], choices=['enable', 'disable']), server_ports=dict(type='list', aliases=['port'], default=[]), )) module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False) host = module.params['host'] username = module.params['username'] password = module.params['password'] operation = module.params['operation'] write_config = module.params['write_config'] slb_server = module.params['server_name'] slb_server_ip = module.params['server_ip'] slb_server_status = module.params['server_status'] slb_server_ports = module.params['server_ports'] axapi_base_url = 'https://{0}/axapi/v3/'.format(host) axapi_auth_url = axapi_base_url + 'auth/' signature = axapi_authenticate_v3(module, axapi_auth_url, username, password) # validate the ports data structure validate_ports(module, slb_server_ports) json_post = {"server-list": [{"name": slb_server, "host": slb_server_ip}]} # add optional module parameters if slb_server_ports: json_post['server-list'][0]['port-list'] = slb_server_ports if slb_server_status: json_post['server-list'][0]['action'] = slb_server_status slb_server_data = axapi_call_v3(module, axapi_base_url + 'slb/server/', method='GET', body='', signature=signature) # for empty slb server list if axapi_failure(slb_server_data): slb_server_exists = False else: slb_server_list = [ server['name'] for server in slb_server_data['server-list'] ] if slb_server in slb_server_list: slb_server_exists = True else: slb_server_exists = False changed = False if operation == 'create': if slb_server_exists is False: result = axapi_call_v3(module, axapi_base_url + 'slb/server/', method='POST', body=json.dumps(json_post), signature=signature) if axapi_failure(result): module.fail_json(msg="failed to create the server: %s" % result['response']['err']['msg']) changed = True else: module.fail_json( msg="server already exists, use state='update' instead") changed = False # if we changed things, get the full info regarding result if changed: result = axapi_call_v3(module, axapi_base_url + 'slb/server/' + slb_server, method='GET', body='', signature=signature) else: result = slb_server_data elif operation == 'delete': if slb_server_exists: result = axapi_call_v3(module, axapi_base_url + 'slb/server/' + slb_server, method='DELETE', body='', signature=signature) if axapi_failure(result): module.fail_json(msg="failed to delete server: %s" % result['response']['err']['msg']) changed = True else: result = dict(msg="the server was not present") elif operation == 'update': if slb_server_exists: result = axapi_call_v3(module, axapi_base_url + 'slb/server/', method='PUT', body=json.dumps(json_post), signature=signature) if axapi_failure(result): module.fail_json(msg="failed to update server: %s" % result['response']['err']['msg']) changed = True else: result = dict(msg="the server was not present") # if the config has changed, save the config unless otherwise requested if changed and write_config: write_result = axapi_call_v3(module, axapi_base_url + 'write/memory/', method='POST', body='', signature=signature) if axapi_failure(write_result): module.fail_json(msg="failed to save the configuration: %s" % write_result['response']['err']['msg']) # log out gracefully and exit axapi_call_v3(module, axapi_base_url + 'logoff/', method='POST', body='', signature=signature) module.exit_json(changed=changed, content=result)
def main(): argument_spec = a10_argument_spec() argument_spec.update(url_argument_spec()) argument_spec.update( dict( state=dict(type='str', default='present', choices=['present', 'absent']), 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' ]), servers=dict(type='list', aliases=['server', 'member'], default=[]), partition=dict(type='str', default=[]), )) module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False) host = module.params['host'] username = module.params['username'] password = module.params['password'] partition = module.params['partition'] state = module.params['state'] write_config = module.params['write_config'] 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_servers = module.params['servers'] if slb_service_group is None: module.fail_json(msg='service_group is required') 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 not slb_service_group_proto or slb_service_group_proto.lower() == 'tcp': protocol = 2 else: protocol = 3 # validate the server data list structure validate_servers(module, slb_servers) json_post = { 'service_group': { 'name': slb_service_group, 'protocol': protocol, 'lb_method': load_balancing_methods[slb_service_group_method], } } # first we authenticate to get a session id session_url = axapi_authenticate(module, axapi_base_url, username, password) # then we select the active-partition axapi_call(module, session_url + '&method=system.partition.active', json.dumps({'name': partition})) # then we check to see if the specified group exists slb_result = axapi_call(module, session_url + '&method=slb.service_group.search', json.dumps({'name': slb_service_group})) slb_service_group_exist = not axapi_failure(slb_result) changed = False if state == 'present': # before creating/updating we need to validate that servers # defined in the servers list exist to prevent errors checked_servers = [] for server in slb_servers: result = axapi_call(module, session_url + '&method=slb.server.search', json.dumps({'name': server['server']})) if axapi_failure(result): module.fail_json( msg= "the server %s specified in the servers list does not exist" % server['server']) checked_servers.append(server['server']) if not slb_service_group_exist: result = axapi_call( module, session_url + '&method=slb.service_group.create', json.dumps(json_post)) if axapi_failure(result): module.fail_json(msg=result['response']['err']['msg']) changed = True else: # check to see if the service group definition without the # server members is different, and update that individually # if it needs it do_update = False for field in VALID_SERVICE_GROUP_FIELDS: if json_post['service_group'][field] != slb_result[ 'service_group'][field]: do_update = True break if do_update: result = axapi_call( module, session_url + '&method=slb.service_group.update', json.dumps(json_post)) if axapi_failure(result): module.fail_json(msg=result['response']['err']['msg']) changed = True # next we pull the defined list of servers out of the returned # results to make it a bit easier to iterate over defined_servers = slb_result.get('service_group', {}).get('member_list', []) # next we add/update new member servers from the user-specified # list if they're different or not on the target device for server in slb_servers: found = False different = False for def_server in defined_servers: if server['server'] == def_server['server']: found = True for valid_field in VALID_SERVER_FIELDS: if server[valid_field] != def_server[valid_field]: different = True break if found or different: break # add or update as required server_data = { "name": slb_service_group, "member": server, } if not found: result = axapi_call( module, session_url + '&method=slb.service_group.member.create', json.dumps(server_data)) changed = True elif different: result = axapi_call( module, session_url + '&method=slb.service_group.member.update', json.dumps(server_data)) changed = True # finally, remove any servers that are on the target # device but were not specified in the list given for server in defined_servers: found = False for slb_server in slb_servers: if server['server'] == slb_server['server']: found = True break # remove if not found server_data = { "name": slb_service_group, "member": server, } if not found: result = axapi_call( module, session_url + '&method=slb.service_group.member.delete', json.dumps(server_data)) changed = True # if we changed things, get the full info regarding # the service group for the return data below if changed: result = axapi_call( module, session_url + '&method=slb.service_group.search', json.dumps({'name': slb_service_group})) else: result = slb_result elif state == 'absent': if slb_service_group_exist: result = axapi_call( module, session_url + '&method=slb.service_group.delete', json.dumps({'name': slb_service_group})) changed = True else: result = dict(msg="the service group was not present") # if the config has changed, save the config unless otherwise requested if changed and write_config: write_result = axapi_call( module, session_url + '&method=system.action.write_memory') if axapi_failure(write_result): module.fail_json(msg="failed to save the configuration: %s" % write_result['response']['err']['msg']) # log out of the session nicely and exit axapi_call(module, session_url + '&method=session.close') module.exit_json(changed=changed, content=result)
def main(): argument_spec = a10_argument_spec() argument_spec.update(url_argument_spec()) argument_spec.update( dict( state=dict(type='str', default='present', choices=['present', 'absent']), server_name=dict(type='str', aliases=['server'], required=True), server_ip=dict(type='str', aliases=['ip', 'address']), server_status=dict(type='str', default='enabled', aliases=['status'], choices=['enabled', 'disabled']), server_ports=dict(type='list', aliases=['port'], default=[]), partition=dict(type='str', default=[]), )) module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False) host = module.params['host'] partition = module.params['partition'] username = module.params['username'] password = module.params['password'] state = module.params['state'] write_config = module.params['write_config'] slb_server = module.params['server_name'] slb_server_ip = module.params['server_ip'] slb_server_status = module.params['server_status'] slb_server_ports = module.params['server_ports'] if slb_server is None: module.fail_json(msg='server_name is required') axapi_base_url = 'https://%s/services/rest/V2.1/?format=json' % host session_url = axapi_authenticate(module, axapi_base_url, username, password) # validate the ports data structure validate_ports(module, slb_server_ports) json_post = { 'server': { 'name': slb_server, } } # add optional module parameters if slb_server_ip: json_post['server']['host'] = slb_server_ip if slb_server_ports: json_post['server']['port_list'] = slb_server_ports if slb_server_status: json_post['server']['status'] = axapi_enabled_disabled( slb_server_status) axapi_call(module, session_url + '&method=system.partition.active', json.dumps({'name': partition})) slb_server_data = axapi_call(module, session_url + '&method=slb.server.search', json.dumps({'name': slb_server})) slb_server_exists = not axapi_failure(slb_server_data) changed = False if state == 'present': if not slb_server_exists: if not slb_server_ip: module.fail_json( msg='you must specify an IP address when creating a server' ) result = axapi_call(module, session_url + '&method=slb.server.create', json.dumps(json_post)) if axapi_failure(result): module.fail_json(msg="failed to create the server: %s" % result['response']['err']['msg']) changed = True else: def port_needs_update(src_ports, dst_ports): ''' Checks to determine if the port definitions of the src_ports array are in or different from those in dst_ports. If there is a difference, this function returns true, otherwise false. ''' for src_port in src_ports: found = False different = False for dst_port in dst_ports: if src_port['port_num'] == dst_port['port_num']: found = True for valid_field in VALID_PORT_FIELDS: if src_port[valid_field] != dst_port[ valid_field]: different = True break if found or different: break if not found or different: return True # every port from the src exists in the dst, and none of them were different return False def status_needs_update(current_status, new_status): ''' Check to determine if we want to change the status of a server. If there is a difference between the current status of the server and the desired status, return true, otherwise false. ''' if current_status != new_status: return True return False defined_ports = slb_server_data.get('server', {}).get('port_list', []) current_status = slb_server_data.get('server', {}).get('status') # we check for a needed update several ways # - in case ports are missing from the ones specified by the user # - in case ports are missing from those on the device # - in case we are change the status of a server if (port_needs_update(defined_ports, slb_server_ports) or port_needs_update(slb_server_ports, defined_ports) or status_needs_update( current_status, axapi_enabled_disabled(slb_server_status))): result = axapi_call(module, session_url + '&method=slb.server.update', json.dumps(json_post)) if axapi_failure(result): module.fail_json(msg="failed to update the server: %s" % result['response']['err']['msg']) changed = True # if we changed things, get the full info regarding # the service group for the return data below if changed: result = axapi_call(module, session_url + '&method=slb.server.search', json.dumps({'name': slb_server})) else: result = slb_server_data elif state == 'absent': if slb_server_exists: result = axapi_call(module, session_url + '&method=slb.server.delete', json.dumps({'name': slb_server})) changed = True else: result = dict(msg="the server was not present") # if the config has changed, save the config unless otherwise requested if changed and write_config: write_result = axapi_call( module, session_url + '&method=system.action.write_memory') if axapi_failure(write_result): module.fail_json(msg="failed to save the configuration: %s" % write_result['response']['err']['msg']) # log out of the session nicely and exit axapi_call(module, session_url + '&method=session.close') module.exit_json(changed=changed, content=result)