community.network
community.network copied to clipboard
CNOS - show vlan id <vlan> gives error if no vlan found
SUMMARY
I'm trying to look up a vlan using the cnos_command. If the vlan exists it shows me the output correctly but if the vlan doesn't exists it throws an error
ISSUE TYPE
- Bug Report
COMPONENT NAME
community.network.cnos_command:
ANSIBLE VERSION
ansible 2.9.6
config file = /etc/ansible/ansible.cfg
configured module search path = ['/home/itfadmin/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3/dist-packages/ansible
executable location = /usr/bin/ansible
python version = 3.8.10 (default, Jun 2 2021, 10:49:15) [GCC 9.4.0]
COLLECTION VERSION
V3.0.0
CONFIGURATION
HOST_KEY_CHECKING(/etc/ansible/ansible.cfg) = False
OS / ENVIRONMENT
Target OS Lenovo CNOS 10.10.6.0
STEPS TO REPRODUCE
Run the playbook with a vlan that doesn't exists on the switch
- name: Retrieve CNOS VLAN
community.network.cnos_command:
commands:
- show vlan id 476
register: showCnosVlan
when: ansible_network_os == "community.network.cnos"
no_log: false
EXPECTED RESULTS
To run without error so I can use the output later on in my playbook.
ACTUAL RESULTS
TASK [Retrieve CNOS VLAN] *****************************************************************************************************************************************************task path: /etc/ansible/playbooks/DocumentVlan.yml:19
<10.1.103.109> attempting to start connection
<10.1.103.109> using connection plugin ansible.netcommon.network_cli
<10.1.103.109> found existing local domain socket, using it!
<10.1.103.109> updating play_context for connection
<10.1.103.109>
<10.1.103.109> local domain socket path is /root/.ansible/pc/5087f60c82
<10.1.103.109> ESTABLISH LOCAL CONNECTION FOR USER: root
<10.1.103.109> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-local-2927146rvi17at5/ansible-tmp-1628085113.710412-62146422633539 `" && echo ansible-tmp-1628085113.710412-62146422633539="` echo /root/.ansible/tmp/ansible-local-2927146rvi17at5/ansible-tmp-1628085113.710412-62146422633539 `" ) && sleep 0'
Using module file /root/.ansible/collections/ansible_collections/community/network/plugins/modules/cnos_command.py
<10.1.103.109> PUT /root/.ansible/tmp/ansible-local-2927146rvi17at5/tmpy7n7n3f8 TO /root/.ansible/tmp/ansible-local-2927146rvi17at5/ansible-tmp-1628085113.710412-62146422633539/AnsiballZ_cnos_command.py
<10.1.103.109> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-local-2927146rvi17at5/ansible-tmp-1628085113.710412-62146422633539/ /root/.ansible/tmp/ansible-local-2927146rvi17at5/ansible-tmp-1628085113.710412-62146422633539/AnsiballZ_cnos_command.py && sleep 0'
<10.1.103.109> EXEC /bin/sh -c '/usr/bin/python3 /root/.ansible/tmp/ansible-local-2927146rvi17at5/ansible-tmp-1628085113.710412-62146422633539/AnsiballZ_cnos_command.py && sleep 0'
<10.1.103.109> EXEC /bin/sh -c 'rm -f -r /root/.ansible/tmp/ansible-local-2927146rvi17at5/ansible-tmp-1628085113.710412-62146422633539/ > /dev/null 2>&1 && sleep 0'
The full traceback is:
Traceback (most recent call last):
File "/root/.ansible/tmp/ansible-local-2927146rvi17at5/ansible-tmp-1628085113.710412-62146422633539/AnsiballZ_cnos_command.py", line 102, in <module>
_ansiballz_main()
File "/root/.ansible/tmp/ansible-local-2927146rvi17at5/ansible-tmp-1628085113.710412-62146422633539/AnsiballZ_cnos_command.py", line 94, in _ansiballz_main
invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)
File "/root/.ansible/tmp/ansible-local-2927146rvi17at5/ansible-tmp-1628085113.710412-62146422633539/AnsiballZ_cnos_command.py", line 40, in invoke_module
runpy.run_module(mod_name='ansible_collections.community.network.plugins.modules.cnos_command', init_globals=None, run_name='__main__', alter_sys=True)
File "/usr/lib/python3.8/runpy.py", line 207, in run_module
return _run_module_code(code, init_globals, run_name, mod_spec)
File "/usr/lib/python3.8/runpy.py", line 97, in _run_module_code
_run_code(code, mod_globals, init_globals,
File "/usr/lib/python3.8/runpy.py", line 87, in _run_code
exec(code, run_globals)
File "/tmp/ansible_community.network.cnos_command_payload_w2zhqf9e/ansible_community.network.cnos_command_payload.zip/ansible_collections/community/network/plugins/modules/cnos_command.py", line 203, in <module>
File "/tmp/ansible_community.network.cnos_command_payload_w2zhqf9e/ansible_community.network.cnos_command_payload.zip/ansible_collections/community/network/plugins/modules/cnos_command.py", line 173, in main
File "/tmp/ansible_community.network.cnos_command_payload_w2zhqf9e/ansible_community.network.cnos_command_payload.zip/ansible_collections/community/network/plugins/module_utils/network/cnos/cnos.py", line 170, in run_commands
File "/tmp/ansible_community.network.cnos_command_payload_w2zhqf9e/ansible_community.network.cnos_command_payload.zip/ansible/module_utils/connection.py", line 185, in __rpc__
ansible.module_utils.connection.ConnectionError: show vlan id 476
VLAN 476 not found in current VLAN database.
SW109#
fatal: [SW109]: FAILED! => {
"changed": false,
"module_stderr": "Traceback (most recent call last):\n File \"/root/.ansible/tmp/ansible-local-2927146rvi17at5/ansible-tmp-1628085113.710412-62146422633539/AnsiballZ_cnos_command.py\", line 102, in <module>\n _ansiballz_main()\n File \"/root/.ansible/tmp/ansible-local-2927146rvi17at5/ansible-tmp-1628085113.710412-62146422633539/AnsiballZ_cnos_command.py\", line 94, in _ansiballz_main\n invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n File \"/root/.ansible/tmp/ansible-local-2927146rvi17at5/ansible-tmp-1628085113.710412-62146422633539/AnsiballZ_cnos_command.py\", line 40, in invoke_module\n runpy.run_module(mod_name='ansible_collections.community.network.plugins.modules.cnos_command', init_globals=None, run_name='__main__', alter_sys=True)\n File \"/usr/lib/python3.8/runpy.py\", line 207, in run_module\n return _run_module_code(code, init_globals, run_name, mod_spec)\n File \"/usr/lib/python3.8/runpy.py\", line 97, in _run_module_code\n _run_code(code, mod_globals, init_globals,\n File \"/usr/lib/python3.8/runpy.py\", line 87, in _run_code\n exec(code, run_globals)\n File \"/tmp/ansible_community.network.cnos_command_payload_w2zhqf9e/ansible_community.network.cnos_command_payload.zip/ansible_collections/community/network/plugins/modules/cnos_command.py\", line 203, in <module>\n File \"/tmp/ansible_community.network.cnos_command_payload_w2zhqf9e/ansible_community.network.cnos_command_payload.zip/ansible_collections/community/network/plugins/modules/cnos_command.py\", line 173, in main\n File \"/tmp/ansible_community.network.cnos_command_payload_w2zhqf9e/ansible_community.network.cnos_command_payload.zip/ansible_collections/community/network/plugins/module_utils/network/cnos/cnos.py\", line 170, in run_commands\n File \"/tmp/ansible_community.network.cnos_command_payload_w2zhqf9e/ansible_community.network.cnos_command_payload.zip/ansible/module_utils/connection.py\", line 185, in __rpc__\nansible.module_utils.connection.ConnectionError: show vlan id 476\r\nVLAN 476 not found in current VLAN database.\r\nSW109#\n",
"module_stdout": "",
"msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
"rc": 1
}
Files identified in the description:
If these files are incorrect, please update the component name
section of the description or use the !component
bot command.
cc @istaicu @mihaibroc click here for bot help
Hi. After doing some research I found out that this is sort of a design issue. The returned message is treated as an error, and an AnsibleConnectionFailure is raised. Any returned message that contains one of the following keywords will be treated the same way: Error, Bad secret, invalid input, incomplete|ambiguous command, connection timed out, not found, returned error code.
The file in question, where things "break" is network_cli.py, which is not Lenovo specific, but used by the entire network community. I have the following trace, when I used the latest network_cli.py version found at this link: https://github.com/ansible-collections/ansible.netcommon/tree/main/plugins/connection. With an older version, the situation is the same, but the trace is slightly different, and the connection failure is thrown in the _find_prompt function.
File "/usr/lib/python3.6/site-packages/ansible/utils/jsonrpc.py", line 45, in handle_request
result = rpc_method(*args, **kwargs)
File "/usr/lib/python3.6/site-packages/ansible/plugins/cliconf/cnos.py", line 114, in get
return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, newline=newline, check_all=check_all)
File "/usr/lib/python3.6/site-packages/ansible/plugins/cliconf/__init__.py", line 127, in send_command
resp = self._connection.send(**kwargs)
File "/usr/lib/python3.6/site-packages/ansible/plugins/connection/network_cli.py", line 336, in wrapped
return func(self, *args, **kwargs)
File "/usr/lib/python3.6/site-packages/ansible/plugins/connection/network_cli.py", line 995, in send
command, prompt, answer, newline, prompt_retry_check, check_all
File "/usr/lib/python3.6/site-packages/ansible/plugins/connection/network_cli.py", line 951, in receive
check_all,
File "/usr/lib/python3.6/site-packages/ansible/plugins/connection/network_cli.py", line 809, in receive_paramiko
raise AnsibleConnectionFailure(errored_response)
ansible.errors.AnsibleConnectionFailure: show vlan id 150^M
VLAN 150 not found in current VLAN database.^M
MA_14#
I'm adding @Qalthos to this conversation, since I've seen that he is the one that last modified the netcommon community lately.
Hi @Qalthos, can you please advice on this issue?
Thanks, Ioana
cc @RRNegru @mihdm click here for bot help
As @istaicu mentioned, in the latest snapshot of network_cli.py from ansible.netcommon, the exception is raised in Connection.receive_paramiko()
:
if self._find_error(window):
# We can't exit here, as we need to drain the buffer in case
# the error isn't fatal, and will be using the buffer again
errored_response = window
if self._find_prompt(window):
if errored_response:
raise AnsibleConnectionFailure(errored_response)
The command output is checked for a list of error patterns by calling _find_error()
and, if there is a match, this is signaled in errored_response
after which an exception will be raised when the prompt will be detected (with _find_prompt()
)
The error patterns that are being checked are found in https://github.com/ansible-collections/community.network/blob/main/plugins/terminal/cnos.py
terminal_stderr_re = [
re.compile(br"% ?Error"),
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.compile(br"'[^']' +returned error code: ?\d+"),
]
In our case, there is a match of 'not found'
in the output of the show command (VLAN 476 not found in current VLAN database
).
So this would be considered normal behavior as long as 'not found' is being treated as an error in the output of any show command.
Probably some solutions for this issue could be
- remove the
'not found'
pattern from the above list (but this could break other Ansible playbooks where this is considered an error) - change the output of the
show vlan
command (highly unlikely since the Lenovo support for CNOS switches is now in maintenance mode)
Considering the above I would suggest that this issue to be closed since it doesn't seem to exist a safe fix for this corner case.