ansible-collections / community.routeros

Ansible modules for managing MikroTik RouterOS instances.
https://galaxy.ansible.com/ui/repo/published/community/routeros/
GNU General Public License v3.0
95 stars 44 forks source link

RouterOS Commands Don't Seem to Be Working #61

Open archhorde opened 2 years ago

archhorde commented 2 years ago
SUMMARY

I have tried running a known good old playbook and a newer playbook that do similar things, the tasks say they completed but the commands are not run on the Mikrotik devices. The playbooks are simple, all they do is download a file with ftp and then run the scrip with import. I am able to run the same commands manually on the devices, so it doesn't appear to be an issue there. I also tried putting the individual commands instead of downloading the script but that made difference. The error appears to be ansible splitting up the commands into multiple lines which causes Mikrotik to not know how to proceed but I could be wrong. I have updated everything on the server using apt and rebooted the server with no change.

ISSUE TYPE
COMPONENT NAME

MIkrotik RouterOS

ANSIBLE VERSION
ansible [core 2.11.1]
  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, Sep 28 2021, 16:10:42) [GCC 9.3.0]
  jinja version = 2.10.1
  libyaml = True
COLLECTION VERSION
# /home/user/.ansible/collections/ansible_collections
Collection         Version
------------------ -------
community.routeros 1.2.0

# /usr/lib/python3/dist-packages/ansible_collections
Collection         Version
------------------ -------
community.routeros 1.2.0
CONFIGURATION
DEFAULT_REMOTE_PORT(/etc/ansible/ansible.cfg) = 7022
DEFAULT_TIMEOUT(/etc/ansible/ansible.cfg) = 1000
HOST_KEY_CHECKING(/etc/ansible/ansible.cfg) = False
PERSISTENT_COMMAND_TIMEOUT(/etc/ansible/ansible.cfg) = 60
PERSISTENT_CONNECT_TIMEOUT(/etc/ansible/ansible.cfg) = 60
OS / ENVIRONMENT

Running on Ubuntu 20

STEPS TO REPRODUCE
Here is the playbook. Usernames/passwords have been edited for security.

---
- hosts: all
  connection: network_cli
  gather_facts: false

  tasks:
   - name: Enable DHCP Snooping
     routeros_command:
       commands:
         /tool fetch address=10.10.72.2 src-path=/srv/ftp/enable-dhcp-snooping-crs326.rsc user=xxx password=xxx dst-path=enable-dhcp-snooping-crs326.rsc port=21 mode=ftp
         /import enable-dhcp-snooping-crs326.rsc

I just tested it on one host but here is the host file:

[all:vars]
ansible_user=xxx
ansible_ssh_pass=xxx
ansible_port=7022
ansible_network_os=routeros

[snooptest]

SW1 ansible_host=10.241.0.59
EXPECTED RESULTS

No output from the playbook but the devices should be changed. The contents of the Mikrotik script are below, all it's doing is enabling dhcp snooping and then setting a few ports to trusted.

/int bridge set dhcp-snooping=yes numbers=0 /int bridge port set trusted=yes numbers=0 /int bridge port set trusted=yes numbers=24 /int bridge port set trusted=yes numbers=25

ACTUAL RESULTS

The mikrotik devices show that ansible logs in like usual, but then the file is never downloaded or ran. Note that if I do the fetch and import commands manually it works fine. Replaced user/pass as usual.

user@Linux-Ansible:/etc/ansible$ sudo ansible-playbook enable_dhcp_snoop_crs326.yml -l snooptest -vvvv
ansible-playbook [core 2.11.6]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3/dist-packages/ansible
  ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible-playbook
  python version = 3.8.10 (default, Sep 28 2021, 16:10:42) [GCC 9.3.0]
  jinja version = 2.10.1
  libyaml = True
Using /etc/ansible/ansible.cfg as config file
setting up inventory plugins
host_list declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
script declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
auto declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
Parsed /etc/ansible/hosts inventory source with ini plugin
redirecting (type: modules) ansible.builtin.routeros_command to community.routeros.command
Loading collection community.routeros from /usr/lib/python3/dist-packages/ansible_collections/community/routeros
Loading callback plugin default of type stdout, v2.0 from /usr/lib/python3/dist-packages/ansible/plugins/callback/default.py
Skipping callback 'default', as we already have a stdout callback.
Skipping callback 'minimal', as we already have a stdout callback.
Skipping callback 'oneline', as we already have a stdout callback.

