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

Mikrotik RouterOS Platform Unable to Respond to Command Line Prompts

Open archhorde opened this issue 4 years ago • 4 comments
trafficstars

SUMMARY

Initially opened this on the master ansible page under issue #75305, but was told to post here instead. I am trying to make configuration changes on RouterOS that require you to respond to a yes or no prompt, but there does not seem to be a way to do this. I found the below link and tried it, however I am getting an error when using it with RouterOS (probably doesnt exist in the module).

https://docs.ansible.com/ansible/latest/network/user_guide/network_working_with_command_output.html

Is this just a feature that does not exist and would need to be developed, or am I doing something wrong?

ISSUE TYPE
  • Bug Report
COMPONENT NAME

routeros module

ANSIBLE VERSION

  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/netblazr/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/netblazr/.local/lib/python3.8/site-packages/ansible
  ansible collection location = /home/netblazr/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/netblazr/.local/bin/ansible
  python version = 3.8.10 (default, Jun  2 2021, 10:49:15) [GCC 9.4.0]
  jinja version = 2.10.1
  libyaml = True

COLLECTION VERSION

/.ansible/collections/ansible_collections
Collection         Version
------------------ -------
community.routeros 1.2.0


CONFIGURATION


DEFAULT_LOG_PATH(/etc/ansible/ansible.cfg) = /etc/ansible/ansible.log
DEFAULT_REMOTE_PORT(/etc/ansible/ansible.cfg) = 7022
DEFAULT_REMOTE_USER(/etc/ansible/ansible.cfg) = admin
DEFAULT_TIMEOUT(/etc/ansible/ansible.cfg) = 1000
HOST_KEY_CHECKING(/etc/ansible/ansible.cfg) = False

OS / ENVIRONMENT

Ubuntu 20.04

STEPS TO REPRODUCE

Command that I run is here: ansible-playbook mipse_upgrade.yml -k -i test_host

Host file is below:
[all:vars]
ansible_user=####
ansible_port=####
ansible_network_os=routeros

SW1 ansible_host=10.28.134.3
SW2 ansible_host=10.28.134.4
SW3 ansible_host=10.28.139.2
SW4 ansible_host=10.28.139.3
SW5 ansible_host=10.28.143.2
SW6 ansible_host=10.28.143.3

Playbook is below:

    hosts: all
    connection: network_cli
    gather_facts: false
    vars:
    upgrade: 6.47.10

    tasks:

        name: Get OS Version
        routeros_command:
        commands: /system routerboard print
        register: output

        name: Get Current Firmware Line
        set_fact:
        current: "{{ item | replace('current-firmware: ', '') | trim }}"
        when: "'current-firmware:' in item"
        loop: "{{ output.stdout_lines[0] }}"

        name: Download new firmware if needed
        routeros_command:
        commands: /tool fetch address=10.10.72.2 src-path=/srv/ftp/routeros-mipsbe-6.47.10.npk user=#### password=#### dst-path=routeros-mipsbe-6.47.10.npk port=21 mode=ftp
        when: current is version_compare(upgrade, '<')

        name: Upgrade Firmware
        routeros_command:
        commands:
        - /system routerboard upgrade
        prompt:
        - "Do you really want to upgrade firmware? [y/n]"
        answer:
        - 'y'
        when: current is version_compare(upgrade, '<')

        name: Reboot the router
        routeros_command:
        commands: ":execute {/system reboot;delay 1;quit}"
        when: current is version_compare(upgrade, '<')


EXPECTED RESULTS

Expected ansible to respond to the prompt Do you really want to upgrade firmware? [y/n] with a "y" causing the router to upgrade. But this seems to be unsupported by RouterOS.

ACTUAL RESULTS

SSH password:

PLAY [all] ****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************

TASK [Get OS Version] *****************************************************************************************************************************************************************************************************************************************************************************************************************************************************
[DEPRECATION WARNING]: Distribution Ubuntu 20.04 on host SW3 should use /usr/bin/python3, but is using /usr/bin/python for backward compatibility with prior Ansible releases. A future Ansible release will default to using the discovered platform python for this host. See https://docs.ansible.com/ansible/2.11/reference_appendices/interpreter_discovery.html for
more information. This feature will be removed in version 2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
ok: [SW3]
[DEPRECATION WARNING]: Distribution Ubuntu 20.04 on host SW1 should use /usr/bin/python3, but is using /usr/bin/python for backward compatibility with prior Ansible releases. A future Ansible release will default to using the discovered platform python for this host. See https://docs.ansible.com/ansible/2.11/reference_appendices/interpreter_discovery.html for
more information. This feature will be removed in version 2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
ok: [SW1]
[DEPRECATION WARNING]: Distribution Ubuntu 20.04 on host SW2 should use /usr/bin/python3, but is using /usr/bin/python for backward compatibility with prior Ansible releases. A future Ansible release will default to using the discovered platform python for this host. See https://docs.ansible.com/ansible/2.11/reference_appendices/interpreter_discovery.html for
more information. This feature will be removed in version 2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
ok: [SW2]
[DEPRECATION WARNING]: Distribution Ubuntu 20.04 on host SW5 should use /usr/bin/python3, but is using /usr/bin/python for backward compatibility with prior Ansible releases. A future Ansible release will default to using the discovered platform python for this host. See https://docs.ansible.com/ansible/2.11/reference_appendices/interpreter_discovery.html for
more information. This feature will be removed in version 2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
ok: [SW5]
[DEPRECATION WARNING]: Distribution Ubuntu 20.04 on host SW4 should use /usr/bin/python3, but is using /usr/bin/python for backward compatibility with prior Ansible releases. A future Ansible release will default to using the discovered platform python for this host. See https://docs.ansible.com/ansible/2.11/reference_appendices/interpreter_discovery.html for
more information. This feature will be removed in version 2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
ok: [SW4]
[DEPRECATION WARNING]: Distribution Ubuntu 20.04 on host SW6 should use /usr/bin/python3, but is using /usr/bin/python for backward compatibility with prior Ansible releases. A future Ansible release will default to using the discovered platform python for this host. See https://docs.ansible.com/ansible/2.11/reference_appendices/interpreter_discovery.html for
more information. This feature will be removed in version 2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
ok: [SW6]

