From f518eaab7dcc1c6a29077bdfc61cbcf8d5306451 Mon Sep 17 00:00:00 2001 From: Aaron Hicks Date: Wed, 19 Jun 2024 13:36:12 +1200 Subject: [PATCH 1/6] Allow type variable to override automatic type set in a Network Manager nmconnect file --- templates/ethernet_nmconnection.j2 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/templates/ethernet_nmconnection.j2 b/templates/ethernet_nmconnection.j2 index 604fd9a..452ec6c 100644 --- a/templates/ethernet_nmconnection.j2 +++ b/templates/ethernet_nmconnection.j2 @@ -2,7 +2,11 @@ [connection] id={{ item.device }} +{% if 'type' in item %} +type={{ item.type }} +{% else %} type={{ ('vlan' if item.device is match(vlan_interface_regex) else 'dummy' if item.device is match(dummy_interface_regex) else 'ethernet') }} +{% endif %} interface-name={{ item.device }} {% if item.zone is defined %} zone={{ item.zone }} From 8cafb580c3d38eebe3859a514ab68ef852f09630 Mon Sep 17 00:00:00 2001 From: Aaron Hicks Date: Wed, 19 Jun 2024 14:37:37 +1200 Subject: [PATCH 2/6] Need to modify the state checks for `lo` devices --- handlers/main.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/handlers/main.yml b/handlers/main.yml index 36f4fec..aec08bf 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -137,6 +137,8 @@ {% for interface in all_interfaces_changed %} if [[ '{{ interface }}' == *dummy* ]]; then allowed_states='UNKNOWN|UP' + elif [[ '{{ interface }}' == 'lo' ]]; then + allowed_states='UNKNOWN' else allowed_states='UP' fi From 73957329652af32d2ff9215d4173f244ac1339c5 Mon Sep 17 00:00:00 2001 From: Aaron Hicks Date: Wed, 19 Jun 2024 14:52:33 +1200 Subject: [PATCH 3/6] Update ether_check to handle loopback --- filter_plugins/filters.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/filter_plugins/filters.py b/filter_plugins/filters.py index e616f25..36c7f90 100644 --- a/filter_plugins/filters.py +++ b/filter_plugins/filters.py @@ -102,20 +102,20 @@ def _interface_check(context, interface, interface_type=None): elif fact_address and fact_address not in interface.get('allowed_addresses', []): return _fail("Interface %s has an IPv4 address but none was " "requested" % device) - + # Static IPv6 address if interface.get("bootproto") == "static" and interface.get("ip6"): fact_address = fact.get("ipv6", []) # IP address if len(fact_address) == 0: return _fail("Interface %s has no IPv6 address" % device) - + for item in fact_address: if item["address"] == interface["ip6"]["address"] and item["prefix"] == str(interface["ip6"]["prefix"]): break else: return _fail("Interface %s has incorrect IPv6 address" % device) - + # Gateway if interface["ip6"].get("gateway"): fact_gateway = context["ansible_facts"].get("default_ipv6", {}).get("gateway") @@ -143,6 +143,8 @@ def ether_check(context, interface): """ if interface.get('type') == 'ipoib': result = _interface_check(context, interface, "infiniband") + elif interface.get('type') == 'loopback': + result = _interface_check(context, interface, "loopback") else: result = _interface_check(context, interface, "ether") return result From 54fdd37037ee5d20fbc998726963add2b56cb77e Mon Sep 17 00:00:00 2001 From: Aaron Hicks Date: Wed, 19 Jun 2024 16:44:49 +1200 Subject: [PATCH 4/6] Update readme with loopback example --- README.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 564143e..5573938 100644 --- a/README.md +++ b/README.md @@ -446,7 +446,8 @@ bouncing network interfaces before they are active. This can be done by setting ``` 18) Routes and rules can be a mix of strings and hashes (a.k.a. dict, mapping, associative array, etc.) allowing - the role to handle rules and routes outside the expected formats. + the role to handle rules and routes outside the expected formats. These can also be applied to loopback devices in + distributions using Network Manager's new `nmconnect` configuration files (e.g. RHEL8 & RHEL9). The example below configures an interface, to act as a second interface so that any traffic that hits it is returned via the same interface. In addition internal traffic is marked so it can be picked up by some other service (like HAproxy). @@ -469,11 +470,19 @@ interfaces_ether_interfaces: network: 0.0.0.0 netmask: 0.0.0.0 gateway: 10.10.10.254 - - "local 0.0.0.0/0 dev lo table marktable" rules: - from: 10.10.10.1 table: frontend - "fwmark 1 lookup marktable" + - device: lo + type: loopback + # Setting bootproto to dhcp is required to set `method=auto` in the nmconnect file + bootproto: dhcp + route: + - table: marktable + device: lo + network: 0.0.0.0 + netmask: 0 ``` Example Playbook From 319ab2c5830c31f8e74c4bb1fad40d5180ca1cad Mon Sep 17 00:00:00 2001 From: Aaron Hicks Date: Fri, 21 Jun 2024 13:46:37 +1200 Subject: [PATCH 5/6] Improve readme exampel --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 5573938..d109a7b 100644 --- a/README.md +++ b/README.md @@ -477,12 +477,15 @@ interfaces_ether_interfaces: - device: lo type: loopback # Setting bootproto to dhcp is required to set `method=auto` in the nmconnect file + # This replicates `ip route add local 0.0.0.0/0 dev lo table 100"` bootproto: dhcp route: - table: marktable device: lo network: 0.0.0.0 netmask: 0 + options: + - type: local ``` Example Playbook From 6f187cb0d1cd601022e7e1ab0f6eb73dfb9ce1cf Mon Sep 17 00:00:00 2001 From: Aaron Hicks Date: Fri, 21 Jun 2024 15:37:10 +1200 Subject: [PATCH 6/6] loopback devices need a [loopback] option --- templates/ethernet_nmconnection.j2 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/templates/ethernet_nmconnection.j2 b/templates/ethernet_nmconnection.j2 index 452ec6c..307f99e 100644 --- a/templates/ethernet_nmconnection.j2 +++ b/templates/ethernet_nmconnection.j2 @@ -31,6 +31,12 @@ parent={{ item.device | regex_replace(vlan_interface_regex, '\g') }} id={{ item.device | regex_replace(vlan_interface_regex, '\g') }} {% endif %} +{% if 'type' in item %} +{% if item.type == 'loopback' %} +[loopback] + +{% endif %} +{% endif %} [ipv4] {% if item.bootproto == 'dhcp' %} method=auto