首页 > 解决方案 > 如何重复ansible任务直到结果失败+显示每次重试的时间戳?

问题描述

我正在尝试解决网络自动化问题。问题是我们有一个奇怪的行为网络设备(SNOM 电话)以链的形式连接到某个 Cisco 交换机端口。问题是其中一部手机(每次都是不同的手机)随机消失,之后此类设备无法通过 DHCP 获得 IP 地址。我们仍然没有找到重现问题的方法,所以我在 DHCP 服务器上启用了调试日志,现在等待其中一个 MAC 地址将从交换机接口 MAC 地址表中消失。

由于 cisco 不支持 linux 'watch' 命令,我为此编写了一个简单的 ansible playbook:

---
- name: show mac address-table 
  hosts: ios
  gather_facts: no


  tasks:

  - name: show mac address-table interface Fa0/31
    ios_command:
      commands: show mac address-table interface Fa0/31
      wait_for:
        - result[0] contains 0004.1341.799e
        - result[0] contains 0004.134a.f67d
        - result[0] contains 0004.138e.1a53
    register: result
    until: result is failed
    retries: 1000
  - debug: var=result

但在那个配置中,我看到唯一

FAILED - RETRYING: show mac address-table interface Fa0/31 (660 retries left).
FAILED - RETRYING: show mac address-table interface Fa0/31 (659 retries left).
FAILED - RETRYING: show mac address-table interface Fa0/31 (658 retries left).
FAILED - RETRYING: show mac address-table interface Fa0/31 (657 retries left).

在输出。我尝试使用 anstomlog 回调插件,但它仅显示成功条件的时间戳(即在我的情况下 - 结果失败)

所以,我正在寻找一个建议,如何实现这两个目标:

提前致谢!

标签: networkingansibleciscosnom

解决方案


好吧,因为最初的问题是关于 Ansible,所以我通过保存时间戳并从路由器获取 dhcp 日志并按时间戳和 MAC 地址过滤日志来解决了这个问题:

---
- name: Find switch port by host ip address
  hosts: all
  gather_facts: no
  connection: local
  roles:
    - Juniper.junos  
  vars:
    systime: "{{ ansible_date_time.time }}"
    timestamp: "{{ ansible_date_time.date }}_{{ systime }}"
    connection_settings:
      host: "{{ ansible_host }}"
      timeout: 120
    snom_mac_addresses:
      - '00_04:13_41:79_9e'
      - '00_04:13_4a:f6_7d'
      - '00_04:13_8e:1a_53'

  tasks:

  - name: show mac address-table interface Fa0/31
    ios_command:
      commands: show mac address-table interface Fa0/31
      wait_for:
        - result[0] contains {{ snom_mac_addresses[0] | replace(':', '.')| replace('_', '') }}
        - result[0] contains {{ snom_mac_addresses[1] | replace(':', '.')| replace('_', '') }}
        - result[0] contains {{ snom_mac_addresses[2] | replace(':', '.')| replace('_', '') }}
        - result[0] contains {{ snom_mac_addresses[3] | replace(':', '.')| replace('_', '') }}
    register: result
    until: result is failed
    retries: 1000
    ignore_errors: True
    when: inventory_hostname == 'access-switch'


  - name: save timestamp in Junos format
    set_fact: 
      junos_timestamp: "{{ lookup('pipe','date +%b_%_d_%H:%M') | replace('_', ' ') }}"
    run_once: yes
    delegate_to: localhost

  - debug: 
      var: junos_timestamp
    run_once: yes
    delegate_to: localhost

  - name: get dhcp log from router
    junos_scp:
      provider: "{{ connection_settings }}"
      src: /var/log/dhcp-service.log
      remote_src: true
    when: inventory_hostname == 'router'

  - name: filter log for time
    run_once: yes
    shell: "egrep -i '{{ junos_timestamp }}' dhcp-service.log"
    register: grep_time_output
    delegate_to: localhost

  - debug: var=grep_time_output.stdout_lines    

  - name: filter log for time and mac
    run_once: yes
    shell: "egrep -i '{{ snom_mac_addresses | join('|') | replace(':', ' ')| replace('_', ' ') }}' dhcp-service.log"
    register: grep_mac_output
    delegate_to: localhost

  - debug: var=grep_mac_output.stdout_lines

很确定这看起来不像是一个优雅的解决方案,但至少我在一个 Ansible 环境中完成了所有工作,任何人都可以重用我的部分代码而无需进行重大重构。

只是一个疑问 - 我必须使用我自己的 mac 地址格式,因为 Cisco 和 Juniper 调试日志以不同的方式打印它们:

瞻博网络调试日志:

Mar  6 13:14:19.582886 [MSTR][DEBUG] client_key_compose: Composing key (0x1c6aa00) for cid_l 7, cid d4 a3 3d a1 e2 38, mac d4 a3 3d a1 e2 38, htype 1, subnet 10.111.111.1, ifindx 0, opt82_l 0, opt82 NULL

思科:

 30    0004.133d.39fb    DYNAMIC     Po1

但也许有一种聪明的方法可以在 Ansible 中处理所有不同格式的 mac 地址。


推荐阅读