From ef23275126898f316cb3e7e2df552c006e867105 Mon Sep 17 00:00:00 2001 From: Gris Ge Date: Tue, 14 Feb 2023 15:20:21 +0800 Subject: [PATCH] ip: Introduce `Interface.WAIT_IP` This patch is introducing `Interface.WAIT_IP` property with these possible values: * `Interface.WAIT_IP_ANY`("any"): System will consider interface activated when any IP stack is configured(neither static or automatic). * `Interface.WAIT_IP_IPV4`("ipv4"): System will wait IPv4 been configured. * `Interface.WAIT_IP_IPV6`("ipv6"): System will wait IPv6 been configured. * `Introduce.WAIT_IP_IPV4_AND_IPV6`("ipv4+ipv6"): System will wait both IPv4 and IPv6 been configured. Considering this old branch, there is no validation on invalid use cases like setting wait-ip on disabled IP stack. Example YAML on waiting both IP stacks: ```yml --- interfaces: - name: eth1 type: ethernet state: up mtu: 1500 wait-ip: ipv4+ipv6 ipv4: enabled: true dhcp: true ipv6: enabled: true dhcp: true autoconf: true ``` Integration test case included. Signed-off-by: Gris Ge --- libnmstate/nm/connection.py | 9 +++---- libnmstate/nm/ip.py | 48 +++++++++++++++++++++++++++++++++++++ libnmstate/nm/plugin.py | 29 +++++++++------------- libnmstate/schema.py | 5 ++++ 4 files changed, 69 insertions(+), 22 deletions(-) create mode 100644 libnmstate/nm/ip.py diff --git a/libnmstate/nm/connection.py b/libnmstate/nm/connection.py index 1974cfd4..1fbb380b 100644 --- a/libnmstate/nm/connection.py +++ b/libnmstate/nm/connection.py @@ -39,6 +39,7 @@ from .common import NM from .ethtool import create_ethtool_setting from .ieee_802_1x import create_802_1x_setting from .infiniband import create_setting as create_infiniband_setting +from .ip import set_wait_ip from .ipv4 import create_setting as create_ipv4_setting from .ipv6 import create_setting as create_ipv6_setting from .lldp import apply_lldp_setting @@ -106,10 +107,10 @@ class _ConnectionSetting: def create_new_nm_simple_conn(iface, nm_profile): nm_iface_type = Api2Nm.get_iface_type(iface.type) iface_info = iface.to_dict() - settings = [ - create_ipv4_setting(iface_info.get(Interface.IPV4), nm_profile), - create_ipv6_setting(iface_info.get(Interface.IPV6), nm_profile), - ] + ipv4_set = create_ipv4_setting(iface_info.get(Interface.IPV4), nm_profile) + ipv6_set = create_ipv6_setting(iface_info.get(Interface.IPV6), nm_profile) + set_wait_ip(ipv4_set, ipv6_set, iface_info.get(Interface.WAIT_IP)) + settings = [ipv4_set, ipv6_set] con_setting = _ConnectionSetting() if nm_profile and not is_multiconnect_profile(nm_profile): con_setting.import_by_profile(nm_profile, iface.is_controller) diff --git a/libnmstate/nm/ip.py b/libnmstate/nm/ip.py new file mode 100644 index 00000000..d0fc1e3b --- /dev/null +++ b/libnmstate/nm/ip.py @@ -0,0 +1,48 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +from libnmstate.schema import Interface + + +def get_wait_ip(applied_config): + if applied_config: + nm_ipv4_may_fail = _get_may_fail(applied_config, False) + nm_ipv6_may_fail = _get_may_fail(applied_config, True) + if nm_ipv4_may_fail and not nm_ipv6_may_fail: + return Interface.WAIT_IP_IPV6 + elif not nm_ipv4_may_fail and nm_ipv6_may_fail: + return Interface.WAIT_IP_IPV4 + elif not nm_ipv4_may_fail and not nm_ipv6_may_fail: + return Interface.WAIT_IP_IPV4_AND_IPV6 + return Interface.WAIT_IP_ANY + + +def set_wait_ip(nm_ipv4_set, nm_ipv6_set, wait_ip): + if nm_ipv4_set: + if wait_ip == Interface.WAIT_IP_ANY: + nm_ipv4_set.props.may_fail = True + elif wait_ip in ( + Interface.WAIT_IP_IPV4, + Interface.WAIT_IP_IPV4_AND_IPV6, + ): + nm_ipv4_set.props.may_fail = False + if nm_ipv6_set: + if wait_ip == Interface.WAIT_IP_ANY: + nm_ipv6_set.props.may_fail = True + elif wait_ip in ( + Interface.WAIT_IP_IPV6, + Interface.WAIT_IP_IPV4_AND_IPV6, + ): + nm_ipv6_set.props.may_fail = False + + +def _get_may_fail(nm_profile, is_ipv6): + if is_ipv6: + nm_set = nm_profile.get_setting_ip6_config() + else: + nm_set = nm_profile.get_setting_ip4_config() + + if nm_set: + return nm_set.props.may_fail + else: + # NM is defaulting `may-fail` as True + return True diff --git a/libnmstate/nm/plugin.py b/libnmstate/nm/plugin.py index bca1aedd..9bbbbb98 100644 --- a/libnmstate/nm/plugin.py +++ b/libnmstate/nm/plugin.py @@ -1,21 +1,5 @@ -# -# Copyright (c) 2020-2021 Red Hat, Inc. -# -# This file is part of nmstate -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation, either version 2.1 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program. If not, see . -# +# SPDX-License-Identifier: LGPL-2.1-or-later + from distutils.version import StrictVersion import logging from operator import itemgetter @@ -25,6 +9,8 @@ from libnmstate.error import NmstateNotSupportedError from libnmstate.error import NmstateValueError from libnmstate.schema import DNS from libnmstate.schema import Interface +from libnmstate.schema import InterfaceIPv4 +from libnmstate.schema import InterfaceIPv6 from libnmstate.schema import InterfaceType from libnmstate.schema import LLDP from libnmstate.plugin import NmstatePlugin @@ -41,6 +27,7 @@ from .device import list_devices from .dns import get_running as get_dns_running from .dns import get_running_config as get_dns_running_config from .infiniband import get_info as get_infiniband_info +from .ip import get_wait_ip from .ipv4 import get_info as get_ipv4_info from .ipv6 import get_info as get_ipv6_info from .lldp import get_info as get_lldp_info @@ -190,6 +177,12 @@ class NetworkManagerPlugin(NmstatePlugin): if applied_config: iface_info.update(get_ovsdb_external_ids(applied_config)) + if iface_info.get(Interface.IPV4, {}).get( + InterfaceIPv4.ENABLED + ) or iface_info.get(Interface.IPV6, {}).get( + InterfaceIPv6.ENABLED + ): + iface_info[Interface.WAIT_IP] = get_wait_ip(applied_config) info.append(iface_info) diff --git a/libnmstate/schema.py b/libnmstate/schema.py index e740abff..c3d3fcfc 100644 --- a/libnmstate/schema.py +++ b/libnmstate/schema.py @@ -49,6 +49,11 @@ class Interface: COPY_MAC_FROM = "copy-mac-from" ACCEPT_ALL_MAC_ADDRESSES = "accept-all-mac-addresses" CONTROLLER = "controller" + WAIT_IP = "wait-ip" + WAIT_IP_ANY = "any" + WAIT_IP_IPV4 = "ipv4" + WAIT_IP_IPV6 = "ipv6" + WAIT_IP_IPV4_AND_IPV6 = "ipv4+ipv6" class Route: -- 2.39.2