feat(configuration): multi-backend networking, bind by match not MAC
This commit is contained in:
@@ -1,38 +1,51 @@
|
||||
---
|
||||
- name: Read network interfaces
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- ip
|
||||
- -o
|
||||
- link
|
||||
- show
|
||||
register: configuration_ip_link
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Detect available network interface names
|
||||
vars:
|
||||
configuration_detected_interfaces: >-
|
||||
{{
|
||||
configuration_ip_link.stdout
|
||||
| default('')
|
||||
| regex_findall('^[0-9]+: ([^:]+):', multiline=True)
|
||||
| reject('equalto', 'lo')
|
||||
| list
|
||||
}}
|
||||
ansible.builtin.set_fact:
|
||||
configuration_detected_interfaces: "{{ configuration_detected_interfaces }}"
|
||||
|
||||
- name: Validate at least one network interface detected
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- configuration_detected_interfaces | length > 0
|
||||
fail_msg: Failed to detect any network interfaces.
|
||||
|
||||
- name: Set DNS configuration facts
|
||||
ansible.builtin.set_fact:
|
||||
configuration_dns_list: "{{ system_cfg.network.dns.servers }}"
|
||||
configuration_dns_search: "{{ system_cfg.network.dns.search }}"
|
||||
|
||||
- name: Configure networking
|
||||
ansible.builtin.include_tasks: "{{ configuration_network_task_map[os] | default('network_nm.yml') }}"
|
||||
# 2+ unnamed interfaces would all match the first-ethernet glob, leaving the rest unconfigured.
|
||||
- name: Require an explicit name on every interface for multi-NIC
|
||||
vars:
|
||||
_unnamed: "{{ system_cfg.network.interfaces | map(attribute='name', default='') | map('string') | select('equalto', '') | list | length }}"
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- system_cfg.network.interfaces | length <= 1 or _unnamed == 0
|
||||
fail_msg: >-
|
||||
Multi-NIC (system.network.interfaces with 2+ entries) requires a name on
|
||||
every interface; the first-adapter glob only binds a single NIC.
|
||||
|
||||
# Probe /mnt to detect the stack the installed rootfs will run (nothing runs in
|
||||
# the chroot). NM is checked first and wins, since bootstrap installs it on every
|
||||
# family; the rest are the fallback for a non-NM base image.
|
||||
- name: Probe the installed network stack on the target rootfs
|
||||
ansible.builtin.stat:
|
||||
path: "{{ item }}"
|
||||
register: configuration_net_probe
|
||||
loop:
|
||||
- /mnt/usr/bin/nmcli
|
||||
- /mnt/usr/lib/systemd/system/NetworkManager.service
|
||||
- /mnt/usr/sbin/netplan
|
||||
- /mnt/etc/netplan
|
||||
- /mnt/sbin/ifup
|
||||
- /mnt/usr/sbin/ifup
|
||||
- /mnt/etc/systemd/system/multi-user.target.wants/systemd-networkd.service
|
||||
- /mnt/etc/systemd/system/dbus-org.freedesktop.network1.service
|
||||
loop_control:
|
||||
label: "{{ item }}"
|
||||
|
||||
- name: Resolve the network backend from the probe
|
||||
vars:
|
||||
_found: "{{ configuration_net_probe.results | selectattr('stat.exists') | map(attribute='item') | list }}"
|
||||
ansible.builtin.set_fact:
|
||||
configuration_network_backend: >-
|
||||
{{
|
||||
'nm' if (['/mnt/usr/bin/nmcli', '/mnt/usr/lib/systemd/system/NetworkManager.service'] | intersect(_found))
|
||||
else 'netplan' if (['/mnt/usr/sbin/netplan', '/mnt/etc/netplan'] | intersect(_found))
|
||||
else 'eni' if (['/mnt/sbin/ifup', '/mnt/usr/sbin/ifup'] | intersect(_found))
|
||||
else 'networkd' if (['/mnt/etc/systemd/system/multi-user.target.wants/systemd-networkd.service', '/mnt/etc/systemd/system/dbus-org.freedesktop.network1.service'] | intersect(_found))
|
||||
else 'nm'
|
||||
}}
|
||||
|
||||
- name: Configure networking for the detected backend {{ configuration_network_backend }}
|
||||
ansible.builtin.include_tasks: "network_{{ configuration_network_backend }}.yml"
|
||||
|
||||
35
roles/configuration/tasks/network_eni.yml
Normal file
35
roles/configuration/tasks/network_eni.yml
Normal file
@@ -0,0 +1,35 @@
|
||||
---
|
||||
# ifupdown can't glob iface stanzas (no mapping on ifupdown2/Proxmox), so ENI binds
|
||||
# a literal name detected here. The chroot only sees live-ISO names: on a real
|
||||
# ifupdown base, set system.network.interfaces[].name to the installed name. Bootstrap
|
||||
# installs NetworkManager, so this fires only on a non-NM base image.
|
||||
- name: Detect ethernet interface names
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- ip
|
||||
- -o
|
||||
- link
|
||||
- show
|
||||
register: configuration_eni_link
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Resolve detected ethernet interface names
|
||||
ansible.builtin.set_fact:
|
||||
configuration_eni_detected: >-
|
||||
{{
|
||||
configuration_eni_link.stdout | default('')
|
||||
| regex_findall('^[0-9]+: ([^:@]+)[@:].*?link/ether', multiline=True)
|
||||
}}
|
||||
|
||||
- name: Ensure the network configuration directory exists
|
||||
ansible.builtin.file:
|
||||
path: /mnt/etc/network
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
- name: Write the ifupdown interfaces file
|
||||
ansible.builtin.template:
|
||||
src: network_eni.j2
|
||||
dest: /mnt/etc/network/interfaces
|
||||
mode: "0644"
|
||||
12
roles/configuration/tasks/network_netplan.yml
Normal file
12
roles/configuration/tasks/network_netplan.yml
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
- name: Ensure the netplan directory exists
|
||||
ansible.builtin.file:
|
||||
path: /mnt/etc/netplan
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
- name: Write the netplan configuration
|
||||
ansible.builtin.template:
|
||||
src: network_netplan.j2
|
||||
dest: /mnt/etc/netplan/10-sg.yaml
|
||||
mode: "0600"
|
||||
18
roles/configuration/tasks/network_networkd.yml
Normal file
18
roles/configuration/tasks/network_networkd.yml
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
- name: Ensure the systemd-networkd directory exists
|
||||
ansible.builtin.file:
|
||||
path: /mnt/etc/systemd/network
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
- name: Write systemd-networkd configuration per interface
|
||||
vars:
|
||||
configuration_iface: "{{ item }}"
|
||||
ansible.builtin.template:
|
||||
src: network_networkd.j2
|
||||
dest: "/mnt/etc/systemd/network/10-static-{{ idx }}.network"
|
||||
mode: "0644"
|
||||
loop: "{{ system_cfg.network.interfaces }}"
|
||||
loop_control:
|
||||
index_var: idx
|
||||
label: "10-static-{{ idx }}"
|
||||
@@ -2,7 +2,6 @@
|
||||
- name: Copy NetworkManager keyfile per interface
|
||||
vars:
|
||||
configuration_iface: "{{ item }}"
|
||||
configuration_iface_name: "{{ item.name | default(configuration_detected_interfaces[idx] | default('')) }}"
|
||||
configuration_net_uuid: "{{ ('LAN-' ~ idx ~ '-' ~ hostname) | ansible.builtin.to_uuid }}"
|
||||
ansible.builtin.template:
|
||||
src: network.j2
|
||||
|
||||
Reference in New Issue
Block a user