import nmstate-1.1.0-3.el8
This commit is contained in:
parent
1bb48d27a3
commit
aaa1c8b9f1
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +1,2 @@
|
|||||||
SOURCES/nmstate-1.0.2.tar.gz
|
SOURCES/nmstate-1.1.0.tar.gz
|
||||||
SOURCES/nmstate.gpg
|
SOURCES/nmstate.gpg
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
eeda8a0238732e5dc37e2217ed6e316f76c93145 SOURCES/nmstate-1.0.2.tar.gz
|
0b7795853d1f7735cb05817389f188884d1f6f09 SOURCES/nmstate-1.1.0.tar.gz
|
||||||
b5f872551d434e2c62b30d70471efaeede83ab44 SOURCES/nmstate.gpg
|
b5f872551d434e2c62b30d70471efaeede83ab44 SOURCES/nmstate.gpg
|
||||||
|
53
SOURCES/0001-nmstatectl-fix-long-arguments-support.patch
Normal file
53
SOURCES/0001-nmstatectl-fix-long-arguments-support.patch
Normal 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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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>
|
From: Fernando Fernandez Mancera <ffmancera@riseup.net>
|
||||||
Date: Mon, 26 Jul 2021 16:13:15 +0200
|
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
|
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
|
"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
|
Ref: https://bugzilla.redhat.com/1985879
|
||||||
|
|
||||||
Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
|
Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
|
||||||
|
Signed-off-by: Gris Ge <fge@redhat.com>
|
||||||
---
|
---
|
||||||
libnmstate/nispor/route.py | 13 +++++++++----
|
libnmstate/nispor/route.py | 13 +++++++++----
|
||||||
tests/integration/route_test.py | 30 +++++++++++++++++++++++++++++-
|
1 file changed, 9 insertions(+), 4 deletions(-)
|
||||||
2 files changed, 38 insertions(+), 5 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/libnmstate/nispor/route.py b/libnmstate/nispor/route.py
|
diff --git a/libnmstate/nispor/route.py b/libnmstate/nispor/route.py
|
||||||
index 510ddc3..9852ba5 100644
|
index 510ddc3..9852ba5 100644
|
||||||
@ -81,5 +82,5 @@ index 510ddc3..9852ba5 100644
|
|||||||
return {
|
return {
|
||||||
Route.TABLE_ID: np_rt.table,
|
Route.TABLE_ID: np_rt.table,
|
||||||
--
|
--
|
||||||
2.31.1
|
2.32.0
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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-----
|
|
16
SOURCES/nmstate-1.1.0.tar.gz.asc
Normal file
16
SOURCES/nmstate-1.1.0.tar.gz.asc
Normal 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-----
|
@ -3,28 +3,18 @@
|
|||||||
%define libname libnmstate
|
%define libname libnmstate
|
||||||
|
|
||||||
Name: nmstate
|
Name: nmstate
|
||||||
Version: 1.0.2
|
Version: 1.1.0
|
||||||
Release: 14%{?dist}
|
Release: 3%{?dist}
|
||||||
Summary: Declarative network manager API
|
Summary: Declarative network manager API
|
||||||
License: LGPLv2+
|
License: LGPLv2+
|
||||||
URL: https://github.com/%{srcname}/%{srcname}
|
URL: https://github.com/%{srcname}/%{srcname}
|
||||||
Source0: %{url}/releases/download/v%{version}/%{srcname}-%{version}.tar.gz
|
Source0: %{url}/releases/download/v%{version}/%{srcname}-%{version}.tar.gz
|
||||||
Source1: %{url}/releases/download/v%{version}/%{srcname}-%{version}.tar.gz.asc
|
Source1: %{url}/releases/download/v%{version}/%{srcname}-%{version}.tar.gz.asc
|
||||||
Source2: https://www.nmstate.io/nmstate.gpg
|
Source2: https://www.nmstate.io/nmstate.gpg
|
||||||
Patch1: BZ_1931751-nmstate-fix-return-code.patch
|
Patch1: 0001-nmstatectl-fix-long-arguments-support.patch
|
||||||
Patch2: BZ_1931355-SRIOV-wait-VF-mount-decrease.patch
|
Patch2: 0002-nm-ethtool-Preserve-existing-ethtool-settings-when-u.patch
|
||||||
Patch3: BZ_1932247-nm-Don-t-touch-unmanaged-interface-unless-desired.patch
|
Patch3: 0003-ovs-fix-state-ignore-for-ovs-port-when-removing-them.patch
|
||||||
Patch4: BZ_1961914-do-not-use-unmanaged-interface-for-dns.patch
|
Patch4: 0004-nispor-fix-show-of-empty-next_hop_address-and-destin.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
|
|
||||||
BuildArch: noarch
|
BuildArch: noarch
|
||||||
BuildRequires: python3-devel
|
BuildRequires: python3-devel
|
||||||
BuildRequires: python3-setuptools
|
BuildRequires: python3-setuptools
|
||||||
@ -82,8 +72,10 @@ gpgv2 --keyring ./gpgkey-mantainers.gpg %{SOURCE1} %{SOURCE0}
|
|||||||
%doc README.md
|
%doc README.md
|
||||||
%doc examples/
|
%doc examples/
|
||||||
%{_mandir}/man8/nmstatectl.8*
|
%{_mandir}/man8/nmstatectl.8*
|
||||||
|
%{_mandir}/man8/nmstate-autoconf.8*
|
||||||
%{python3_sitelib}/nmstatectl
|
%{python3_sitelib}/nmstatectl
|
||||||
%{_bindir}/nmstatectl
|
%{_bindir}/nmstatectl
|
||||||
|
%{_bindir}/nmstate-autoconf
|
||||||
|
|
||||||
%files -n python3-%{libname}
|
%files -n python3-%{libname}
|
||||||
%license LICENSE
|
%license LICENSE
|
||||||
@ -97,36 +89,45 @@ gpgv2 --keyring ./gpgkey-mantainers.gpg %{SOURCE1} %{SOURCE0}
|
|||||||
%{python3_sitelib}/%{libname}/plugins/__pycache__/nmstate_plugin_ovsdb*
|
%{python3_sitelib}/%{libname}/plugins/__pycache__/nmstate_plugin_ovsdb*
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
* Wed Jul 28 2021 Fernando Fernandez Mancera <ferferna@redhat.com> - 1.0.2-14
|
* Tue Jul 27 2021 Gris Ge <fge@redhat.com> - 1.1.0-3
|
||||||
- Fix showing routes without next-hop-address or destination. RHBZ#1986285
|
- 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
|
* Fri Jul 23 2021 Gris Ge <fge@redhat.com> - 1.1.0-2
|
||||||
- Fix SR-IOV BCM57416 failure when creating VFs. RHBZ#1979515
|
- Preserving existing ethtool settings. RHBZ#1984764
|
||||||
- Fix applying route rule changes over ovs interface. RHBZ#1979943
|
|
||||||
|
|
||||||
* Tue Jul 06 2021 Gris Ge <fge@redhat.com> - 1.0.2-12
|
* Thu Jul 15 2021 Gris Ge <fge@redhat.com> - 1.1.0-1
|
||||||
- Fix setting IP on ovs interface sharing the same name with bridge. RHBZ#1979220
|
- Upgrade to 1.1.0.
|
||||||
|
|
||||||
* Thu Jun 03 2021 Gris Ge <fge@redhat.com> - 1.0.2-11
|
* Fri Jul 09 2021 Gris Ge <fge@redhat.com> - 1.1.0-0.7.alpha7
|
||||||
- Only validate desired bone interface. RHBZ#1966457
|
- Upgarde to 1.1.0 alpha7.
|
||||||
|
|
||||||
* Tue Jun 01 2021 Gris Ge <fge@redhat.com> - 1.0.2-10
|
* Thu Jul 01 2021 Gris Ge <fge@redhat.com> - 1.1.0-0.6.alpha6
|
||||||
- Fix bond option fail_over_mac=active. RHBZ#1966457
|
- Upgrade to 1.1.0 alpha6.
|
||||||
|
|
||||||
* Tue Jun 01 2021 Gris Ge <fge@redhat.com> - 1.0.2-9
|
* Mon Jun 21 2021 Fernando Fernandez Mancera <ferferna@redhat.com> - 1.1.0-0.5.alpha4
|
||||||
- Fix bond option tlb_dynamic_lb. RHBZ#1966379
|
- Upgrade to 1.1.0 alpha4.
|
||||||
|
|
||||||
* Mon May 31 2021 Fernando Fernandez Mancera <ferferna@redhat.com> - 1.0.2-8
|
* Wed Jun 16 2021 Fernando Fernandez Mancera <ferferna@redhat.com> - 1.1.0-0.4.alpha3
|
||||||
- Remove test changes from patches.
|
- Rebuild to introduce CI gating tier1 tests. RHBZ#1813357
|
||||||
|
|
||||||
* Mon May 31 2021 Fernando Fernandez Mancera <ferferna@redhat.com> - 1.0.2-7
|
* Tue Jun 08 2021 Gris Ge <fge@redhat.com> - 1.1.0-0.3.alpha3
|
||||||
- Fix OVS bugs and route removal bug: RHBZ#1964440 RHBZ#1964439
|
- Upgrade to 1.1.0 alpha3.
|
||||||
|
|
||||||
* Wed May 19 2021 Gris Ge <fge@redhat.com> - 1.0.2-6
|
* Mon Jun 07 2021 Fernando Fernandez Mancera <ferferna@redhat.com> - 1.1.0-0.2
|
||||||
- Fix OVS bugs: RHBZ#1961912 RHBZ#1961913 RHBZ#1961914
|
- Upgrade to 1.1.0 alpha2.
|
||||||
|
|
||||||
* Wed Mar 03 2021 Fernando Fernandez Mancera <ferferna@redhat.com> - 1.0.2-5
|
* Wed May 19 2021 Wen Liang <wenliang@redhat.com> - 1.1.0-0.1
|
||||||
- New patch for fixing unmanaged interfaces being managed. RHBZ#1932247
|
- 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
|
* Tue Feb 23 2021 Gris Ge <fge@redhat.com> - 1.0.2-4
|
||||||
- New patch for SRIOV decrease VF amount. RHBZ#1931355
|
- New patch for SRIOV decrease VF amount. RHBZ#1931355
|
||||||
|
Loading…
Reference in New Issue
Block a user