ansible-collections / ansible.netcommon

Ansible Network Collection for Common Code
GNU General Public License v3.0
143 stars 102 forks source link

command timeout triggered, timeout value is 30 secs failure message using cli_command on dellos10 switch #86

Open Akasurde opened 4 years ago

Akasurde commented 4 years ago

From @srivaa31 on Jul 14, 2020 10:33

SUMMARY

shutdown command on switch interface consistently fails with "command timeout triggered, timeout value is 30 secs" message

ISSUE TYPE
COMPONENT NAME

cli_command module

ANSIBLE VERSION
ansible 2.9.4
  config file = /var/lib/jenkins/workspace/Ansible_QA/Automation/ansible.cfg
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.6/site-packages/ansible
  executable location = /usr/local/bin/ansible
  python version = 3.6.8 (default, Nov 21 2019, 19:31:34) [GCC 8.3.1 20190507 (Red Hat 8.3.1-4)]
CONFIGURATION
DEFAULT_PRIVATE_KEY_FILE(/var/lib/jenkins/workspace/Ansible_QA/Automation/ansible.cfg) = /root/.ssh/id_rsa
DEFAULT_REMOTE_USER(/var/lib/jenkins/workspace/Ansible_QA/Automation/ansible.cfg) = root
DISPLAY_SKIPPED_HOSTS(/var/lib/jenkins/workspace/Ansible_QA/Automation/ansible.cfg) = False
HOST_KEY_CHECKING(/var/lib/jenkins/workspace/Ansible_QA/Automation/ansible.cfg) = False
INTERPRETER_PYTHON(/var/lib/jenkins/workspace/Ansible_QA/Automation/ansible.cfg) = auto
OS / ENVIRONMENT

CentOS Linux release 8.1.1911 (Core)

STEPS TO REPRODUCE

switch_shutdown.yml

---
- name: shutdown same ports on all switches
  debug:
    msg: "Shutdown test case "

- name: Add config mode as first command
  set_fact:
    cli_switch_commands:
      - config

- name: Add commands for each port shutdown
  vars:
    current_port_command: "interface Tengigabitethernet 0/{{ item }}"
  set_fact:
    cli_switch_commands: "{{ cli_switch_commands + [current_port_command, 'shutdown'] }}"
  loop: "{{ shutdown_ports }}"

- name: Send all commands to switch
  debug:
    msg: "{{item}}"
  loop: "{{ cli_switch_commands }}"

- name: sending....
  cli_command:
    command: "{{ item }}"
  loop: "{{ cli_switch_commands }}"
  delegate_to: TOR_A

switch.yml <- playbook file

---
- name: Shutdown ports on TOR switches
  hosts: switches
  gather_facts: false
  roles:
     - switch_test

switch_test is the role file task file is switch_shutdown.yml

Content of hosts file below /etc/ansible/hosts

[switches]
TOR_A ansible_host=100.80.81.248 ansible_user=admin ansible_pass=Raid4us! ansible_connection=network_cli ansible_network_os=dellos10 ansible_become=yes ansible_become_method=enable ansible_command_timeout=30
EXPECTED RESULTS

Successful login to switch and shut down of specified port

ACTUAL RESULTS
failed: [TOR_A -> 100.80.81.248] (item=config) => {"ansible_loop_var": "item", "changed": false, "item": "config", "msg": "command timeout triggered, timeout value is 30 secs.\nSee the timeout setting options in the Network Debug and Troubleshooting Guide."}
failed: [TOR_A -> 100.80.81.248] (item=interface Tengigabitethernet 0/34) => {"ansible_loop_var": "item", "changed": false, "item": "interface Tengigabitethernet 0/34", "msg": "command timeout triggered, timeout value is 30 secs.\nSee the timeout setting options in the Network Debug and Troubleshooting Guide."}
failed: [TOR_A -> 100.80.81.248] (item=shutdown) => {"ansible_loop_var": "item", "changed": false, "item": "shutdown", "msg": "command timeout triggered, timeout value is 30 secs.\nSee the timeout setting options in the Network Debug and Troubleshooting Guide."}

Copied from original issue: ansible/ansible#70633

Qalthos commented 4 years ago

So first of all, cli_command is designed to send single exec mode commands to a device and return the result. To configure a device as you are, you should be using cli_config with something like this:

---
- name: shutdown same ports on all switches
  debug:
    msg: "Shutdown test case"

- name: Send configuration to switch
  cli_config:
    config: |
        "interface Tengigabitethernet 0/{{ item }}"
        shutdown
  loop: "{{ shutdown_ports }}"

Or even better, a template to send the whole thing as a single request.

Your real problem, though, is that you are using delegate_to unnecessarily. You have already specified the host you wish to send the commands to in your inventory by specifying them in the hosts key of your playbook. delegate_to is normally used to pass control off to a proxy host, but this is unsupported for network modules.

srivaa31 commented 4 years ago

Thanks for your response @Qalthos . However , I run into below exception when I use cli_config

