Auflisten von Netzwerkschnittstellen in Ansible

7

Ich möchte mit Ansible eine geordnete Liste der Netzwerkschnittstellen auf einem Computer erhalten. Moderne Linux-Systeme verwenden eth0, eth1 usw. nicht. Die Namen sind also unvorhersehbar. In unserem Netzwerk verbinden wir die Schnittstelle mit der niedrigsten Nummer mit dem LAN und die Schnittstelle mit der höchsten Nummer mit dem WAN, sodass ich die Position der Schnittstelle in einer geordneten Liste verwenden kann, um ihre Funktion zu bestimmen.

Ich suche nach dem kanonischen Weg, dies in Ansible zu tun. Damit ich so etwas wie {{ansible_eth0.ipv4.address}} verwenden kann. (Wobei eth0 ein anderer Name ist).

Selbst wenn ich manuell eine Variable mit dem Namen der Schnittstelle setze, scheint es keine Möglichkeit zu geben, die IP dieser Schnittstelle zu ermitteln (unter Verwendung des Inhalts der Variablen).

Ich möchte die Ansible-Fakten verarbeiten, um das zu erhalten, was ich möchte, anstatt ein Shell-Skript auf dem Remote-System auszuführen.

Neik
quelle
Eigentlich sind die Namen jetzt völlig vorhersehbar. Sie waren vorher unvorhersehbar , als sie alle eth * waren.
Michael Hampton
Wenn ich eine neue Maschine mit einer Schnittstelle bekomme, weiß ich nicht, wie die Schnittstelle lautet, bis ich sie einschalte. Das meine ich mit unvorhersehbar.
Neik
Richtig, aber Sie wissen auch nicht, welche Schnittstelle eth0 und welche eth1 ist, bis Sie sie einschalten ... und Sie wissen nicht, ob sie beim nächsten Neustart die Plätze wechseln (weshalb diese nicht mehr verwendet werden). . Und zumindest manchmal können Sie die neuen Schnittstellennamen kennen, bevor Sie das System zum ersten Mal einschalten und installieren.
Michael Hampton
Ich stimme Neik zu: Wenn Sie einen dieser Millionen (virtuellen) Server mit nur einer Netzwerkkarte haben, war der Schnittstellenname vorhersehbar: 'eth0'. Seit der Erfindung der 'vorhersehbaren NIC-Namen' ist der NIC-Name eines einzelnen Servers meines Erachtens unvorhersehbar geworden. Anstatt 'eth0' zu verwenden, müssen wir jetzt die Schnittstellennamen auflisten, um den Standardnamen zu erhalten. Was ist daran vorhersehbar?
Anneb
Ich habe festgestellt, ansible_default_ipv4.addressdass dies die Standard-IPv4-Adresse und ansible_default_ipv4.interfacedie Standard-IPv4-Schnittstelle angibt. Dies beantwortet Ihre Frage nicht, hat mir jedoch als Problemumgehung in einer Situation geholfen, in der die Standardschnittstelle eth0auf bestimmten Systemen und eth1auf anderen benannt wurde.
StockB

Antworten:

8

Die ansible_interfacesTatsache listet alle vorhandenen Netzwerkschnittstellen auf.

Michael Hampton
quelle
3

Ich verstehe, woher Neik kommt, also habe ich nach einigem Experimentieren eine Aufgabe gefunden, die den Trick macht.

Wie Michael Hamilton oben erwähnt hat ansible_interfaces, enthält die Tatsache eine Liste aller Netzwerkschnittstellen und sie scheinen in Ordnung zu sein (dh die erste Ethernet-Schnittstelle hätte eth0, die zweite eth1 usw. genannt). Also ein bisschen set_factMagie und viel Experimentieren später:

- 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'] }}"

Dies durchläuft alle ansible_interfacesEinträge für die aktuelle Maschine und erstellt eine Liste der hostvars[inventory_hostname]['ansible_' + item]Einträge, die typegleich "ether" sind.

Also jetzt ansible_eth.0und ansible_eth.1sollte in etwa dem alten ansible_eth0bzw. ansible_eth1entsprechen.

Ich habe dies nicht gründlich getestet, um sicherzustellen, dass die Bestellung immer wie erwartet funktioniert, aber es scheint den Trick zu tun.

Vielen Dank an diese StackOverflow-Antwort, die mir gezeigt hat, wie man die Liste mit with_items erstellt.

PaulR
quelle
with_items: - "{{ hostvars[inventory_hostname]['ansible_interfaces'] }}"Kann ersetzt werden durch:with_items: "{{ansible_interfaces}}"
Rwky
2

Einige Hinweise, um eine Schnittstelle zu erhalten, wenn wir einige Informationen kennen:

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 }}"

einige kurze Erklärungen:

simohe
quelle
1

Es ist schon eine Weile her, seit ich ansible berührt habe, aber ohne weitere Details würde ich etwas erwarten wie:

ip link show | grep mode | sed 's/://g' | awk '{print $1,$2}'

arbeiten...

1 lo
2 eth0
Daniel Widrick
quelle
1
Ich hätte klarstellen sollen, dass ich nach dem kanonischen Weg suche, dies in Ansible zu tun. Damit ich Dinge wie {{ansible_eth0.ipv4.address}} verwenden kann. Ich möchte nicht, dass unnötige Änderungsereignisse durch Skripte meine Ausgabe durcheinander bringen.
Neik