diff --git a/.gitignore b/.gitignore index 18b3d9b..54812f7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ -SOURCES/nmstate-1.0.2.tar.gz +SOURCES/nmstate-1.1.0.tar.gz SOURCES/nmstate.gpg diff --git a/.nmstate.metadata b/.nmstate.metadata index a6d3e02..f6d19a1 100644 --- a/.nmstate.metadata +++ b/.nmstate.metadata @@ -1,2 +1,2 @@ -eeda8a0238732e5dc37e2217ed6e316f76c93145 SOURCES/nmstate-1.0.2.tar.gz +0b7795853d1f7735cb05817389f188884d1f6f09 SOURCES/nmstate-1.1.0.tar.gz b5f872551d434e2c62b30d70471efaeede83ab44 SOURCES/nmstate.gpg diff --git a/SOURCES/0001-nmstatectl-fix-long-arguments-support.patch b/SOURCES/0001-nmstatectl-fix-long-arguments-support.patch new file mode 100644 index 0000000..4334857 --- /dev/null +++ b/SOURCES/0001-nmstatectl-fix-long-arguments-support.patch @@ -0,0 +1,53 @@ +From 99c7f643bab33a26c317e1b72ca3b8490cb1ea60 Mon Sep 17 00:00:00 2001 +From: Fernando Fernandez Mancera +Date: Fri, 16 Jul 2021 08:57:27 +0200 +Subject: [PATCH 1/4] nmstatectl: fix long arguments support + +The support for long arguments is broken. This patch is fixing it and +solving the following errors: + +``` +[root@d0b4a6a0f7a5 nmstate-workspace]# nmstatectl show --running-config +usage: nmstatectl [-h] [--version] + {commit,edit,rollback,set,apply,show,version,gc} ... +nmstatectl: error: unrecognized arguments: --running-config +[root@d0b4a6a0f7a5 nmstate-workspace]# nmstatectl show --show-secrets +usage: nmstatectl [-h] [--version] + {commit,edit,rollback,set,apply,show,version,gc} ... +nmstatectl: error: unrecognized arguments: --show-secrets +``` + +Integration test case added. + +Signed-off-by: Fernando Fernandez Mancera +Signed-off-by: Gris Ge +--- + nmstatectl/nmstatectl.py | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/nmstatectl/nmstatectl.py b/nmstatectl/nmstatectl.py +index a9f4cb6..6f83069 100644 +--- a/nmstatectl/nmstatectl.py ++++ b/nmstatectl/nmstatectl.py +@@ -223,14 +223,16 @@ def setup_subcommand_show(subparsers): + dest="yaml", + ) + parser_show.add_argument( +- "-r, --running-config", ++ "-r", ++ "--running-config", + help="Show running configurations", + default=False, + action="store_true", + dest="running_config", + ) + parser_show.add_argument( +- "-s, --show-secrets", ++ "-s", ++ "--show-secrets", + help="Show secrets also", + default=False, + action="store_true", +-- +2.32.0 + diff --git a/SOURCES/0002-nm-ethtool-Preserve-existing-ethtool-settings-when-u.patch b/SOURCES/0002-nm-ethtool-Preserve-existing-ethtool-settings-when-u.patch new file mode 100644 index 0000000..5f5ebec --- /dev/null +++ b/SOURCES/0002-nm-ethtool-Preserve-existing-ethtool-settings-when-u.patch @@ -0,0 +1,105 @@ +From b1cb57d1dc4bba6592ba5cfc5c810a2ad19ac941 Mon Sep 17 00:00:00 2001 +From: Gris Ge +Date: Thu, 22 Jul 2021 18:40:50 +0800 +Subject: [PATCH 2/4] nm ethtool: Preserve existing ethtool settings when + undesired + +When user does not define ethtool settings in desire state, +we should preserve existing ethtool setting. + +Integration test case included. + +Signed-off-by: Gris Ge +Signed-off-by: Fernando Fernandez Mancera +--- + libnmstate/nm/connection.py | 18 +++--------------- + libnmstate/nm/ethtool.py | 26 +++++++++++++++++++++++++- + 2 files changed, 28 insertions(+), 16 deletions(-) + +diff --git a/libnmstate/nm/connection.py b/libnmstate/nm/connection.py +index 5d60f6d..5a79c6f 100644 +--- a/libnmstate/nm/connection.py ++++ b/libnmstate/nm/connection.py +@@ -22,8 +22,6 @@ + import uuid + + from libnmstate.error import NmstatePluginError +-from libnmstate.ifaces import IfaceEthtool +-from libnmstate.schema import Ethtool + from libnmstate.schema import Interface + from libnmstate.schema import InterfaceType + from libnmstate.schema import LinuxBridge as LB +@@ -240,19 +238,9 @@ def create_new_nm_simple_conn(iface, nm_profile): + if iface.ieee_802_1x_conf: + settings.append(create_802_1x_setting(iface.ieee_802_1x_conf)) + +- if Ethtool.CONFIG_SUBTREE in iface.original_desire_dict: +- iface_ethtool = IfaceEthtool( +- iface.original_desire_dict[Ethtool.CONFIG_SUBTREE] +- ) +- iface_ethtool.canonicalize( +- iface.original_desire_dict[Ethtool.CONFIG_SUBTREE] +- ) +- setting = create_ethtool_setting( +- iface_ethtool, +- nm_profile, +- ) +- if setting: +- settings.append(setting) ++ ethtool_setting = create_ethtool_setting(iface, nm_profile) ++ if ethtool_setting: ++ settings.append(ethtool_setting) + + nm_simple_conn = NM.SimpleConnection.new() + for setting in settings: +diff --git a/libnmstate/nm/ethtool.py b/libnmstate/nm/ethtool.py +index 466f4f9..3cad1bf 100644 +--- a/libnmstate/nm/ethtool.py ++++ b/libnmstate/nm/ethtool.py +@@ -22,6 +22,7 @@ import logging + from .common import NM + from .common import GLib + ++from libnmstate.ifaces import IfaceEthtool + from libnmstate.schema import Ethtool + + +@@ -59,7 +60,7 @@ _NM_COALESCE_OPT_NAME_MAP = { + } + + +-def create_ethtool_setting(iface_ethtool, base_con_profile): ++def _create_ethtool_setting(iface_ethtool, base_con_profile): + nm_setting = None + + if base_con_profile: +@@ -159,3 +160,26 @@ def nm_set_pause(nm_setting, autoneg, rx, tx): + tx_value, + ) + # pylint: enable=no-member ++ ++ ++def create_ethtool_setting(iface, base_con_profile): ++ if Ethtool.CONFIG_SUBTREE in iface.original_desire_dict: ++ iface_ethtool = IfaceEthtool( ++ iface.original_desire_dict[Ethtool.CONFIG_SUBTREE] ++ ) ++ iface_ethtool.canonicalize( ++ iface.original_desire_dict[Ethtool.CONFIG_SUBTREE] ++ ) ++ return _create_ethtool_setting( ++ iface_ethtool, ++ base_con_profile, ++ ) ++ else: ++ # Preserve existing setting but not create new ++ if base_con_profile: ++ ethtool_setting = base_con_profile.get_setting_by_name( ++ NM.SETTING_ETHTOOL_SETTING_NAME ++ ) ++ if ethtool_setting: ++ return ethtool_setting.duplicate() ++ return None +-- +2.32.0 + diff --git a/SOURCES/0003-ovs-fix-state-ignore-for-ovs-port-when-removing-them.patch b/SOURCES/0003-ovs-fix-state-ignore-for-ovs-port-when-removing-them.patch new file mode 100644 index 0000000..ba000ef --- /dev/null +++ b/SOURCES/0003-ovs-fix-state-ignore-for-ovs-port-when-removing-them.patch @@ -0,0 +1,87 @@ +From f4d190653c55d399b32afc956b2b4a1ff8d20101 Mon Sep 17 00:00:00 2001 +From: Fernando Fernandez Mancera +Date: Mon, 26 Jul 2021 09:58:23 +0200 +Subject: [PATCH 3/4] ovs: fix state=ignore for ovs port when removing them + +When removing an ovs port while the interface is marked as ignored, the +interface should not being removed from the ovs bridge as the user +specidied it should be ignored. + +Example: + +``` +interfaces: +- name: dummy0 + type: dummy + state: ignore +- name: ovsbr0 + type: ovs-bridge + state: up + bridge: + port: + - name: ovs0 +``` + +Integration test case added. + +Signed-off-by: Fernando Fernandez Mancera +Signed-off-by: Gris Ge +--- + libnmstate/nm/profiles.py | 22 ++++++++++++++++++++-- + 1 file changed, 20 insertions(+), 2 deletions(-) + +diff --git a/libnmstate/nm/profiles.py b/libnmstate/nm/profiles.py +index beda5c7..3b0b6be 100644 +--- a/libnmstate/nm/profiles.py ++++ b/libnmstate/nm/profiles.py +@@ -23,6 +23,8 @@ + import logging + from operator import attrgetter + ++from libnmstate.schema import Interface ++from libnmstate.schema import InterfaceState + from libnmstate.schema import InterfaceType + + from .common import NM +@@ -359,7 +361,7 @@ def _delete_orphan_nm_ovs_port_profiles( + continue + # When OVS port has no child, delete it + ovs_bridge_iface = ovs_bridge_profile.iface +- if not _nm_ovs_port_has_child( ++ if not _nm_ovs_port_has_child_or_is_ignored( + nm_profile, ovs_bridge_iface, net_state + ): + ProfileDelete( +@@ -404,7 +406,9 @@ def _use_uuid_as_controller_and_parent(nm_profiles): + nm_profile.update_parent(uuid) + + +-def _nm_ovs_port_has_child(nm_profile, ovs_bridge_iface, net_state): ++def _nm_ovs_port_has_child_or_is_ignored( ++ nm_profile, ovs_bridge_iface, net_state ++): + ovs_port_uuid = nm_profile.get_uuid() + ovs_port_name = nm_profile.get_interface_name() + for ovs_iface_name in ovs_bridge_iface.port: +@@ -415,4 +419,18 @@ def _nm_ovs_port_has_child(nm_profile, ovs_bridge_iface, net_state): + and ovs_iface.controller_type == InterfaceType.OVS_PORT + ): + return True ++ # Gather the ovs bridge interface from the current state in order to check ++ # if any port is ignored in the original desired state. ++ current_ovs_bridge = net_state.ifaces.get_cur_iface( ++ ovs_bridge_iface.name, InterfaceType.OVS_BRIDGE ++ ) ++ if current_ovs_bridge: ++ for port_name in current_ovs_bridge.port: ++ port_iface = net_state.ifaces.all_kernel_ifaces.get(port_name) ++ if ( ++ port_iface ++ and port_iface.original_desire_dict.get(Interface.STATE) ++ == InterfaceState.IGNORE ++ ): ++ return True + return False +-- +2.32.0 + diff --git a/SOURCES/BZ_1986285-nispor-fix-show-of-empty-next_hop_address-and-destin.patch b/SOURCES/0004-nispor-fix-show-of-empty-next_hop_address-and-destin.patch similarity index 86% rename from SOURCES/BZ_1986285-nispor-fix-show-of-empty-next_hop_address-and-destin.patch rename to SOURCES/0004-nispor-fix-show-of-empty-next_hop_address-and-destin.patch index d653412..40be31b 100644 --- a/SOURCES/BZ_1986285-nispor-fix-show-of-empty-next_hop_address-and-destin.patch +++ b/SOURCES/0004-nispor-fix-show-of-empty-next_hop_address-and-destin.patch @@ -1,7 +1,8 @@ -From ab55d90e31a121f1cb18d79582a8f4d2a138df91 Mon Sep 17 00:00:00 2001 +From 369ed3210ecedfa1deda88a6eb7cacc19a47f89d Mon Sep 17 00:00:00 2001 From: Fernando Fernandez Mancera Date: Mon, 26 Jul 2021 16:13:15 +0200 -Subject: [PATCH] nispor: fix show of empty next_hop_address and destination +Subject: [PATCH 4/4] nispor: fix show of empty next_hop_address and + destination The correct way of representing an empty next_hop_address is using "0.0.0.0" for IPv4 and "::" for IPv6. This configuration is valid @@ -33,10 +34,10 @@ Integration test case added. Ref: https://bugzilla.redhat.com/1985879 Signed-off-by: Fernando Fernandez Mancera +Signed-off-by: Gris Ge --- - libnmstate/nispor/route.py | 13 +++++++++---- - tests/integration/route_test.py | 30 +++++++++++++++++++++++++++++- - 2 files changed, 38 insertions(+), 5 deletions(-) + libnmstate/nispor/route.py | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/libnmstate/nispor/route.py b/libnmstate/nispor/route.py index 510ddc3..9852ba5 100644 @@ -81,5 +82,5 @@ index 510ddc3..9852ba5 100644 return { Route.TABLE_ID: np_rt.table, -- -2.31.1 +2.32.0 diff --git a/SOURCES/BZ_1931355-SRIOV-wait-VF-mount-decrease.patch b/SOURCES/BZ_1931355-SRIOV-wait-VF-mount-decrease.patch deleted file mode 100644 index f215f9f..0000000 --- a/SOURCES/BZ_1931355-SRIOV-wait-VF-mount-decrease.patch +++ /dev/null @@ -1,166 +0,0 @@ -From 80c97b27707b036f0a54988ade4bda3ccb342b34 Mon Sep 17 00:00:00 2001 -From: Fernando Fernandez Mancera -Date: Mon, 22 Feb 2021 12:03:11 +0100 -Subject: [PATCH 1/2] SR-IOV: increase the verification timeout if SR-IOV is - present - -Certain drivers like i40e take a long time to modify the VFs in the -kernel. Nmstate is timing out on verification because of that. In order -to fix this, nmstate is incresing the verification time if SR-IOV is -present on the desired state. - -Signed-off-by: Fernando Fernandez Mancera -Signed-off-by: Gris Ge ---- - libnmstate/ifaces/ethernet.py | 6 ++++++ - libnmstate/netapplier.py | 18 +++++++++++++++++- - 2 files changed, 23 insertions(+), 1 deletion(-) - -diff --git a/libnmstate/ifaces/ethernet.py b/libnmstate/ifaces/ethernet.py -index 292b7bc..ca8501b 100644 ---- a/libnmstate/ifaces/ethernet.py -+++ b/libnmstate/ifaces/ethernet.py -@@ -65,6 +65,12 @@ class EthernetIface(BaseIface): - def is_peer(self): - return self._is_peer - -+ @property -+ def is_sriov(self): -+ return self.raw.get(Ethernet.CONFIG_SUBTREE, {}).get( -+ Ethernet.SRIOV_SUBTREE -+ ) -+ - def create_sriov_vf_ifaces(self): - return [ - EthernetIface( -diff --git a/libnmstate/netapplier.py b/libnmstate/netapplier.py -index cf208d1..3c5759b 100644 ---- a/libnmstate/netapplier.py -+++ b/libnmstate/netapplier.py -@@ -24,6 +24,7 @@ import time - - from libnmstate import validator - from libnmstate.error import NmstateVerificationError -+from libnmstate.schema import InterfaceType - - from .nmstate import create_checkpoints - from .nmstate import destroy_checkpoints -@@ -37,6 +38,7 @@ from .version import get_version - MAINLOOP_TIMEOUT = 35 - VERIFY_RETRY_INTERNAL = 1 - VERIFY_RETRY_TIMEOUT = 5 -+VERIFY_RETRY_TIMEOUT_INCREASE = 4 - - - def apply( -@@ -109,7 +111,13 @@ def _apply_ifaces_state(plugins, net_state, verify_change, save_to_disk): - plugin.apply_changes(net_state, save_to_disk) - verified = False - if verify_change: -- for _ in range(VERIFY_RETRY_TIMEOUT): -+ if _net_state_contains_sriov_interface(net_state): -+ # If SR-IOV is present, the verification timeout is being increased -+ # to avoid timeouts due to slow drivers like i40e. -+ verify_retry = VERIFY_RETRY_TIMEOUT * VERIFY_RETRY_TIMEOUT_INCREASE -+ else: -+ verify_retry = VERIFY_RETRY_TIMEOUT -+ for _ in range(verify_retry): - try: - _verify_change(plugins, net_state) - verified = True -@@ -120,6 +128,14 @@ def _apply_ifaces_state(plugins, net_state, verify_change, save_to_disk): - _verify_change(plugins, net_state) - - -+def _net_state_contains_sriov_interface(net_state): -+ for iface in net_state.ifaces.all_kernel_ifaces.values(): -+ if iface.type == InterfaceType.ETHERNET and iface.is_sriov: -+ return True -+ -+ return False -+ -+ - def _verify_change(plugins, net_state): - current_state = show_with_plugins(plugins) - net_state.verify(current_state) --- -2.27.0 - - -From 439fe3a51a82060c5b62974c6c9fbdf403c4196b Mon Sep 17 00:00:00 2001 -From: Fernando Fernandez Mancera -Date: Mon, 22 Feb 2021 13:33:06 +0100 -Subject: [PATCH 2/2] SR-IOV: fail on verification if `total_vfs` does not - match vfs len - -Signed-off-by: Fernando Fernandez Mancera -Signed-off-by: Gris Ge ---- - libnmstate/ifaces/ethernet.py | 11 +++++++++++ - libnmstate/ifaces/ifaces.py | 14 ++++++++++++++ - 2 files changed, 25 insertions(+) - -diff --git a/libnmstate/ifaces/ethernet.py b/libnmstate/ifaces/ethernet.py -index ca8501b..55772ce 100644 ---- a/libnmstate/ifaces/ethernet.py -+++ b/libnmstate/ifaces/ethernet.py -@@ -61,6 +61,14 @@ class EthernetIface(BaseIface): - .get(Ethernet.SRIOV.TOTAL_VFS, 0) - ) - -+ @property -+ def sriov_vfs(self): -+ return ( -+ self.raw.get(Ethernet.CONFIG_SUBTREE, {}) -+ .get(Ethernet.SRIOV_SUBTREE, {}) -+ .get(Ethernet.SRIOV.VFS_SUBTREE, []) -+ ) -+ - @property - def is_peer(self): - return self._is_peer -@@ -108,6 +116,9 @@ class EthernetIface(BaseIface): - for i in range(self.sriov_total_vfs, old_sriov_total_vfs) - ] - -+ def check_total_vfs_matches_vf_list(self, total_vfs): -+ return total_vfs == len(self.sriov_vfs) -+ - - def _capitalize_sriov_vf_mac(state): - vfs = ( -diff --git a/libnmstate/ifaces/ifaces.py b/libnmstate/ifaces/ifaces.py -index 44c9e61..6c94a98 100644 ---- a/libnmstate/ifaces/ifaces.py -+++ b/libnmstate/ifaces/ifaces.py -@@ -238,6 +238,8 @@ class Ifaces: - if new_iface.name not in self._kernel_ifaces: - new_iface.mark_as_desired() - new_ifaces.append(new_iface) -+ else: -+ self._kernel_ifaces[new_iface.name].mark_as_desired() - for new_iface in new_ifaces: - self._kernel_ifaces[new_iface.name] = new_iface - -@@ -656,6 +658,18 @@ class Ifaces: - cur_iface.state_for_verify(), - ) - ) -+ elif ( -+ iface.type == InterfaceType.ETHERNET and iface.is_sriov -+ ): -+ if not cur_iface.check_total_vfs_matches_vf_list( -+ iface.sriov_total_vfs -+ ): -+ raise NmstateVerificationError( -+ "The NIC exceeded the waiting time for " -+ "verification and it is failing because " -+ "the `total_vfs` does not match the VF " -+ "list length." -+ ) - - def gen_dns_metadata(self, dns_state, route_state): - iface_metadata = dns_state.gen_metadata(self, route_state) --- -2.27.0 - diff --git a/SOURCES/BZ_1931751-nmstate-fix-return-code.patch b/SOURCES/BZ_1931751-nmstate-fix-return-code.patch deleted file mode 100644 index 78b6774..0000000 --- a/SOURCES/BZ_1931751-nmstate-fix-return-code.patch +++ /dev/null @@ -1,29 +0,0 @@ -From b26ab850172a41557cad42cc011bd00d7c108c88 Mon Sep 17 00:00:00 2001 -From: Gris Ge -Date: Tue, 23 Feb 2021 13:52:19 +0800 -Subject: [PATCH] nmstatectl: Fix return code of set command - -The deprecated command `set` should still return the error like -old behaviour. - -Signed-off-by: Gris Ge ---- - nmstatectl/nmstatectl.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/nmstatectl/nmstatectl.py b/nmstatectl/nmstatectl.py -index df59942..c94d603 100644 ---- a/nmstatectl/nmstatectl.py -+++ b/nmstatectl/nmstatectl.py -@@ -323,7 +323,7 @@ def show(args): - - def set(args): - warnings.warn("Using 'set' is deprecated, use 'apply' instead.") -- apply(args) -+ return apply(args) - - - def apply(args): --- -2.27.0 - diff --git a/SOURCES/BZ_1932247-nm-Don-t-touch-unmanaged-interface-unless-desired.patch b/SOURCES/BZ_1932247-nm-Don-t-touch-unmanaged-interface-unless-desired.patch deleted file mode 100644 index ea46af7..0000000 --- a/SOURCES/BZ_1932247-nm-Don-t-touch-unmanaged-interface-unless-desired.patch +++ /dev/null @@ -1,223 +0,0 @@ -From ccdcd8f86544a6364109a0c0142d05a5afacf64e Mon Sep 17 00:00:00 2001 -From: Gris Ge -Date: Tue, 2 Mar 2021 15:31:20 +0800 -Subject: [PATCH] nm: Don't touch unmanaged interface unless desired - -We should ignore NetworkManager unmanaged interface when applying and -verifying unless certain interface listed in desired state explicitly. - -Introduced new plugin interface -`NmstatePlugin.get_ignored_kernel_interface_names()` where plugin may -include a list of interface names which should be ignored during -verification stage. - -Integration test case added to simulate CNV usage on partial editing -a linux bridge holding NM unmanaged interface. - -Signed-off-by: Gris Ge ---- - libnmstate/ifaces/base_iface.py | 3 ++ - libnmstate/ifaces/ifaces.py | 26 ++++++++-------- - libnmstate/netapplier.py | 6 ++++ - libnmstate/nispor/plugin.py | 6 +++- - libnmstate/nm/plugin.py | 25 ++++++++++++++++ - libnmstate/plugin.py | 7 +++++ - tests/integration/linux_bridge_test.py | 8 +---- - tests/integration/nm/linux_bridge_test.py | 36 ++++++++++++++++++++++- - 8 files changed, 95 insertions(+), 22 deletions(-) - -diff --git a/libnmstate/ifaces/base_iface.py b/libnmstate/ifaces/base_iface.py -index 227c1d20..e3f2a1ca 100644 ---- a/libnmstate/ifaces/base_iface.py -+++ b/libnmstate/ifaces/base_iface.py -@@ -322,6 +322,9 @@ class BaseIface: - def mark_as_up(self): - self.raw[Interface.STATE] = InterfaceState.UP - -+ def mark_as_ignored(self): -+ self.raw[Interface.STATE] = InterfaceState.IGNORE -+ - @property - def is_controller(self): - return False -diff --git a/libnmstate/ifaces/ifaces.py b/libnmstate/ifaces/ifaces.py -index 6c94a986..efa24aa3 100644 ---- a/libnmstate/ifaces/ifaces.py -+++ b/libnmstate/ifaces/ifaces.py -@@ -95,7 +95,6 @@ class Ifaces: - self._kernel_ifaces = {} - self._user_space_ifaces = _UserSpaceIfaces() - self._cur_user_space_ifaces = _UserSpaceIfaces() -- self._ignored_ifaces = set() - if cur_iface_infos: - for iface_info in cur_iface_infos: - cur_iface = _to_specific_iface_obj(iface_info, save_to_disk) -@@ -143,10 +142,6 @@ class Ifaces: - ): - # Ignore interface with unknown type - continue -- if iface.is_ignore: -- self._ignored_ifaces.add( -- (iface.name, iface.type, iface.is_user_space_only) -- ) - if cur_iface: - iface.merge(cur_iface) - iface.mark_as_desired() -@@ -169,6 +164,10 @@ class Ifaces: - - self._pre_edit_validation_and_cleanup() - -+ @property -+ def _ignored_ifaces(self): -+ return [iface for iface in self.all_ifaces() if iface.is_ignore] -+ - def _apply_copy_mac_from(self): - for iface in self.all_kernel_ifaces.values(): - if iface.type not in ( -@@ -284,7 +283,7 @@ class Ifaces: - if not defiend in desire state - """ - for iface in self.all_ifaces(): -- if iface.is_up and iface.is_controller: -+ if iface.is_desired and iface.is_up and iface.is_controller: - for port_name in iface.port: - port_iface = self._kernel_ifaces[port_name] - if not port_iface.is_desired and not port_iface.is_up: -@@ -550,13 +549,14 @@ class Ifaces: - return None - - def _remove_iface(self, iface_name, iface_type): -- cur_iface = self._cur_kernel_ifaces.get(iface_name, iface_type) -+ cur_iface = self._user_space_ifaces.get(iface_name, iface_type) - if cur_iface: - self._user_space_ifaces.remove(cur_iface) - else: - cur_iface = self._kernel_ifaces.get(iface_name) - if ( -- iface_type -+ cur_iface -+ and iface_type - and iface_type != InterfaceType.UNKNOWN - and iface_type == cur_iface.type - ): -@@ -813,14 +813,14 @@ class Ifaces: - port_controller_map[port_name] = iface.name - - def _remove_ignore_interfaces(self, ignored_ifaces): -- for iface_name, iface_type, _ in ignored_ifaces: -- self._remove_iface(iface_name, iface_type) -+ for iface in ignored_ifaces: -+ self._remove_iface(iface.name, iface.type) - - # Only kernel interface can be used as port - ignored_kernel_iface_names = set( -- iface_name -- for iface_name, _, is_user_space_only in ignored_ifaces -- if not is_user_space_only -+ iface.name -+ for iface in ignored_ifaces -+ if not iface.is_user_space_only - ) - - # Remove ignored port -diff --git a/libnmstate/netapplier.py b/libnmstate/netapplier.py -index 3c5759b4..a020f003 100644 ---- a/libnmstate/netapplier.py -+++ b/libnmstate/netapplier.py -@@ -107,8 +107,14 @@ def rollback(*, checkpoint=None): - - - def _apply_ifaces_state(plugins, net_state, verify_change, save_to_disk): -+ for plugin in plugins: -+ for iface_name in plugin.get_ignored_kernel_interface_names(): -+ iface = net_state.ifaces.all_kernel_ifaces.get(iface_name) -+ if iface and not iface.is_desired: -+ iface.mark_as_ignored() - for plugin in plugins: - plugin.apply_changes(net_state, save_to_disk) -+ - verified = False - if verify_change: - if _net_state_contains_sriov_interface(net_state): -diff --git a/libnmstate/nispor/plugin.py b/libnmstate/nispor/plugin.py -index dc0ea760..19b21d56 100644 ---- a/libnmstate/nispor/plugin.py -+++ b/libnmstate/nispor/plugin.py -@@ -159,7 +159,11 @@ class NisporPlugin(NmstatePlugin): - np_state = NisporNetState.retrieve() - logging.debug(f"Nispor: current network state {np_state}") - for iface in net_state.ifaces.all_ifaces(): -- if iface.is_desired: -+ if iface.is_ignore: -+ logging.debug( -+ f"Nispor: Interface {iface.name} {iface.type} ignored" -+ ) -+ elif iface.is_desired: - logging.debug( - f"Nispor: desired network state {iface.to_dict()}" - ) -diff --git a/libnmstate/nm/plugin.py b/libnmstate/nm/plugin.py -index 302b4cca..335d93c7 100644 ---- a/libnmstate/nm/plugin.py -+++ b/libnmstate/nm/plugin.py -@@ -36,6 +36,7 @@ from .checkpoint import get_checkpoints - from .common import NM - from .context import NmContext - from .device import get_device_common_info -+from .device import get_iface_type - 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 -@@ -268,6 +269,21 @@ class NetworkManagerPlugin(NmstatePlugin): - ) - return NmProfiles(None).generate_config_strings(net_state) - -+ def get_ignored_kernel_interface_names(self): -+ """ -+ Return a list of unmanged kernel interface names. -+ """ -+ ignored_ifaces = set() -+ for nm_dev in list_devices(self.client): -+ if ( -+ nm_dev -+ and nm_dev.get_iface() -+ and not nm_dev.get_managed() -+ and _is_kernel_iface(nm_dev) -+ ): -+ ignored_ifaces.add(nm_dev.get_iface()) -+ return list(ignored_ifaces) -+ - - def _remove_ovs_bridge_unsupported_entries(iface_info): - """ -@@ -283,3 +299,12 @@ def _remove_ovs_bridge_unsupported_entries(iface_info): - - def _nm_utils_decode_version(): - return f"{NM.MAJOR_VERSION}.{NM.MINOR_VERSION}.{NM.MICRO_VERSION}" -+ -+ -+def _is_kernel_iface(nm_dev): -+ iface_type = get_iface_type(nm_dev) -+ return iface_type != InterfaceType.UNKNOWN and iface_type not in ( -+ InterfaceType.OVS_BRIDGE, -+ InterfaceType.OVS_INTERFACE, -+ InterfaceType.OVS_PORT, -+ ) -diff --git a/libnmstate/plugin.py b/libnmstate/plugin.py -index ef3874ff..e1d9ad58 100644 ---- a/libnmstate/plugin.py -+++ b/libnmstate/plugin.py -@@ -128,3 +128,10 @@ class NmstatePlugin(metaclass=ABCMeta): - persistently. - """ - return [] -+ -+ def get_ignored_kernel_interface_names(self): -+ """ -+ Return a list of kernel interface names which should be ignored -+ during verification stage. -+ """ -+ return [] --- -2.29.2 - diff --git a/SOURCES/BZ_1961912-fix-ovs-interface-activation.patch b/SOURCES/BZ_1961912-fix-ovs-interface-activation.patch deleted file mode 100644 index 81109e5..0000000 --- a/SOURCES/BZ_1961912-fix-ovs-interface-activation.patch +++ /dev/null @@ -1,137 +0,0 @@ -From 95d77329b30c9a9a435a881941e27f9a1bed074e Mon Sep 17 00:00:00 2001 -From: Fernando Fernandez Mancera -Date: Wed, 5 May 2021 10:14:40 +0200 -Subject: [PATCH 1/2] nm.profile: do not activate new interfaces twice - -The current code is always adding the action MODIFIED if the interface -is marked as up on the desired state. When a new interface is being -added, Nmstate is adding two actions MODIFIED and NEW_*, that is -incorrect. - -This patch is improving the performance when creating new interfaces. - -Signed-off-by: Fernando Fernandez Mancera -Signed-off-by: Gris Ge ---- - libnmstate/nm/profile.py | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/libnmstate/nm/profile.py b/libnmstate/nm/profile.py -index b4814d9..e117dfe 100644 ---- a/libnmstate/nm/profile.py -+++ b/libnmstate/nm/profile.py -@@ -164,7 +164,6 @@ class NmProfile: - if self._iface.is_virtual and self._nm_dev: - self._add_action(NmProfile.ACTION_DELETE_DEVICE) - elif self._iface.is_up and not self._needs_veth_activation(): -- self._add_action(NmProfile.ACTION_MODIFIED) - if not self._nm_dev: - if self._iface.type == InterfaceType.OVS_PORT: - self._add_action(NmProfile.ACTION_NEW_OVS_PORT) -@@ -176,6 +175,8 @@ class NmProfile: - self._add_action(NmProfile.ACTION_NEW_VXLAN) - else: - self._add_action(NmProfile.ACTION_NEW_IFACES) -+ else: -+ self._add_action(NmProfile.ACTION_MODIFIED) - - elif self._iface.is_down: - if self._nm_ac: --- -2.31.1 - - -From 9ea925a9a978671881e428abf82aac39c01376e8 Mon Sep 17 00:00:00 2001 -From: Fernando Fernandez Mancera -Date: Wed, 5 May 2021 10:52:32 +0200 -Subject: [PATCH 2/2] nm.profile: activate modified ovs-port first - -When removing an ovs-br with an ovs-iface attached and creating a new -ovs-br with the ovs-iface attached in the same transaction the order of -the activations is important. - -The ovs-port must be activated before the ovs-iface. If not, NM will -throw a dependency error. This error is correct because the ovs-iface -depends on the ovs-port, so it must be updated first. - -This fixes: - -``` -Traceback (most recent call last): - File "/usr/lib/python3.6/site-packages/libnmstate/nm/checkpoint.py", line 93, in _refresh_checkpoint_timeout - self._dbuspath, self._timeout, cancellable, cb, cb_data -TypeError: Argument 1 does not allow None as a value -^CTraceback (most recent call last): - File "/usr/lib/python3.6/site-packages/libnmstate/nmstate.py", line 53, in plugin_context - yield plugins - File "/usr/lib/python3.6/site-packages/libnmstate/netapplier.py", line 78, in apply - _apply_ifaces_state(plugins, net_state, verify_change, save_to_disk) - File "/usr/lib/python3.6/site-packages/libnmstate/netapplier.py", line 116, in _apply_ifaces_state - plugin.apply_changes(net_state, save_to_disk) - File "/usr/lib/python3.6/site-packages/libnmstate/nm/plugin.py", line 204, in apply_changes - NmProfiles(self.context).apply_config(net_state, save_to_disk) - File "/usr/lib/python3.6/site-packages/libnmstate/nm/profiles.py", line 89, in apply_config - self._ctx.wait_all_finish() - File "/usr/lib/python3.6/site-packages/libnmstate/nm/context.py", line 213, in wait_all_finish - raise tmp_error -libnmstate.error.NmstateLibnmError: Activate profile uuid:3a359cd0-d68a-4c7a-ae50-f97b47390142 iface:net type: ovs-interface failed: reason= -``` - -Integration test added - -Ref: https://bugzilla.redhat.com/1947287 - -Signed-off-by: Fernando Fernandez Mancera -Signed-off-by: Gris Ge ---- - libnmstate/nm/profile.py | 13 ++++++++++++- - 1 file changed, 12 insertions(+), 1 deletion(-) - -diff --git a/libnmstate/nm/profile.py b/libnmstate/nm/profile.py -index e117dfe..b655885 100644 ---- a/libnmstate/nm/profile.py -+++ b/libnmstate/nm/profile.py -@@ -69,6 +69,8 @@ class NmProfile: - ACTION_OTHER_MASTER = "other_master" - ACTION_DELETE_PROFILE = "delete_profile" - ACTION_TOP_MASTER = "top_master" -+ ACTION_MODIFIED_OVS_PORT = "modified_ovs_port" -+ ACTION_MODIFIED_OVS_IFACE = "modified_ovs_iface" - - # This is order on group for activation/deactivation - ACTIONS = ( -@@ -81,6 +83,8 @@ class NmProfile: - ACTION_NEW_OVS_IFACE, - ACTION_NEW_VETH, - ACTION_NEW_VETH_PEER, -+ ACTION_MODIFIED_OVS_PORT, -+ ACTION_MODIFIED_OVS_IFACE, - ACTION_MODIFIED, - ACTION_NEW_VLAN, - ACTION_NEW_VXLAN, -@@ -176,7 +180,12 @@ class NmProfile: - else: - self._add_action(NmProfile.ACTION_NEW_IFACES) - else: -- self._add_action(NmProfile.ACTION_MODIFIED) -+ if self._iface.type == InterfaceType.OVS_PORT: -+ self._add_action(NmProfile.ACTION_MODIFIED_OVS_PORT) -+ if self._iface.type == InterfaceType.OVS_INTERFACE: -+ self._add_action(NmProfile.ACTION_MODIFIED_OVS_IFACE) -+ else: -+ self._add_action(NmProfile.ACTION_MODIFIED) - - elif self._iface.is_down: - if self._nm_ac: -@@ -420,6 +429,8 @@ class NmProfile: - def do_action(self, action): - if action in ( - NmProfile.ACTION_MODIFIED, -+ NmProfile.ACTION_MODIFIED_OVS_PORT, -+ NmProfile.ACTION_MODIFIED_OVS_IFACE, - NmProfile.ACTION_ACTIVATE_FIRST, - NmProfile.ACTION_TOP_MASTER, - NmProfile.ACTION_NEW_IFACES, --- -2.31.1 - diff --git a/SOURCES/BZ_1961914-do-not-use-unmanaged-interface-for-dns.patch b/SOURCES/BZ_1961914-do-not-use-unmanaged-interface-for-dns.patch deleted file mode 100644 index c6b7af3..0000000 --- a/SOURCES/BZ_1961914-do-not-use-unmanaged-interface-for-dns.patch +++ /dev/null @@ -1,163 +0,0 @@ -From 72edab395316ba1ae69ea4d788b0572c935759ac Mon Sep 17 00:00:00 2001 -From: Fernando Fernandez Mancera -Date: Tue, 27 Apr 2021 10:19:02 +0200 -Subject: [PATCH] net_state: mark ifaces as ignored earlier - -Nmstate is not touching unmanaged interfaces if they are not being -included in the desired state. If an unmanaged interface has a default -gateway configured and we try to add a dns server, Nmstate will pick the -unmanaged interface because at that point it is not marked as ignored. - -As the interface is being marked as ignored later, the changes are not -being applied and is failing on verification. In order to avoid this, -the unmanaged interfaces should be marked as ignored earlier so they are -not considered for DNS/Routes changes. - -Ref: https://bugzilla.redhat.com/1944582 - -Signed-off-by: Fernando Fernandez Mancera -Signed-off-by: Gris Ge ---- - libnmstate/dns.py | 11 +++++++++-- - libnmstate/net_state.py | 13 +++++++++++-- - libnmstate/netapplier.py | 19 +++++++++++++------ - 3 files changed, 33 insertions(+), 10 deletions(-) - -diff --git a/libnmstate/dns.py b/libnmstate/dns.py -index 1fb2cc8..d44a869 100644 ---- a/libnmstate/dns.py -+++ b/libnmstate/dns.py -@@ -133,7 +133,7 @@ class DnsState: - Return tuple: (ipv4_iface, ipv6_iface) - """ - ipv4_iface, ipv6_iface = self._find_ifaces_with_static_gateways( -- route_state -+ ifaces, route_state - ) - if not (ipv4_iface and ipv6_iface): - ( -@@ -147,7 +147,7 @@ class DnsState: - - return ipv4_iface, ipv6_iface - -- def _find_ifaces_with_static_gateways(self, route_state): -+ def _find_ifaces_with_static_gateways(self, ifaces, route_state): - """ - Return tuple of interfaces with IPv4 and IPv6 static gateways. - """ -@@ -158,6 +158,11 @@ class DnsState: - if ipv4_iface and ipv6_iface: - return (ipv4_iface, ipv6_iface) - if route.is_gateway: -+ # Only interfaces not ignored can be considered as valid -+ # static gateway for nameservers. -+ iface = ifaces.all_kernel_ifaces.get(iface_name) -+ if iface and iface.is_ignore: -+ continue - if route.is_ipv6: - ipv6_iface = iface_name - else: -@@ -168,6 +173,8 @@ class DnsState: - ipv4_iface = None - ipv6_iface = None - for iface in ifaces.all_kernel_ifaces.values(): -+ if iface.is_ignore: -+ continue - if ipv4_iface and ipv6_iface: - return (ipv4_iface, ipv6_iface) - for family in (Interface.IPV4, Interface.IPV6): -diff --git a/libnmstate/net_state.py b/libnmstate/net_state.py -index 5dc7b43..713b7dc 100644 ---- a/libnmstate/net_state.py -+++ b/libnmstate/net_state.py -@@ -1,5 +1,5 @@ - # --# Copyright (c) 2020 Red Hat, Inc. -+# Copyright (c) 2020-2021 Red Hat, Inc. - # - # This file is part of nmstate - # -@@ -26,8 +26,8 @@ from libnmstate.schema import Interface - from libnmstate.schema import Route - from libnmstate.schema import RouteRule - --from .ifaces import Ifaces - from .dns import DnsState -+from .ifaces import Ifaces - from .route import RouteState - from .route_rule import RouteRuleState - from .state import state_match -@@ -37,6 +37,7 @@ class NetState: - def __init__( - self, - desire_state, -+ ignored_ifnames=[], - current_state=None, - save_to_disk=True, - gen_conf_mode=False, -@@ -49,6 +50,8 @@ class NetState: - save_to_disk, - gen_conf_mode, - ) -+ if not gen_conf_mode: -+ self._mark_ignored_kernel_ifaces(ignored_ifnames) - self._route = RouteState( - self._ifaces, - desire_state.get(Route.KEY), -@@ -70,6 +73,12 @@ class NetState: - self._ifaces.gen_route_metadata(self._route) - self._ifaces.gen_route_rule_metadata(self._route_rule, self._route) - -+ def _mark_ignored_kernel_ifaces(self, ignored_ifnames): -+ for iface_name in ignored_ifnames: -+ iface = self._ifaces.all_kernel_ifaces.get(iface_name) -+ if iface and not iface.is_desired: -+ iface.mark_as_ignored() -+ - def verify(self, current_state): - self._ifaces.verify(current_state.get(Interface.KEY)) - self._dns.verify(current_state.get(DNS.KEY)) -diff --git a/libnmstate/netapplier.py b/libnmstate/netapplier.py -index a020f00..202494d 100644 ---- a/libnmstate/netapplier.py -+++ b/libnmstate/netapplier.py -@@ -73,7 +73,10 @@ def apply( - validator.validate_capabilities( - desired_state, plugins_capabilities(plugins) - ) -- net_state = NetState(desired_state, current_state, save_to_disk) -+ ignored_ifnames = _get_ignored_interface_names(plugins) -+ net_state = NetState( -+ desired_state, ignored_ifnames, current_state, save_to_disk -+ ) - checkpoints = create_checkpoints(plugins, rollback_timeout) - _apply_ifaces_state(plugins, net_state, verify_change, save_to_disk) - if commit: -@@ -107,11 +110,6 @@ def rollback(*, checkpoint=None): - - - def _apply_ifaces_state(plugins, net_state, verify_change, save_to_disk): -- for plugin in plugins: -- for iface_name in plugin.get_ignored_kernel_interface_names(): -- iface = net_state.ifaces.all_kernel_ifaces.get(iface_name) -- if iface and not iface.is_desired: -- iface.mark_as_ignored() - for plugin in plugins: - plugin.apply_changes(net_state, save_to_disk) - -@@ -145,3 +143,12 @@ def _net_state_contains_sriov_interface(net_state): - def _verify_change(plugins, net_state): - current_state = show_with_plugins(plugins) - net_state.verify(current_state) -+ -+ -+def _get_ignored_interface_names(plugins): -+ ifaces = set() -+ for plugin in plugins: -+ for iface_name in plugin.get_ignored_kernel_interface_names(): -+ ifaces.add(iface_name) -+ -+ return ifaces --- -2.31.1 - diff --git a/SOURCES/BZ_1964439-ovs-Fix-is_ovs_running-in-container-environment.patch b/SOURCES/BZ_1964439-ovs-Fix-is_ovs_running-in-container-environment.patch deleted file mode 100644 index 5856e10..0000000 --- a/SOURCES/BZ_1964439-ovs-Fix-is_ovs_running-in-container-environment.patch +++ /dev/null @@ -1,222 +0,0 @@ -From 48c7645ce8849ac31298e6c2b1d5661d0f581279 Mon Sep 17 00:00:00 2001 -From: Gris Ge -Date: Mon, 17 May 2021 16:09:52 +0800 -Subject: [PATCH 1/2] ovs: Fix `is_ovs_running()` in container environment. - -In k8s container environment, the OVS database socket -/var/run/openvswitch/db.sock is mounted from host, so NM can managed it -without the ovs daemon running in container. - -To support that, this patch removed the top level checking on -`is_ovs_running()` and trust plugin raise the proper error on failure. - -Patched the NM plugin to check the error -`NM.DeviceStateReason.OVSDB_FAILED` on activation failure, raise -`NmstateDependencyError` if OVS DB failed to connected. - -NM will not raise any error when creating OVS internal interface with -OVSDB mounted to /dev/null, NM will keep showing the OVS interface as -ACTIVATING, changed the fallback checker to give only 30 seconds for OVS -interface to exit `NM.DeviceState.PREPARE`, if not treat it as OVS -daemon malfunctioning. - -Updated integration test case to mask(mount /dev/null) the OVS DB socket -file for simulating the stopped OVS daemon. - -Signed-off-by: Gris Ge -Signed-off-by: Fernando Fernandez Mancera ---- - libnmstate/ifaces/ovs.py | 15 ---------- - libnmstate/nm/active_connection.py | 47 ++++++++++++++++++++++++++---- - libnmstate/nm/plugin.py | 3 +- - libnmstate/validator.py | 16 +++------- - tests/integration/ovs_test.py | 41 +++++++++++--------------- - 5 files changed, 64 insertions(+), 58 deletions(-) - -diff --git a/libnmstate/ifaces/ovs.py b/libnmstate/ifaces/ovs.py -index 24d4aba..28892ad 100644 ---- a/libnmstate/ifaces/ovs.py -+++ b/libnmstate/ifaces/ovs.py -@@ -19,7 +19,6 @@ - - from copy import deepcopy - from operator import itemgetter --import subprocess - import warnings - - from libnmstate.error import NmstateValueError -@@ -252,20 +251,6 @@ class OvsInternalIface(BaseIface): - self._info.pop(Interface.MAC, None) - - --def is_ovs_running(): -- try: -- subprocess.run( -- ("systemctl", "status", "openvswitch"), -- stdout=subprocess.DEVNULL, -- stderr=subprocess.DEVNULL, -- check=True, -- timeout=SYSTEMCTL_TIMEOUT_SECONDS, -- ) -- return True -- except Exception: -- return False -- -- - def is_ovs_lag_port(port_state): - return port_state.get(OVSBridge.Port.LINK_AGGREGATION_SUBTREE) is not None - -diff --git a/libnmstate/nm/active_connection.py b/libnmstate/nm/active_connection.py -index ddf93a7..150256f 100644 ---- a/libnmstate/nm/active_connection.py -+++ b/libnmstate/nm/active_connection.py -@@ -20,6 +20,7 @@ - import logging - - from libnmstate.error import NmstateLibnmError -+from libnmstate.error import NmstateDependencyError - from libnmstate.error import NmstateInternalError - - from .common import GLib -@@ -33,6 +34,7 @@ from .ipv6 import is_dynamic as is_ipv6_dynamic - - NM_AC_STATE_CHANGED_SIGNAL = "state-changed" - FALLBACK_CHECKER_INTERNAL = 15 -+MAX_OVS_IFACE_PREPARE_TIME = FALLBACK_CHECKER_INTERNAL * 2 - GIO_ERROR_DOMAIN = "g-io-error-quark" - - -@@ -92,6 +94,7 @@ class ProfileActivation: - self._dev_handlers = set() - self._action = None - self._fallback_checker = None -+ self._fallback_checker_counter = 0 - - def run(self): - specific_object = None -@@ -336,19 +339,53 @@ class ProfileActivation: - self._activation_clean_up() - self._ctx.finish_async(self._action) - elif not is_activating(self._nm_ac, self._nm_dev): -- reason = f"{self._nm_ac.get_state_reason()}" -+ nm_ac_reason = f"{self._nm_ac.get_state_reason()}" -+ nm_dev_reason = None - if self._nm_dev: -- reason += f" {self._nm_dev.get_state_reason()}" -+ nm_dev_reason = self._nm_dev.get_state_reason() -+ -+ if nm_dev_reason == NM.DeviceStateReason.OVSDB_FAILED: -+ error = NmstateDependencyError( -+ f"{self._action} failed: failed to communicating with " -+ f"Open vSwitch database, {nm_dev_reason}" -+ ) -+ else: -+ reason = nm_ac_reason + ( -+ str(nm_dev_reason) if nm_dev_reason else "" -+ ) -+ error = NmstateLibnmError( -+ f"{self._action} failed: reason={reason}" -+ ) - self._activation_clean_up() -- self._ctx.fail( -- NmstateLibnmError(f"{self._action} failed: reason={reason}") -- ) -+ self._ctx.fail(error) - - def _fallback_checker_callback(self, _user_data): -+ self._fallback_checker_counter += 1 - nm_dev = get_nm_dev(self._ctx, self._iface_name, self._iface_type) - if nm_dev: - self._nm_dev = nm_dev - self._activation_progress_check() -+ # When OVSDB connection is invalid(such as been mounted as -+ # /dev/null), NM will hang on the activation of ovs internal -+ # interface with state ACITVATING with reason UNKNOWN forever with -+ # no state change signal. The fallback check only found it -+ # as activating which lead us hang till killed by idle timeout. -+ # To prevent that, when we found OVS interface interface in -+ # `NM.DeviceState.PREPARE` on in second call of fallbacker, -+ # we fail the action as NmstateDependencyError. -+ if ( -+ self._fallback_checker_counter -+ >= MAX_OVS_IFACE_PREPARE_TIME / FALLBACK_CHECKER_INTERNAL -+ and nm_dev.get_device_type() == NM.DeviceType.OVS_INTERFACE -+ and nm_dev.get_state() == NM.DeviceState.PREPARE -+ ): -+ self._ctx.fail( -+ NmstateDependencyError( -+ f"{self._action} failed: timeout on creating OVS " -+ "interface, please check Open vSwitch daemon" -+ ) -+ ) -+ - return GLib.SOURCE_CONTINUE - - -diff --git a/libnmstate/nm/plugin.py b/libnmstate/nm/plugin.py -index 335d93c..da933b3 100644 ---- a/libnmstate/nm/plugin.py -+++ b/libnmstate/nm/plugin.py -@@ -23,7 +23,6 @@ from operator import itemgetter - from libnmstate.error import NmstateDependencyError - from libnmstate.error import NmstateNotSupportedError - from libnmstate.error import NmstateValueError --from libnmstate.ifaces.ovs import is_ovs_running - from libnmstate.schema import DNS - from libnmstate.schema import Interface - from libnmstate.schema import InterfaceType -@@ -103,7 +102,7 @@ class NetworkManagerPlugin(NmstatePlugin): - @property - def capabilities(self): - capabilities = [] -- if has_ovs_capability(self.client) and is_ovs_running(): -+ if has_ovs_capability(self.client): - capabilities.append(NmstatePlugin.OVS_CAPABILITY) - if has_team_capability(self.client): - capabilities.append(NmstatePlugin.TEAM_CAPABILITY) -diff --git a/libnmstate/validator.py b/libnmstate/validator.py -index 02890b4..cd3b540 100644 ---- a/libnmstate/validator.py -+++ b/libnmstate/validator.py -@@ -22,7 +22,6 @@ import logging - - import jsonschema as js - --from libnmstate.ifaces.ovs import is_ovs_running - from libnmstate.schema import Interface - from libnmstate.schema import InterfaceType - from libnmstate.error import NmstateDependencyError -@@ -50,7 +49,6 @@ def validate_interface_capabilities(ifaces_state, capabilities): - ifaces_types = {iface_state.get("type") for iface_state in ifaces_state} - has_ovs_capability = NmstatePlugin.OVS_CAPABILITY in capabilities - has_team_capability = NmstatePlugin.TEAM_CAPABILITY in capabilities -- ovs_is_running = is_ovs_running() - for iface_type in ifaces_types: - is_ovs_type = iface_type in ( - InterfaceType.OVS_BRIDGE, -@@ -58,18 +56,12 @@ def validate_interface_capabilities(ifaces_state, capabilities): - InterfaceType.OVS_PORT, - ) - if is_ovs_type and not has_ovs_capability: -- if not ovs_is_running: -- raise NmstateDependencyError( -- "openvswitch service is not started." -- ) -- else: -- raise NmstateDependencyError( -- "Open vSwitch NetworkManager support not installed " -- "and started" -- ) -+ raise NmstateDependencyError( -+ "Open vSwitch support not properly installed or started" -+ ) - elif iface_type == InterfaceType.TEAM and not has_team_capability: - raise NmstateDependencyError( -- "NetworkManager-team plugin not installed and started" -+ "Team support not properly installed or started" - ) - - --- -2.31.1 - diff --git a/SOURCES/BZ_1964440-nm-ipv4-Deactivate-profile-when-route-removed.patch b/SOURCES/BZ_1964440-nm-ipv4-Deactivate-profile-when-route-removed.patch deleted file mode 100644 index 1ffe314..0000000 --- a/SOURCES/BZ_1964440-nm-ipv4-Deactivate-profile-when-route-removed.patch +++ /dev/null @@ -1,86 +0,0 @@ -From af8199135907d300014b5052571ca3e445455af7 Mon Sep 17 00:00:00 2001 -From: Gris Ge -Date: Tue, 25 May 2021 16:50:06 +0800 -Subject: [PATCH 2/2] nm ipv4: Deactivate profile when route removed. - -The bug https://bugzilla.redhat.com/show_bug.cgi?id=1962551 has shown -IPv4 route also share the same problem. - -Whenever we got a route removal, we deactivate that profile via -NetworkManager. - -Integration test case included. - -Signed-off-by: Gris Ge -Signed-off-by: Fernando Fernandez Mancera ---- - libnmstate/nm/profile.py | 5 +++-- - libnmstate/route.py | 19 +++++++---------- - tests/integration/route_test.py | 37 ++++++++++++++++++++++++++++++--- - 3 files changed, 45 insertions(+), 16 deletions(-) - -diff --git a/libnmstate/nm/profile.py b/libnmstate/nm/profile.py -index b655885..6b20b21 100644 ---- a/libnmstate/nm/profile.py -+++ b/libnmstate/nm/profile.py -@@ -49,7 +49,7 @@ from .translator import Api2Nm - IMPORT_NM_DEV_TIMEOUT = 5 - IMPORT_NM_DEV_RETRY_INTERNAL = 0.5 - FALLBACK_CHECKER_INTERNAL = 15 --IPV6_ROUTE_REMOVED = "_ipv6_route_removed" -+ROUTE_REMOVED = "_route_removed" - - - class NmProfile: -@@ -193,9 +193,10 @@ class NmProfile: - elif self._iface.is_virtual and self._nm_dev: - self._add_action(NmProfile.ACTION_DELETE_DEVICE) - -- if self._iface.raw.get(IPV6_ROUTE_REMOVED): -+ if self._iface.raw.get(ROUTE_REMOVED): - # This is a workaround for NM bug: - # https://bugzilla.redhat.com/1837254 -+ # https://bugzilla.redhat.com/1962551 - self._add_action(NmProfile.ACTION_DEACTIVATE_FIRST) - - if self._iface.is_controller and self._iface.is_up: -diff --git a/libnmstate/route.py b/libnmstate/route.py -index cdea198..d373427 100644 ---- a/libnmstate/route.py -+++ b/libnmstate/route.py -@@ -36,7 +36,7 @@ from .state import StateEntry - DEFAULT_ROUTE_TABLE = 254 - - --IPV6_ROUTE_REMOVED = "_ipv6_route_removed" -+ROUTE_REMOVED = "_route_removed" - - - class RouteEntry(StateEntry): -@@ -235,16 +235,13 @@ class RouteState: - for route in route_set: - if not rt.match(route): - new_routes.add(route) -- if route.is_ipv6: -- # The routes match and therefore it is being removed. -- # Nmstate will check if it is an IPv6 route and if so, -- # marking the interface as deactivate first. -- # -- # This is a workaround for NM bug: -- # https://bugzilla.redhat.com/1837254 -- ifaces.all_kernel_ifaces[iface_name].raw[ -- IPV6_ROUTE_REMOVED -- ] = True -+ # The routes match and therefore it is being removed. -+ # marking the interface as deactivate first. -+ # -+ # This is a workaround for NM bug: -+ # https://bugzilla.redhat.com/1837254 -+ # https://bugzilla.redhat.com/1962551 -+ ifaces.all_kernel_ifaces[iface_name].raw[ROUTE_REMOVED] = True - if new_routes != route_set: - self._routes[iface_name] = new_routes - --- -2.31.1 - diff --git a/SOURCES/BZ_1966379_fix_bond_opt_tlb_dynamic_lb.patch b/SOURCES/BZ_1966379_fix_bond_opt_tlb_dynamic_lb.patch deleted file mode 100644 index 1d70d68..0000000 --- a/SOURCES/BZ_1966379_fix_bond_opt_tlb_dynamic_lb.patch +++ /dev/null @@ -1,74 +0,0 @@ -From e503eb8241dda600ef16741c29cab83443ae0528 Mon Sep 17 00:00:00 2001 -From: Gris Ge -Date: Tue, 1 Jun 2021 10:13:33 +0800 -Subject: [PATCH 1/2] nm bond: Fixing `tlb_dynamic_lb` option - -NM only takes 1 or 0 for True/False, currently only "use_carrier" -and "tlb_dynamic_lb" are boolean. - -Integration test case included. NM 1.31 is required for bug -https://bugzilla.redhat.com/show_bug.cgi?id=1959934 - -Signed-off-by: Gris Ge ---- - libnmstate/nm/bond.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/libnmstate/nm/bond.py b/libnmstate/nm/bond.py -index cebac4d..067d87f 100644 ---- a/libnmstate/nm/bond.py -+++ b/libnmstate/nm/bond.py -@@ -92,7 +92,7 @@ def _nm_fix_bond_options(option_name, option_value): - option_name, option_value - ) - ) -- elif option_name == "use_carrier": -+ elif option_name in ("use_carrier", "tlb_dynamic_lb"): - option_value = 1 if option_value else 0 - - return str(option_value) --- -2.31.1 - - -From 1d6c7715dfbcb5021016bcd7b4f1f9fa357b2f20 Mon Sep 17 00:00:00 2001 -From: Gris Ge -Date: Tue, 1 Jun 2021 10:41:57 +0800 -Subject: [PATCH 2/2] nm bond: Fix preserving `all_slaves_active` option - -When `all_slaves_active` was previously set via nmstate or NM, follow up -bond modification will fail with: - - NmstateNotImplementedError: Unsupported bond option: 'all_slaves_active'='0' - -This is because the option returned by `_get_bond_options_from_profiles()` is -not canonicalized. - -Expand the check to cover `1` and `0`. - -Integration test case included. - -Signed-off-by: Gris Ge ---- - libnmstate/nm/bond.py | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/libnmstate/nm/bond.py b/libnmstate/nm/bond.py -index 067d87f..1642319 100644 ---- a/libnmstate/nm/bond.py -+++ b/libnmstate/nm/bond.py -@@ -82,9 +82,9 @@ def create_setting(iface, wired_setting, base_con_profile): - - def _nm_fix_bond_options(option_name, option_value): - if option_name == "all_slaves_active": -- if option_value == "delivered": -+ if option_value in ("delivered", "1"): - option_value = 1 -- elif option_value == "dropped": -+ elif option_value in ("dropped", "0"): - option_value = 0 - else: - raise NmstateNotImplementedError( --- -2.31.1 - diff --git a/SOURCES/BZ_1966457_Fix_bond_fail_over_mac.patch b/SOURCES/BZ_1966457_Fix_bond_fail_over_mac.patch deleted file mode 100644 index c72cc8f..0000000 --- a/SOURCES/BZ_1966457_Fix_bond_fail_over_mac.patch +++ /dev/null @@ -1,35 +0,0 @@ -From b1e94d1aa04f51b2d15711c8e7ab37198b173065 Mon Sep 17 00:00:00 2001 -From: Gris Ge -Date: Tue, 1 Jun 2021 16:33:15 +0800 -Subject: [PATCH] bond: Fix bond fail_over_mac=active - -With bond interface in fail_over_mac=active and active-backup mode, -any future change via nmstate will fail as nmstate is validating -on current state instead of desire state for this bond mac restriction. - -Fixed the code to only validate bond mac restriction on desired or -changed bond interface. - -Integration test case include. - -Signed-off-by: Gris Ge ---- - libnmstate/ifaces/bond.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/libnmstate/ifaces/bond.py b/libnmstate/ifaces/bond.py -index 138386e..01859b0 100644 ---- a/libnmstate/ifaces/bond.py -+++ b/libnmstate/ifaces/bond.py -@@ -88,7 +88,7 @@ class BondIface(BaseIface): - - def pre_edit_validation_and_cleanup(self): - super().pre_edit_validation_and_cleanup() -- if self.is_up: -+ if self.is_up and (self.is_desired or self.is_changed): - self._discard_bond_option_when_mode_change() - self._validate_bond_mode() - self._fix_mac_restriced_mode() --- -2.31.1 - diff --git a/SOURCES/BZ_1966457_only_validate_desired_bond.patch b/SOURCES/BZ_1966457_only_validate_desired_bond.patch deleted file mode 100644 index fd4a581..0000000 --- a/SOURCES/BZ_1966457_only_validate_desired_bond.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 355bc8f052e35084405343a0b94ccf06007c31f3 Mon Sep 17 00:00:00 2001 -From: Gris Ge -Date: Wed, 2 Jun 2021 19:53:25 +0800 -Subject: [PATCH] bond: Don't validate current bond status - -If a bond interface is only marked as changed due to other -interface(like bridge port list change), its original desire information -is fully read from current status, there is no need to validate it. - -The fix is only validate on desired bond interface. - -Signed-off-by: Gris Ge ---- - libnmstate/ifaces/bond.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/libnmstate/ifaces/bond.py b/libnmstate/ifaces/bond.py -index 01859b0..6311f5f 100644 ---- a/libnmstate/ifaces/bond.py -+++ b/libnmstate/ifaces/bond.py -@@ -88,7 +88,7 @@ class BondIface(BaseIface): - - def pre_edit_validation_and_cleanup(self): - super().pre_edit_validation_and_cleanup() -- if self.is_up and (self.is_desired or self.is_changed): -+ if self.is_up and self.is_desired: - self._discard_bond_option_when_mode_change() - self._validate_bond_mode() - self._fix_mac_restriced_mode() --- -2.31.1 - diff --git a/SOURCES/BZ_1979220_static_ip_on_ovs_same_name.patch b/SOURCES/BZ_1979220_static_ip_on_ovs_same_name.patch deleted file mode 100644 index 5321f17..0000000 --- a/SOURCES/BZ_1979220_static_ip_on_ovs_same_name.patch +++ /dev/null @@ -1,245 +0,0 @@ -From 9f505f21b90cf122539fbe9bc3bf78ef170f5c12 Mon Sep 17 00:00:00 2001 -From: Gris Ge -Date: Tue, 6 Jul 2021 11:53:55 +0800 -Subject: [PATCH] nm ovs: Fix OVS bridge and interface using the same name - -Nmstate will fail on verification when setting ip to OVS interface -sharing the same name with OVS bridge. - -This is caused by NM plugin does not index with interface type when -retrieving interface applied configure which lead to OVS bridge or OVS -interface applied configure overlapping each other. - -To fix this problem, we use `NetworkManagerPlugin._kernel_nic_applied_configs` -and `NetworkManagerPlugin._userspace_nic_applied_configs()` to -differentiate them. The kernel data is still indexed by interface name, -the user space data is indexed by interface name and type. - -Integration test case included as tier 1 as OpenShift need it. - -Signed-off-by: Gris Ge ---- - libnmstate/nm/device.py | 8 +++++ - libnmstate/nm/plugin.py | 61 ++++++++++++++++++++++++++------------- - libnmstate/nm/profiles.py | 38 ++++++++++++++++++++---- - 3 files changed, 81 insertions(+), 26 deletions(-) - -diff --git a/libnmstate/nm/device.py b/libnmstate/nm/device.py -index 3c58bae..4c97733 100644 ---- a/libnmstate/nm/device.py -+++ b/libnmstate/nm/device.py -@@ -198,3 +198,11 @@ def get_nm_dev(ctx, iface_name, iface_type): - ): - return nm_dev - return None -+ -+ -+def is_kernel_iface(nm_dev): -+ iface_type = get_iface_type(nm_dev) -+ return iface_type != InterfaceType.UNKNOWN and iface_type not in ( -+ InterfaceType.OVS_BRIDGE, -+ InterfaceType.OVS_PORT, -+ ) -diff --git a/libnmstate/nm/plugin.py b/libnmstate/nm/plugin.py -index da933b3..9c774e5 100644 ---- a/libnmstate/nm/plugin.py -+++ b/libnmstate/nm/plugin.py -@@ -36,6 +36,7 @@ from .common import NM - from .context import NmContext - from .device import get_device_common_info - from .device import get_iface_type -+from .device import is_kernel_iface - 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 -@@ -63,7 +64,8 @@ class NetworkManagerPlugin(NmstatePlugin): - def __init__(self): - self._ctx = None - self._checkpoint = None -- self.__applied_configs = None -+ self.__kernel_nic_applied_configs = None -+ self.__userspace_nic_applied_configs = None - - @property - def priority(self): -@@ -79,10 +81,28 @@ class NetworkManagerPlugin(NmstatePlugin): - self._ctx = None - - @property -- def _applied_configs(self): -- if self.__applied_configs is None: -- self.__applied_configs = get_all_applied_configs(self.context) -- return self.__applied_configs -+ def _kernel_nic_applied_configs(self): -+ if ( -+ self.__kernel_nic_applied_configs is None -+ or self.__userspace_nic_applied_configs is None -+ ): -+ ( -+ self.__kernel_nic_applied_configs, -+ self.__userspace_nic_applied_configs, -+ ) = get_all_applied_configs(self.context) -+ return self.__kernel_nic_applied_configs -+ -+ @property -+ def _userspace_nic_applied_configs(self): -+ if ( -+ self.__kernel_nic_applied_configs is None -+ or self.__userspace_nic_applied_configs is None -+ ): -+ ( -+ self.__kernel_nic_applied_configs, -+ self.__userspace_nic_applied_configs, -+ ) = get_all_applied_configs(self.context) -+ return self.__userspace_nic_applied_configs - - @property - def checkpoint(self): -@@ -120,8 +140,6 @@ class NetworkManagerPlugin(NmstatePlugin): - def get_interfaces(self): - info = [] - -- applied_configs = self._applied_configs -- - devices_info = [ - (dev, get_device_common_info(dev)) - for dev in list_devices(self.client) -@@ -131,6 +149,16 @@ class NetworkManagerPlugin(NmstatePlugin): - if not dev.get_managed(): - # Skip unmanaged interface - continue -+ if is_kernel_iface(dev): -+ applied_config = self._kernel_nic_applied_configs.get( -+ dev.get_iface() -+ ) -+ else: -+ iface_type = get_iface_type(dev) -+ applied_config = self._userspace_nic_applied_configs.get( -+ f"{dev.get_iface()}{iface_type}" -+ ) -+ - nm_ac = dev.get_active_connection() - if ( - nm_ac -@@ -140,7 +168,6 @@ class NetworkManagerPlugin(NmstatePlugin): - continue - - iface_info = Nm2Api.get_common_device_info(devinfo) -- applied_config = applied_configs.get(iface_info[Interface.NAME]) - - act_con = dev.get_active_connection() - iface_info[Interface.IPV4] = get_ipv4_info(act_con, applied_config) -@@ -193,11 +220,14 @@ class NetworkManagerPlugin(NmstatePlugin): - def get_dns_client_config(self): - return { - DNS.RUNNING: get_dns_running(self.client), -- DNS.CONFIG: get_dns_running_config(self._applied_configs), -+ DNS.CONFIG: get_dns_running_config( -+ self._kernel_nic_applied_configs -+ ), - } - - def refresh_content(self): -- self.__applied_configs = None -+ self.__kernel_nic_applied_configs = None -+ self.__userspace_nic_applied_configs = None - - def apply_changes(self, net_state, save_to_disk): - NmProfiles(self.context).apply_config(net_state, save_to_disk) -@@ -278,7 +308,7 @@ class NetworkManagerPlugin(NmstatePlugin): - nm_dev - and nm_dev.get_iface() - and not nm_dev.get_managed() -- and _is_kernel_iface(nm_dev) -+ and is_kernel_iface(nm_dev) - ): - ignored_ifaces.add(nm_dev.get_iface()) - return list(ignored_ifaces) -@@ -298,12 +328,3 @@ def _remove_ovs_bridge_unsupported_entries(iface_info): - - def _nm_utils_decode_version(): - return f"{NM.MAJOR_VERSION}.{NM.MINOR_VERSION}.{NM.MICRO_VERSION}" -- -- --def _is_kernel_iface(nm_dev): -- iface_type = get_iface_type(nm_dev) -- return iface_type != InterfaceType.UNKNOWN and iface_type not in ( -- InterfaceType.OVS_BRIDGE, -- InterfaceType.OVS_INTERFACE, -- InterfaceType.OVS_PORT, -- ) -diff --git a/libnmstate/nm/profiles.py b/libnmstate/nm/profiles.py -index 905a6c8..90e0e70 100644 ---- a/libnmstate/nm/profiles.py -+++ b/libnmstate/nm/profiles.py -@@ -27,7 +27,9 @@ from libnmstate.schema import InterfaceType - from .common import NM - from .device import is_externally_managed - from .device import list_devices -+from .device import get_iface_type - from .device import get_nm_dev -+from .device import is_kernel_iface - from .dns import get_dns_config_iface_names - from .ipv4 import acs_and_ip_profiles as acs_and_ip4_profiles - from .ipv6 import acs_and_ip_profiles as acs_and_ip6_profiles -@@ -129,7 +131,13 @@ def _append_nm_ovs_port_iface(net_state): - - - def get_all_applied_configs(context): -- applied_configs = {} -+ """ -+ Return two dictionaries. -+ First one for kernel interface with interface name as key. -+ Second one for user space interface with interface name and type as key. -+ """ -+ kernel_nic_applied_configs = {} -+ userspace_nic_applid_configs = {} - for nm_dev in list_devices(context.client): - if ( - nm_dev.get_state() -@@ -150,19 +158,37 @@ def get_all_applied_configs(context): - flags=0, - cancellable=context.cancellable, - callback=_get_applied_config_callback, -- user_data=(iface_name, action, applied_configs, context), -+ user_data=( -+ iface_name, -+ action, -+ kernel_nic_applied_configs, -+ userspace_nic_applid_configs, -+ context, -+ ), - ) - context.wait_all_finish() -- return applied_configs -+ return kernel_nic_applied_configs, userspace_nic_applid_configs - - - def _get_applied_config_callback(nm_dev, result, user_data): -- iface_name, action, applied_configs, context = user_data -+ ( -+ iface_name, -+ action, -+ kernel_nic_applied_configs, -+ userspace_nic_applid_configs, -+ context, -+ ) = user_data - context.finish_async(action) - try: -+ iface_name = nm_dev.get_iface() - remote_conn, _ = nm_dev.get_applied_connection_finish(result) -- # TODO: We should use both interface name and type as key below. -- applied_configs[nm_dev.get_iface()] = remote_conn -+ if is_kernel_iface(nm_dev): -+ kernel_nic_applied_configs[iface_name] = remote_conn -+ else: -+ iface_type = get_iface_type(nm_dev) -+ userspace_nic_applid_configs[ -+ f"{iface_name}{iface_type}" -+ ] = remote_conn - except Exception as e: - logging.warning( - "Failed to retrieve applied config for device " --- -2.32.0 - diff --git a/SOURCES/BZ_1979515-SR-IOV-Fix-BCM57416-failure-when-creating-VFs.patch b/SOURCES/BZ_1979515-SR-IOV-Fix-BCM57416-failure-when-creating-VFs.patch deleted file mode 100644 index b4d9111..0000000 --- a/SOURCES/BZ_1979515-SR-IOV-Fix-BCM57416-failure-when-creating-VFs.patch +++ /dev/null @@ -1,125 +0,0 @@ -From 61e775a19652ff1b17581e53367f05921304edfb Mon Sep 17 00:00:00 2001 -From: Fernando Fernandez Mancera -Date: Thu, 10 Jun 2021 14:55:33 +0200 -Subject: [PATCH 1/2] SR-IOV: Fix BCM57416 failure when creating VFs - -Currently there is not a way to see the relation between a SR-IOV PF and -its VFs. Broadcom BCM57416 follows a different name pattern for PF and -VF, therefore it needs to be parsed if present. - -PF name: ens2f0np0 -VF name: ens2f0v0 - -The different name pattern is due to: - 1. The `n` is for `multi-port PCI device` support. - 2. The `p*` is `phys_port_name` provided by the BCM driver `bnxt_en`. - -Ref: https://bugzilla.redhat.com/1959679 - -Signed-off-by: Fernando Fernandez Mancera ---- - libnmstate/ifaces/ethernet.py | 38 ++++++++++++++++++++++++++++++++--- - libnmstate/nm/profiles.py | 8 ++++++++ - 2 files changed, 43 insertions(+), 3 deletions(-) - -diff --git a/libnmstate/ifaces/ethernet.py b/libnmstate/ifaces/ethernet.py -index 55772ce..a47a718 100644 ---- a/libnmstate/ifaces/ethernet.py -+++ b/libnmstate/ifaces/ethernet.py -@@ -25,6 +25,11 @@ from libnmstate.schema import InterfaceState - from .base_iface import BaseIface - - -+BNXT_DRIVER_PHYS_PORT_PREFIX = "p" -+MULTIPORT_PCI_DEVICE_PREFIX = "n" -+IS_GENERATED_VF_METADATA = "_is_generated_vf" -+ -+ - class EthernetIface(BaseIface): - def __init__(self, info, save_to_disk=True): - super().__init__(info, save_to_disk) -@@ -80,21 +85,48 @@ class EthernetIface(BaseIface): - ) - - def create_sriov_vf_ifaces(self): -- return [ -+ # Currently there is not a way to see the relation between a SR-IOV PF -+ # and its VFs. Broadcom BCM57416 follows a different name pattern for -+ # PF and VF, therefore it needs to be parsed if present. -+ # -+ # PF name: ens2f0np0 -+ # VF name: ens2f0v0 -+ # -+ # The different name pattern is due to: -+ # 1. The `n` is for `multi-port PCI device` support. -+ # 2. The `p*` is `phys_port_name` provided by the BCM driver -+ # `bnxt_en`. -+ # -+ # If the NIC is following the standard pattern "pfname+v+vfid", this -+ # split will not touch it and the vf_pattern will be the PF name. -+ # Ref: https://bugzilla.redhat.com/1959679 -+ vf_pattern = self.name -+ multiport_pattern = ( -+ MULTIPORT_PCI_DEVICE_PREFIX + BNXT_DRIVER_PHYS_PORT_PREFIX -+ ) -+ if len(self.name.split(multiport_pattern)) == 2: -+ vf_pattern = self.name.split(multiport_pattern)[0] -+ -+ vf_ifaces = [ - EthernetIface( - { - # According to manpage of systemd.net-naming-scheme(7), - # SRIOV VF interface will have v{slot} in device name. - # Currently, nmstate has no intention to support - # user-defined udev rule on SRIOV interface naming policy. -- Interface.NAME: f"{self.name}v{i}", -+ Interface.NAME: f"{vf_pattern}v{i}", - Interface.TYPE: InterfaceType.ETHERNET, -- # VF will be in DOWN state initialy. -+ # VF will be in DOWN state initialy - Interface.STATE: InterfaceState.DOWN, - } - ) - for i in range(0, self.sriov_total_vfs) - ] -+ # The generated vf metadata cannot be part of the original dict. -+ for vf in vf_ifaces: -+ vf._info[IS_GENERATED_VF_METADATA] = True -+ -+ return vf_ifaces - - def remove_vfs_entry_when_total_vfs_decreased(self): - vfs_count = len( -diff --git a/libnmstate/nm/profiles.py b/libnmstate/nm/profiles.py -index 90e0e70..ec3ef70 100644 ---- a/libnmstate/nm/profiles.py -+++ b/libnmstate/nm/profiles.py -@@ -40,6 +40,9 @@ from .veth import create_iface_for_nm_veth_peer - from .veth import is_nm_veth_supported - - -+IS_GENERATED_VF_METADATA = "_is_generated_vf" -+ -+ - class NmProfiles: - def __init__(self, context): - self._ctx = context -@@ -63,6 +66,7 @@ class NmProfiles: - all_profiles = [ - NmProfile(self._ctx, iface) - for iface in net_state.ifaces.all_ifaces() -+ if not _is_only_for_verify(iface) - ] - - for profile in all_profiles: -@@ -409,3 +413,7 @@ def _nm_ovs_port_has_child(nm_profile, ovs_bridge_iface, net_state): - ): - return True - return False -+ -+ -+def _is_only_for_verify(iface): -+ return iface.to_dict().get(IS_GENERATED_VF_METADATA) --- -2.31.1 - diff --git a/SOURCES/BZ_1979943-ovs-Regenerate-iface-metadata-after-RouteRule-metada.patch b/SOURCES/BZ_1979943-ovs-Regenerate-iface-metadata-after-RouteRule-metada.patch deleted file mode 100644 index e484490..0000000 --- a/SOURCES/BZ_1979943-ovs-Regenerate-iface-metadata-after-RouteRule-metada.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 55d5092c04a974985c4db8609c73d6b92a674cae Mon Sep 17 00:00:00 2001 -From: Gris Ge -Date: Thu, 8 Jul 2021 15:49:48 +0800 -Subject: [PATCH 2/2] ovs: Regenerate iface metadata after RouteRule metadata - generation - -When desire state only contain route rule for OVS interface route table -ID, NetworkManager will complains: - - A connection with a 'ovs-interface' setting must have a master. - -The root cause is because interface metadata is not generated if desire -state has no interface at all. - -The fix is regenerate interface metadata on changed/desired interface -after route rule metadata generation. - -Integration test case added and marked as tier1 due to RHV requirement. - -Signed-off-by: Gris Ge ---- - libnmstate/ifaces/base_iface.py | 5 ++-- - libnmstate/ifaces/ifaces.py | 4 ++-- - libnmstate/ifaces/linux_bridge.py | 8 +++++-- - libnmstate/net_state.py | 3 +++ - tests/integration/ovs_test.py | 40 +++++++++++++++++++++++++++++++ - 5 files changed, 54 insertions(+), 6 deletions(-) - -diff --git a/libnmstate/ifaces/base_iface.py b/libnmstate/ifaces/base_iface.py -index e3f2a1c..a76491e 100644 ---- a/libnmstate/ifaces/base_iface.py -+++ b/libnmstate/ifaces/base_iface.py -@@ -350,8 +350,9 @@ class BaseIface: - def gen_metadata(self, ifaces): - if self.is_controller and not self.is_absent: - for port_name in self.port: -- port_iface = ifaces.all_kernel_ifaces[port_name] -- port_iface.set_controller(self.name, self.type) -+ port_iface = ifaces.all_kernel_ifaces.get(port_name) -+ if port_iface: -+ port_iface.set_controller(self.name, self.type) - - def update(self, info): - self._info.update(info) -diff --git a/libnmstate/ifaces/ifaces.py b/libnmstate/ifaces/ifaces.py -index efa24aa..c240abd 100644 ---- a/libnmstate/ifaces/ifaces.py -+++ b/libnmstate/ifaces/ifaces.py -@@ -158,7 +158,7 @@ class Ifaces: - self._validate_infiniband_as_bridge_port() - self._validate_infiniband_as_bond_port() - self._apply_copy_mac_from() -- self._gen_metadata() -+ self.gen_metadata() - for iface in self.all_ifaces(): - iface.pre_edit_validation_and_cleanup() - -@@ -569,7 +569,7 @@ class Ifaces: - else: - self._kernel_ifaces[iface.name] = iface - -- def _gen_metadata(self): -+ def gen_metadata(self): - for iface in self.all_ifaces(): - # Generate metadata for all interface in case any of them - # been marked as changed by DNS/Route/RouteRule. -diff --git a/libnmstate/ifaces/linux_bridge.py b/libnmstate/ifaces/linux_bridge.py -index bc7768f..09d68cb 100644 ---- a/libnmstate/ifaces/linux_bridge.py -+++ b/libnmstate/ifaces/linux_bridge.py -@@ -125,9 +125,13 @@ class LinuxBridgeIface(BridgeIface): - super().gen_metadata(ifaces) - if not self.is_absent: - for port_config in self.port_configs: -- ifaces.all_kernel_ifaces[ -+ port_iface = ifaces.all_kernel_ifaces.get( - port_config[LinuxBridge.Port.NAME] -- ].update({BridgeIface.BRPORT_OPTIONS_METADATA: port_config}) -+ ) -+ if port_iface: -+ port_iface.update( -+ {BridgeIface.BRPORT_OPTIONS_METADATA: port_config} -+ ) - - def remove_port(self, port_name): - if self._bridge_config: -diff --git a/libnmstate/net_state.py b/libnmstate/net_state.py -index 713b7dc..780981c 100644 ---- a/libnmstate/net_state.py -+++ b/libnmstate/net_state.py -@@ -72,6 +72,9 @@ class NetState: - self._ifaces.gen_dns_metadata(self._dns, self._route) - self._ifaces.gen_route_metadata(self._route) - self._ifaces.gen_route_rule_metadata(self._route_rule, self._route) -+ # DND/Route/RouteRule might introduced new changed interface -+ # Regnerate interface metadata -+ self._ifaces.gen_metadata() - - def _mark_ignored_kernel_ifaces(self, ignored_ifnames): - for iface_name in ignored_ifnames: --- -2.31.1 - diff --git a/SOURCES/nmstate-1.0.2.tar.gz.asc b/SOURCES/nmstate-1.0.2.tar.gz.asc deleted file mode 100644 index ef664a4..0000000 --- a/SOURCES/nmstate-1.0.2.tar.gz.asc +++ /dev/null @@ -1,16 +0,0 @@ ------BEGIN PGP SIGNATURE----- - -iQIzBAABCAAdFiEEfUQ+BAINyWGvqJXerIciWuEsPqMFAmAueEYACgkQrIciWuEs -PqPJxw//UmWdCJgoClFkEpWqWUkjMmfkGh70PoxtuOeNrAYwHv9zCHDBFjLtaDG1 -18+jakwrVIlTiFHZqfz1g3o0Te86w5rKiU2y0FBtBPZ1cdcJZk2Is5wb/JJo78n+ -9sWRfZmSN0SMiJ5HfzhTdZ2RsZYRSaDPSUxchRY03LzsBusxoK8swWu9oUHqmYKd -S3k4skP5ZQvpHtKzq9w1lfU4YAw42sRvXHW/++HqGgE0rypf+Wlcu9C+It9kVLCr -3rdp8iTGTg+LRg7LxFmEsRlmPpxhO25LaxjFvYSFnhE94xOt28KXeHBYs8hPPRwh -+z2w6zJ3hgIrLh10IPzePTWk//KNWDRaAJXQTCma1UE4jdL3+wbxb8H3vl5VCrBU -3fuj3JwfvFU1NuDf+yuJ0sCKzNXaAzpYYgfIaCaPdtBpg5jl2DTEfEF8QZKYuJDU -ueCo6reBAlwJzce433aSzBXshFbHG/RdD09duS3p84Dn6ljEN3GfJwUAC9s9TsAQ -U5+rWog6zMpVke/9yqwEf1KmqtLM3/+Ih30CHb3ZoPTf05KB14k0d1CLDdC9d9dy -gN0w8xjdTUXbUXW/XIvRVX9KWqyNI6lnZoL0MWzPwUmMxwPJkRpAVpLKpgyUrVpD -yjtLTFDZJNmfmbi2b0myFFcc2chaXmYlpLCP8vfRYJA3mCee6Xg= -=b/Mh ------END PGP SIGNATURE----- diff --git a/SOURCES/nmstate-1.1.0.tar.gz.asc b/SOURCES/nmstate-1.1.0.tar.gz.asc new file mode 100644 index 0000000..3c2d190 --- /dev/null +++ b/SOURCES/nmstate-1.1.0.tar.gz.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCAAdFiEE8f1XsqXpyNthgIbGbM3lj+QeKP8FAmDvw+4ACgkQbM3lj+Qe +KP+WjA/+Nky4rMOTNG16iwV8wc0hvWJdHL6XzDnHR2rrUHPGLMg4ia2B5MhYGKpl +/1eQk2UnA2rFTLC2P+TlKJbTFTUytxDvoCbR7ODCmneSJ65txG3XFDEd0soGayn4 +w5UchowGTqGEMu/P1ORihYtYC6b8Q1gHFUomqcvryOtdE6b6lzQAMyU/VrG3vEwG +dSsFWJh6PyMi2WTS5+CAHUYPbs3wZbNxTU74PyHch1Hcl3zwXa3bheqzHZojYh28 +GvvaPXBAHD6xwnCOWTMw3hBgLnjTZKsc62aFqgJ1Zz1VqN+Xlo8mlTZYDGhzwNU3 +m0UfRz2tSeqpbTFty3ObzTfDNYiXe4Y3J6ktD3pjt7Pf/uKY8NNbOKlZ4WhWrqPn +VGB67ci/pcMQjw/vCPVjOQwpjVMm/EaZ6GQw8TAxbsb9tB5w2NoTncMkNNiPNB4/ +5gquK2zZL8hsPqcE5yY/n+2/zgxhO7E7KuE20dbt1BCW+wmS4e77a7cx3EFgLc7f +oTGGuh3T+zdI/kxt5FAUBNnFiPWN9zJjQ8e080j7UIyL1Rhpvp+xG70ujwHvfL1I +qczeFT77eI2aMNU9iX/vbkVdgEKlxD6YDw626PxJR5WQz99zHiKwfDPUf9rJW72q +tAbGZ3DjfMk/VrerOMFDEGPA1V9Fs9kxGye1DIPAVw4IOwAbqE8= +=9EnL +-----END PGP SIGNATURE----- diff --git a/SPECS/nmstate.spec b/SPECS/nmstate.spec index 1e574ec..3d4e265 100644 --- a/SPECS/nmstate.spec +++ b/SPECS/nmstate.spec @@ -3,28 +3,18 @@ %define libname libnmstate Name: nmstate -Version: 1.0.2 -Release: 14%{?dist} +Version: 1.1.0 +Release: 3%{?dist} Summary: Declarative network manager API License: LGPLv2+ URL: https://github.com/%{srcname}/%{srcname} Source0: %{url}/releases/download/v%{version}/%{srcname}-%{version}.tar.gz Source1: %{url}/releases/download/v%{version}/%{srcname}-%{version}.tar.gz.asc Source2: https://www.nmstate.io/nmstate.gpg -Patch1: BZ_1931751-nmstate-fix-return-code.patch -Patch2: BZ_1931355-SRIOV-wait-VF-mount-decrease.patch -Patch3: BZ_1932247-nm-Don-t-touch-unmanaged-interface-unless-desired.patch -Patch4: BZ_1961914-do-not-use-unmanaged-interface-for-dns.patch -Patch5: BZ_1961912-fix-ovs-interface-activation.patch -Patch6: BZ_1964439-ovs-Fix-is_ovs_running-in-container-environment.patch -Patch7: BZ_1964440-nm-ipv4-Deactivate-profile-when-route-removed.patch -Patch8: BZ_1966379_fix_bond_opt_tlb_dynamic_lb.patch -Patch9: BZ_1966457_Fix_bond_fail_over_mac.patch -Patch10: BZ_1966457_only_validate_desired_bond.patch -Patch11: BZ_1979220_static_ip_on_ovs_same_name.patch -Patch12: BZ_1979515-SR-IOV-Fix-BCM57416-failure-when-creating-VFs.patch -Patch13: BZ_1979943-ovs-Regenerate-iface-metadata-after-RouteRule-metada.patch -Patch14: BZ_1986285-nispor-fix-show-of-empty-next_hop_address-and-destin.patch +Patch1: 0001-nmstatectl-fix-long-arguments-support.patch +Patch2: 0002-nm-ethtool-Preserve-existing-ethtool-settings-when-u.patch +Patch3: 0003-ovs-fix-state-ignore-for-ovs-port-when-removing-them.patch +Patch4: 0004-nispor-fix-show-of-empty-next_hop_address-and-destin.patch BuildArch: noarch BuildRequires: python3-devel BuildRequires: python3-setuptools @@ -82,8 +72,10 @@ gpgv2 --keyring ./gpgkey-mantainers.gpg %{SOURCE1} %{SOURCE0} %doc README.md %doc examples/ %{_mandir}/man8/nmstatectl.8* +%{_mandir}/man8/nmstate-autoconf.8* %{python3_sitelib}/nmstatectl %{_bindir}/nmstatectl +%{_bindir}/nmstate-autoconf %files -n python3-%{libname} %license LICENSE @@ -97,36 +89,45 @@ gpgv2 --keyring ./gpgkey-mantainers.gpg %{SOURCE1} %{SOURCE0} %{python3_sitelib}/%{libname}/plugins/__pycache__/nmstate_plugin_ovsdb* %changelog -* Wed Jul 28 2021 Fernando Fernandez Mancera - 1.0.2-14 -- Fix showing routes without next-hop-address or destination. RHBZ#1986285 +* Tue Jul 27 2021 Gris Ge - 1.1.0-3 +- Fix state=ignore for OVS interface. RHBZ#1944054 +- Fix verification for next hop address 0.0.0.0. RHBZ#1985879 -* Thu Jul 08 2021 Fernando Fernandez Mancera - 1.0.2-13 -- Fix SR-IOV BCM57416 failure when creating VFs. RHBZ#1979515 -- Fix applying route rule changes over ovs interface. RHBZ#1979943 +* Fri Jul 23 2021 Gris Ge - 1.1.0-2 +- Preserving existing ethtool settings. RHBZ#1984764 -* Tue Jul 06 2021 Gris Ge - 1.0.2-12 -- Fix setting IP on ovs interface sharing the same name with bridge. RHBZ#1979220 +* Thu Jul 15 2021 Gris Ge - 1.1.0-1 +- Upgrade to 1.1.0. -* Thu Jun 03 2021 Gris Ge - 1.0.2-11 -- Only validate desired bone interface. RHBZ#1966457 +* Fri Jul 09 2021 Gris Ge - 1.1.0-0.7.alpha7 +- Upgarde to 1.1.0 alpha7. -* Tue Jun 01 2021 Gris Ge - 1.0.2-10 -- Fix bond option fail_over_mac=active. RHBZ#1966457 +* Thu Jul 01 2021 Gris Ge - 1.1.0-0.6.alpha6 +- Upgrade to 1.1.0 alpha6. -* Tue Jun 01 2021 Gris Ge - 1.0.2-9 -- Fix bond option tlb_dynamic_lb. RHBZ#1966379 +* Mon Jun 21 2021 Fernando Fernandez Mancera - 1.1.0-0.5.alpha4 +- Upgrade to 1.1.0 alpha4. -* Mon May 31 2021 Fernando Fernandez Mancera - 1.0.2-8 -- Remove test changes from patches. +* Wed Jun 16 2021 Fernando Fernandez Mancera - 1.1.0-0.4.alpha3 +- Rebuild to introduce CI gating tier1 tests. RHBZ#1813357 -* Mon May 31 2021 Fernando Fernandez Mancera - 1.0.2-7 -- Fix OVS bugs and route removal bug: RHBZ#1964440 RHBZ#1964439 +* Tue Jun 08 2021 Gris Ge - 1.1.0-0.3.alpha3 +- Upgrade to 1.1.0 alpha3. -* Wed May 19 2021 Gris Ge - 1.0.2-6 -- Fix OVS bugs: RHBZ#1961912 RHBZ#1961913 RHBZ#1961914 +* Mon Jun 07 2021 Fernando Fernandez Mancera - 1.1.0-0.2 +- Upgrade to 1.1.0 alpha2. -* Wed Mar 03 2021 Fernando Fernandez Mancera - 1.0.2-5 -- New patch for fixing unmanaged interfaces being managed. RHBZ#1932247 +* Wed May 19 2021 Wen Liang - 1.1.0-0.1 +- Upgrade to 1.1.0 alpha1. + +* Tue Apr 20 2021 Fernando Fernandez Mancera - 1.0.3-1 +- Upgrade to 1.0.3. RHBZ#1942458 + +* Fri Mar 26 2021 Fernando Fernandez Mancera - 1.0.2-6 +- Rebuild for RHEL 8.5. RHBZ#1935710 + +* Fri Mar 26 2021 Fernando Fernandez Mancera - 1.0.2-5 +- New patch for fixing unmanaged interfaces being managed. RHBZ#1935710 * Tue Feb 23 2021 Gris Ge - 1.0.2-4 - New patch for SRIOV decrease VF amount. RHBZ#1931355