# This code is part of Ansible, but is an independent component. # This particular file snippet, and this file snippet only, is BSD licensed. # Modules you write using this snippet, which is embedded dynamically by Ansible # still belong to the author of the module, and may assign their own license # to the complete work. # # Copyright (c), Michael DeHaan , 2012-2013 # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import json from ansible.module_utils.urls import fetch_url AXAPI_PORT_PROTOCOLS = { 'tcp': 2, 'udp': 3, } AXAPI_VPORT_PROTOCOLS = { 'tcp': 2, 'udp': 3, 'fast-http': 9, 'http': 11, 'https': 12, } def a10_argument_spec(): return 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, no_log=True), write_config=dict(type='bool', default=False) ) def axapi_failure(result): if 'response' in result and result['response'].get('status') == 'fail': return True return False def axapi_call(module, url, post=None): ''' Returns a datastructure based on the result of the API call ''' rsp, info = fetch_url(module, url, data=post) if not rsp or info['status'] >= 400: module.fail_json(msg="failed to connect (status code %s), error was %s" % (info['status'], info.get('msg', 'no error given'))) try: raw_data = rsp.read() data = json.loads(raw_data) except ValueError: # at least one API call (system.action.write_config) returns # XML even when JSON is requested, so do some minimal handling # here to prevent failing even when the call succeeded if 'status="ok"' in raw_data.lower(): data = {"response": {"status": "OK"}} else: data = {"response": {"status": "fail", "err": {"msg": raw_data}}} except Exception: module.fail_json(msg="could not read the result from the host") finally: rsp.close() return data def axapi_authenticate(module, base_url, username, password): url = '%s&method=authenticate&username=%s&password=%s' % (base_url, username, password) result = axapi_call(module, url) if axapi_failure(result): return module.fail_json(msg=result['response']['err']['msg']) sessid = result['session_id'] return base_url + '&session_id=' + sessid def axapi_authenticate_v3(module, base_url, username, password): url = base_url auth_payload = {"credentials": {"username": username, "password": password}} result = axapi_call_v3(module, url, method='POST', body=json.dumps(auth_payload)) if axapi_failure(result): return module.fail_json(msg=result['response']['err']['msg']) signature = result['authresponse']['signature'] return signature def axapi_call_v3(module, url, method=None, body=None, signature=None): ''' Returns a datastructure based on the result of the API call ''' if signature: headers = {'content-type': 'application/json', 'Authorization': 'A10 %s' % signature} else: headers = {'content-type': 'application/json'} rsp, info = fetch_url(module, url, method=method, data=body, headers=headers) if not rsp or info['status'] >= 400: module.fail_json(msg="failed to connect (status code %s), error was %s" % (info['status'], info.get('msg', 'no error given'))) try: raw_data = rsp.read() data = json.loads(raw_data) except ValueError: # at least one API call (system.action.write_config) returns # XML even when JSON is requested, so do some minimal handling # here to prevent failing even when the call succeeded if 'status="ok"' in raw_data.lower(): data = {"response": {"status": "OK"}} else: data = {"response": {"status": "fail", "err": {"msg": raw_data}}} except Exception: module.fail_json(msg="could not read the result from the host") finally: rsp.close() return data def axapi_enabled_disabled(flag): ''' The axapi uses 0/1 integer values for flags, rather than strings or booleans, so convert the given flag to a 0 or 1. For now, params are specified as strings only so thats what we check. ''' if flag == 'enabled': return 1 else: return 0 def axapi_get_port_protocol(protocol): return AXAPI_PORT_PROTOCOLS.get(protocol.lower(), None) def axapi_get_vport_protocol(protocol): return AXAPI_VPORT_PROTOCOLS.get(protocol.lower(), None)