import nmstate-0.3.4-27.el8_3
This commit is contained in:
parent
654b4d10bc
commit
a764ed7069
@ -0,0 +1,82 @@
|
||||
From cc7e6da98cc992d2e6d8aa85cd78f02fb8ef8ac3 Mon Sep 17 00:00:00 2001
|
||||
From: Fernando Fernandez Mancera <ffmancera@riseup.net>
|
||||
Date: Sun, 21 Feb 2021 22:43:57 +0100
|
||||
Subject: [PATCH 2/5] SR-IOV: Do not create VF profiles automatically
|
||||
|
||||
As VFs are Ethernet type and Nmstate is automatically adding them to the
|
||||
desired state and marking them as desired, the profile is being created.
|
||||
This is wrong as Nmstate should only wait for verification of the VFs.
|
||||
|
||||
In order to fix this, the new VF interfaces are being marked as so. This
|
||||
way Nmstate is not creating the profiles anymore.
|
||||
|
||||
Integration test case added.
|
||||
|
||||
Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
|
||||
---
|
||||
libnmstate/ifaces/ethernet.py | 10 ++++
|
||||
libnmstate/ifaces/ifaces.py | 1 +
|
||||
libnmstate/nm/applier.py | 5 ++
|
||||
tests/integration/nm/sriov_test.py | 92 ++++++++++++++++++++++++++++++
|
||||
4 files changed, 108 insertions(+)
|
||||
create mode 100644 tests/integration/nm/sriov_test.py
|
||||
|
||||
diff --git a/libnmstate/ifaces/ethernet.py b/libnmstate/ifaces/ethernet.py
|
||||
index 3e1bdc5d..f1ece5f5 100644
|
||||
--- a/libnmstate/ifaces/ethernet.py
|
||||
+++ b/libnmstate/ifaces/ethernet.py
|
||||
@@ -25,6 +25,9 @@ from libnmstate.schema import InterfaceState
|
||||
from .base_iface import BaseIface
|
||||
|
||||
|
||||
+IS_NEW_SR_IOV_VF = "_is_new_sr_iov_vf"
|
||||
+
|
||||
+
|
||||
class EthernetIface(BaseIface):
|
||||
def merge(self, other):
|
||||
"""
|
||||
@@ -57,6 +60,13 @@ class EthernetIface(BaseIface):
|
||||
.get(Ethernet.SRIOV.TOTAL_VFS, 0)
|
||||
)
|
||||
|
||||
+ @property
|
||||
+ def is_new_sr_iov_vf(self):
|
||||
+ return self.raw.get(IS_NEW_SR_IOV_VF)
|
||||
+
|
||||
+ def mark_as_new_sr_iov_vf(self):
|
||||
+ self.raw[IS_NEW_SR_IOV_VF] = True
|
||||
+
|
||||
def create_sriov_vf_ifaces(self):
|
||||
return [
|
||||
EthernetIface(
|
||||
diff --git a/libnmstate/ifaces/ifaces.py b/libnmstate/ifaces/ifaces.py
|
||||
index 67ab91c4..a7af9712 100644
|
||||
--- a/libnmstate/ifaces/ifaces.py
|
||||
+++ b/libnmstate/ifaces/ifaces.py
|
||||
@@ -144,6 +144,7 @@ class Ifaces:
|
||||
for new_iface in iface.create_sriov_vf_ifaces():
|
||||
if new_iface.name not in self._ifaces:
|
||||
new_iface.mark_as_desired()
|
||||
+ new_iface.mark_as_new_sr_iov_vf()
|
||||
new_ifaces.append(new_iface)
|
||||
for new_iface in new_ifaces:
|
||||
self._ifaces[new_iface.name] = new_iface
|
||||
diff --git a/libnmstate/nm/applier.py b/libnmstate/nm/applier.py
|
||||
index 8e38df54..cd319ffb 100644
|
||||
--- a/libnmstate/nm/applier.py
|
||||
+++ b/libnmstate/nm/applier.py
|
||||
@@ -119,6 +119,11 @@ def apply_changes(context, net_state, save_to_disk):
|
||||
original_desired_iface_state = {}
|
||||
if net_state.ifaces.get(ifname):
|
||||
iface = net_state.ifaces[ifname]
|
||||
+ if iface.type == InterfaceType.ETHERNET and iface.is_new_sr_iov_vf:
|
||||
+ # For new vfs automatically added to the desired state is just
|
||||
+ # for verification, Nmstate should not create a profile for
|
||||
+ # them.
|
||||
+ continue
|
||||
if iface.is_desired:
|
||||
original_desired_iface_state = iface.original_dict
|
||||
if (
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,112 @@
|
||||
From c55d39e8485a26490afc36d71fd9d20528ab6fd2 Mon Sep 17 00:00:00 2001
|
||||
From: Gris Ge <fge@redhat.com>
|
||||
Date: Thu, 18 Feb 2021 18:01:17 +0800
|
||||
Subject: [PATCH 1/5] SRIOV: Remove VF interface when total-vfs decrease
|
||||
|
||||
When `Ethernet.SRIOV.TOTAL_VFS` decrease, we should mark removed VF
|
||||
interface as absent.
|
||||
|
||||
Both integration and unit test cases have been include.
|
||||
The integration test has been tested on real SRIOV hardware.
|
||||
|
||||
Signed-off-by: Gris Ge <fge@redhat.com>
|
||||
Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
|
||||
---
|
||||
libnmstate/ifaces/base_iface.py | 5 +++++
|
||||
libnmstate/ifaces/ethernet.py | 20 ++++++++++++++++++
|
||||
libnmstate/ifaces/ifaces.py | 24 +++++++++++++++++++++
|
||||
tests/integration/sriov_test.py | 37 +++++++++++++++++++++++++++++++++
|
||||
4 files changed, 86 insertions(+)
|
||||
|
||||
diff --git a/libnmstate/ifaces/base_iface.py b/libnmstate/ifaces/base_iface.py
|
||||
index 564d583a..b4ade867 100644
|
||||
--- a/libnmstate/ifaces/base_iface.py
|
||||
+++ b/libnmstate/ifaces/base_iface.py
|
||||
@@ -177,6 +177,11 @@ class BaseIface:
|
||||
def mark_as_desired(self):
|
||||
self._is_desired = True
|
||||
|
||||
+ def mark_as_absent_by_desire(self):
|
||||
+ self.mark_as_desired()
|
||||
+ self._info[Interface.STATE] = InterfaceState.ABSENT
|
||||
+ self._origin_info[Interface.STATE] = InterfaceState.ABSENT
|
||||
+
|
||||
def to_dict(self):
|
||||
return deepcopy(self._info)
|
||||
|
||||
diff --git a/libnmstate/ifaces/ethernet.py b/libnmstate/ifaces/ethernet.py
|
||||
index 644fe6dd..3e1bdc5d 100644
|
||||
--- a/libnmstate/ifaces/ethernet.py
|
||||
+++ b/libnmstate/ifaces/ethernet.py
|
||||
@@ -74,6 +74,26 @@ class EthernetIface(BaseIface):
|
||||
for i in range(0, self.sriov_total_vfs)
|
||||
]
|
||||
|
||||
+ def remove_vfs_entry_when_total_vfs_decreased(self):
|
||||
+ vfs_count = len(
|
||||
+ self._info[Ethernet.CONFIG_SUBTREE]
|
||||
+ .get(Ethernet.SRIOV_SUBTREE, {})
|
||||
+ .get(Ethernet.SRIOV.VFS_SUBTREE, [])
|
||||
+ )
|
||||
+ if vfs_count > self.sriov_total_vfs:
|
||||
+ [
|
||||
+ self._info[Ethernet.CONFIG_SUBTREE][Ethernet.SRIOV_SUBTREE][
|
||||
+ Ethernet.SRIOV.VFS_SUBTREE
|
||||
+ ].pop()
|
||||
+ for _ in range(self.sriov_total_vfs, vfs_count)
|
||||
+ ]
|
||||
+
|
||||
+ def get_delete_vf_interface_names(self, old_sriov_total_vfs):
|
||||
+ return [
|
||||
+ f"{self.name}v{i}"
|
||||
+ for i in range(self.sriov_total_vfs, old_sriov_total_vfs)
|
||||
+ ]
|
||||
+
|
||||
|
||||
def _capitalize_sriov_vf_mac(state):
|
||||
vfs = (
|
||||
diff --git a/libnmstate/ifaces/ifaces.py b/libnmstate/ifaces/ifaces.py
|
||||
index ee75125d..67ab91c4 100644
|
||||
--- a/libnmstate/ifaces/ifaces.py
|
||||
+++ b/libnmstate/ifaces/ifaces.py
|
||||
@@ -99,6 +99,7 @@ class Ifaces:
|
||||
self._create_virtual_slaves()
|
||||
self._create_sriov_vfs_when_changed()
|
||||
self._validate_unknown_slaves()
|
||||
+ self._mark_vf_interface_as_absent_when_sriov_vf_decrease()
|
||||
self._validate_unknown_parent()
|
||||
self._gen_metadata()
|
||||
for iface in self._ifaces.values():
|
||||
@@ -147,6 +148,29 @@ class Ifaces:
|
||||
for new_iface in new_ifaces:
|
||||
self._ifaces[new_iface.name] = new_iface
|
||||
|
||||
+ def _mark_vf_interface_as_absent_when_sriov_vf_decrease(self):
|
||||
+ """
|
||||
+ When SRIOV TOTAL_VFS decreased, we should mark certain VF interfaces
|
||||
+ as absent and also remove the entry in `Ethernet.SRIOV.VFS_SUBTREE`.
|
||||
+ """
|
||||
+ for iface_name, iface in self._ifaces.items():
|
||||
+ if iface.type != InterfaceType.ETHERNET or not iface.is_up:
|
||||
+ continue
|
||||
+ if iface_name not in self.current_ifaces:
|
||||
+ continue
|
||||
+ cur_iface = self.current_ifaces[iface_name]
|
||||
+ if (
|
||||
+ cur_iface.sriov_total_vfs != 0
|
||||
+ and iface.sriov_total_vfs < cur_iface.sriov_total_vfs
|
||||
+ ):
|
||||
+ iface.remove_vfs_entry_when_total_vfs_decreased()
|
||||
+ for vf_name in iface.get_delete_vf_interface_names(
|
||||
+ cur_iface.sriov_total_vfs
|
||||
+ ):
|
||||
+ vf_iface = self._ifaces.get(vf_name)
|
||||
+ if vf_iface:
|
||||
+ vf_iface.mark_as_absent_by_desire()
|
||||
+
|
||||
def _pre_edit_validation_and_cleanup(self):
|
||||
self._validate_over_booked_slaves()
|
||||
self._validate_vlan_mtu()
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,79 @@
|
||||
From a43609607abe30b973f1cb78cb1754f1a9a91514 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 4/5] SR-IOV: fail on verification if `total_vfs` does not
|
||||
match vfs len
|
||||
|
||||
Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
|
||||
---
|
||||
libnmstate/ifaces/ethernet.py | 11 +++++++++++
|
||||
libnmstate/ifaces/ifaces.py | 17 +++++++++++++++++
|
||||
2 files changed, 28 insertions(+)
|
||||
|
||||
diff --git a/libnmstate/ifaces/ethernet.py b/libnmstate/ifaces/ethernet.py
|
||||
index 1c3ca266..4903bde7 100644
|
||||
--- a/libnmstate/ifaces/ethernet.py
|
||||
+++ b/libnmstate/ifaces/ethernet.py
|
||||
@@ -52,6 +52,14 @@ class EthernetIface(BaseIface):
|
||||
_capitalize_sriov_vf_mac(state)
|
||||
return state
|
||||
|
||||
+ @property
|
||||
+ def sriov_vfs(self):
|
||||
+ return (
|
||||
+ self.raw.get(Ethernet.CONFIG_SUBTREE, {})
|
||||
+ .get(Ethernet.SRIOV_SUBTREE, {})
|
||||
+ .get(Ethernet.SRIOV.VFS_SUBTREE, {})
|
||||
+ )
|
||||
+
|
||||
@property
|
||||
def sriov_total_vfs(self):
|
||||
return (
|
||||
@@ -109,6 +117,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 b212ebb5..1d30d0c6 100644
|
||||
--- a/libnmstate/ifaces/ifaces.py
|
||||
+++ b/libnmstate/ifaces/ifaces.py
|
||||
@@ -146,6 +146,11 @@ class Ifaces:
|
||||
new_iface.mark_as_desired()
|
||||
new_iface.mark_as_new_sr_iov_vf()
|
||||
new_ifaces.append(new_iface)
|
||||
+ else:
|
||||
+ # When the VFs are being modified, all VFs link are
|
||||
+ # being removed from kernel and created again. Nmstate
|
||||
+ # must verify they have been created.
|
||||
+ self._ifaces[new_iface.name].mark_as_desired()
|
||||
for new_iface in new_ifaces:
|
||||
self._ifaces[new_iface.name] = new_iface
|
||||
|
||||
@@ -403,6 +408,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.29.2
|
||||
|
@ -0,0 +1,102 @@
|
||||
From afb3f2dfeb5364e8a9a0bde4ad9062f1585a8795 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 3/5] 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>
|
||||
---
|
||||
libnmstate/ifaces/ethernet.py | 5 +++++
|
||||
libnmstate/ifaces/ifaces.py | 4 ++++
|
||||
libnmstate/netapplier.py | 18 +++++++++++++++++-
|
||||
3 files changed, 26 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/libnmstate/ifaces/ethernet.py b/libnmstate/ifaces/ethernet.py
|
||||
index f1ece5f5..1c3ca266 100644
|
||||
--- a/libnmstate/ifaces/ethernet.py
|
||||
+++ b/libnmstate/ifaces/ethernet.py
|
||||
@@ -67,6 +67,11 @@ class EthernetIface(BaseIface):
|
||||
def mark_as_new_sr_iov_vf(self):
|
||||
self.raw[IS_NEW_SR_IOV_VF] = True
|
||||
|
||||
+ 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/ifaces/ifaces.py b/libnmstate/ifaces/ifaces.py
|
||||
index a7af9712..b212ebb5 100644
|
||||
--- a/libnmstate/ifaces/ifaces.py
|
||||
+++ b/libnmstate/ifaces/ifaces.py
|
||||
@@ -325,6 +325,10 @@ class Ifaces:
|
||||
def current_ifaces(self):
|
||||
return self._cur_ifaces
|
||||
|
||||
+ @property
|
||||
+ def all_ifaces(self):
|
||||
+ return self._ifaces
|
||||
+
|
||||
@property
|
||||
def state_to_edit(self):
|
||||
return [
|
||||
diff --git a/libnmstate/netapplier.py b/libnmstate/netapplier.py
|
||||
index 24df4d56..6aa1ac07 100644
|
||||
--- a/libnmstate/netapplier.py
|
||||
+++ b/libnmstate/netapplier.py
|
||||
@@ -23,6 +23,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
|
||||
@@ -35,6 +36,7 @@ from .net_state import NetState
|
||||
MAINLOOP_TIMEOUT = 35
|
||||
VERIFY_RETRY_INTERNAL = 1
|
||||
VERIFY_RETRY_TIMEOUT = 5
|
||||
+VERIFY_RETRY_TIMEOUT_INCREASE = 4
|
||||
|
||||
|
||||
def apply(
|
||||
@@ -104,7 +106,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
|
||||
@@ -115,6 +123,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_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.29.2
|
||||
|
@ -0,0 +1,38 @@
|
||||
From cb4cbff0da01bb1e6546c2b28ef2760ec1f89f74 Mon Sep 17 00:00:00 2001
|
||||
From: Fernando Fernandez Mancera <ffmancera@riseup.net>
|
||||
Date: Wed, 24 Feb 2021 17:12:13 +0100
|
||||
Subject: [PATCH 5/5] bridge: do not bring up existing ports
|
||||
|
||||
Nmstate should not try to bring up existing ports on a bridge when
|
||||
modifying it. The ports will be bring up when being added to the it, if
|
||||
the bridge is being modified later, the ports are not going to be
|
||||
automatically up.
|
||||
|
||||
Ref: https://bugzilla.redhat.com/1932247
|
||||
|
||||
Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
|
||||
---
|
||||
libnmstate/ifaces/ifaces.py | 5 +
|
||||
tests/integration/nm/linux_bridge_test.py | 112 +++++++++++++++++++++-
|
||||
2 files changed, 116 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/libnmstate/ifaces/ifaces.py b/libnmstate/ifaces/ifaces.py
|
||||
index 1d30d0c6..5f1f548d 100644
|
||||
--- a/libnmstate/ifaces/ifaces.py
|
||||
+++ b/libnmstate/ifaces/ifaces.py
|
||||
@@ -194,7 +194,12 @@ class Ifaces:
|
||||
"""
|
||||
for iface in self._ifaces.values():
|
||||
if iface.is_up and iface.is_master:
|
||||
+ cur_iface = self.current_ifaces.get(iface.name)
|
||||
for slave_name in iface.slaves:
|
||||
+ if cur_iface and slave_name in cur_iface.slaves:
|
||||
+ # Nmstate should not touch the port interface which has
|
||||
+ # already been included in current interface.
|
||||
+ continue
|
||||
slave_iface = self._ifaces[slave_name]
|
||||
if not slave_iface.is_desired and not slave_iface.is_up:
|
||||
slave_iface.mark_as_up()
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,77 @@
|
||||
From fb9352b902f8fec813c149e02e97c7014ef6399c Mon Sep 17 00:00:00 2001
|
||||
From: Fernando Fernandez Mancera <ffmancera@riseup.net>
|
||||
Date: Mon, 1 Mar 2021 16:25:57 +0100
|
||||
Subject: [PATCH] nm.applier: ignore not desired unmanaged ifaces
|
||||
|
||||
Nmstate will ignore not desired unmanaged interfaces. If an existing
|
||||
unmanaged port of a bridge is not being included in the desired state
|
||||
bridge port list, it will not be removed. Basically, Nmstate will not be
|
||||
able to remove unmanaged ports from a bridge.
|
||||
|
||||
Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
|
||||
---
|
||||
libnmstate/ifaces/ifaces.py | 11 ++++++---
|
||||
libnmstate/nm/applier.py | 11 ++++++++-
|
||||
tests/integration/linux_bridge_test.py | 1 +
|
||||
tests/integration/nm/linux_bridge_test.py | 30 +++--------------------
|
||||
4 files changed, 21 insertions(+), 32 deletions(-)
|
||||
|
||||
diff --git a/libnmstate/ifaces/ifaces.py b/libnmstate/ifaces/ifaces.py
|
||||
index 5f1f548d..cfc306c6 100644
|
||||
--- a/libnmstate/ifaces/ifaces.py
|
||||
+++ b/libnmstate/ifaces/ifaces.py
|
||||
@@ -193,7 +193,7 @@ class Ifaces:
|
||||
if not defiend in desire state
|
||||
"""
|
||||
for iface in self._ifaces.values():
|
||||
- if iface.is_up and iface.is_master:
|
||||
+ if iface.is_desired and iface.is_up and iface.is_master:
|
||||
cur_iface = self.current_ifaces.get(iface.name)
|
||||
for slave_name in iface.slaves:
|
||||
if cur_iface and slave_name in cur_iface.slaves:
|
||||
@@ -353,14 +353,17 @@ class Ifaces:
|
||||
|
||||
def _remove_unknown_interface_type_slaves(self):
|
||||
"""
|
||||
- When master containing slaves with unknown interface type, they should
|
||||
- be removed from master slave list before verifying.
|
||||
+ When master containing slaves with unknown interface type or down
|
||||
+ state, they should be removed from master slave list before verifying.
|
||||
"""
|
||||
for iface in self._ifaces.values():
|
||||
if iface.is_up and iface.is_master and iface.slaves:
|
||||
for slave_name in iface.slaves:
|
||||
slave_iface = self._ifaces[slave_name]
|
||||
- if slave_iface.type == InterfaceType.UNKNOWN:
|
||||
+ if (
|
||||
+ slave_iface.type == InterfaceType.UNKNOWN
|
||||
+ or slave_iface.state != InterfaceState.UP
|
||||
+ ):
|
||||
iface.remove_slave(slave_name)
|
||||
|
||||
def verify(self, cur_iface_infos):
|
||||
diff --git a/libnmstate/nm/applier.py b/libnmstate/nm/applier.py
|
||||
index cd319ffb..da2dab5b 100644
|
||||
--- a/libnmstate/nm/applier.py
|
||||
+++ b/libnmstate/nm/applier.py
|
||||
@@ -80,7 +80,16 @@ def apply_changes(context, net_state, save_to_disk):
|
||||
_preapply_dns_fix(context, net_state)
|
||||
_mark_nm_external_subordinate_changed(context, net_state)
|
||||
|
||||
- ifaces_desired_state = net_state.ifaces.state_to_edit
|
||||
+ ifaces_desired_state = []
|
||||
+ for iface in net_state.ifaces.all_ifaces.values():
|
||||
+ nm_dev = context.get_nm_dev(iface.name)
|
||||
+ if nm_dev and not nm_dev.get_managed() and not iface.is_desired:
|
||||
+ # We don't change NM.Device from unmanaged to managed unless
|
||||
+ # been asked explicitly in desire state
|
||||
+ continue
|
||||
+ if iface.is_changed or iface.is_desired:
|
||||
+ ifaces_desired_state.append(iface.to_dict())
|
||||
+
|
||||
ifaces_desired_state.extend(
|
||||
_create_proxy_ifaces_desired_state(ifaces_desired_state)
|
||||
)
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,146 @@
|
||||
From 34b689a86c7cd4bcf5ab5cf7d903acba7d60f4be Mon Sep 17 00:00:00 2001
|
||||
From: Gris Ge <fge@redhat.com>
|
||||
Date: Wed, 10 Feb 2021 23:28:37 +0800
|
||||
Subject: [PATCH] bridge/bond: New property `Interface.COPY_MAC_FROM`
|
||||
|
||||
Introducing `Interface.COPY_MAC_FROM` allowing bridge or bond
|
||||
to use MAC address from specified port.
|
||||
|
||||
Example:
|
||||
|
||||
```yaml
|
||||
---
|
||||
interfaces:
|
||||
- name: bond99
|
||||
type: bond
|
||||
state: up
|
||||
copy-mac-from: eth1
|
||||
link-aggregation:
|
||||
mode: balance-rr
|
||||
port:
|
||||
- eth2
|
||||
- eth1
|
||||
```
|
||||
|
||||
Integration test case included.
|
||||
|
||||
Signed-off-by: Gris Ge <fge@redhat.com>
|
||||
Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
|
||||
---
|
||||
libnmstate/ifaces/base_iface.py | 14 +++++++++++
|
||||
libnmstate/ifaces/ifaces.py | 30 +++++++++++++++++++++++
|
||||
libnmstate/schema.py | 1 +
|
||||
libnmstate/schemas/operational-state.yaml | 4 +++
|
||||
tests/integration/bond_test.py | 13 ++++++++++
|
||||
tests/integration/linux_bridge_test.py | 14 +++++++++++
|
||||
6 files changed, 76 insertions(+)
|
||||
|
||||
diff --git a/libnmstate/ifaces/base_iface.py b/libnmstate/ifaces/base_iface.py
|
||||
index b4ade867..3dbcfe52 100644
|
||||
--- a/libnmstate/ifaces/base_iface.py
|
||||
+++ b/libnmstate/ifaces/base_iface.py
|
||||
@@ -391,6 +391,20 @@ class BaseIface:
|
||||
for family, rules in route_rule_metadata.items():
|
||||
self.raw[family][BaseIface.ROUTE_RULES_METADATA] = rules
|
||||
|
||||
+ @property
|
||||
+ def copy_mac_from(self):
|
||||
+ return self._info.get(Interface.COPY_MAC_FROM)
|
||||
+
|
||||
+ def apply_copy_mac_from(self, mac):
|
||||
+ """
|
||||
+ * Add MAC to original desire.
|
||||
+ * Remove Interface.COPY_MAC_FROM from original desire.
|
||||
+ * Update MAC of merge iface
|
||||
+ """
|
||||
+ self.raw[Interface.MAC] = mac
|
||||
+ self._origin_info[Interface.MAC] = mac
|
||||
+ self._origin_info.pop(Interface.COPY_MAC_FROM, None)
|
||||
+
|
||||
|
||||
def _remove_empty_description(state):
|
||||
if state.get(Interface.DESCRIPTION) == "":
|
||||
diff --git a/libnmstate/ifaces/ifaces.py b/libnmstate/ifaces/ifaces.py
|
||||
index cfc306c6..1e4d2231 100644
|
||||
--- a/libnmstate/ifaces/ifaces.py
|
||||
+++ b/libnmstate/ifaces/ifaces.py
|
||||
@@ -101,12 +101,42 @@ class Ifaces:
|
||||
self._validate_unknown_slaves()
|
||||
self._mark_vf_interface_as_absent_when_sriov_vf_decrease()
|
||||
self._validate_unknown_parent()
|
||||
+ self._apply_copy_mac_from()
|
||||
self._gen_metadata()
|
||||
for iface in self._ifaces.values():
|
||||
iface.pre_edit_validation_and_cleanup()
|
||||
|
||||
self._pre_edit_validation_and_cleanup()
|
||||
|
||||
+ def _apply_copy_mac_from(self):
|
||||
+ for iface in self._ifaces.values():
|
||||
+ if iface.type not in (
|
||||
+ InterfaceType.LINUX_BRIDGE,
|
||||
+ InterfaceType.BOND,
|
||||
+ ):
|
||||
+ continue
|
||||
+ if not iface.copy_mac_from:
|
||||
+ continue
|
||||
+
|
||||
+ if iface.copy_mac_from not in iface.slaves:
|
||||
+ raise NmstateValueError(
|
||||
+ f"The interface {iface.name} is holding invalid "
|
||||
+ f"{Interface.COPY_MAC_FROM} property "
|
||||
+ f"as {iface.copy_mac_from} is not in the port "
|
||||
+ f"list: {iface.port}"
|
||||
+ )
|
||||
+ port_iface = self._ifaces.get(iface.copy_mac_from)
|
||||
+ # TODO: bridge/bond might refering the mac from new veth in the
|
||||
+ # same desire state, it too complex to support that.
|
||||
+ if not port_iface:
|
||||
+ raise NmstateValueError(
|
||||
+ f"The interface {iface.name} is holding invalid "
|
||||
+ f"{Interface.COPY_MAC_FROM} property "
|
||||
+ f"as the port {iface.copy_mac_from} does not exists yet"
|
||||
+ )
|
||||
+
|
||||
+ iface.apply_copy_mac_from(port_iface.mac)
|
||||
+
|
||||
def _create_virtual_slaves(self):
|
||||
"""
|
||||
Certain master interface could have virtual slaves which does not
|
||||
diff --git a/libnmstate/schema.py b/libnmstate/schema.py
|
||||
index 8a86c48d..455dbf8f 100644
|
||||
--- a/libnmstate/schema.py
|
||||
+++ b/libnmstate/schema.py
|
||||
@@ -44,6 +44,7 @@ class Interface:
|
||||
|
||||
MAC = "mac-address"
|
||||
MTU = "mtu"
|
||||
+ COPY_MAC_FROM = "copy-mac-from"
|
||||
|
||||
|
||||
class Route:
|
||||
diff --git a/libnmstate/schemas/operational-state.yaml b/libnmstate/schemas/operational-state.yaml
|
||||
index d856aa5c..8fdeaeec 100644
|
||||
--- a/libnmstate/schemas/operational-state.yaml
|
||||
+++ b/libnmstate/schemas/operational-state.yaml
|
||||
@@ -249,6 +249,8 @@ definitions:
|
||||
type: string
|
||||
enum:
|
||||
- bond
|
||||
+ copy-mac-from:
|
||||
+ type: string
|
||||
link-aggregation:
|
||||
type: object
|
||||
properties:
|
||||
@@ -267,6 +269,8 @@ definitions:
|
||||
- $ref: "#/definitions/interface-linux-bridge/ro"
|
||||
ro:
|
||||
properties:
|
||||
+ copy-mac-from:
|
||||
+ type: string
|
||||
bridge:
|
||||
type: object
|
||||
properties:
|
||||
--
|
||||
2.29.2
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
Name: nmstate
|
||||
Version: 0.3.4
|
||||
Release: 25%{?dist}
|
||||
Release: 27%{?dist}
|
||||
Summary: Declarative network manager API
|
||||
License: LGPLv2+
|
||||
URL: https://github.com/%{srcname}/%{srcname}
|
||||
@ -29,6 +29,13 @@ Patch15: BZ_1908724-sriov-use-verification-retry-to-wait-VF-been-created.
|
||||
Patch16: BZ_1916073_better-handling-for-timeout.patch
|
||||
Patch17: BZ_1918712_use_uuid_for_vlan_vxlan_parent.patch
|
||||
Patch18: BZ_1916073_retry_on_failure_when_activate.patch
|
||||
Patch19: BZ_1931290-SRIOV-Remove-VF-interface-when-total-vfs-decrease.patch
|
||||
Patch20: BZ_1931290-SRIOV-Do-not-create-VF-profiles-automatically.patch
|
||||
Patch21: BZ_1931784-SR-IOV-increase-the-verification-timeout-if-SR-IOV.patch
|
||||
Patch22: BZ_1931784-SR-IOV-fail-on-verification-if-total_vfs-does-not-ma.patch
|
||||
Patch23: BZ_1932247-bridge-do-not-bring-up-existing-ports.patch
|
||||
Patch24: BZ_1932247-nm.applier-ignore-not-desired-unmanaged-ifaces.patch
|
||||
Patch25: BZ_1933538-bridge-bond-New-property-Interface.COPY_MAC_FROM.patch
|
||||
BuildArch: noarch
|
||||
BuildRequires: python3-devel
|
||||
BuildRequires: python3-setuptools
|
||||
@ -99,6 +106,14 @@ gpgv2 --keyring ./gpgkey-mantainers.gpg %{SOURCE1} %{SOURCE0}
|
||||
%{python3_sitelib}/%{libname}/plugins/__pycache__/nmstate_plugin_ovsdb*
|
||||
|
||||
%changelog
|
||||
* Wed Mar 03 2021 Fernando Fernandez Mancera <ferferna@redhat.com> - 0.3.4-27
|
||||
- Introduce `Interface.COPY_MAC_FROM` from bond and bridge. RHBZ#1933538
|
||||
|
||||
* Wed Mar 03 2021 Fernando Fernandez Mancera <ferferna@redhat.com> - 0.3.4-26
|
||||
- New patch do not activating SR-IOV VFs automatically. RHBZ#1931290
|
||||
- New patch fixing Nmstate waits when SR-IOV VFs are decreased. RHBZ#1931784
|
||||
- New patch fixing Nmstate activating unmanaged bridge ports. RHBZ#1932247
|
||||
|
||||
* Fri Feb 05 2021 Gris Ge <fge@redhat.com> - 0.3.4-25
|
||||
- Remove patch for fixing the autoconnect on existing profile. RHBZ#1918712
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user