updates to nxos shared module

This commit address a number of minor updates the nxos shared module

* connect() is now lazy loaded
* parse inner output messages when errored
* code syntax cleanup
pull/13443/merge
Peter Sprygada 8 years ago
parent 2984ffdfac
commit c039ac524d

@ -25,10 +25,11 @@ NET_COMMON_ARGS = dict(
password=dict(no_log=True), password=dict(no_log=True),
transport=dict(default='cli', choices=['cli', 'nxapi']), transport=dict(default='cli', choices=['cli', 'nxapi']),
use_ssl=dict(default=False, type='bool'), use_ssl=dict(default=False, type='bool'),
provider=dict() provider=dict(type='dict')
) )
NXAPI_COMMAND_TYPES = ['cli_show', 'cli_show_ascii', 'cli_conf', 'bash'] NXAPI_COMMAND_TYPES = ['cli_show', 'cli_show_ascii', 'cli_conf', 'bash']
NXAPI_ENCODINGS = ['json', 'xml'] NXAPI_ENCODINGS = ['json', 'xml']
def to_list(val): def to_list(val):
@ -49,7 +50,7 @@ class Nxapi(object):
self.module.params['url_password'] = module.params['password'] self.module.params['url_password'] = module.params['password']
self.url = None self.url = None
self.enable = None self._nxapi_auth = None
def _get_body(self, commands, command_type, encoding, version='1.2', chunk='0', sid=None): def _get_body(self, commands, command_type, encoding, version='1.2', chunk='0', sid=None):
"""Encodes a NXAPI JSON request message """Encodes a NXAPI JSON request message
@ -58,8 +59,9 @@ class Nxapi(object):
commands = ' ;'.join(commands) commands = ' ;'.join(commands)
if encoding not in NXAPI_ENCODINGS: if encoding not in NXAPI_ENCODINGS:
self.module.fail_json("Invalid encoding. Received %s. Expected one of %s" % msg = 'invalid encoding, received %s, exceped one of %s' % \
(encoding, ','.join(NXAPI_ENCODINGS))) (encoding, ','.join(NXAPI_ENCODINGS))
self.module_fail_json(msg=msg)
msg = { msg = {
'version': version, 'version': version,
@ -92,39 +94,36 @@ class Nxapi(object):
clist = to_list(commands) clist = to_list(commands)
if command_type not in NXAPI_COMMAND_TYPES: if command_type not in NXAPI_COMMAND_TYPES:
self.module.fail_json(msg="Invalid command_type. Received %s. Expected one of %s." % msg = 'invalid command_type, received %s, exceped one of %s' % \
(command_type, ','.join(NXAPI_COMMAND_TYPES))) (command_type, ','.join(NXAPI_COMMAND_TYPES))
self.module_fail_json(msg=msg)
debug = dict()
data = self._get_body(clist, command_type, encoding) data = self._get_body(clist, command_type, encoding)
data = self.module.jsonify(data) data = self.module.jsonify(data)
headers = {'Content-Type': 'application/json'} headers = {'Content-Type': 'application/json'}
if self._nxapi_auth:
headers['Cookie'] = self._nxapi_auth
response, headers = fetch_url(self.module, self.url, data=data, response, headers = fetch_url(self.module, self.url, data=data,
headers=headers, method='POST') headers=headers, method='POST')
self._nxapi_auth = headers.get('set-cookie')
if headers['status'] != 200: if headers['status'] != 200:
self.module.fail_json(**headers) self.module.fail_json(**headers)
response = self.module.from_json(response.read()) response = self.module.from_json(response.read())
result = list() result = list()
try: output = response['ins_api']['outputs']['output']
output = response['ins_api']['outputs']['output'] for item in to_list(output):
if isinstance(output, list): if item['code'] != '200':
for item in response['ins_api']['outputs']['output']: self.module.fail_json(**item)
if item['code'] != '200':
self.module.fail_json(msg=item['msg'], command=item['input'],
code=item['code'])
else:
result.append(item['body'])
elif output['code'] != '200':
self.module.fail_json(msg=item['msg'], command=item['input'],
code=item['code'])
else: else:
result.append(output['body']) result.append(item['body'])
except Exception:
self.module.fail_json(**headers)
return result return result
@ -142,12 +141,11 @@ class Cli(object):
username = self.module.params['username'] username = self.module.params['username']
password = self.module.params['password'] password = self.module.params['password']
self.shell = Shell()
try: try:
self.shell = Shell()
self.shell.open(host, port=port, username=username, password=password) self.shell.open(host, port=port, username=username, password=password)
except Exception, exc: except Exception, exc:
msg = 'failed to connecto to %s:%s - %s' % (host, port, str(exc)) msg = 'failed to connect to %s:%s - %s' % (host, port, str(exc))
self.module.fail_json(msg=msg) self.module.fail_json(msg=msg)
def send(self, commands, encoding='text'): def send(self, commands, encoding='text'):
@ -160,6 +158,11 @@ class NetworkModule(AnsibleModule):
super(NetworkModule, self).__init__(*args, **kwargs) super(NetworkModule, self).__init__(*args, **kwargs)
self.connection = None self.connection = None
self._config = None self._config = None
self._connected = False
@property
def connected(self):
return self._connected
@property @property
def config(self): def config(self):
@ -183,24 +186,31 @@ class NetworkModule(AnsibleModule):
self.connection = Cli(self) self.connection = Cli(self)
self.connection.connect() self.connection.connect()
if self.params['transport'] == 'cli': if self.params['transport'] == 'cli':
self.execute('terminal length 0') self.connection.send('terminal length 0')
self._connected = True
def configure_cli(self, commands):
commands = to_list(commands)
commands.insert(0, 'configure')
responses = self.execute(commands)
responses.pop(0)
return responses
def configure(self, commands): def configure(self, commands):
commands = to_list(commands) commands = to_list(commands)
if self.params['transport'] == 'cli': if self.params['transport'] == 'cli':
commands.insert(0, 'configure') return self.configure_cli(commands)
responses = self.execute(commands)
responses.pop(0)
else: else:
responses = self.execute(commands, command_type='cli_conf') return self.execute(commands, command_type='cli_conf')
return responses
def execute(self, commands, **kwargs): def execute(self, commands, **kwargs):
try: if not self.connected:
return self.connection.send(commands, **kwargs) self.connect()
except Exception, exc: return self.connection.send(commands, **kwargs)
self.fail_json(msg=exc.message, commands=commands)
def disconnect(self): def disconnect(self):
self.connection.close() self.connection.close()
@ -212,7 +222,6 @@ class NetworkModule(AnsibleModule):
cmd = 'show running-config' cmd = 'show running-config'
if self.params.get('include_defaults'): if self.params.get('include_defaults'):
cmd += ' all' cmd += ' all'
response = self.execute(cmd) response = self.execute(cmd)
return response[0] return response[0]
@ -231,5 +240,4 @@ def get_module(**kwargs):
if module.params['transport'] == 'cli' and not HAS_PARAMIKO: if module.params['transport'] == 'cli' and not HAS_PARAMIKO:
module.fail_json(msg='paramiko is required but does not appear to be installed') module.fail_json(msg='paramiko is required but does not appear to be installed')
module.connect()
return module return module

Loading…
Cancel
Save