ansible-collections / cisco.ios

Ansible Network Collection for Cisco IOS
GNU General Public License v3.0
294 stars 171 forks source link

Multi-line command not supported #395

Open Booooooosh opened 3 years ago

Booooooosh commented 3 years ago
SUMMARY

We are performing a full config push using ios_config module. It seems like the module still doesn't like multi-line banner command. The banner motd command can be executed only when it's in one line. There are quite a few similar issues from years ago but it seems that this bug still exists.

ISSUE TYPE
COMPONENT NAME

ios_config

ANSIBLE VERSION
ansible 2.10.5
OS / ENVIRONMENT

Cisco IOS XE Software, Version 16.05.01a

STEPS TO REPRODUCE
---
- name: apply_config
  hosts: all
  connection: network_cli
  gather_facts: no

  vars:
    ansible_become: false
    ansible_network_os: ios
    ansible_user: my-user

  tasks:
  - name: ios_config
    cisco.ios.ios_config:
      match: none

      src: banner_config.txt
      multiline_delimiter: "\n"

banner_config.txt

banner motd \x03
This is obviously
a multi-line
banner
\x03
EXPECTED RESULTS

Successful deployment and device banner updated.

ACTUAL RESULTS
fatal: [12.196.112.164]: FAILED! => {
    "changed": false,
    "module_stderr": "Traceback (most recent call last):\n  File \"/Users/tangbosc/.ansible/tmp/ansible-local-34107uplvirq/ansible-tmp-1629217664.631277-3414-176772367337582/AnsiballZ_ios_config.py\", line 102, in <module>\n    _ansiballz_main()\n  File \"/Users/tangbosc/.ansible/tmp/ansible-local-34107uplvirq/ansible-tmp-1629217664.631277-3414-176772367337582/AnsiballZ_ios_config.py\", line 94, in _ansiballz_main\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n  File \"/Users/tangbosc/.ansible/tmp/ansible-local-34107uplvirq/ansible-tmp-1629217664.631277-3414-176772
  1 banner motd \x03 ar367337582/AnsiballZ_ios_config.py\", line 40, in invoke_module\n    runpy.run_module(mod_name='ansible_collections.cisco.ios.plugins.modules.ios_config', init_globals=None, run_name='__main__', alter_sys=True)\n  File \"/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.7/lib/python3.7/runpy.py\", line 205, in run_module\n    return _run_module_code(code, init_globals, run_name, mod_spec)\n  File \"/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.7/lib/python3.7/runpy.py\", line 96, in _run_module_code\n    mod_name, mod_spec, pkg_name, script_name)\n  File \"/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.7/lib/python3.7/runpy.py\", line 85, in _run_code\n    exec(code, run_globals)\n  File \"/var/folders/m_/sbrwgwwj4xq7fyx6050zs4rhjb5g3j/T/ansible_cisco.ios.ios_config_payload_zp3nobru/ansible_cisco.ios.ios_config_payload.zip/ansible_collections/cisco/ios/plugins/modules/ios_config.py\", line 577, in <module>\n  File \"/var/folders/m_/sbrwgwwj4xq7fyx6050zs4rhjb5g3j/T/ansible_cisco.ios.ios_config_payload_zp3nobru/ansible_cisco.ios.ios_config_payload.zip/ansible_collections/cisco/ios/plugins/modules/ios_config.py\", line 502, in main\n  File \"/var/folders/m_/sbrwgwwj4xq7fyx6050zs4rhjb5g3j/T/ansible_cisco.ios.ios_config_payload_zp3nobru/ansible_cisco.ios.ios_config_payload.zip/ansible_collections/cisco/ios/plugins/modules/ios_config.py\", line 376, in edit_config_or_macro\n  File \"/var/folders/m_/sbrwgwwj4xq7fyx6050zs4rhjb5g3j/T/ansible_cisco.ios.ios_config_payload_zp3nobru/ansible_cisco.ios.ios_config_payload.zip/ansible/module_utils/connection.py\", line 195, in __rpc__\nansible.module_utils.connection.ConnectionError: timeout value 300 seconds reached while trying to send command: b'banner motd \\\\x03'\n",

Basically, the device is expecting the multi-line banner however the module seems not to be able to handle the prompt and hence resulting a timeout.

That being said, if I change the banner_config.txt to

banner motd \x03 This is obviously a multi-line banner \x03

It completed without issue and device banner is updated.

Booooooosh commented 3 years ago

I know that there is a ios_banner module that specifically solve for multi-line banner. However, it will require us to parse the input config file, isolate the banner part and feed it into two separate module. It will be really convenient for us to be able to push the entire config using just ios_config module.

Thank you for your help!

KB-perByte commented 3 years ago

Hey, @Booooooosh that is the intended behavior of the config module when you are pushing an input from an src. the multiline_delimiter is there to specify the start and end of a multiline value not to be used as a separator for multiline, Even then you should be able to use the ios_banner module. Let us know if that helps.

Booooooosh commented 3 years ago

I previously also tried the following

---
- name: apply_config
  hosts: all
  connection: network_cli
  gather_facts: no

  vars:
    ansible_become: false
    ansible_network_os: ios
    ansible_user: my-user

  tasks:
  - name: ios_config
    cisco.ios.ios_config:
      match: none

      src: banner_config.txt
      multiline_delimiter: "@"

with banner_config set to

banner motd @
This is obviously
a multi-line
banner
@

with no luck either. I'm suspecting whether multiline banner command is supported within ios_config module or not.

That being said, yes, we are able to do the same thing using ios_banner module. However, that will require us to modify the config file (removing the banner portion from the original config) and that's something we want to avoid. So it will be great if ios_config module supports multi-line banner by default.

Booooooosh commented 3 years ago

It seems that when we extract banner form the candidate / src config we don't take into account the user defined delimiter and defaults to a \^C. Code. This can be the root cause where the module isn't parsing mult-line banner correctly?

Booooooosh commented 3 years ago

Also the regex is banner <type> \^C(.+?)(?=\^C)

While it matches banner motd ^C message ^C

It doesn't match multi-line version since . doesn't include \n by default.

KB-perByte commented 3 years ago

Hi @Booooooosh That is right, we can consider the fix and check if it passes all the test cases in CI, you can raise a PR for the same, or I can push the required changes. Thanks for looking into it.

Thorbijoern commented 3 years ago

hi, i have the same issue. using ios_banner as workaround would be fine, but we also want to deploy other things like macros and aaa authentication fail-message using ansible. there are no modules for that, so we would need the multiline functionality of ios_config. Is someone allready working on this issue?

KB-perByte commented 3 years ago

Hey, @Thorbijoern I am looking at the issue, can you share some more detail or open an issue explaining the same. Thanks

Thorbijoern commented 3 years ago

disclaimer: i'm only a dev bulding some scripts and playbooks to automate config deployment to switches and other network hardware in my company, i don't fully know how cisco devices or cisco ios works.

while testing i stumbled uppon the problem that different config commands don't work with the ios_config module by default because they require multiline input at the shell and use a different prompt for that, i then found out about the multiline_delimiter param and tried it but had no luck in getting it to work, like @Booooooosh. for the cisco ios config options banner exec and banner login i could just use the ios_banner module, it would work and only make the maintenance of the playbooks/roles slightly more work. But we also want to set aaa authentication fail-message and macros on the switches using ansible, for example:

aaa authentication fail-message ^

UNAUTHORIZED ACCESS!

^

and simply some macros we want to configure making it a bit simpler for our networking department to manually check things on the switches. I don't know if there are more ios commands which could require multiline inputs, but we would like macros and aaa authentication fail-message to also work with multiline inputs from a playbook or a (partial) config file handed to ios_config (using the src param).

Thanks for looking into the problem

Thorbijoern commented 3 years ago

i'm not a regex wizzard, but the regex which was allready quoted by @Booooooosh supports multiline like this: banner motd @([\s\S]+?)(?=@) the set [\s\S] matches every character and +? matches between one to unlimeted chars of that set but does lazy matching to match as little as possible. it would only be needed to drop in the vars for the banner type and the chosen delimiter.

i don't quite know which other parts of the module would need changes to fully support multiline arguments and configs, because the module seems to be a wrapper onto the cli of the switch and these multiline config parameters come with a different prompt at the terminal. as example:

foobar(config)#banner login @
Enter TEXT message.  End with the character '@'.
test banner, only for test

@
foobar(config)#

but i wasn't able to test the regex yet inside the module.