ansible-collections / cisco.ios

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

ios_logging_global not detecting "logging <ip>" #508

Closed hyberdk closed 2 years ago

hyberdk commented 2 years ago
SUMMARY

On Cisco 3560 switches, the command for logging to syslog hosts are "logging 10.0.53.230" and not "logging host 10.0.53.230" module ios_logging_global detects this incorrectly and tries to push "logging host 10.0.53.230"

I dont see an option to tell the module that its a different CLI command.

ISSUE TYPE
COMPONENT NAME

cisco.ios.ios_logging_global

ANSIBLE VERSION
ansible [core 2.12.1]
  config file = /home/eslau/ansible-awx-configs/execution_enviroments/device_config_ee/ansible.cfg
  configured module search path = ['/home/eslau/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/eslau/ansible-awx-configs/venv/lib/python3.8/site-packages/ansible
  ansible collection location = /home/eslau/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/eslau/ansible-awx-configs/venv/bin/ansible
  python version = 3.8.10 (default, Nov 26 2021, 20:14:08) [GCC 9.3.0]
  jinja version = 3.0.3
  libyaml = True
COLLECTION VERSION
Collection Version
---------- -------
cisco.ios  2.6.0  
CONFIGURATION
HOST_KEY_CHECKING(env: ANSIBLE_HOST_KEY_CHECKING) = False
OS / ENVIRONMENT

Ubuntu 21.04 LTS, in virtual environment.

Package            Version  
------------------ ---------
ansible            5.2.0    
ansible-core       2.12.1   
bcrypt             3.2.0    
certifi            2021.10.8
cffi               1.15.0   
charset-normalizer 2.0.10   
cryptography       36.0.1   
idna               3.3      
Jinja2             3.0.3    
MarkupSafe         2.0.1    
packaging          21.3     
paramiko           2.9.2    
pip                20.0.2   
pkg-resources      0.0.0    
pycparser          2.21     
PyNaCl             1.5.0    
pynetbox           6.5.0    
pyparsing          3.0.7    
PyYAML             6.0      
requests           2.27.1   
resolvelib         0.5.4    
setuptools         44.0.0   
six                1.16.0   
urllib3            1.26.8   
Collection        Version
----------------- -------
ansible.netcommon 2.5.0  
ansible.utils     2.4.3  
awx.awx           19.4.0 
cisco.ios         2.6.0  
community.docker  2.1.1  
community.general 4.3.0  
STEPS TO REPRODUCE

use the following configuration on a 3560 series Cisco switch running version 12.2(55).SE5. Tested in a WS-C3560-24PS

! existing configuration on device
logging buffered 40000
logging trap debugging
logging origin-id hostname
logging source-interface Vlan100
logging 10.0.53.230
- name: enable logging
  cisco.ios.ios_logging_global:
    config:
      console:
      monitor:
      buffered:
        size: '40000'
      trap: 'debugging'
      source_interface:
        - interface: 'Vlan100'
      origin_id:
        tag: 'hostname'
      hosts:
        - hostname: '10.0.53.230'
      discriminator: []
    state: overridden
EXPECTED RESULTS

expected result is that the ios_logging_global would detect the different CLI command on this older version switch and adapt to it.

ACTUAL RESULTS

the playbook does not see the "logging 10.0.53.230" command but executes the "logging host 10.0.53.230" every time. This command is accepted by the switch, but not shown in the configuration, hence on next run it will push it again.

TASK [roles/config_logging : enable logging] **************************************************************************************************************************************************
task path: /opt/ansible-configs/roles/config_logging/tasks/ios.logging.yml:12
redirecting (type: connection) ansible.builtin.network_cli to ansible.netcommon.network_cli
<10.210.241.3> attempting to start connection
<10.210.241.3> using connection plugin ansible.netcommon.network_cli
Found ansible-connection at path /opt/ansible-configs/venv/bin/ansible-connection
<10.210.241.3> found existing local domain socket, using it!
<10.210.241.3> invoked shell using ssh_type: paramiko
<10.210.241.3> ssh connection done, setting terminal
<10.210.241.3> loaded terminal plugin for network_os cisco.ios.ios
<10.210.241.3> Response received, triggered 'persistent_buffer_read_timeout' timer of 0.1 seconds
<10.210.241.3> firing event: on_open_shell()
<10.210.241.3> Response received, triggered 'persistent_buffer_read_timeout' timer of 0.1 seconds
<10.210.241.3> Response received, triggered 'persistent_buffer_read_timeout' timer of 0.1 seconds
<10.210.241.3> Response received, triggered 'persistent_buffer_read_timeout' timer of 0.1 seconds
<10.210.241.3> ssh connection has completed successfully
<10.210.241.3> Response received, triggered 'persistent_buffer_read_timeout' timer of 0.1 seconds
<10.210.241.3> Response received, triggered 'persistent_buffer_read_timeout' timer of 0.1 seconds
<10.210.241.3> Response received, triggered 'persistent_buffer_read_timeout' timer of 0.1 seconds
<10.210.241.3> Response received, triggered 'persistent_buffer_read_timeout' timer of 0.1 seconds
<10.210.241.3> updating play_context for connection
<10.210.241.3> 
<10.210.241.3> local domain socket path is /home/eslau/.ansible/pc/9eb88d90f9
redirecting (type: action) cisco.ios.ios_logging_global to cisco.ios.ios
redirecting (type: action) cisco.ios.ios_logging_global to cisco.ios.ios
<10.210.241.3> ANSIBLE_NETWORK_IMPORT_MODULES: disabled
<10.210.241.3> ANSIBLE_NETWORK_IMPORT_MODULES: module execution time may be extended
<10.210.241.3> ESTABLISH LOCAL CONNECTION FOR USER: eslau
<10.210.241.3> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/eslau/.ansible/tmp/ansible-local-1137369j__stu7n `"&& mkdir "` echo /home/eslau/.ansible/tmp/ansible-local-1137369j__stu7n/ansible-tmp-1643979439.8485744-1137589-117868998469893 `" && echo ansible-tmp-1643979439.8485744-1137589-117868998469893="` echo /home/eslau/.ansible/tmp/ansible-local-1137369j__stu7n/ansible-tmp-1643979439.8485744-1137589-117868998469893 `" ) && sleep 0'
Using module file /opt/ansible-configs/venv/lib/python3.8/site-packages/ansible_collections/cisco/ios/plugins/modules/ios_logging_global.py
<10.210.241.3> PUT /home/eslau/.ansible/tmp/ansible-local-1137369j__stu7n/tmpk0l2n29t TO /home/eslau/.ansible/tmp/ansible-local-1137369j__stu7n/ansible-tmp-1643979439.8485744-1137589-117868998469893/AnsiballZ_ios_logging_global.py
<10.210.241.3> EXEC /bin/sh -c 'chmod u+x /home/eslau/.ansible/tmp/ansible-local-1137369j__stu7n/ansible-tmp-1643979439.8485744-1137589-117868998469893/ /home/eslau/.ansible/tmp/ansible-local-1137369j__stu7n/ansible-tmp-1643979439.8485744-1137589-117868998469893/AnsiballZ_ios_logging_global.py && sleep 0'
<10.210.241.3> EXEC /bin/sh -c '/opt/ansible-configs/venv/bin/python3 /home/eslau/.ansible/tmp/ansible-local-1137369j__stu7n/ansible-tmp-1643979439.8485744-1137589-117868998469893/AnsiballZ_ios_logging_global.py && sleep 0'
<10.210.241.3> EXEC /bin/sh -c 'rm -f -r /home/eslau/.ansible/tmp/ansible-local-1137369j__stu7n/ansible-tmp-1643979439.8485744-1137589-117868998469893/ > /dev/null 2>&1 && sleep 0'
changed: [aucol-sw02] => {
    "after": {
        "buffered": {
            "size": 40000
        },
        "origin_id": {
            "tag": "hostname"
        },
        "source_interface": [
            {
                "interface": "Vlan100"
            }
        ],
        "trap": "debugging"
    },
    "before": {
        "buffered": {
            "size": 40000
        },
        "origin_id": {
            "tag": "hostname"
        },
        "source_interface": [
            {
                "interface": "Vlan100"
            }
        ],
        "trap": "debugging"
    },
    "changed": true,
    "commands": [
        "logging host 10.0.53.230"
    ],
    "invocation": {
        "module_args": {
            "config": {
                "buffered": {
                    "discriminator": null,
                    "filtered": null,
                    "severity": null,
                    "size": 40000,
                    "xml": null
                },
                "buginf": null,
                "cns_events": null,
                "console": null,
                "count": null,
                "delimiter": null,
                "discriminator": [],
                "dmvpn": null,
                "esm": null,
                "exception": null,
                "facility": null,
                "filter": null,
                "history": null,
                "hosts": [
                    {
                        "discriminator": null,
                        "filtered": null,
                        "hostname": "10.0.53.230",
                        "ipv6": null,
                        "sequence_num_session": null,
                        "session_id": null,
                        "stream": null,
                        "transport": null,
                        "vrf": null,
                        "xml": null
                    }
                ],
                "logging_on": null,
                "message_counter": null,
                "monitor": null,
                "origin_id": {
                    "tag": "hostname",
                    "text": null
                },
                "persistent": null,
                "policy_firewall": null,
                "queue_limit": null,
                "rate_limit": null,
                "reload": null,
                "server_arp": null,
                "snmp_trap": null,
                "source_interface": [
                    {
                        "interface": "Vlan100",
                        "vrf": null
                    }
                ],
                "trap": "debugging",
                "userinfo": null
            },
            "running_config": null,
            "state": "overridden"
        }
    }
}
redirecting (type: action) cisco.ios.ios_config to cisco.ios.ios
KB-perByte commented 2 years ago

Hey, @hyberdk can you please share the IOS version on the device you are working on? Note - the supported IOS version is v15+ for the platform. Regards

hyberdk commented 2 years ago

Hi @KB-perByte,

thanks for the quick reply. The IOS version is 12.2(55).SE5

here is the print from "show version":

Cisco IOS Software, C3560 Software (C3560-IPBASEK9-M), Version 12.2(55)SE5, RELEASE SOFTWARE (fc1)

so I guess technically its not supported or?

But is there a work-around except using the ios_config module?

KB-perByte commented 2 years ago

Thanks for confirming, @hyberdk you can definitely use the config modules to push the data. As you are looking at IOS v12.x and the version has reached its EOL around 2013 it is not a supported version.

hyberdk commented 2 years ago

Thanks for the feedback @KB-perByte

Yeah I know the platform is old, really old.. we are finally migrating away from it, but with more than 1000 devices deployed, it takes a while and also the current chip shortage is not helping.

just to be absolutely sure, you are saying there is no way to alter the behavior in logging_global right? My only option is to use the ios_config module perhaps with a jinja template?

KB-perByte commented 2 years ago

Hey @hyberdk, looking at your use case, let me discuss it with my team internally and get back to you. Regards

KB-perByte commented 2 years ago

And in the meanwhile, as you have access to the device of that specific version, can you please share the output of logging <some_ip> ? for me to check the suboptions available within the parent host attribute as per the present module behavior. Regards

hyberdk commented 2 years ago

Hi @KB-perByte,

sorry about the late reply, I missed your last message..

hope this helps:

AUCOL-SW02(config)#logging ?            
  Hostname or A.B.C.D  IP address of the logging host
  buffered             Set buffered logging parameters
  buginf               Enable buginf logging for debugging
  cns-events           Set CNS Event logging level
  console              Set console logging parameters
  count                Count every log message and timestamp last occurance
  delimiter            Append delimiter to syslog messages
  discriminator        Create or modify a message discriminator
  esm                  Set ESM filter restrictions
  exception            Limit size of exception flush output
  facility             Facility parameter for syslog messages
  file                 Set logging file parameters
  filter               Specify logging filter
  history              Configure syslog history table
  host                 Set syslog server IP address and parameters
  message-counter      Configure log message to include certain counter value 
  monitor              Set terminal line (monitor) logging parameters
  on                   Enable logging to all enabled destinations
  origin-id            Add origin ID to syslog messages
  queue-limit          Set logger message queue size
  rate-limit           Set messages per second limit
  reload               Set reload logging level
  source-interface     Specify interface for source address in logging transactions
  trap                 Set syslog server logging level

AUCOL-SW02(config)#logging 1.1.1.1 ?
  <cr>

AUCOL-SW02(config)#logging host 1.1.1.1 ?
  discriminator         Specify a message discriminator indentifier for this logging session
  filtered              Enable filtered logging
  sequence-num-session  Include session sequence number tag in syslog message
  session-id            Specify syslog message session ID tagging
  transport             Specify the transport protocol (default=UDP)
  vrf                   Set VRF option
  xml                   Enable logging in XML
  <cr>

and a "show run | inc logging" looks like this:

AUCOL-SW02#show run | inc logging
logging buffered 40000
logging trap debugging
logging origin-id hostname
logging source-interface Vlan100
logging 10.0.53.230

AUCOL-SW02#

now the switch accepts the logging host 10.0.53.230, but its shown in the running-config as "logging 10.0.53.230" so I think if you can make the module look for either "logging host 10.0.53.230" OR "logging 10.0.53.230" it should work fine.

Hope that helps.

KB-perByte commented 2 years ago

Hey, @hyberdk the issue reported is being considered and I am gonna push a PR to fix the same, as the command mentioned is valid in the context of some versions of IOS v15. Regards

KB-perByte commented 2 years ago

hey @hyberdk, Wanted to discuss the possible fix with you here, as the module supports IOS v15+ and a command like logging 10.0.1.1 and logging host 10.0.1.1 both are termed valid for the device, we can check for the version of the device running and fire the desired command in that scope. But as v12 specifically renders it like logging 10.0.1.1 it will not be considered in the facts and would impact idempotency in that version of IOS, on the other hand, v15+ renders it as logging host 10.0.1.1 even if the command fired is logging 10.0.1.1. So it will not cause any change for further supported versions. Would that solve your issue? Regards

hyberdk commented 2 years ago

Hi @KB-perByte,

Im not 100% sure if I understand you correctly. I agree that older devices render the command "logging 10.0.1.1" and newer devices (assuming 15+) as "logging host 10.0.1.1", Im not sure when Cisco did change the command and it could very well be on different versions on different models.

So from my point of view the best approach is to make the regex (I assume that is what you are using) match both something like ^logging\s(?:host\s)?[0-9\w\.]+

The problem of detecting the version is that 1. Cisco uses horrible versioning that includes parentheses and such which causes issues with the version() function on top of that they are not very structured in when they implement stuff especially in earlier versions (but I guess you already know that ;-)

I actually have a similar problem on #514 where the device is also reporting different than what the module expect.

Hope that clarifies it, else let me know.

KB-perByte commented 2 years ago

Hey @hyberdk, we are using regexes to convert the config data to structured data, but we are not using regexes for validations and there are specific reasons why we don't wanna use regex to validate the specific types of data and pick up accordingly ref. Having said that, for such reasons where the implementations are based on supported versions, we have pushed back making a change for the older version of IOS as they make the maintenance of the module extremely confusing. That's why I mentioned in the above comment we can still manage to push the host command as logging 10.0.1.1 as it is valid even for a few releases of IOS 15 but a change in regex would make it support an EOL version of IOS. That is not recommended. There is a temporary way out, where I can help you with a changed copy of ref. to support your use case but that would require you to make a manual change. Thanks.

hyberdk commented 2 years ago

Hi @KB-perByte,

thanks a lot for your help and your offer to help me in this matter. We internally have a philosophy that we should do all we can to use standard code and not "tweak" it with custom patches. So if your proposal cannot go into the official code, I would rather solve it like this:

- name: enable logging for IOS version >= 15.0 or (>3.3 and <4)
  cisco.ios.ios_logging_global:
    config:
      console:
      monitor:
      buffered:
        size: '{{ config_context.logging.buffer_size }}'
      trap: '{{ config_context.logging.syslog.log_level }}'
      source_interface:
        - interface: '{{ config_context.logging.syslog.src_interface }}'
      origin_id:
        tag: '{{ config_context.logging.syslog.origin_id }}'
      hosts:
        - hostname: '{{ config_context.logging.syslog.host }}'
      discriminator: []
    state: overridden
  when: 
    #when version more than 15 or between 3.3 and <4 (to catch older IOS-XE devices like 4500X)
    ansible_facts.net_version is version('15.0', '>=') or (ansible_facts.net_version is version('3.3', '>=') and ansible_facts.net_version is version('4.0', '<'))

- name: configure logging command for IOS versions >12 and <15 (old devices)
  cisco.ios.ios_config:
    running_config: '{{ ansible_facts.net_config }}'
    src: lagacy_ios_logging.j2
  when: 
    ansible_facts.net_version is version('12.0', '>=') and ansible_facts.net_version is version('15.0', '<')

and the jinja template is just:

logging trap {{ config_context.logging.syslog.log_level }}
logging origin-id {{ config_context.logging.syslog.origin_id }}
logging source-interface {{ config_context.logging.syslog.src_interface }}
logging {{ config_context.logging.syslog.host }}

obviously for legacy devices it would not remove additional configuration, but it would be sure to include our syslog server in the correct way.. Not as good as the module, but okay for devices that we are replacing..

KB-perByte commented 2 years ago

Hey @hyberdk, that is definitely one way of doing stuff, but yes the resource modules are there for changing the experience for good. But for the sake of unsupported versions or EOL releases, we face a similar situation. Well, it was great discussing the issue. as per the conclusion, I am closing the reported issue. Thanks