mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-07-02 14:40:19 -07:00
[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:
parent
bd399ec674
commit
9f86b923e9
23 changed files with 220 additions and 132 deletions
|
@ -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()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue