创建系统接口名称及其mac地址的列表



我正试图从Debian 11服务器上创建一个接口名称及其mac地址的列表,最初,我试图只按顺序获取mac地址,但现在我意识到我需要一个如下所示的列表:

eth0 <SOME_MAC>
eth1 <SOME_MAC>
...

我想将此列表作为变量传递,然后在下一个任务中使用它在/etc/systemd/network目录中创建一个10-persistent-net.link文件。

我目前使用的任务是:

- name: Get mac addresses of all interfaces except local
debug:
msg: "{{ ansible_interfaces |
map('regex_replace','^','ansible_') |
map('extract',hostvars[inventory_hostname]) |
selectattr('macaddress','defined') |
map(attribute='macaddress') |
list }}"

正如你所看到的,我正在使用debug模块来测试我的代码,我不知道如何创建我想要的列表并将其作为变量传递。

上面的代码给出了以下结果:

ok: [target1] => 
msg:
- 08:00:27:d6:08:1a
- 08:00:27:3a:3e:ff
- f6:ac:58:a9:35:33
- 08:00:27:3f:82:c2
- 08:00:27:64:6a:f8
ok: [target2] => 
msg:
- 08:00:27:34:70:60
- 42:04:1a:ff:6c:46
- 42:04:1a:ff:6c:46
- 08:00:27:d6:08:1a
- 08:00:27:9c:d7:af
- f6:ac:58:a9:35:33

对于使用哪个模块将列表作为变量传递以及如何首先创建列表,我们将不胜感激。

请注意我使用的是Ansible v5.9.0,每台服务器可能有任何数量的接口,其中一些可能有ethx接口名称格式,而另一些可能有enspxbrx等接口格式。

更新:根据评论中的建议,我必须提到,我需要为每个目标列出一个列表,该列表将用于针对每个目标运行的自然主机循环任务。

更新2:由于我是Ansible的新手,根据同事的建议,我有一种印象,即接口名称及其MAC地址的列表是我需要的变量,以便传递到下一个任务,然而,在所有评论和回答中,我现在意识到我完全朝着错误的方向前进。请接受我的道歉,并将其归咎于我对Ansible缺乏经验和知识。最后,事实证明,在Ansible中,接口名称及其MAC地址的字典最适合这种操作。

获取变量的列表

blacklist: ['lo']
interfaces: "{{ ['ansible_']|
product(ansible_interfaces|
difference(blacklist))|
map('join')|list }}"

获取变量的值并创建字典

devices: "{{ interfaces|
map('extract', vars)|
items2dict(key_name='device',
value_name='macaddress') }}"

钞票

  • 字典比列表更有效率。密钥必须是唯一的
  • YAML(又名映射(中的字典是">一组无序的键/值节点对,每个键都是唯一的">
  • 从Python 3.7版起,字典已订购。。因此,在使用Python3.7及更高版本时,也会对Ansible(YAML(字典进行排序。例如
devices:
docker0: 02:42:35:39:f7:f5
eth0: 80:3f:5d:14:b1:d3
eth1: e4:6f:13:f5:09:80
wlan0: 64:5d:86:5d:16:b9
xenbr0: 80:3f:5d:14:b1:d3
  • 请参阅Jinja,了解如何创建各种格式的输出。例如
- debug:
msg: |-
{% for ifc, mac in devices.items() %}
{{ ifc }} {{ mac }}
{% endfor %}

给出

msg: |-
wlan0 64:5d:86:5d:16:b9
eth0 80:3f:5d:14:b1:d3
eth1 e4:6f:13:f5:09:80
xenbr0 80:3f:5d:14:b1:d3
docker0 02:42:35:39:f7:f5

你可以看到金贾的输出没有被命令。事实上,当你重复任务时,顺序甚至不会持久。如果要对行进行排序,请使用过滤器排序。例如,

- debug:
msg: |-
{% for ifc, mac in devices.items()|sort %}
{{ ifc }} {{ mac }}
{% endfor %}

给出

msg: |-
docker0 02:42:35:39:f7:f5
eth0 80:3f:5d:14:b1:d3
eth1 e4:6f:13:f5:09:80
wlan0 64:5d:86:5d:16:b9
xenbr0 80:3f:5d:14:b1:d3

我就是这么做的。

请注意,我的示例使用json_query过滤器,该过滤器需要在您的ansible控制器上使用pip install jmespath

---
- name: Create a formated list for all interfaces
hosts: all

vars:
elligible_interfaces: "{{ ansible_interfaces | reject('==', 'lo') }}"
interfaces_list_raw: >-
{{
hostvars[inventory_hostname]
| dict2items
| selectattr('value.device', 'defined')
| selectattr('value.device', 'in', elligible_interfaces)
| map(attribute='value')
}}
interface_query: >-
[].[device, macaddress]
interfaces_formated_list: >-
{{ interfaces_list_raw | json_query(interface_query) | map('join', ' ') }}
tasks:
- name: Show our calculated var
debug:
var: interfaces_formated_list

这使得在我的localhost:上运行

$ ansible-playbook -i localhost, /tmp/test.yml 
PLAY [Create a formated list for all interfaces] **************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************
ok: [localhost]
TASK [Show our calculated var] ********************************************************************************************************************
ok: [localhost] => {
"interfaces_formated_list": [
"docker0 02:42:98:b8:4e:75",
"enp4s0 50:3e:aa:14:17:8f",
"vboxnet0 0a:00:27:00:00:00",
"veth7201fce 92:ab:61:7e:df:65"
]
}
PLAY RECAP ****************************************************************************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

正如您所看到的,这显示了您可能想要在用例中过滤掉的几个接口。您可以检查interfaces_list_raw并创建额外的过滤器来实现您的目标。但至少你明白了。

最新更新