import nmstate-1.1.0-3.el8

This commit is contained in:
CentOS Sources 2021-11-09 04:46:09 -05:00 committed by Stepan Oksanichenko
parent 1bb48d27a3
commit aaa1c8b9f1
22 changed files with 308 additions and 1701 deletions

2
.gitignore vendored
View File

@ -1,2 +1,2 @@
SOURCES/nmstate-1.0.2.tar.gz
SOURCES/nmstate-1.1.0.tar.gz
SOURCES/nmstate.gpg

View File

@ -1,2 +1,2 @@
eeda8a0238732e5dc37e2217ed6e316f76c93145 SOURCES/nmstate-1.0.2.tar.gz
0b7795853d1f7735cb05817389f188884d1f6f09 SOURCES/nmstate-1.1.0.tar.gz
b5f872551d434e2c62b30d70471efaeede83ab44 SOURCES/nmstate.gpg

View File

@ -0,0 +1,53 @@
From 99c7f643bab33a26c317e1b72ca3b8490cb1ea60 Mon Sep 17 00:00:00 2001
From: Fernando Fernandez Mancera <ffmancera@riseup.net>
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 <ffmancera@riseup.net>
Signed-off-by: Gris Ge <fge@redhat.com>
---
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

View File

@ -0,0 +1,105 @@
From b1cb57d1dc4bba6592ba5cfc5c810a2ad19ac941 Mon Sep 17 00:00:00 2001
From: Gris Ge <fge@redhat.com>
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 <fge@redhat.com>
Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
---
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

View File

@ -0,0 +1,87 @@
From f4d190653c55d399b32afc956b2b4a1ff8d20101 Mon Sep 17 00:00:00 2001
From: Fernando Fernandez Mancera <ffmancera@riseup.net>
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 <ffmancera@riseup.net>
Signed-off-by: Gris Ge <fge@redhat.com>
---
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

View File

@ -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 <ffmancera@riseup.net>
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 <ffmancera@riseup.net>
Signed-off-by: Gris Ge <fge@redhat.com>
---
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

View File

@ -1,166 +0,0 @@
From 80c97b27707b036f0a54988ade4bda3ccb342b34 Mon Sep 17 00:00:00 2001
From: Fernando Fernandez Mancera <ffmancera@riseup.net>
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 <ffmancera@riseup.net>
Signed-off-by: Gris Ge <fge@redhat.com>
---
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 <ffmancera@riseup.net>
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 <ffmancera@riseup.net>
Signed-off-by: Gris Ge <fge@redhat.com>
---
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

View File

@ -1,29 +0,0 @@
From b26ab850172a41557cad42cc011bd00d7c108c88 Mon Sep 17 00:00:00 2001
From: Gris Ge <fge@redhat.com>
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 <fge@redhat.com>
---
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

View File

@ -1,223 +0,0 @@
From ccdcd8f86544a6364109a0c0142d05a5afacf64e Mon Sep 17 00:00:00 2001
From: Gris Ge <fge@redhat.com>
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 <fge@redhat.com>
---
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

View File

