根据IP地址发现linux接口名称

时间:2017-08-13 10:06:10

标签: linux ansible

我有在linux系统中搜索指定IP的代码:

- name: find IP
  set_fact:
    ip: "{{ item }}"
  with_items: "{{ansible_all_ipv4_addresses}}"
  when: "item.startswith('10.')"

并且工作正常,但我无法找到如何根据事实“ip”发现基于IP的接口名称 有人可以提供一些建议或者可能有一些例子如何做到这一点?

1 个答案:

答案 0 :(得分:3)

Ansible提供了ansible_interfaces事实中的接口列表。您可以使用它来迭代可用的接口,检查每个接口是否有给定的IP地址。

这最终会比听起来更棘手,因为你需要构建事实名称,这意味着而不是简单的事情:

ansible_eth0

您需要:

hostvars[inventory_hostname]["ansible_%s" % item]

另一个复杂因素是Ansible将ip地址划分为" primary" (ansible_eth0.ipv4.address)和"次要" (ansible_eth0.ipv4_secondaries),其中后者是带有address个键的字典列表。假设我们正在迭代item设置为接口名称,我们可以得到这样的主要地址:

hostvars[inventory_hostname]["ansible_%s" % item].ipv4.address

但是!对于没有分配ipv4地址或由于某种原因没有相应ansible_<interface>事实的接口,这将失败。所以我们需要优雅地处理这种情况:

(hostvars[inventory_hostname]["ansible_%s" % item]|default({}).get('ipv4', {}).get('address')

这使用default过滤器来确保我们从字典开始,然后我们使用几个级别的Python .get(key, default)方法。

检查辅助地址是类似的,但要求我们使用map过滤器,因为ipv4_secondaries为我们提供了一个字典列表,我们真正想要的是一个地址列表(以便我们可以检查如果我们的目标地址是列出的in

((hostvars[inventory_hostname]['ansible_%s' % item]|default({}))
.get('ipv4_secondaries'))|map(attribute='address')|list

全部放在一起:

- hosts: localhost
  vars:
    target_address: 192.168.122.1
  tasks:
    - set_fact:
        target_interface: "{{ item }}"
      when: >
        (hostvars[inventory_hostname]['ansible_%s' % item]|default({}))
        .get('ipv4', {}).get('address') == target_address
        or
        target_address in ((hostvars[inventory_hostname]['ansible_%s' % item]|default({}))
        .get('ipv4_secondaries'))|map(attribute='address')|list
      with_items:
        - "{{ ansible_interfaces }}"

    - debug:
        msg: >-
          found interface {{ target_interface }}
          with address {{ target_address }}

如果我在我的系统上运行此操作,则剧本运行结束于:

TASK [debug] *******************************************************************
ok: [localhost] => {
    "msg": "found interface virbr0 with address 192.168.24.1"
}

如果我跑:

ansible-playbook playbook.yml -e target_address=192.168.1.75

我明白了:

TASK [debug] *******************************************************************
ok: [localhost] => {
    "msg": "found interface eth0 with address 192.168.1.75"
}

从上面可以看出,这并不是Ansible所要求的那种任务。将所有这些逻辑填充到Ansible模块中可能会更好,这样您就可以使用Python(或其他语言)以更优雅的方式执行查找。

<强>更新

Here是针对同一问题的基于模块的解决方案。