community.network icon indicating copy to clipboard operation
community.network copied to clipboard

CNOS - show vlan id <vlan> gives error if no vlan found

Open Superset1986 opened this issue 2 years ago • 5 comments

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
}

Superset1986 avatar Aug 04 '21 14:08 Superset1986

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.

click here for bot help

ansibullbot avatar Nov 10 '21 06:11 ansibullbot

cc @istaicu @mihaibroc click here for bot help

ansibullbot avatar Nov 17 '21 19:11 ansibullbot

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

istaicu avatar Dec 13 '21 09:12 istaicu

cc @RRNegru @mihdm click here for bot help

ansibullbot avatar Jan 15 '22 00:01 ansibullbot

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.

mihdm avatar Apr 06 '22 11:04 mihdm