我想使用 Ansible 获取机器上的网络接口的有序列表。现代 Linux 系统不使用 eth0、eth1 等。因此名称不可预测。在我们的网络上,我们将编号最小的接口连接到 LAN,将编号最大的接口连接到 WAN,因此我可以使用接口在有序列表中的位置来确定其功能。
我正在寻找在 Ansible 中执行此操作的规范方法。这样我就可以使用类似 {{ansible_eth0.ipv4.address}} 的东西。(其中 eth0 是其他名称)。
即使我手动设置一个带有接口名称的变量,似乎也没有办法获取该接口的 IP(使用变量的内容)。
我想处理 Ansible 事实来获取我想要的东西,而不是在远程系统上运行 shell 脚本。
答案1
事实ansible_interfaces
列出了所有现有的网络接口。
答案2
当我们了解一些信息时,获取接口的一些提示:
var:
allNetworkInterfaces: "{{ ansible_facts | dict2items | selectattr('value.ipv4', 'defined') | map(attribute='value') | list }}"
allNetworkInterfaces_variant2: "{{ ansible_facts.interfaces | map('extract', ansible_facts ) | list }}"
interfaceWithKnownIp: "{{ ansible_facts | dict2items | selectattr('value.ipv4', 'defined') | selectattr('value.ipv4.address', 'equalto', myKnowIpV4) | first }}"
interfaceWithKnownIp_fromVar: "{{ allNetworkInterfaces | selectattr('ipv4.address', 'equalto', myKnowIpV4) | first }}"
interfacesWithPartialKnowMac: "{{ allNetworkInterfaces | selectattr('macaddress', 'match', knownMacPrefix~'.*') | list }}"
interfacesWitKnowType: "{{ allNetworkInterfaces | selectattr('type', 'equalto', knownType) | sort(attribute='device') | list }}"
# extended on 2020-10-28
queryForKnownIpv6: "[*].{device: device, ipv4: ipv4, ipv6: ipv6[? address == 'fe80::a00:27ff:fe38:ad36']}[?ipv6])" # string must be in ' # sorry, only partial interface info, did not find out how to return all info directly
interfacesWithKnownIpv6: '{{ allNetworkInterfaces | json_query(queryForKnownIpv6) | first }}'
queryForKnownIpv4_linux: "[?ipv4.address == '{{ myKnownIpV4 }}']}[?ipv4])" # string must be in '
interfacesWithKnownIp_variantJsonQuery: '{{ allNetworkInterfaces | json_query(queryForKnownIpv4_linux) | first }}'
一些简短的解释:
- 字典2项目因为选择属性期望一个数组
- 地图(属性='...')解开这个数组
- 地图('提取',...)从中提取接口
ansible_facts
ansible_facts.interfaces
是相同的ansible_interfaces
- json_query()为了灵活地选择和解包,欢迎使用 `map()? 替代变体
答案3
我理解 Neik 的出发点,因此经过一些实验后,我认为我找到了一项可以解决问题的任务。
正如 Michael Hamilton 上面提到的,ansible_interfaces
事实是包含所有网络接口的列表,并且它们似乎按顺序排列(即,第一个以太网接口将被称为 eth0,第二个以太网接口被称为 eth1,等等)。因此,set_fact
稍后需要一点魔法和大量实验:
- name: define traditional ethernet facts
set_fact:
ansible_eth: "{% set ansible_eth = ansible_eth|default([]) + [hostvars[inventory_hostname]['ansible_' + item]] %}{{ ansible_eth|list }}"
when: hostvars[inventory_hostname]['ansible_' + item]['type'] == 'ether'
with_items:
- "{{ hostvars[inventory_hostname]['ansible_interfaces'] }}"
ansible_interfaces
这将循环遍历当前机器的所有条目并构建一个hostvars[inventory_hostname]['ansible_' + item]
等于type
“ether”的条目列表。
因此现在ansible_eth.0
和ansible_eth.1
应该分别大致相当于旧的ansible_eth0
和ansible_eth1
。
我还没有彻底测试过这一点以确保订单总是按预期进行,但它似乎确实起了作用。
非常感谢这个 StackOverflow 答案向我展示如何使用 with_items 构建列表。
答案4
与 Daniel Widrick 的答案非常相似,但避免使用较旧的答案,而with_items
使用loop
。此外,我只想找到 wifi 接口,它仍然wlan0
适用于树莓派。它还会找到许多其他适配器,因为大多数适配器都以 开头wl
(但不是全部)
- name: Get wifi adapter
set_fact:
wifi_adapter: '{{ item }}'
loop: '{{ ansible_facts.interfaces }}'
when: 'item.startswith("wl")'enter code here