Blame SOURCES/BZ_1933538-bridge-bond-New-property-Interface.COPY_MAC_FROM.patch

520691
From 34b689a86c7cd4bcf5ab5cf7d903acba7d60f4be Mon Sep 17 00:00:00 2001
520691
From: Gris Ge <fge@redhat.com>
520691
Date: Wed, 10 Feb 2021 23:28:37 +0800
520691
Subject: [PATCH] bridge/bond: New property `Interface.COPY_MAC_FROM`
520691
520691
Introducing `Interface.COPY_MAC_FROM` allowing bridge or bond
520691
to use MAC address from specified port.
520691
520691
Example:
520691
520691
```yaml
520691
---
520691
interfaces:
520691
- name: bond99
520691
  type: bond
520691
  state: up
520691
  copy-mac-from: eth1
520691
  link-aggregation:
520691
    mode: balance-rr
520691
    port:
520691
    - eth2
520691
    - eth1
520691
```
520691
520691
Integration test case included.
520691
520691
Signed-off-by: Gris Ge <fge@redhat.com>
520691
Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
520691
---
520691
 libnmstate/ifaces/base_iface.py           | 14 +++++++++++
520691
 libnmstate/ifaces/ifaces.py               | 30 +++++++++++++++++++++++
520691
 libnmstate/schema.py                      |  1 +
520691
 libnmstate/schemas/operational-state.yaml |  4 +++
520691
 tests/integration/bond_test.py            | 13 ++++++++++
520691
 tests/integration/linux_bridge_test.py    | 14 +++++++++++
520691
 6 files changed, 76 insertions(+)
520691
520691
diff --git a/libnmstate/ifaces/base_iface.py b/libnmstate/ifaces/base_iface.py
520691
index b4ade867..3dbcfe52 100644
520691
--- a/libnmstate/ifaces/base_iface.py
520691
+++ b/libnmstate/ifaces/base_iface.py
520691
@@ -391,6 +391,20 @@ class BaseIface:
520691
         for family, rules in route_rule_metadata.items():
520691
             self.raw[family][BaseIface.ROUTE_RULES_METADATA] = rules
520691
 
520691
+    @property
520691
+    def copy_mac_from(self):
520691
+        return self._info.get(Interface.COPY_MAC_FROM)
520691
+
520691
+    def apply_copy_mac_from(self, mac):
520691
+        """
520691
+        * Add MAC to original desire.
520691
+        * Remove Interface.COPY_MAC_FROM from original desire.
520691
+        * Update MAC of merge iface
520691
+        """
520691
+        self.raw[Interface.MAC] = mac
520691
+        self._origin_info[Interface.MAC] = mac
520691
+        self._origin_info.pop(Interface.COPY_MAC_FROM, None)
520691
+
520691
 
520691
 def _remove_empty_description(state):
520691
     if state.get(Interface.DESCRIPTION) == "":
520691
diff --git a/libnmstate/ifaces/ifaces.py b/libnmstate/ifaces/ifaces.py
520691
index cfc306c6..1e4d2231 100644
520691
--- a/libnmstate/ifaces/ifaces.py
520691
+++ b/libnmstate/ifaces/ifaces.py
520691
@@ -101,12 +101,42 @@ class Ifaces:
520691
             self._validate_unknown_slaves()
520691
             self._mark_vf_interface_as_absent_when_sriov_vf_decrease()
520691
             self._validate_unknown_parent()
520691
+            self._apply_copy_mac_from()
520691
             self._gen_metadata()
520691
             for iface in self._ifaces.values():
520691
                 iface.pre_edit_validation_and_cleanup()
520691
 
520691
             self._pre_edit_validation_and_cleanup()
520691
 
520691
+    def _apply_copy_mac_from(self):
520691
+        for iface in self._ifaces.values():
520691
+            if iface.type not in (
520691
+                InterfaceType.LINUX_BRIDGE,
520691
+                InterfaceType.BOND,
520691
+            ):
520691
+                continue
520691
+            if not iface.copy_mac_from:
520691
+                continue
520691
+
520691
+            if iface.copy_mac_from not in iface.slaves:
520691
+                raise NmstateValueError(
520691
+                    f"The interface {iface.name} is holding invalid "
520691
+                    f"{Interface.COPY_MAC_FROM} property "
520691
+                    f"as {iface.copy_mac_from} is not in the port "
520691
+                    f"list: {iface.port}"
520691
+                )
520691
+            port_iface = self._ifaces.get(iface.copy_mac_from)
520691
+            # TODO: bridge/bond might refering the mac from new veth in the
520691
+            #       same desire state, it too complex to support that.
520691
+            if not port_iface:
520691
+                raise NmstateValueError(
520691
+                    f"The interface {iface.name} is holding invalid "
520691
+                    f"{Interface.COPY_MAC_FROM} property "
520691
+                    f"as the port {iface.copy_mac_from} does not exists yet"
520691
+                )
520691
+
520691
+            iface.apply_copy_mac_from(port_iface.mac)
520691
+
520691
     def _create_virtual_slaves(self):
520691
         """
520691
         Certain master interface could have virtual slaves which does not
520691
diff --git a/libnmstate/schema.py b/libnmstate/schema.py
520691
index 8a86c48d..455dbf8f 100644
520691
--- a/libnmstate/schema.py
520691
+++ b/libnmstate/schema.py
520691
@@ -44,6 +44,7 @@ class Interface:
520691
 
520691
     MAC = "mac-address"
520691
     MTU = "mtu"
520691
+    COPY_MAC_FROM = "copy-mac-from"
520691
 
520691
 
520691
 class Route:
520691
diff --git a/libnmstate/schemas/operational-state.yaml b/libnmstate/schemas/operational-state.yaml
520691
index d856aa5c..8fdeaeec 100644
520691
--- a/libnmstate/schemas/operational-state.yaml
520691
+++ b/libnmstate/schemas/operational-state.yaml
520691
@@ -249,6 +249,8 @@ definitions:
520691
           type: string
520691
           enum:
520691
             - bond
520691
+        copy-mac-from:
520691
+          type: string
520691
         link-aggregation:
520691
           type: object
520691
           properties:
520691
@@ -267,6 +269,8 @@ definitions:
520691
         - $ref: "#/definitions/interface-linux-bridge/ro"
520691
     ro:
520691
       properties:
520691
+        copy-mac-from:
520691
+          type: string
520691
         bridge:
520691
           type: object
520691
           properties:
520691
-- 
520691
2.29.2
520691