Handling prompt validation with netcommon.cli

Hi !

I’m currently working (or fighting) with some Aruba switches and Ansible. Aruba Ansible module is quite poor unfortunately not high quality as Cisco’s…anyway I have to deal with that :slight_smile:

I’m working on a playbook and tasks to enable enable then configure snmpv3 on those switches.

To better understand my issue, first I must explain how it’s configured manually :

  1. go to conf t mode
  2. launch snmpv3 enable command
  3. It starts a workflow (yes, you can’t configure it another way…) that asks authentication password + privacy password. Those 2 prompts needs to be validated with Enter key.
  4. Then another 2 prompts “Would you like to create a user that uses SHA? [y/n]” & “Would you like to restrict SNMPv1 and SNMPv2c messages to have read only
    access (you can set this later by the command ‘snmpv3 restricted-access’)? [y/n]” where I press ‘n’ EXCEPT, pressing a key automatically validate your choice (so no need to enter) and here’s my pain.
aruba-switch# conf t
aruba-switch(config)# snmpv3 enable
SNMPv3 Initialization process.
Creating user 'initial'
Authentication Protocol: MD5
Enter authentication password: ********* <= This need keyboard input + enter validation
Privacy protocol is DES
Enter privacy password: ********* <= This need keyboard input + enter validation
User 'initial' has been created
Would you like to create a user that uses SHA? [y/n] n <= This is "automatically" validated when y/n is pressed
User creation is done. SNMPv3 is now functional.
Would you like to restrict SNMPv1 and SNMPv2c messages to have read only
access (you can set this later by the command 'snmpv3 restricted-access')? [y/n] n <= This is "automatically" validated when y/n is pressed
aruba-switch(config)#

From an Ansible perspective, here’s how I translate all of that :

---
- name: enable-snmpv3-aruba-switch
  hosts: all
  become: true
  become_method: enable

  vars:
    ansible_connection: ansible.netcommon.network_cli
    ansible_network_os: arubanetworks.aos_switch.arubaoss
    ansible_user: my_account
    ansible_password: my_password

  tasks:
  - name: Enable SNMPv3
    ansible.netcommon.cli_command:
      command: '{{ item }}'
      check_all: True
      prompt:
        - "Enter authentication password:"
        - "Enter privacy password:"
        - "Would you like to create a user that uses SHA? [y/n]"
        - "Would you like to restrict SNMPv1 and SNMPv2c messages to have read only access (you can set this later by the command 'snmpv3 restricted-access')? [y/n]"
      answer:
        - "123456789"
        - "123456789"
        - "n"
        - "n"
    loop:
    - configure
    - snmpv3 enable

Here’s my issue :
On the prompt parameters, the first 2 prompts are alright, but it seems the 2 last “Would you like to…” aren’t validated, I mean, ansible doesn’t receive any return from this task and the task fails due to a timeout (i tried 30,60 and 120sec timeout to be sure )

It’s seems very tricky but is there any possibility to say I want my prompt answers to press/not press enter ?

Thanks a lot for reading
Gael

[EDIT]
Here’s a sample of debug trace where prompt command are sent:

2024-03-07 11:51:12,658 p=321809 u=si n=ansible | send command: b'configure terminal\r'
2024-03-07 11:51:12,658 p=321809 u=si n=ansible | command: b'configure terminal'
2024-03-07 11:51:12,658 p=321809 u=si n=ansible | response-1: b'\x1b[24;15Hconfigure \x1b[24;15H\x1b[?25h\x1b[24;25H\x1b[24;25Hterminal\x1b[24;25H\x1b[?25h\x1b[24;33H\x1b[1;0H\x1b[1M\x1b[24;1H\x1b[1L\x1b[24;33H\x1b[24;1H\x1b[2K\x1b[24;1H\x1b[?25h\x1b[24;1H\x1b[1;24r\x1b[24;1H\x1b[1;24r\x1b[24;1H\x1b[24;1H\x1b[2K\x1b[24;1H\x1b[?25h\x1b[24;1H\x1b[24;1Hmy_switch(config)# \x1b[24;1H\x1b[24;23H\x1b[24;1H\x1b[?25h\x1b[24;23H'
2024-03-07 11:51:12,660 p=321809 u=si n=ansible | matched cli prompt 'b'terminalmy_switch(config)# '' with regex 'b'[\\r\\n]?[\\w]*\\(.+\\)\\s*[\\^\\*]?(?:\\[.+\\])? ?#(?:\\s*)$'' from response 'b'configure terminalmy_switch(config)# ''
2024-03-07 11:51:12,660 p=321818 u=si n=ansible | jsonrpc request: b'{"jsonrpc": "2.0", "method": "get", "id": "0f6a88ca-13bf-4e98-aee6-23194c7d1cc5", "params": [[], {"command": "snmpv3 enable", "check_all": true, "prompt": ["Enter authentication password*", "Enter privacy password*", "Would you like to create a user*", "Would you like to restrict SNMPv1 and SNMPv2c messages to have read only access*"], "answer": ["123456789", "123456789", "n", "n"], "newline": true, "sendonly": false}]}'
2024-03-07 11:51:42,660 p=321818 u=si n=ansible | command timeout triggered, timeout value is 30 secs.
See the timeout setting options in the Network Debug and Troubleshooting Guide.