TASK [switch_test : Send configuration to switch] ******************************************************************************************************************************************************************************
task path: /var/lib/jenkins/workspace/Ansible_QA/Automation/roles/switch_test/tasks/switch_shutdown.yml:6
The full traceback is:
Traceback (most recent call last):
  File "/root/.ansible/tmp/ansible-local-27251gfwqahn4/ansible-tmp-1594999309.616183-280419117836686/AnsiballZ_cli_config.py", line 102, in <module>
    _ansiballz_main()
  File "/root/.ansible/tmp/ansible-local-27251gfwqahn4/ansible-tmp-1594999309.616183-280419117836686/AnsiballZ_cli_config.py", line 94, in _ansiballz_main
    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)
  File "/root/.ansible/tmp/ansible-local-27251gfwqahn4/ansible-tmp-1594999309.616183-280419117836686/AnsiballZ_cli_config.py", line 40, in invoke_module
    runpy.run_module(mod_name='ansible.modules.network.cli.cli_config', init_globals=None, run_name='__main__', alter_sys=True)
  File "/usr/lib64/python3.6/runpy.py", line 205, in run_module
    return _run_module_code(code, init_globals, run_name, mod_spec)
  File "/usr/lib64/python3.6/runpy.py", line 96, in _run_module_code
    mod_name, mod_spec, pkg_name, script_name)
  File "/usr/lib64/python3.6/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/tmp/ansible_cli_config_payload_y4ee3wgn/ansible_cli_config_payload.zip/ansible/modules/network/cli/cli_config.py", line 400, in <module>
  File "/tmp/ansible_cli_config_payload_y4ee3wgn/ansible_cli_config_payload.zip/ansible/modules/network/cli/cli_config.py", line 366, in main
  File "/tmp/ansible_cli_config_payload_y4ee3wgn/ansible_cli_config_payload.zip/ansible/module_utils/connection.py", line 185, in __rpc__
ansible.module_utils.connection.ConnectionError: q must be exactly 160, 224, or 256 bits long

failed: [TOR_A] (item=34) => {
    "ansible_loop_var": "item",
    "changed": false,
    "item": 34,
    "module_stderr": "Traceback (most recent call last):\n  File \"/root/.ansible/tmp/ansible-local-27251gfwqahn4/ansible-tmp-1594999309.616183-280419117836686/AnsiballZ_cli_config.py\", line 102, in <module>\n    _ansiballz_main()\n  File \"/root/.ansible/tmp/ansible-local-27251gfwqahn4/ansible-tmp-1594999309.616183-280419117836686/AnsiballZ_cli_config.py\", line 94, in _ansiballz_main\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n  File \"/root/.ansible/tmp/ansible-local-27251gfwqahn4/ansible-tmp-1594999309.616183-280419117836686/AnsiballZ_cli_config.py\", line 40, in invoke_module\n    runpy.run_module(mod_name='ansible.modules.network.cli.cli_config', init_globals=None, run_name='__main__', alter_sys=True)\n  File \"/usr/lib64/python3.6/runpy.py\", line 205, in run_module\n    return _run_module_code(code, init_globals, run_name, mod_spec)\n  File \"/usr/lib64/python3.6/runpy.py\", line 96, in _run_module_code\n    mod_name, mod_spec, pkg_name, script_name)\n  File \"/usr/lib64/python3.6/runpy.py\", line 85, in _run_code\n    exec(code, run_globals)\n  File \"/tmp/ansible_cli_config_payload_y4ee3wgn/ansible_cli_config_payload.zip/ansible/modules/network/cli/cli_config.py\", line 400, in <module>\n  File \"/tmp/ansible_cli_config_payload_y4ee3wgn/ansible_cli_config_payload.zip/ansible/modules/network/cli/cli_config.py\", line 366, in main\n  File \"/tmp/ansible_cli_config_payload_y4ee3wgn/ansible_cli_config_payload.zip/ansible/module_utils/connection.py\", line 185, in __rpc__\nansible.module_utils.connection.ConnectionError: q must be exactly 160, 224, or 256 bits long\n",
    "module_stdout": "",
    "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
    "rc": 1
}
srivaa31 commented 4 years ago

If I continue to use cli_command with the same script (after removing delegate_to) the result changes for me as below:

failed: [TOR_A] (item=config) => {"ansible_loop_var": "item", "changed": false, "item": "config", "msg": "q must be exactly 160, 224, or 256 bits long"}
failed: [TOR_A] (item=interface Tengigabitethernet 0/34) => {"ansible_loop_var": "item", "changed": false, "item": "interface Tengigabitethernet 0/34", "msg": "q must be exactly 160, 224, or 256 bits long"}

I fail to comprehend the part : "msg": "q must be exactly 160, 224, or 256 bits long"}

Qalthos commented 4 years ago

So "q must be exactly 160, 224, or 256 bits long" is an internal paramiko issue (or, rather, a cryptography issue that paramiko is letting pass up) relating to parsing DSA keys. This seems particularly suspect given that you're supplying a password and while you have DEFAULT_PRIVATE_KEY_FILE set, it appears to be an RSA key.

Given that you're using a password anyway, the quickest way to avoid that issue is to set ANSIBLE_PARAMIKO_LOOK_FOR_KEYS=False and disable DEFAULT_PRIVATE_KEY_FILE from your configuration to make sure that ansible only authenticates using the supplied password.