[CLI_CONF] Refactor nxos module common library to use cliconf plugin (#31524)

* refactor nxos modules

Signed-off-by: Trishna Guha <trishnaguha17@gmail.com>

* get_config update

* fix get_config

* update nxos module

* device_info

* fix conflict

* add failure message check

* pep8 fixes

* use get_capabilities to check cliconf

* Add logic to detect platform in get_capabilities and cache in module_utils

* return msg in edit_config

* fix conflicts

* make modules compatible

* fix nxos cliconf api

Signed-off-by: Trishna Guha <trishnaguha17@gmail.com>

* cache capabilities

* Update transport queries to get_capabilities in module level

* fix unit tests

* load_config error code

* remove unnecessary change

* Refactor nxos_install_os module
This commit is contained in:
Trishna Guha 2017-12-19 12:22:33 +05:30 committed by GitHub
parent bd399ec674
commit 9f86b923e9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 220 additions and 132 deletions

View file

@ -29,11 +29,13 @@
#
import collections
import json
import re
from ansible.module_utils._text import to_text
from ansible.module_utils.basic import env_fallback, return_values
from ansible.module_utils.network.common.utils import to_list, ComplexList
from ansible.module_utils.connection import exec_command
from ansible.module_utils.connection import Connection, ConnectionError
from ansible.module_utils.six import iteritems, string_types
from ansible.module_utils.urls import fetch_url
@ -107,39 +109,34 @@ class Cli:
def __init__(self, module):
self._module = module
self._device_configs = {}
self._connection = None
def exec_command(self, command):
if isinstance(command, dict):
command = self._module.jsonify(command)
return exec_command(self._module, command)
def _get_connection(self):
if self._connection:
return self._connection
self._connection = Connection(self._module._socket_path)
return self._connection
def get_config(self, flags=None):
"""Retrieves the current config from the device or cache
"""
flags = [] if flags is None else flags
cmd = 'show running-config '
cmd += ' '.join(flags)
cmd = cmd.strip()
try:
return self._device_configs[cmd]
except KeyError:
rc, out, err = self.exec_command(cmd)
if rc != 0:
self._module.fail_json(msg=to_text(err))
try:
cfg = to_text(out, errors='surrogate_or_strict').strip()
except UnicodeError as e:
self._module.fail_json(msg=u'Failed to decode config: %s' % to_text(out))
self._device_configs[cmd] = cfg
if self._device_configs != {}:
return self._device_configs
else:
connection = self._get_connection()
out = connection.get_config(flags=flags)
cfg = to_text(out, errors='surrogate_then_replace').strip()
self._device_configs = cfg
return cfg
def run_commands(self, commands, check_rc=True):
"""Run list of commands on remote device and return results
"""
responses = list()
connection = self._get_connection()
for item in to_list(commands):
if item['output'] == 'json' and not is_json(item['command']):
@ -149,29 +146,34 @@ class Cli:
else:
cmd = item['command']
rc, out, err = self.exec_command(cmd)
out = ''
try:
out = connection.get(cmd)
code = 0
except ConnectionError as e:
code = getattr(e, 'code', 1)
message = getattr(e, 'err', e)
err = to_text(message, errors='surrogate_then_replace')
try:
out = to_text(out, errors='surrogate_or_strict')
except UnicodeError:
self._module.fail_json(msg=u'Failed to decode output from %s: %s' % (cmd, to_text(out)))
if check_rc and rc != 0:
self._module.fail_json(msg=to_text(err))
if check_rc and code != 0:
self._module.fail_json(msg=err)
if not check_rc and rc != 0:
if not check_rc and code != 0:
try:
out = self._module.from_json(err)
except ValueError:
out = to_text(err).strip()
out = to_text(message).strip()
else:
try:
out = self._module.from_json(out)
except ValueError:
out = to_text(out).strip()
if item['output'] == 'json' and out != '' and isinstance(out, string_types):
self._module.fail_json(msg='failed to retrieve output of %s in json format' % item['command'])
responses.append(out)
return responses
@ -181,24 +183,37 @@ class Cli:
if opts is None:
opts = {}
rc, out, err = self.exec_command('configure')
if rc != 0:
self._module.fail_json(msg='unable to enter configuration mode', output=to_text(err))
connection = self._get_connection()
msgs = []
for cmd in config:
rc, out, err = self.exec_command(cmd)
if opts.get('ignore_timeout') and rc == 1:
msgs.append(err)
try:
responses = connection.edit_config(config)
out = json.loads(responses)[1:-1]
msg = out
except ConnectionError as e:
code = getattr(e, 'code', 1)
message = getattr(e, 'err', e)
err = to_text(message, errors='surrogate_then_replace')
if opts.get('ignore_timeout') and code:
msgs.append(code)
return msgs
elif rc != 0:
self._module.fail_json(msg=to_text(err))
elif out:
msgs.append(out)
elif code:
self._module.fail_json(msg=err)
self.exec_command('end')
msgs.extend(msg)
return msgs
def get_capabilities(self):
"""Returns platform info of the remove device
"""
if hasattr(self._module, '_capabilities'):
return self._module._capabilities
connection = self._get_connection()
capabilities = connection.get_capabilities()
self._module._capabilities = json.loads(capabilities)
return self._module._capabilities
class Nxapi:
@ -301,8 +316,8 @@ class Nxapi:
)
self._nxapi_auth = headers.get('set-cookie')
if opts.get('ignore_timeout') and headers['status'] == -1:
result.append(headers['msg'])
if opts.get('ignore_timeout') and re.search(r'(-1|5\d\d)', str(headers['status'])):
result.append(headers['status'])
return result
elif headers['status'] != 200:
self._error(**headers)
@ -384,6 +399,9 @@ class Nxapi:
else:
return []
def get_capabilities(self):
return {}
def is_json(cmd):
return str(cmd).endswith('| json')
@ -425,7 +443,7 @@ def get_config(module, flags=None):
flags = [] if flags is None else flags
conn = get_connection(module)
return conn.get_config(flags)
return conn.get_config(flags=flags)
def run_commands(module, commands, check_rc=True):
@ -436,3 +454,8 @@ def run_commands(module, commands, check_rc=True):
def load_config(module, config, return_error=False, opts=None):
conn = get_connection(module)
return conn.load_config(config, return_error, opts)
def get_capabilities(module):
conn = get_connection(module)
return conn.get_capabilities()