Я хотел бы получить упорядоченный список сетевых интерфейсов на машине, использующей Ansible. Современные системы Linux не используют eth0, eth1 и т. Д. Так что названия непредсказуемы. В нашей сети мы подключаем интерфейс с наименьшим номером к локальной сети, а с самым высоким - к глобальной сети, поэтому я могу использовать положение интерфейса в упорядоченном списке для определения его функции.
Я ищу канонический способ сделать это в Ansible. Так что я могу использовать что-то вроде {{ansible_eth0.ipv4.address}}. (Где eth0 - какое-то другое имя).
Даже если я вручную установил переменную с именем интерфейса, похоже, нет способа получить IP этого интерфейса (используя содержимое переменной).
Я хотел бы обработать факты Ansible, чтобы получить то, что мне нужно, вместо того, чтобы запускать сценарий оболочки в удаленной системе.
В ansible_interfaces
В факте перечислены все существующие сетевые интерфейсы.
Я понимаю, откуда приходит Нейк, поэтому после небольшого эксперимента я думаю, что нашел задачу, которая поможет.
Как упоминал Майкл Гамильтон выше, ansible_interfaces
fact содержит список всех сетевых интерфейсов, и они кажутся упорядоченными (т.е. первый интерфейс Ethernet назывался бы 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
равно «эфиру».
Так что сейчас ansible_eth.0
и ansible_eth.1
должен быть примерно эквивалентен старому ansible_eth0
и ansible_eth1
соответственно.
Я не проверял это полностью, чтобы гарантировать, что порядок всегда работает так, как ожидалось, но, похоже, это помогает.
Большое спасибо этот ответ StackOverflow за то, что показал мне, как создать список с помощью with_items.
Некоторые подсказки для получения интерфейса, когда мы знаем некоторую информацию:
var:
allNetworkInterfaces: "{{ ansible_facts | dict2items | selectattr('value.ipv4', 'defined') | map(attribute='value') | list }}"
allNetworkInterfaces_var2: "{{ 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 }}"
несколько коротких объяснений:
ansible_facts
ansible_facts.interfaces
такой же как ansible_interfaces
Прошло некоторое время с тех пор, как я коснулся анзибля, но без дополнительной информации я ожидал бы чего-то вроде:
ip link show | grep mode | sed 's/://g' | awk '{print $1,$2}'
работать...
1 lo
2 eth0