TASK [Get Current Firmware Line] ******************************************************************************************************************************************************************************************************************************************************************************************************************************************
skipping: [SW1] => (item=routerboard: yes)
skipping: [SW1] => (item=             model: CRS125-24G-1S)
skipping: [SW1] => (item=     serial-number: 7381067E1946)
skipping: [SW1] => (item=     firmware-type: ar9344)
skipping: [SW1] => (item=  factory-firmware: 3.33)
skipping: [SW2] => (item=routerboard: yes)
skipping: [SW2] => (item=             model: CRS125-24G-1S)
skipping: [SW2] => (item=     serial-number: 738106DEC18F)
skipping: [SW2] => (item=     firmware-type: ar9344)
skipping: [SW2] => (item=  factory-firmware: 3.33)
skipping: [SW3] => (item=routerboard: yes)
skipping: [SW3] => (item=             model: CRS125-24G-1S)
skipping: [SW3] => (item=     serial-number: 738106FA5F2A)
skipping: [SW4] => (item=routerboard: yes)
skipping: [SW4] => (item=             model: CRS125-24G-1S)
skipping: [SW4] => (item=     serial-number: 738106BE8983)
skipping: [SW4] => (item=     firmware-type: ar9344)
skipping: [SW4] => (item=  factory-firmware: 3.33)
skipping: [SW3] => (item=     firmware-type: ar9344)
skipping: [SW5] => (item=routerboard: yes)
skipping: [SW3] => (item=  factory-firmware: 3.33)
skipping: [SW5] => (item=             model: CRS125-24G-1S)
skipping: [SW5] => (item=     serial-number: 738106160FA2)
skipping: [SW5] => (item=     firmware-type: ar9344)
skipping: [SW5] => (item=  factory-firmware: 3.33)
ok: [SW3] => (item=  current-firmware: 6.45.9)
skipping: [SW3] => (item=  upgrade-firmware: 6.47.10)
ok: [SW4] => (item=  current-firmware: 6.45.9)
skipping: [SW4] => (item=  upgrade-firmware: 6.47.10)
skipping: [SW6] => (item=routerboard: yes)
skipping: [SW6] => (item=             model: CRS125-24G-1S)
skipping: [SW6] => (item=     serial-number: 738106E28184)
skipping: [SW6] => (item=     firmware-type: ar9344)
skipping: [SW6] => (item=  factory-firmware: 3.33)
ok: [SW1] => (item=  current-firmware: 6.47.10)
skipping: [SW1] => (item=  upgrade-firmware: 6.47.10)
ok: [SW2] => (item=  current-firmware: 6.45.9)
skipping: [SW2] => (item=  upgrade-firmware: 6.47.10)
ok: [SW5] => (item=  current-firmware: 6.45.9)
skipping: [SW5] => (item=  upgrade-firmware: 6.47.10)
ok: [SW6] => (item=  current-firmware: 6.45.9)
skipping: [SW6] => (item=  upgrade-firmware: 6.47.10)

TASK [Download new firmware if needed] ************************************************************************************************************************************************************************************************************************************************************************************************************************************
skipping: [SW1]
ok: [SW3]
ok: [SW6]
ok: [SW4]
ok: [SW2]
ok: [SW5]

TASK [Upgrade Firmware] ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************
skipping: [SW1]
fatal: [SW3]: FAILED! => {"changed": false, "msg": "Unsupported parameters for (routeros_command) module: answer, prompt. Supported parameters include: retries, commands, interval, wait_for, match."}
fatal: [SW2]: FAILED! => {"changed": false, "msg": "Unsupported parameters for (routeros_command) module: answer, prompt. Supported parameters include: retries, commands, interval, wait_for, match."}
fatal: [SW4]: FAILED! => {"changed": false, "msg": "Unsupported parameters for (routeros_command) module: answer, prompt. Supported parameters include: retries, commands, interval, wait_for, match."}
fatal: [SW5]: FAILED! => {"changed": false, "msg": "Unsupported parameters for (routeros_command) module: answer, prompt. Supported parameters include: retries, commands, interval, wait_for, match."}
fatal: [SW6]: FAILED! => {"changed": false, "msg": "Unsupported parameters for (routeros_command) module: answer, prompt. Supported parameters include: retries, commands, interval, wait_for, match."}