Short Answer

Change your prompts to this:

  - name: Enable SNMPv3
    ansible.netcommon.cli_command:
      command: '{{ item }}'
      check_all: True
      prompt:
        - "Enter authentication password:"
        - "Enter privacy password:"
        - "Would you like to create a user that uses SHA\? \[y/n\]"
        - "Would you like to restrict SNMPv1 and SNMPv2c messages to have read only access \(you can set this later by the command 'snmpv3 restricted-access'\)\? \[y/n\]"
      answer:
        - "123456789"
        - "123456789"
        - "n"
        - "n"
    loop:
    - configure
    - snmpv3 enable

Slightly Longer Answer

I’m looking at the ansible.netcommon.cli_command documentation. The prompt parameter says:

A single regex pattern or a sequence of patterns to evaluate the expected prompt from command.

The key takeaway is that the supplied value is a regex. This means that you need to escape you special characters with a backslash "" because they mean something other than their literal string value.

i.e. [y/n] means that you want the prompt to look for “y”, “/”, or “n” in the position that [y/n] is found in your regex.

For more details on regex, here’s a nice Regex Cheat Sheet and a really nice Online regex tester. The second link is great for trial and error learning.

2 Likes

Hi, thanks for quick answer ! actually the escape character isn’t processed if prompt is between quotes.

Without quotes it’s the same error as I had earlier (everything fails due to timeout).

I’ll have a look at the regex part in details and made some test , but actually it seems that ansible interpreter isn’t able to receive answer from prompt (like some question needs to be confirm with Enter, and some not at all)

For instance if you need to :

  • write a command then press Enter for confirmation => ansible instruction behaviour is ok.
  • write a command then press a key (ex: y/n) that auto-confirm when pressed => ansible behaviour is not ok/not able to retrieve result.

[EDIT]
Tried with a more general regex like :
Would you like to create a user that uses SHA.* but result is the same

Does Aruba CLI act like Cisco CLI (I don’t know Aruba stuff specifically)?

What mean is, if you just copied and pasted all those command lines at one time, would it work on the Aruba?

For instance, if the prompt was interactive (no enter key after confirming the [y/n]) I would be able to copy/paste all of the commands to the Cisco device like below and it would work.

conf t
snmpv3 enable
<auth_pass>
<priv_pass>
nn

The only real difference here is that “nn” instead of “nENTERn” because the prompt is interactive and isn’t expecting ENTER.

If that does work similar to Cisco, what if you try this:

  - name: Enable SNMPv3
    ansible.netcommon.cli_command:
      command: "config\nsnmpv3 enable\n{{ auth_pass }}\n{{ priv_pass }}\nnn\n"

Or if you don’t like putting it all one line:

  - name: Enable SNMPv3
    ansible.netcommon.cli_command:
      command: |
        config
        snmpv3 enable
        {{ auth_pass }}
        {{ priv_pass }}
        nn

It’s a very hack way to do it, but if it works it could get you in the right direction for a better solution.

2 Likes

Really good idea ! Too simple to think about it like to copy paste manually.

Or if you don’t like putting it all one line:

  - name: Enable SNMPv3
    ansible.netcommon.cli_command:
      command: |
        config
        snmpv3 enable
        {{ auth_pass }}
        {{ priv_pass }}
        nn

It’s a very hack way to do it, but if it works it could get you in the right direction for a better solution.

After double testing, those solutions are working great, that’s how I’ll handle this I think (no choice ! )

Thanks very very much for your help and explanations !

1 Like

Don’t forget to mark my answer as the solution if it works. It will help others who search for something similar find your answer, and more importantly I get that sweet sweet social cred. :wink:

1 Like

Sometimes basic is the best :smiley:
Yes done, I forgot to tick it , thanks thanks a lot :slight_smile:

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.