From 7563d93901aa771eadebaae2998a7e758af9abb8 Mon Sep 17 00:00:00 2001 From: Ganesh Nalawade Date: Sat, 20 May 2017 01:45:53 +0530 Subject: [PATCH] Add nxos changes for Python3 (#24602) * Add nxos changes for Python3 Make `execute_command` arguments and its return value complaint to PY3 changes made in PR #24431 * Fix CI issues * Fix review comment Replace surrogate_or_strict with surrogate_then_replace as per review comment os PR #24601 --- lib/ansible/module_utils/nxos.py | 46 ++++++++++++++++++---------- lib/ansible/plugins/terminal/nxos.py | 29 +++++++++--------- test/sanity/pep8/legacy-files.txt | 2 -- 3 files changed, 43 insertions(+), 34 deletions(-) diff --git a/lib/ansible/module_utils/nxos.py b/lib/ansible/module_utils/nxos.py index 64262733371..19793ea7776 100644 --- a/lib/ansible/module_utils/nxos.py +++ b/lib/ansible/module_utils/nxos.py @@ -30,6 +30,7 @@ import re import collections +from ansible.module_utils._text import to_text from ansible.module_utils.basic import env_fallback, return_values from ansible.module_utils.network_common import to_list, ComplexList from ansible.module_utils.connection import exec_command @@ -60,12 +61,12 @@ ARGS_DEFAULT_VALUE = { 'timeout': 10 } + def check_args(module, warnings): provider = module.params['provider'] or {} for key in nxos_argument_spec: if key not in ['provider', 'transport'] and module.params[key]: - warnings.append('argument %s has been deprecated and will be ' - 'removed in a future version' % key) + warnings.append('argument %s has been deprecated and will be removed in a future version' % key) # set argument's default value if not provided in input # This is done to avoid unwanted argument deprecation warning @@ -79,6 +80,7 @@ def check_args(module, warnings): if provider.get(param): module.no_log_values.update(return_values(provider[param])) + def load_params(module): provider = module.params.get('provider') or dict() for key, value in iteritems(provider): @@ -86,6 +88,7 @@ def load_params(module): if module.params.get(key) is None and value is not None: module.params[key] = value + def get_connection(module): global _DEVICE_CONNECTION if not _DEVICE_CONNECTION: @@ -97,6 +100,7 @@ def get_connection(module): _DEVICE_CONNECTION = conn return _DEVICE_CONNECTION + class Cli: def __init__(self, module): @@ -120,8 +124,8 @@ class Cli: except KeyError: rc, out, err = self.exec_command(cmd) if rc != 0: - self._module.fail_json(msg=err) - cfg = str(out).strip() + self._module.fail_json(msg=to_text(err, errors='surrogate_then_replace')) + cfg = to_text(out, errors='surrogate_then_replace').strip() self._device_configs[cmd] = cfg return cfg @@ -139,9 +143,9 @@ class Cli: cmd = item['command'] rc, out, err = self.exec_command(cmd) - + out = to_text(out, errors='surrogate_then_replace') if check_rc and rc != 0: - self._module.fail_json(msg=err) + self._module.fail_json(msg=to_text(err, errors='surrogate_then_replace')) try: out = self._module.from_json(out) @@ -156,15 +160,16 @@ class Cli: """ rc, out, err = self.exec_command('configure') if rc != 0: - self._module.fail_json(msg='unable to enter configuration mode', output=err) + self._module.fail_json(msg='unable to enter configuration mode', output=to_text(err, errors='surrogate_then_replace')) for cmd in config: rc, out, err = self.exec_command(cmd) if rc != 0: - self._module.fail_json(msg=err) + self._module.fail_json(msg=to_text(err, errors='surrogate_then_replace')) self.exec_command('end') + class Nxapi: OUTPUT_TO_COMMAND_TYPE = { @@ -277,14 +282,13 @@ class Nxapi: self._error(output=output, **item) elif 'body' in item: result.append(item['body']) - #else: + # else: # error in command but since check_status is disabled # silently drop it. - #result.append(item['msg']) + # result.append(item['msg']) return result - def get_config(self, flags=[]): """Retrieves the current config from the device or cache """ @@ -300,7 +304,6 @@ class Nxapi: self._device_configs[cmd] = cfg return cfg - def run_commands(self, commands, check_rc=True): """Run list of commands on remote device and return results """ @@ -308,14 +311,15 @@ class Nxapi: queue = list() responses = list() - _send = lambda commands, output: self.send_request(commands, output, check_status=check_rc) + def _send(commands, output): + return self.send_request(commands, output, check_status=check_rc) for item in to_list(commands): if is_json(item['command']): item['command'] = str(item['command']).split('|')[0] item['output'] = 'json' - if all((output == 'json', item['output'] == 'text')) or all((output =='text', item['output'] == 'json')): + if all((output == 'json', item['output'] == 'text')) or all((output == 'text', item['output'] == 'json')): responses.extend(_send(queue, output)) queue = list() @@ -334,14 +338,20 @@ class Nxapi: self.send_request(commands, output='config') -is_json = lambda x: str(x).endswith('| json') -is_text = lambda x: not is_json +def is_json(cmd): + return str(cmd).endswith('| json') + + +def is_text(cmd): + return not is_json(cmd) + def is_nxapi(module): transport = module.params['transport'] provider_transport = (module.params['provider'] or {}).get('transport') return 'nxapi' in (transport, provider_transport) + def to_command(module, commands): if is_nxapi(module): default_output = 'json' @@ -365,15 +375,17 @@ def to_command(module, commands): return commands + def get_config(module, flags=[]): conn = get_connection(module) return conn.get_config(flags) + def run_commands(module, commands, check_rc=True): conn = get_connection(module) return conn.run_commands(to_command(module, commands), check_rc) + def load_config(module, config): conn = get_connection(module) return conn.load_config(config) - diff --git a/lib/ansible/plugins/terminal/nxos.py b/lib/ansible/plugins/terminal/nxos.py index 5d97aafdab2..ef4fb63a949 100644 --- a/lib/ansible/plugins/terminal/nxos.py +++ b/lib/ansible/plugins/terminal/nxos.py @@ -28,28 +28,27 @@ from ansible.errors import AnsibleConnectionFailure class TerminalModule(TerminalBase): terminal_stdout_re = [ - re.compile(r'[\r\n]?[a-zA-Z]{1}[a-zA-Z0-9-]*[>|#|%](?:\s*)$'), - re.compile(r'[\r\n]?[a-zA-Z]{1}[a-zA-Z0-9-]*\(.+\)#(?:\s*)$') + re.compile(br'[\r\n]?[a-zA-Z]{1}[a-zA-Z0-9-]*[>|#|%](?:\s*)$'), + re.compile(br'[\r\n]?[a-zA-Z]{1}[a-zA-Z0-9-]*\(.+\)#(?:\s*)$') ] terminal_stderr_re = [ - re.compile(r"% ?Error"), - re.compile(r"^% \w+", re.M), - re.compile(r"% ?Bad secret"), - re.compile(r"invalid input", re.I), - re.compile(r"(?:incomplete|ambiguous) command", re.I), - re.compile(r"connection timed out", re.I), - re.compile(r"[^\r\n]+ not found", re.I), - re.compile(r"'[^']' +returned error code: ?\d+"), - re.compile(r"syntax error"), - re.compile(r"unknown command"), - re.compile(r"user not present") + re.compile(br"% ?Error"), + re.compile(br"^% \w+", re.M), + re.compile(br"% ?Bad secret"), + re.compile(br"invalid input", re.I), + re.compile(br"(?:incomplete|ambiguous) command", re.I), + re.compile(br"connection timed out", re.I), + re.compile(br"[^\r\n]+ not found", re.I), + re.compile(br"'[^']' +returned error code: ?\d+"), + re.compile(br"syntax error"), + re.compile(br"unknown command"), + re.compile(br"user not present") ] def on_open_shell(self): try: - for cmd in ['terminal length 0', 'terminal width 511']: + for cmd in (b'terminal length 0', b'terminal width 511'): self._exec_cli_command(cmd) except AnsibleConnectionFailure: raise AnsibleConnectionFailure('unable to set terminal parameters') - diff --git a/test/sanity/pep8/legacy-files.txt b/test/sanity/pep8/legacy-files.txt index 528e095eb4e..3ae817df94b 100644 --- a/test/sanity/pep8/legacy-files.txt +++ b/test/sanity/pep8/legacy-files.txt @@ -65,7 +65,6 @@ lib/ansible/module_utils/netcli.py lib/ansible/module_utils/netconf.py lib/ansible/module_utils/network.py lib/ansible/module_utils/network_common.py -lib/ansible/module_utils/nxos.py lib/ansible/module_utils/openstack.py lib/ansible/module_utils/openswitch.py lib/ansible/module_utils/ordnance.py @@ -814,7 +813,6 @@ lib/ansible/plugins/strategy/linear.py lib/ansible/plugins/terminal/asa.py lib/ansible/plugins/terminal/eos.py lib/ansible/plugins/terminal/junos.py -lib/ansible/plugins/terminal/nxos.py lib/ansible/plugins/test/core.py lib/ansible/plugins/test/files.py lib/ansible/plugins/test/mathstuff.py