TASK [Reboot the router] **************************************************************************************************************************************************************************************************************************************************************************************************************************************************
skipping: [SW1]

PLAY RECAP ****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
SW1                        : ok=2    changed=0    unreachable=0    failed=0    skipped=3    rescued=0    ignored=0
SW2                        : ok=3    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0
SW3                        : ok=3    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0
SW4                        : ok=3    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0
SW5                        : ok=3    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0
SW6                        : ok=3    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

archhorde avatar Jul 22 '21 16:07 archhorde

You can find the documentation for the community.routeros.command module here: https://docs.ansible.com/ansible/latest/collections/community/routeros/command_module.html

It does not mention any module options named prompt or answer. So I guess this is a feature which does not exist yet. Also the networking docs you mentioned (https://docs.ansible.com/ansible/latest/network/user_guide/network_working_with_command_output.html#handling-prompts-in-network-modules) do not say that the RouterOS modules should support this (which would be wrong), only that some network modules do support it.

felixfontein avatar Jul 22 '21 21:07 felixfontein

@archhorde this is not a direct answer to your question but I work around this by setting system routerboard settings set auto-upgrade=yes. This way the firmware follows the upgrades of the OS, which is what MT recommends.

For reference, the full os upgrade role is here. No prompt issues.

---
- name: Assert variables set for os_update
  assert:
    quiet: yes
    that:
      - (os_update_channel=='stable' or os_update_channel=='long-term')
  tags: ['check_vars']

- name: "Set os update channel"
  community.routeros.command:
    commands:
      - :put [/system package update get channel]
      - /system package update set channel={{ os_update_channel }}
  register: update_channel_out
  changed_when: update_channel_out.stdout[0] != os_update_channel

- name: "Set routerboard auto-upgrade if applicable"
  community.routeros.command:
    commands:
      - :if ([/system routerboard get routerboard]) do={/system routerboard settings print}
      - :if ([/system routerboard get routerboard]) do={/system routerboard settings set auto-upgrade=yes}
      - :if ([/system routerboard get routerboard]) do={/system routerboard settings print}
  register: result
  failed_when: result.stdout[1:-1] | join("") != ""
  changed_when: result.stdout[0] != result.stdout[-1]

- name: "Check for new version"
  community.routeros.command:
    commands:
      - /system package update check-for-updates once
      
- pause:
    seconds: 3

- name: "Check if upgrade required"
  community.routeros.command:
    commands:
      - :put [/system package update get status]
      - :put [/system package update get latest-version ]
      - :put [/system package update get installed-version ]
  register: get_status

- name: Fail if router cannot reach upgrade server
  fail:
    msg: The device was unable to reach the update server download.mikrotik.com.
  # ignore_errors: yes
  when: get_status.stdout[0] is search('ERROR')

- set_fact:
    os_version_change_required: "{{ get_status.stdout[0] == 'New version is available' }}"

- debug:
    msg: New version {{ get_status.stdout[1] }} available, installed is {{ get_status.stdout[2] }}
  when: os_version_change_required

- name: Install new firmware if needed and allow_reboot is true 
  when: os_version_change_required and allow_reboot
  block:
    - name: Install and reboot
      community.routeros.command:
        commands:
            - /system package update install
      changed_when: True
    - name: Pause while device is rebooting to avoid failing other roles
      pause:
        seconds: 60

sgrimee avatar Jul 23 '21 09:07 sgrimee

Thank you both for your answers. So responding to prompts is just not implemented yet which is unfortunate, however I was able to get it working by doing the below, after uploading the new firmware file with ftp:

     - ":execute {/system routerboard upgrade;delay 1;quit}"

My routers and switches do not have direct internet access for security reasons, so I cannot use the auto upgrade function that RouterOS has. But this did the trick at least.

It would still be great to be able to respond to prompts for cases that require more than just a simple yes or no response.

archhorde avatar Jul 23 '21 19:07 archhorde

My routers and switches do not have direct internet access for security reasons, so I cannot use the auto upgrade function that RouterOS has. But this did the trick at least.

You're confusing two different things: RouterOS version and firmware/RouterBoard/RouterBOOT version.

RouterOS is updated by placing the appropriate .npk onto the router and rebooting. Its current version is visible in /system packages

The firmware is upgraded by executing /system routerboard upgrade, which will update the firmware to the version of the currently running RouterOS, and again rebooting.

By setting auto-upgrade=yes, this is done automatically as soon as you boot a new version of RouterOS. So the correct way to update everything is:

/system routerboard set auto-upgrade=yes
/system packages update check-for-updates
/system packages update download
/system reboot
[wait for router to come back online with new RouterOS]
/system reboot
[wait for router to come back online with new firmware]

jplitza avatar Oct 18 '21 13:10 jplitza