PLAYBOOK: enable_dhcp_snoop_crs326.yml ************************************************************************************************************************************************************************************************************************************************************************************************************************************
Positional arguments: enable_dhcp_snoop_crs326.yml
verbosity: 4
connection: smart
timeout: 1000
become_method: sudo
tags: ('all',)
inventory: ('/etc/ansible/hosts',)
subset: snooptest
forks: 5
1 plays in enable_dhcp_snoop_crs326.yml

PLAY [all] ****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
META: ran handlers

TASK [Enable DHCP Snooping] ***********************************************************************************************************************************************************************************************************************************************************************************************************************************************
task path: /etc/ansible/enable_dhcp_snoop_crs326.yml:7
redirecting (type: connection) ansible.builtin.network_cli to ansible.netcommon.network_cli
Loading collection ansible.netcommon from /usr/lib/python3/dist-packages/ansible_collections/ansible/netcommon
redirecting (type: terminal) ansible.builtin.routeros to community.routeros.routeros
redirecting (type: cliconf) ansible.builtin.routeros to community.routeros.routeros
<10.241.0.59> attempting to start connection
<10.241.0.59> using connection plugin ansible.netcommon.network_cli
Found ansible-connection at path /usr/bin/ansible-connection
<10.241.0.59> local domain socket does not exist, starting it
<10.241.0.59> control socket path is /root/.ansible/pc/fdd8f497bd
<10.241.0.59> redirecting (type: connection) ansible.builtin.network_cli to ansible.netcommon.network_cli
<10.241.0.59> Loading collection ansible.netcommon from /usr/lib/python3/dist-packages/ansible_collections/ansible/netcommon
<10.241.0.59> redirecting (type: terminal) ansible.builtin.routeros to community.routeros.routeros
<10.241.0.59> Loading collection community.routeros from /usr/lib/python3/dist-packages/ansible_collections/community/routeros
<10.241.0.59> redirecting (type: cliconf) ansible.builtin.routeros to community.routeros.routeros
<10.241.0.59> local domain socket listeners started successfully
<10.241.0.59> loaded cliconf plugin ansible_collections.community.routeros.plugins.cliconf.routeros from path /usr/lib/python3/dist-packages/ansible_collections/community/routeros/plugins/cliconf/routeros.py for network_os routeros
<10.241.0.59> ssh type is set to paramiko
<10.241.0.59>
<10.241.0.59> local domain socket path is /root/.ansible/pc/fdd8f497bd
<10.241.0.59> ESTABLISH LOCAL CONNECTION FOR USER: root
<10.241.0.59> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-local-4310zx41brjw `"&& mkdir "` echo /root/.ansible/tmp/ansible-local-4310zx41brjw/ansible-tmp-1638225568.5912402-4315-255970753186567 `" && echo ansible-tmp-1638225568.5912402-4315-255970753186567="` echo /root/.ansible/tmp/ansible-local-4310zx41brjw/ansible-tmp-1638225568.5912402-4315-255970753186567 `" ) && sleep 0'
redirecting (type: modules) ansible.builtin.routeros_command to community.routeros.command
Using module file /usr/lib/python3/dist-packages/ansible_collections/community/routeros/plugins/modules/command.py
<10.241.0.59> PUT /root/.ansible/tmp/ansible-local-4310zx41brjw/tmp5hvwxkg5 TO /root/.ansible/tmp/ansible-local-4310zx41brjw/ansible-tmp-1638225568.5912402-4315-255970753186567/AnsiballZ_command.py
<10.241.0.59> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-local-4310zx41brjw/ansible-tmp-1638225568.5912402-4315-255970753186567/ /root/.ansible/tmp/ansible-local-4310zx41brjw/ansible-tmp-1638225568.5912402-4315-255970753186567/AnsiballZ_command.py && sleep 0'
<10.241.0.59> EXEC /bin/sh -c '/usr/bin/python3 /root/.ansible/tmp/ansible-local-4310zx41brjw/ansible-tmp-1638225568.5912402-4315-255970753186567/AnsiballZ_command.py && sleep 0'
<10.241.0.59> EXEC /bin/sh -c 'rm -f -r /root/.ansible/tmp/ansible-local-4310zx41brjw/ansible-tmp-1638225568.5912402-4315-255970753186567/ > /dev/null 2>&1 && sleep 0'
ok: [SW1] => {
    "changed": false,
    "invocation": {
        "module_args": {
            "commands": [
                "/tool fetch address=10.10.72.2 src-path=/srv/ftp/enable-dhcp-snooping-crs326.rsc user=user password=xxxxx dst-path=enable-dhcp-snooping-crs326.rsc port=21 mode=ftp /import enable-dhcp-snooping-crs326.rsc"
            ],
            "interval": 1,
            "match": "all",
            "retries": 10,
            "wait_for": null
        }
    },
    "stdout": [
        "/tool fetch address=10.10.72.2 src-path=/srv/ftp/en\n<address=10.10.72.2 src-path=/srv/ftp/ena                                      \n<address=10.10.72.2 src-path=/srv/ftp/enable-dhcp-snooping-crs326.rsc user=netb\n<address=10.10.72.2 src-path=/srv/ftp/enable-dhcp-snooping-crs326.rsc user=net>\n<able-dhcp-snooping-crs326.rsc user=netbl                                      \n<able-dhcp-snooping-crs326.rsc user=user password=xxxxx dst-path=e\n<able-dhcp-snooping-crs326.rsc user=user password=xxxxx dst-path=>\n<lazr password=xxxxx dst-path=en                                      \n<lazr password=xxxxx dst-path=enable-dhcp-snooping-crs326.rsc port=21 \n<lazr password=xxxxx dst-path=enable-dhcp-snooping-crs326.rsc port=21>\n<nable-dhcp-snooping-crs326.rsc port=21 m                                      \n<nable-dhcp-snooping-crs326.rsc port=21 mode=ftp /import enable-dhcp-snooping-c\n<nable-dhcp-snooping-crs326.rsc port=21 mode=ftp /import enable-dhcp-snooping->\n<mode=ftp /import enable-dhcp-snooping-cr                                      \n<mode=ftp /import enable-dhcp-snooping-crs326.rsc\n<mode=ftp /import enable-dhcp-snooping-crs326.rsc\n\nexpected end of command (line 1 column 186)"
    ],
    "stdout_lines": [
        [
            "/tool fetch address=10.10.72.2 src-path=/srv/ftp/en",
            "<address=10.10.72.2 src-path=/srv/ftp/ena                                      ",
            "<address=10.10.72.2 src-path=/srv/ftp/enable-dhcp-snooping-crs326.rsc user=netb",
            "<address=10.10.72.2 src-path=/srv/ftp/enable-dhcp-snooping-crs326.rsc user=net>",
            "<able-dhcp-snooping-crs326.rsc user=netbl                                      ",
            "<able-dhcp-snooping-crs326.rsc user=user password=xxxxx dst-path=e",
            "<able-dhcp-snooping-crs326.rsc user=user password=xxxxx dst-path=>",
            "<lazr password=xxxxx dst-path=en                                      ",
            "<lazr password=xxxxx dst-path=enable-dhcp-snooping-crs326.rsc port=21 ",
            "<lazr password=xxxxx dst-path=enable-dhcp-snooping-crs326.rsc port=21>",
            "<nable-dhcp-snooping-crs326.rsc port=21 m                                      ",
            "<nable-dhcp-snooping-crs326.rsc port=21 mode=ftp /import enable-dhcp-snooping-c",
            "<nable-dhcp-snooping-crs326.rsc port=21 mode=ftp /import enable-dhcp-snooping->",
            "<mode=ftp /import enable-dhcp-snooping-cr                                      ",
            "<mode=ftp /import enable-dhcp-snooping-crs326.rsc",
            "<mode=ftp /import enable-dhcp-snooping-crs326.rsc",
            "",
            "expected end of command (line 1 column 186)"
        ]
    ]
}
META: ran handlers
META: ran handlers

PLAY RECAP ****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
SW1                        : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
felixfontein commented 2 years ago

You are passing two commands concatenated as a single one. Please use a YAML list to pass two separate commands:

       commands:
         - /tool fetch address=10.10.72.2 src-path=/srv/ftp/enable-dhcp-snooping-crs326.rsc user=xxx password=xxx dst-path=enable-dhcp-snooping-crs326.rsc port=21 mode=ftp
         - /import enable-dhcp-snooping-crs326.rsc
archhorde commented 2 years ago

Hi,

I have had this exact syntax working with other playbooks, it seems odd that it would not work here. But when I separated them into two tasks it worked. Was this something changed in a recent update? Thank you for the advice.

felixfontein commented 2 years ago

It might have been random luck that it worked in other cases. The command module passes commands over SSH, which is quite sensitive to a lot of things, so things can easily go wrong even if things seem to work fine in similar other cases.