nxos enable mode (#39355)
* nxos enable mode Signed-off-by: Trishna Guha <trishnaguha17@gmail.com> * fix prompt Signed-off-by: Trishna Guha <trishnaguha17@gmail.com> * Add authorize,auth_pass Signed-off-by: Trishna Guha <trishnaguha17@gmail.com> * remove byte string from exec_cli_command Signed-off-by: Trishna Guha <trishnaguha17@gmail.com> * Add on_become test Signed-off-by: Trishna Guha <trishnaguha17@gmail.com> * removed_in_version Signed-off-by: Trishna Guha <trishnaguha17@gmail.com>
This commit is contained in:
parent
83df7249fd
commit
f08332acb4
10 changed files with 162 additions and 1 deletions
|
@ -49,6 +49,9 @@ nxos_provider_spec = {
|
|||
'password': dict(fallback=(env_fallback, ['ANSIBLE_NET_PASSWORD']), no_log=True),
|
||||
'ssh_keyfile': dict(fallback=(env_fallback, ['ANSIBLE_NET_SSH_KEYFILE'])),
|
||||
|
||||
'authorize': dict(fallback=(env_fallback, ['ANSIBLE_NET_AUTHORIZE']), type='bool'),
|
||||
'auth_pass': dict(no_log=True, fallback=(env_fallback, ['ANSIBLE_NET_AUTH_PASS'])),
|
||||
|
||||
'use_ssl': dict(type='bool'),
|
||||
'use_proxy': dict(default=True, type='bool'),
|
||||
'validate_certs': dict(type='bool'),
|
||||
|
@ -68,6 +71,9 @@ nxos_top_spec = {
|
|||
'password': dict(removed_in_version=2.9, no_log=True),
|
||||
'ssh_keyfile': dict(removed_in_version=2.9),
|
||||
|
||||
'authorize': dict(fallback=(env_fallback, ['ANSIBLE_NET_AUTHORIZE']), type='bool'),
|
||||
'auth_pass': dict(removed_in_version=2.9, no_log=True),
|
||||
|
||||
'use_ssl': dict(removed_in_version=2.9, type='bool'),
|
||||
'validate_certs': dict(removed_in_version=2.9, type='bool'),
|
||||
'timeout': dict(removed_in_version=2.9, type='int'),
|
||||
|
|
|
@ -63,6 +63,10 @@ class ActionModule(_ActionModule):
|
|||
pc.password = provider['password'] or self._play_context.password
|
||||
pc.private_key_file = provider['ssh_keyfile'] or self._play_context.private_key_file
|
||||
pc.timeout = int(provider['timeout'] or C.PERSISTENT_COMMAND_TIMEOUT)
|
||||
pc.become = provider['authorize'] or False
|
||||
if pc.become:
|
||||
pc.become_method = 'enable'
|
||||
pc.become_pass = provider['auth_pass']
|
||||
|
||||
display.vvv('using connection plugin %s (was local)' % pc.connection, pc.remote_addr)
|
||||
connection = self._shared_loader_obj.connection_loader.get('persistent', pc, sys.stdin)
|
||||
|
|
|
@ -20,9 +20,11 @@ from __future__ import (absolute_import, division, print_function)
|
|||
__metaclass__ = type
|
||||
|
||||
import re
|
||||
import json
|
||||
|
||||
from ansible.plugins.terminal import TerminalBase
|
||||
from ansible.errors import AnsibleConnectionFailure
|
||||
from ansible.module_utils._text import to_bytes, to_text
|
||||
|
||||
|
||||
class TerminalModule(TerminalBase):
|
||||
|
@ -48,9 +50,50 @@ class TerminalModule(TerminalBase):
|
|||
re.compile(br"invalid (.+?)at '\^' marker", re.I)
|
||||
]
|
||||
|
||||
def on_become(self, passwd=None):
|
||||
if self._get_prompt().endswith(b'enable#'):
|
||||
return
|
||||
|
||||
out = self._exec_cli_command('show privilege')
|
||||
out = to_text(out, errors='surrogate_then_replace').strip()
|
||||
if 'Disabled' in out:
|
||||
raise AnsibleConnectionFailure('Feature privilege is not enabled')
|
||||
|
||||
# if already at privilege level 15 return
|
||||
if '15' in out:
|
||||
return
|
||||
|
||||
cmd = {u'command': u'enable'}
|
||||
if passwd:
|
||||
cmd[u'prompt'] = to_text(r"(?i)[\r\n]?Password: $", errors='surrogate_or_strict')
|
||||
cmd[u'answer'] = passwd
|
||||
cmd[u'prompt_retry_check'] = True
|
||||
|
||||
try:
|
||||
self._exec_cli_command(to_bytes(json.dumps(cmd), errors='surrogate_or_strict'))
|
||||
prompt = self._get_prompt()
|
||||
if prompt is None or not prompt.strip().endswith(b'enable#'):
|
||||
raise AnsibleConnectionFailure('failed to elevate privilege to enable mode still at prompt [%s]' % prompt)
|
||||
except AnsibleConnectionFailure as e:
|
||||
prompt = self._get_prompt()
|
||||
raise AnsibleConnectionFailure('unable to elevate privilege to enable mode, at prompt [%s] with error: %s' % (prompt, e.message))
|
||||
|
||||
def on_unbecome(self):
|
||||
prompt = self._get_prompt()
|
||||
if prompt is None:
|
||||
# if prompt is None most likely the terminal is hung up at a prompt
|
||||
return
|
||||
|
||||
if b'(config' in prompt:
|
||||
self._exec_cli_command('end')
|
||||
self._exec_cli_command('exit')
|
||||
|
||||
elif prompt.endswith(b'enable#'):
|
||||
self._exec_cli_command('exit')
|
||||
|
||||
def on_open_shell(self):
|
||||
try:
|
||||
for cmd in (b'terminal length 0', b'terminal width 511'):
|
||||
for cmd in ('terminal length 0', 'terminal width 511'):
|
||||
self._exec_cli_command(cmd)
|
||||
except AnsibleConnectionFailure:
|
||||
raise AnsibleConnectionFailure('unable to set terminal parameters')
|
||||
|
|
3
test/integration/targets/nxos_become/defaults/main.yaml
Normal file
3
test/integration/targets/nxos_become/defaults/main.yaml
Normal file
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
testcase: "*"
|
||||
test_items: []
|
2
test/integration/targets/nxos_become/meta/main.yml
Normal file
2
test/integration/targets/nxos_become/meta/main.yml
Normal file
|
@ -0,0 +1,2 @@
|
|||
dependencies:
|
||||
- prepare_nxos_tests
|
33
test/integration/targets/nxos_become/tasks/cli.yaml
Normal file
33
test/integration/targets/nxos_become/tasks/cli.yaml
Normal file
|
@ -0,0 +1,33 @@
|
|||
---
|
||||
- name: collect common cli test cases
|
||||
find:
|
||||
paths: "{{ role_path }}/tests/common"
|
||||
patterns: "{{ testcase }}.yaml"
|
||||
connection: local
|
||||
register: test_cases
|
||||
|
||||
- name: collect cli test cases
|
||||
find:
|
||||
paths: "{{ role_path }}/tests/cli"
|
||||
patterns: "{{ testcase }}.yaml"
|
||||
connection: local
|
||||
register: cli_cases
|
||||
|
||||
- set_fact:
|
||||
test_cases:
|
||||
files: "{{ test_cases.files }} + {{ cli_cases.files }}"
|
||||
|
||||
- name: set test_items
|
||||
set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
|
||||
|
||||
- name: run test cases (connection=network_cli)
|
||||
include: "{{ test_case_to_run }} ansible_connection=network_cli connection={}"
|
||||
with_items: "{{ test_items }}"
|
||||
loop_control:
|
||||
loop_var: test_case_to_run
|
||||
|
||||
- name: run test case (connection=local)
|
||||
include: "{{ test_case_to_run }} ansible_connection=local connection={{ cli }}"
|
||||
with_first_found: "{{ test_items }}"
|
||||
loop_control:
|
||||
loop_var: test_case_to_run
|
3
test/integration/targets/nxos_become/tasks/main.yaml
Normal file
3
test/integration/targets/nxos_become/tasks/main.yaml
Normal file
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
- { include: cli.yaml, tags: ['cli'] }
|
||||
#- { include: nxapi.yaml, tags: ['nxapi'] }
|
27
test/integration/targets/nxos_become/tasks/nxapi.yaml
Normal file
27
test/integration/targets/nxos_become/tasks/nxapi.yaml
Normal file
|
@ -0,0 +1,27 @@
|
|||
---
|
||||
- name: collect common nxapi test cases
|
||||
find:
|
||||
paths: "{{ role_path }}/tests/common"
|
||||
patterns: "{{ testcase }}.yaml"
|
||||
connection: local
|
||||
register: test_cases
|
||||
|
||||
- name: collect nxapi test cases
|
||||
find:
|
||||
paths: "{{ role_path }}/tests/nxapi"
|
||||
patterns: "{{ testcase }}.yaml"
|
||||
connection: local
|
||||
register: nxapi_cases
|
||||
|
||||
- set_fact:
|
||||
test_cases:
|
||||
files: "{{ test_cases.files }} + {{ nxapi_cases.files }}"
|
||||
|
||||
- name: set test_items
|
||||
set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
|
||||
|
||||
- name: run test cases (connection=local)
|
||||
include: "{{ test_case_to_run }} ansible_connection=local connection={{ nxapi }}"
|
||||
with_items: "{{ test_items }}"
|
||||
loop_control:
|
||||
loop_var: test_case_to_run
|
39
test/integration/targets/nxos_become/tests/cli/sanity.yaml
Normal file
39
test/integration/targets/nxos_become/tests/cli/sanity.yaml
Normal file
|
@ -0,0 +1,39 @@
|
|||
---
|
||||
- debug: msg="START connection={{ ansible_connection }}/sanity.yaml"
|
||||
- debug: msg="Using provider={{ connection.transport }}/sanity.yaml"
|
||||
when: ansible_connection == "local"
|
||||
|
||||
- block:
|
||||
- name: update role to priv-14
|
||||
nxos_config:
|
||||
lines:
|
||||
- username admin role priv-14
|
||||
- no username admin role priv-15
|
||||
- enable secret 0 cisco
|
||||
provider: "{{ cli }}"
|
||||
|
||||
- name: reset_connection
|
||||
meta: reset_connection
|
||||
|
||||
- name: run commands with become
|
||||
nxos_command:
|
||||
commands: 'show privilege'
|
||||
provider: "{{ cli }}"
|
||||
become: yes
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "'Current privilege level: 15' in result['stdout'][0]"
|
||||
|
||||
always:
|
||||
- name: teardown
|
||||
nxos_config:
|
||||
lines:
|
||||
- username admin role priv-15
|
||||
- no username admin role priv-14
|
||||
- no enable secret
|
||||
provider: "{{ cli }}"
|
||||
ignore_errors: yes
|
||||
|
||||
- debug: msg="END connection={{ ansible_connection }}/sanity.yaml"
|
|
@ -3,6 +3,7 @@
|
|||
nxos_config:
|
||||
lines:
|
||||
- feature nxapi
|
||||
- feature privilege
|
||||
connection: network_cli
|
||||
ignore_errors: yes
|
||||
|
||||
|
|
Loading…
Reference in a new issue