ansible / ansible

Ansible is a radically simple IT automation platform that makes your applications and systems easier to deploy and maintain. Automate everything from code deployment to network configuration to cloud management, in a language that approaches plain English, using SSH, with no agents to install on remote systems. https://docs.ansible.com.
https://www.ansible.com/
GNU General Public License v3.0
63.02k stars 23.92k forks source link

ios_config doesn't work, feeds garbage data to router - ios_command works with same data #26140

Closed crazzy closed 6 years ago

crazzy commented 7 years ago
ISSUE TYPE
COMPONENT NAME
ANSIBLE VERSION
ansible 2.3.1.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = Default w/o overrides
  python version = 2.7.12 (default, Nov 19 2016, 06:48:10) [GCC 5.4.0 20160609]
CONFIGURATION

Needed these for the module to even connect to the router:

[paramiko_connection]
record_host_keys=False
pty=False
look_for_keys = False
host_key_auto_add = True
[ssh_connection]
ssh_args =
OS / ENVIRONMENT

Working on a fresh Ubuntu 16.04 trying to use ansible to manage a Cisco C6880-X running c6880x-adventerprisek9-mz.SPA.152-1.SY.bin

SUMMARY

The problem is that ios_config seems to be broken and insert garbage characters or something else that makes the commands not run properly on the router. I am certain it's a bug in ios_config as I have tested the same commands (plus the conf t) using ios_command module, although I had to remove the check for lines beginning with conf in that module.

STEPS TO REPRODUCE

I have a very small playbook, which uses bgpq3 to generate cisco-style prefix-lists based upon data in the RIPE database. I have verified that many times, and the commands are ok, those are not the problem.


- name: "Prefix-lists for IPv4 advertised routes"
  local_action: shell "{{role_path}}/helpers/bgpq3-wrapper.sh" -m 24 -4 -S "{{pfx_source}}" -l "{{item.name}}-out" "{{bgpq_format | default("-P")}}" "{{ pfx_objects_v4 }}"
  register: v4_adv_pfx
  with_flattened:
    - "{{transits}}"
    - "{{peering_ix | default([])}}"
  tags:
    - pfx_adv_v4
  check_mode: no

- set_fact:
    list_of_lines: {}
  tags:
    - pfx_adv_v4

- set_fact:
    list_of_lines: "{{ list_of_lines }} + [ '{{ item.1 }}' ]"
  with_subelements:
    - "{{ v4_adv_pfx.results }}"
    - stdout_lines
  tags:
    - pfx_adv_v4

- name: "Applying configuration"
  ios_config:
    provider: "{{ cli }}"
    match: none
    lines: "{{ list_of_lines }}"
  tags:
    - pfx_adv_v4

So right before the last task in the playbook you will have a list of commands looking like this:

no ip prefix-list isp1-out
ip prefix-list isp1-out seq 5 permit 1.0.0.0/24
ip prefix-list isp1-out seq 10 permit 2.0.0.0/23
no ip prefix-list isp2-out
ip prefix-list isp2-out seq 5 permit 1.0.0.0/24
ip prefix-list isp2-out seq 10 permit 2.0.0.0/23

That is correct and working commands that can be pasted right into any Cisco box. However it's not working through ios_config module.

EXPECTED RESULTS

I expected the commands to be run successfully and an OK being reported back.

ACTUAL RESULTS
  1 ---
fatal: [router]: FAILED! => {"changed": false, "command": "{} + [ 'no ip prefix-list isp1-out' ] + [ 'ip prefix-list isp1-out permit 1.0.0.0/24' ] + [ 'ip prefix-list isp1-out permit 2.0.0.0/23' ] + [ 'no ip prefix-list isp2-out' ] + [ 'ip prefix-list isp2-out permit 1.0.0.0/24' ] + [ 'ip prefix-list isp2-out permit 2.0.0.0/23' ]", "failed": true, "msg": "\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\r\n                 ^\r\n% Invalid input detected at '^' marker.\r\n\r\nrouter(config)#", "rc": 1}```

You can switch module to ios_command and just prepend the lines with "conf t" and append "exit" and "wr" and it will work flawlessly. I do however not want to have to do my own edits of modules to make them work (as I have to remove the check for conf t from ios_command, why is that even there?).

ansibot commented 7 years ago

cc @privateip @rcarrillocruz click here for bot help

ganeshrn commented 7 years ago

@crazzy

After I replace list_of_lines in playbook with config commands as below, it runs without any issue.

  tasks:
  - name: Configure NTP
    ios_config:
      lines:
      - no ip prefix-list isp1-out
      - ip prefix-list isp1-out seq 5 permit 1.0.0.0/24
      - ip prefix-list isp1-out seq 10 permit 2.0.0.0/23
      - no ip prefix-list isp2-out
      - ip prefix-list isp2-out seq 5 permit 1.0.0.0/24
      - ip prefix-list isp2-out seq 10 permit 2.0.0.0/23

Hence I suspect logic to create list_of_lines is not correct. Can you please verify this by printing the list_of_lines variable in your playbook before running ios_config task using debug.

- debug:
    name: display list of line
    var: list_of_lines
ganeshrn commented 7 years ago

needs_info

ansibot commented 7 years ago

cc @Qalthos @gundalow @trishnaguha click here for bot help

ansibot commented 7 years ago

cc @kedarX click here for bot help

gundalow commented 6 years ago

Closing as we believe this is fixed. If this isn't the case please reopen this issue.