如何重复ansible任务,直到结果失败+显示每次重试的时间戳?

时间:2019-03-01 10:52:18

标签: networking ansible cisco snom

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

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

---
- 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回调插件,但它仅显示成功条件下的时间戳(即,在我的情况下-结果失败)

因此,我正在寻求有关如何实现这两个目标的建议:

  • 永远运行任务,直到状态失败
  • 每次重试都写入时间戳

谢谢!

2 个答案:

答案 0 :(得分:0)

最好将其重写为普通循环(包含include_tasks),并报告该任务所需的所有信息。

依靠“重试”作为看门狗不是一个好主意。

此外,我认为最好将其重写为独立程序。如果您担心要使用ssh进行切换,netmiko是适用于所有网络设备的大量即用型怪癖的集合。它具有在交换机上执行的“ .command”方法。

答案 1 :(得分:0)

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

!important

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

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

杜松调试日志:

---
- 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

思科:

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

但是也许有一种聪明的方法来处理Ansible中Mac地址的所有不同格式。