mirror of
https://github.com/linux-system-roles/network.git
synced 2026-01-23 02:15:17 +00:00
feat: Support wait_ip property
Add support for the `wait_ip` property, the system will consider
connection activated only when specific IP stack is configured.
This enables flexibility in scenarios such as
IPv6-only networks, where the overall network configuration can still
succeed when IPv4 configuration fails but IPv6 completes successfully.
The `wait_ip` can be configured with the following possible values:
* "any": System will consider interface activated when any IP stack is
configured.
* "ipv4": System will wait IPv4 been configured.
* "ipv6": System will wait IPv6 been configured.
* "ipv4+ipv6": System will wait both IPv4 and IPv6 been configured.
Resolves: https://issues.redhat.com/browse/RHEL-63026
Signed-off-by: Wen Liang <wenliang@redhat.com>
This commit is contained in:
parent
38a61f76e9
commit
d92baacf1f
8 changed files with 128 additions and 0 deletions
10
README.md
10
README.md
|
|
@ -591,6 +591,16 @@ The IP configuration supports the following options:
|
|||
|
||||
The default gateway for IPv4 (`gateway4`) or IPv6 (`gateway6`) packets.
|
||||
|
||||
- `wait_ip`
|
||||
|
||||
The property controls whether the system should wait for a specific IP stack to be
|
||||
configured before considering the connection activated. It can be set to "any",
|
||||
"ipv4","ipv6," or "ipv4+ipv6". When set to "any," the system considers the connection
|
||||
activated when any IP stack is configured. "ipv4" ensures the system waits for IPv4
|
||||
configuration, while "ipv6" ensures the system waits for IPv6 configuration. The
|
||||
"ipv4+ipv6" option requires both IPv4 and IPv6 to be configured before the connection
|
||||
is considered activated.
|
||||
|
||||
- `ipv4_ignore_auto_dns` and `ipv6_ignore_auto_dns`
|
||||
|
||||
If enabled, the automatically configured name servers and search domains (via
|
||||
|
|
|
|||
18
examples/eth_with_wait_ip.yml
Normal file
18
examples/eth_with_wait_ip.yml
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
---
|
||||
- name: Configuring wait_ip on ethernet connection
|
||||
hosts: all
|
||||
vars:
|
||||
network_connections:
|
||||
- name: eth0
|
||||
state: up
|
||||
type: ethernet
|
||||
interface_name: eth0
|
||||
ip:
|
||||
address:
|
||||
- 192.0.2.42/30
|
||||
- 2001:db8::23/64
|
||||
wait_ip: any
|
||||
|
||||
roles:
|
||||
- linux-system-roles.network
|
||||
|
|
@ -1205,6 +1205,22 @@ class NMUtil:
|
|||
)
|
||||
if ip["gateway6"] is not None:
|
||||
s_ip6.set_property(NM.SETTING_IP_CONFIG_GATEWAY, ip["gateway6"])
|
||||
|
||||
# Mapping of wait_ip values to the may-fail settings for IPv4 and IPv6
|
||||
may_fail_mapping = {
|
||||
"any": (True, True),
|
||||
"ipv4": (False, True),
|
||||
"ipv6": (True, False),
|
||||
"ipv4+ipv6": (False, False),
|
||||
}
|
||||
|
||||
may_fail_ipv4, may_fail_ipv6 = may_fail_mapping.get(
|
||||
ip["wait_ip"], (True, True)
|
||||
)
|
||||
|
||||
s_ip4.set_property(NM.SETTING_IP_CONFIG_MAY_FAIL, may_fail_ipv4)
|
||||
s_ip6.set_property(NM.SETTING_IP_CONFIG_MAY_FAIL, may_fail_ipv6)
|
||||
|
||||
if ip["route_metric6"] is not None and ip["route_metric6"] >= 0:
|
||||
s_ip6.set_property(
|
||||
NM.SETTING_IP_CONFIG_ROUTE_METRIC, ip["route_metric6"]
|
||||
|
|
|
|||
|
|
@ -907,6 +907,11 @@ class ArgValidator_DictIP(ArgValidatorDict):
|
|||
ArgValidatorBool("auto6", default_value=None),
|
||||
ArgValidatorBool("ipv4_ignore_auto_dns", default_value=None),
|
||||
ArgValidatorBool("ipv6_ignore_auto_dns", default_value=None),
|
||||
ArgValidatorStr(
|
||||
"wait_ip",
|
||||
enum_values=["any", "ipv4", "ipv6", "ipv4+ipv6"],
|
||||
default_value="any",
|
||||
),
|
||||
ArgValidatorBool("ipv6_disabled", default_value=None),
|
||||
ArgValidatorIP("gateway6", family=socket.AF_INET6),
|
||||
ArgValidatorNum(
|
||||
|
|
@ -960,6 +965,7 @@ class ArgValidator_DictIP(ArgValidatorDict):
|
|||
"auto6": True,
|
||||
"ipv4_ignore_auto_dns": None,
|
||||
"ipv6_ignore_auto_dns": None,
|
||||
"wait_ip": "any",
|
||||
"ipv6_disabled": False,
|
||||
"gateway6": None,
|
||||
"route_metric6": None,
|
||||
|
|
@ -2522,6 +2528,14 @@ class ArgValidator_ListConnections(ArgValidatorList):
|
|||
"ip.ipv4_ignore_auto_dns or ip.ipv6_ignore_auto_dns is not "
|
||||
"supported by initscripts.",
|
||||
)
|
||||
# initscripts does not support ip.wait_ip,
|
||||
# so raise errors when network provider is initscripts
|
||||
if connection["ip"]["wait_ip"] != "any":
|
||||
if mode == self.VALIDATE_ONE_MODE_INITSCRIPTS:
|
||||
raise ValidationError.from_connection(
|
||||
idx,
|
||||
"ip.wait_ip is not supported by initscripts.",
|
||||
)
|
||||
# initscripts does not support ip.dns_options, so raise errors when network
|
||||
# provider is initscripts
|
||||
if connection["ip"]["dns_options"]:
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
vars:
|
||||
autocon_retries: 2
|
||||
interface: dummy0
|
||||
wait_ip: ipv4+ipv6
|
||||
profile: "{{ interface }}"
|
||||
lsr_fail_debug:
|
||||
- __network_connections_result
|
||||
|
|
@ -32,6 +33,7 @@
|
|||
- tasks/assert_profile_present.yml
|
||||
- tasks/assert_device_present.yml
|
||||
- tasks/assert_autoconnect_retries.yml
|
||||
- tasks/assert_may_fail.yml
|
||||
lsr_cleanup:
|
||||
- tasks/cleanup_profile+device.yml
|
||||
- tasks/check_network_dns.yml
|
||||
|
|
|
|||
30
tests/tasks/assert_may_fail.yml
Normal file
30
tests/tasks/assert_may_fail.yml
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
---
|
||||
- name: Get ipv4.may-fail
|
||||
command: >
|
||||
nmcli -f ipv4.may-fail connection show {{ profile }}
|
||||
register: may_fail4
|
||||
ignore_errors: true
|
||||
changed_when: false
|
||||
- name: Get ipv6.may-fail
|
||||
command: >
|
||||
nmcli -f ipv6.may-fail connection show {{ profile }}
|
||||
register: may_fail6
|
||||
ignore_errors: true
|
||||
changed_when: false
|
||||
- name: "Assert that ipv4.may-fail is configured as specified"
|
||||
assert:
|
||||
that:
|
||||
- may_fail4.stdout.split(":")[1] | trim
|
||||
== "no"
|
||||
msg: "ipv4.may-fail is configured as
|
||||
{{ may_fail4.stdout.split(':')[1] | trim }}
|
||||
but wait_ip is specified as {{ wait_ip }}"
|
||||
- name: "Assert that ipv6.may-fail is configured as specified"
|
||||
assert:
|
||||
that:
|
||||
- may_fail6.stdout.split(":")[1] | trim
|
||||
== "no"
|
||||
msg: "ipv6.may-fail is configured as
|
||||
{{ may_fail6.stdout.split(':')[1] | trim }}
|
||||
but wait_ip is specified as {{ wait_ip }}"
|
||||
|
|
@ -12,6 +12,8 @@
|
|||
ip:
|
||||
address:
|
||||
- "192.0.2.42/30"
|
||||
- "2001:db8::23/64"
|
||||
wait_ip: "{{ wait_ip }}"
|
||||
- name: Show result
|
||||
debug:
|
||||
var: __network_connections_result
|
||||
|
|
|
|||
|
|
@ -185,6 +185,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"ip": {
|
||||
"gateway6": None,
|
||||
"gateway4": None,
|
||||
"wait_ip": "any",
|
||||
"route_metric4": None,
|
||||
"auto6": True,
|
||||
"ipv6_disabled": False,
|
||||
|
|
@ -601,6 +602,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"ip": {
|
||||
"gateway6": None,
|
||||
"gateway4": None,
|
||||
"wait_ip": "any",
|
||||
"route_metric4": None,
|
||||
"auto6": True,
|
||||
"ipv6_disabled": False,
|
||||
|
|
@ -663,6 +665,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"ip": {
|
||||
"gateway6": None,
|
||||
"gateway4": None,
|
||||
"wait_ip": "any",
|
||||
"route_metric4": None,
|
||||
"auto6": True,
|
||||
"ipv6_disabled": False,
|
||||
|
|
@ -719,6 +722,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"ip": {
|
||||
"gateway6": None,
|
||||
"gateway4": None,
|
||||
"wait_ip": "any",
|
||||
"route_metric4": None,
|
||||
"auto6": True,
|
||||
"ipv6_disabled": False,
|
||||
|
|
@ -820,6 +824,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"dhcp4_send_hostname": None,
|
||||
"gateway6": None,
|
||||
"gateway4": None,
|
||||
"wait_ip": "any",
|
||||
"auto6": True,
|
||||
"ipv6_disabled": False,
|
||||
"dns": [],
|
||||
|
|
@ -892,6 +897,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"dhcp4_send_hostname": None,
|
||||
"gateway6": None,
|
||||
"gateway4": None,
|
||||
"wait_ip": "any",
|
||||
"auto6": True,
|
||||
"ipv6_disabled": False,
|
||||
"dns": [{"address": "192.168.174.1", "family": socket.AF_INET}],
|
||||
|
|
@ -956,6 +962,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"ip": {
|
||||
"gateway6": "2001:db8::1",
|
||||
"gateway4": None,
|
||||
"wait_ip": "any",
|
||||
"route_metric4": None,
|
||||
"auto6": False,
|
||||
"ipv6_disabled": False,
|
||||
|
|
@ -1093,6 +1100,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"dhcp4_send_hostname": None,
|
||||
"gateway6": None,
|
||||
"gateway4": None,
|
||||
"wait_ip": "any",
|
||||
"dns": [],
|
||||
},
|
||||
"mac": "52:54:00:44:9f:ba",
|
||||
|
|
@ -1131,6 +1139,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"dhcp4_send_hostname": None,
|
||||
"gateway6": None,
|
||||
"gateway4": None,
|
||||
"wait_ip": "any",
|
||||
"auto6": False,
|
||||
"ipv6_disabled": False,
|
||||
"dns": [],
|
||||
|
|
@ -1235,6 +1244,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"dhcp4_send_hostname": None,
|
||||
"gateway6": None,
|
||||
"gateway4": None,
|
||||
"wait_ip": "any",
|
||||
"auto6": True,
|
||||
"ipv6_disabled": False,
|
||||
"dns": [],
|
||||
|
|
@ -1317,6 +1327,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"dhcp4_send_hostname": None,
|
||||
"gateway6": None,
|
||||
"gateway4": None,
|
||||
"wait_ip": "any",
|
||||
"auto6": True,
|
||||
"ipv6_disabled": False,
|
||||
"dns": [],
|
||||
|
|
@ -1438,6 +1449,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"dhcp4_send_hostname": None,
|
||||
"gateway6": None,
|
||||
"gateway4": None,
|
||||
"wait_ip": "any",
|
||||
"ipv6_disabled": False,
|
||||
"dns": [],
|
||||
},
|
||||
|
|
@ -1477,6 +1489,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"dhcp4_send_hostname": None,
|
||||
"gateway6": None,
|
||||
"gateway4": None,
|
||||
"wait_ip": "any",
|
||||
"ipv6_disabled": False,
|
||||
"auto6": False,
|
||||
"dns": [],
|
||||
|
|
@ -1598,6 +1611,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"dhcp4_send_hostname": None,
|
||||
"gateway6": None,
|
||||
"gateway4": None,
|
||||
"wait_ip": "any",
|
||||
"dns": [],
|
||||
},
|
||||
"mac": "33:24:10:24:2f:b9",
|
||||
|
|
@ -1636,6 +1650,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"dhcp4_send_hostname": None,
|
||||
"gateway6": None,
|
||||
"gateway4": None,
|
||||
"wait_ip": "any",
|
||||
"auto6": False,
|
||||
"dns": [],
|
||||
"address": [
|
||||
|
|
@ -1700,6 +1715,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"dhcp4_send_hostname": None,
|
||||
"gateway6": None,
|
||||
"gateway4": None,
|
||||
"wait_ip": "any",
|
||||
"ipv6_disabled": False,
|
||||
"auto6": False,
|
||||
"dns": [],
|
||||
|
|
@ -1818,6 +1834,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"dns_search": [],
|
||||
"gateway4": None,
|
||||
"gateway6": None,
|
||||
"wait_ip": "any",
|
||||
"ipv6_disabled": False,
|
||||
"route": [],
|
||||
"route_append_only": False,
|
||||
|
|
@ -1866,6 +1883,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"dns_search": [],
|
||||
"gateway4": None,
|
||||
"gateway6": None,
|
||||
"wait_ip": "any",
|
||||
"ipv6_disabled": False,
|
||||
"route": [],
|
||||
"route_append_only": False,
|
||||
|
|
@ -1961,6 +1979,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"dhcp4_send_hostname": None,
|
||||
"gateway6": None,
|
||||
"gateway4": None,
|
||||
"wait_ip": "any",
|
||||
"auto6": True,
|
||||
"ipv6_disabled": False,
|
||||
"dns": [],
|
||||
|
|
@ -2045,6 +2064,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"dhcp4_send_hostname": None,
|
||||
"gateway6": None,
|
||||
"gateway4": None,
|
||||
"wait_ip": "any",
|
||||
"auto6": True,
|
||||
"ipv6_disabled": False,
|
||||
"dns": [],
|
||||
|
|
@ -2117,6 +2137,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"dhcp4_send_hostname": None,
|
||||
"gateway4": None,
|
||||
"gateway6": None,
|
||||
"wait_ip": "any",
|
||||
"route_metric4": None,
|
||||
"route_metric6": None,
|
||||
"dns": [],
|
||||
|
|
@ -2160,6 +2181,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"ip": {
|
||||
"gateway6": None,
|
||||
"gateway4": None,
|
||||
"wait_ip": "any",
|
||||
"route_metric4": None,
|
||||
"auto6": True,
|
||||
"ipv6_disabled": False,
|
||||
|
|
@ -2255,6 +2277,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"dns_search": [],
|
||||
"gateway4": None,
|
||||
"gateway6": None,
|
||||
"wait_ip": "any",
|
||||
"route": [],
|
||||
"route_append_only": False,
|
||||
"route_metric4": None,
|
||||
|
|
@ -2302,6 +2325,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"dns_search": [],
|
||||
"gateway4": None,
|
||||
"gateway6": None,
|
||||
"wait_ip": "any",
|
||||
"ipv6_disabled": False,
|
||||
"route": [],
|
||||
"route_append_only": False,
|
||||
|
|
@ -2366,6 +2390,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"dns_search": [],
|
||||
"gateway4": None,
|
||||
"gateway6": None,
|
||||
"wait_ip": "any",
|
||||
"ipv6_disabled": False,
|
||||
"route": [],
|
||||
"route_append_only": False,
|
||||
|
|
@ -2447,6 +2472,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"dns_search": [],
|
||||
"gateway4": None,
|
||||
"gateway6": None,
|
||||
"wait_ip": "any",
|
||||
"ipv6_disabled": False,
|
||||
"route": [],
|
||||
"route_append_only": False,
|
||||
|
|
@ -2534,6 +2560,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"dns_search": [],
|
||||
"gateway4": None,
|
||||
"gateway6": None,
|
||||
"wait_ip": "any",
|
||||
"ipv6_disabled": False,
|
||||
"route": [],
|
||||
"route_append_only": False,
|
||||
|
|
@ -2581,6 +2608,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"dns_search": [],
|
||||
"gateway4": None,
|
||||
"gateway6": None,
|
||||
"wait_ip": "any",
|
||||
"ipv6_disabled": False,
|
||||
"route": [],
|
||||
"route_append_only": False,
|
||||
|
|
@ -2682,6 +2710,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"ip": {
|
||||
"gateway6": None,
|
||||
"gateway4": None,
|
||||
"wait_ip": "any",
|
||||
"route_metric4": None,
|
||||
"auto6": True,
|
||||
"ipv6_disabled": False,
|
||||
|
|
@ -2791,6 +2820,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"ip": {
|
||||
"gateway6": None,
|
||||
"gateway4": None,
|
||||
"wait_ip": "any",
|
||||
"route_metric4": None,
|
||||
"auto6": True,
|
||||
"ipv6_disabled": False,
|
||||
|
|
@ -2951,6 +2981,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"ip": {
|
||||
"gateway6": None,
|
||||
"gateway4": None,
|
||||
"wait_ip": "any",
|
||||
"route_metric4": None,
|
||||
"auto6": True,
|
||||
"ipv6_disabled": False,
|
||||
|
|
@ -3112,6 +3143,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"ip": {
|
||||
"gateway6": None,
|
||||
"gateway4": None,
|
||||
"wait_ip": "any",
|
||||
"route_metric4": None,
|
||||
"auto6": True,
|
||||
"ipv6_disabled": False,
|
||||
|
|
@ -3197,6 +3229,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"ip": {
|
||||
"gateway6": None,
|
||||
"gateway4": None,
|
||||
"wait_ip": "any",
|
||||
"route_metric4": None,
|
||||
"auto6": True,
|
||||
"ipv6_disabled": False,
|
||||
|
|
@ -3282,6 +3315,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"ip": {
|
||||
"gateway6": None,
|
||||
"gateway4": None,
|
||||
"wait_ip": "any",
|
||||
"route_metric4": None,
|
||||
"auto6": True,
|
||||
"ipv6_disabled": False,
|
||||
|
|
@ -3365,6 +3399,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"ip": {
|
||||
"gateway6": None,
|
||||
"gateway4": None,
|
||||
"wait_ip": "any",
|
||||
"route_metric4": None,
|
||||
"auto6": True,
|
||||
"ipv6_disabled": False,
|
||||
|
|
@ -3438,6 +3473,7 @@ class TestValidator(Python26CompatTestCase):
|
|||
"ip": {
|
||||
"gateway6": None,
|
||||
"gateway4": None,
|
||||
"wait_ip": "any",
|
||||
"route_metric4": None,
|
||||
"auto6": True,
|
||||
"ipv6_disabled": False,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue