提高 Ansible 的效率,编写 Nagios 对象以监控 Cisco 接口

问题描述

我编写了一个工作角色,用于检查 Cisco 网络设备非虚拟接口、查找和选择也已启动的中继,并编写一些 Nagios 对象定义以监控状态和利用率。

我一直在努力让它更高效,以便在每个阶段它只适用于有趣的界面:

  1. 查找所有树干
  2. 仅检查中继的运行状态 - 并非所有接口的状态
  3. 仅为中继和上行接口编写 Nagios 对象定义

下面的代码继续缓慢地检查每个物理接口,即使我们可以用已经获得的信息消除非中继。

我一直在努力缩短接口列表,同时保持正确的 iface_index 相关联以供以后在模板中参考。我尝试将 iface_index 设为字典键,其中包含操作状态和主干状态以及其他键/值对,但无法将其组合在一起。

任何灵感将不胜感激,我觉得应该有更好的方法。也提前为我的业余代码道歉。

---

- name: Get physical interface indexes
  delegate_to: 127.0.0.1
  command: "snmpwalk -Oqn -v 3 -l authPriv -u {{ snmpv3user }} -a SHA -A {{ snmpv3_auth_key }} -x AES -X {{ snmpv3_priv_key }} {{ ansible_host }} .1.3.6.1.4.1.9.9.46.1.6.1.1.14"
  register: iface_oids

- name: Extract only the index
  set_fact:
    iface_index: "{{ iface_oids.stdout | regex_findall('\\.([0-9]+) ','last') }}"

- name: Get interface trunk state
  delegate_to: 127.0.0.1
  command: "snmpwalk -Oqv -v 3 -l authPriv -u {{ snmpv3user }} -a SHA -A {{ snmpv3_auth_key }} -x AES -X {{ snmpv3_priv_key }} {{ ansible_host }} .1.3.6.1.4.1.9.9.46.1.6.1.1.14"
  register: iface_trunk_state
  
- name: Get interface oper state
  delegate_to: 127.0.0.1
  command: "snmpwalk -Oqv -v 3 -l authPriv -u {{ snmpv3user }} -a SHA -A {{ snmpv3_auth_key }} -x AES -X {{ snmpv3_priv_key }} {{ ansible_host }} .1.3.6.1.2.1.2.2.1.8.{{ item }}"
  loop: "{{ iface_index }}"
  register: iface_oper_state

- name: Get interface descriptions
  delegate_to: 127.0.0.1
  command: "snmpget -Oqv -v 3 -l authPriv -u {{ snmpv3user }} -a SHA -A {{ snmpv3_auth_key }} -x AES -X {{ snmpv3_priv_key }} {{ ansible_host }} .1.3.6.1.2.1.31.1.1.1.18.{{ item }}"
  loop: "{{ iface_index }}"
  register: iface_description

- name: Get interface names
  delegate_to: 127.0.0.1
  loop: "{{ iface_index }}"
  command: "snmpget -Oqv -v 3 -l authPriv -u {{ snmpv3user }} -a SHA -A {{ snmpv3_auth_key }} -x AES -X {{ snmpv3_priv_key }} {{ ansible_host }} .1.3.6.1.2.1.31.1.1.1.1.{{ item }}"
  register: iface_name

- set_fact:
    nagios_trunks: |
      #
      # Monitor trunking interfaces
      #
      {% for iface in iface_index %}
      {% if (iface_trunk_state.stdout_lines[loop.index0] == "1") and (iface_oper_state.results[loop.index0].stdout[0] == "1") %}
      {% raw %}define service {
      {% endraw %}
          use                     generic-service
          host_name               {{ inventory_hostname }} 
          service_description     {{ inventory_hostname }}:{{ iface_name.results[loop.index0].stdout[1:-1] }} - {{ iface_description.results[loop.index0].stdout[1:-1] }}
          check_command           check-snmp-v3!.1.3.6.1.2.1.2.2.1.8.{{ iface }} -r 1
          notifications_enabled   0
      {% raw %}}
      {% endraw %}
      #
      {% raw %}define service {
      {% endraw %}
          use                     generic-service
          host_name               {{ inventory_hostname }}
          service_description     Link Utilisation INPUT - {{ iface_description.results[loop.index0].stdout[1:-1] }}
          check_command           check-snmp-v3!.1.3.6.1.2.1.31.1.1.1.6.{{ iface }} --rate
          check_interval          5
          notifications_enabled   0
      {% raw %}}
      {% endraw %}
      #
      {% raw %}define service {
      {% endraw %}
          use                     generic-service
          host_name               {{ inventory_hostname }}
          service_description     Link Utilisation OUTPUT - {{ iface_description.results[loop.index0].stdout[1:-1] }}
          check_command           check-snmp-v3!.1.3.6.1.2.1.31.1.1.1.10.{{ iface }} --rate
          check_interval          5
          notifications_enabled   0
      {% raw %}}
      {% endraw %}
      {% endif %}
      {% endfor %}
      #

解决方法

你正在做的事情被称为“bashism”,这不是一种好的风格。如果你正在做一些复杂的事情,在 command 之间有很多互连,最好使用 Python 并编写一个好的 Ansible 模块。这将使游戏变得更简单,并且您手头有合适的工具。

https://docs.ansible.com/ansible/latest/dev_guide/developing_modules_general.html