@ -1,137 +0,0 @@
From 95d77329b30c9a9a435a881941e27f9a1bed074e Mon Sep 17 00:00:00 2001
From: Fernando Fernandez Mancera <ffmancera@riseup.net>
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 <ffmancera@riseup.net>
Signed-off-by: Gris Ge <fge@redhat.com>
---
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 <ffmancera@riseup.net>
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=<enum NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED of type NM.ActiveConnectionStateReason> <enum NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED of type NM.DeviceStateReason>
```
Integration test added
Ref: https://bugzilla.redhat.com/1947287
Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
Signed-off-by: Gris Ge <fge@redhat.com>
---
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

View File

@ -1,163 +0,0 @@
From 72edab395316ba1ae69ea4d788b0572c935759ac Mon Sep 17 00:00:00 2001
From: Fernando Fernandez Mancera <ffmancera@riseup.net>
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 <ffmancera@riseup.net>
Signed-off-by: Gris Ge <fge@redhat.com>
---
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

View File

@ -1,222 +0,0 @@
From 48c7645ce8849ac31298e6c2b1d5661d0f581279 Mon Sep 17 00:00:00 2001
From: Gris Ge <fge@redhat.com>
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 <fge@redhat.com>
Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
---
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

View File

@ -1,86 +0,0 @@
From af8199135907d300014b5052571ca3e445455af7 Mon Sep 17 00:00:00 2001
From: Gris Ge <fge@redhat.com>
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 <fge@redhat.com>
Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
---
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

View File

@ -1,74 +0,0 @@
From e503eb8241dda600ef16741c29cab83443ae0528 Mon Sep 17 00:00:00 2001
From: Gris Ge <fge@redhat.com>
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 <fge@redhat.com>
---
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 <fge@redhat.com>
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 <fge@redhat.com>
---
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

View File

@ -1,35 +0,0 @@
From b1e94d1aa04f51b2d15711c8e7ab37198b173065 Mon Sep 17 00:00:00 2001
From: Gris Ge <fge@redhat.com>
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 <fge@redhat.com>
---
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

View File

@ -1,32 +0,0 @@
From 355bc8f052e35084405343a0b94ccf06007c31f3 Mon Sep 17 00:00:00 2001
From: Gris Ge <fge@redhat.com>
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 <fge@redhat.com>
---
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

View File

@ -1,245 +0,0 @@
From 9f505f21b90cf122539fbe9bc3bf78ef170f5c12 Mon Sep 17 00:00:00 2001
From: Gris Ge <fge@redhat.com>
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 <fge@redhat.com>
---
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

View File

@ -1,125 +0,0 @@
From 61e775a19652ff1b17581e53367f05921304edfb Mon Sep 17 00:00:00 2001
From: Fernando Fernandez Mancera <ffmancera@riseup.net>
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 <ffmancera@riseup.net>
---
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

View File

@ -1,103 +0,0 @@
From 55d5092c04a974985c4db8609c73d6b92a674cae Mon Sep 17 00:00:00 2001
From: Gris Ge <fge@redhat.com>
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 <fge@redhat.com>
---
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

View File

@ -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-----

View File

@ -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-----

View File

@ -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 <ferferna@redhat.com> - 1.0.2-14
- Fix showing routes without next-hop-address or destination. RHBZ#1986285
* Tue Jul 27 2021 Gris Ge <fge@redhat.com> - 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 <ferferna@redhat.com> - 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 <fge@redhat.com> - 1.1.0-2
- Preserving existing ethtool settings. RHBZ#1984764
* Tue Jul 06 2021 Gris Ge <fge@redhat.com> - 1.0.2-12
- Fix setting IP on ovs interface sharing the same name with bridge. RHBZ#1979220
* Thu Jul 15 2021 Gris Ge <fge@redhat.com> - 1.1.0-1
- Upgrade to 1.1.0.
* Thu Jun 03 2021 Gris Ge <fge@redhat.com> - 1.0.2-11
- Only validate desired bone interface. RHBZ#1966457
* Fri Jul 09 2021 Gris Ge <fge@redhat.com> - 1.1.0-0.7.alpha7
- Upgarde to 1.1.0 alpha7.
* Tue Jun 01 2021 Gris Ge <fge@redhat.com> - 1.0.2-10
- Fix bond option fail_over_mac=active. RHBZ#1966457
* Thu Jul 01 2021 Gris Ge <fge@redhat.com> - 1.1.0-0.6.alpha6
- Upgrade to 1.1.0 alpha6.
* Tue Jun 01 2021 Gris Ge <fge@redhat.com> - 1.0.2-9
- Fix bond option tlb_dynamic_lb. RHBZ#1966379
* Mon Jun 21 2021 Fernando Fernandez Mancera <ferferna@redhat.com> - 1.1.0-0.5.alpha4
- Upgrade to 1.1.0 alpha4.
* Mon May 31 2021 Fernando Fernandez Mancera <ferferna@redhat.com> - 1.0.2-8
- Remove test changes from patches.
* Wed Jun 16 2021 Fernando Fernandez Mancera <ferferna@redhat.com> - 1.1.0-0.4.alpha3
- Rebuild to introduce CI gating tier1 tests. RHBZ#1813357
* Mon May 31 2021 Fernando Fernandez Mancera <ferferna@redhat.com> - 1.0.2-7
- Fix OVS bugs and route removal bug: RHBZ#1964440 RHBZ#1964439
* Tue Jun 08 2021 Gris Ge <fge@redhat.com> - 1.1.0-0.3.alpha3
- Upgrade to 1.1.0 alpha3.
* Wed May 19 2021 Gris Ge <fge@redhat.com> - 1.0.2-6
- Fix OVS bugs: RHBZ#1961912 RHBZ#1961913 RHBZ#1961914
* Mon Jun 07 2021 Fernando Fernandez Mancera <ferferna@redhat.com> - 1.1.0-0.2
- Upgrade to 1.1.0 alpha2.
* Wed Mar 03 2021 Fernando Fernandez Mancera <ferferna@redhat.com> - 1.0.2-5
- New patch for fixing unmanaged interfaces being managed. RHBZ#1932247
* Wed May 19 2021 Wen Liang <wenliang@redhat.com> - 1.1.0-0.1
- Upgrade to 1.1.0 alpha1.
* Tue Apr 20 2021 Fernando Fernandez Mancera <ferferna@redhat.com> - 1.0.3-1
- Upgrade to 1.0.3. RHBZ#1942458
* Fri Mar 26 2021 Fernando Fernandez Mancera <ferferna@redhat.com> - 1.0.2-6
- Rebuild for RHEL 8.5. RHBZ#1935710
* Fri Mar 26 2021 Fernando Fernandez Mancera <ferferna@redhat.com> - 1.0.2-5
- New patch for fixing unmanaged interfaces being managed. RHBZ#1935710
* Tue Feb 23 2021 Gris Ge <fge@redhat.com> - 1.0.2-4
- New patch for SRIOV decrease VF amount. RHBZ#1931355