Blob Blame History Raw
From 316f4fc3333627bcd3aef44c4a469cd6c04360ef Mon Sep 17 00:00:00 2001
From: Gris Ge <fge@redhat.com>
Date: Tue, 20 Sep 2022 21:35:47 +0800
Subject: [PATCH 2/2] ip: allow extra IP address found in verification stage

When nmstate applying the network state, there might be another tool
changing the IP addresses of interface, which lead to verification error
as extra IP address found. This is valid use case in kubernetes-nmstate
where keepalived is trying to add VIP(192.168.111.4) to certain interface.

To support that, we introduce `InterfaceIP.ALLOW_EXTRA_ADDRESS` with
default set to true, nmstate verification will ignore extra IP address
after applied.

Considering this is a very corner case, and could make the life of of
OpenshiftSDN engineer easier, I would suggest we accept this breaker of
API behavior.

It is hard to reproduce it in integration test case, hence only added
unit test cases.

Signed-off-by: Gris Ge <fge@redhat.com>
---
 libnmstate/ifaces/base_iface.py     | 20 ++++++
 libnmstate/schema.py                |  1 +
 tests/lib/ifaces/base_iface_test.py | 98 +++++++++++++++++++++++++++++
 tests/lib/testlib/constants.py      |  2 +
 4 files changed, 121 insertions(+)

diff --git a/libnmstate/ifaces/base_iface.py b/libnmstate/ifaces/base_iface.py
index e1b45617..fb2b7bb6 100644
--- a/libnmstate/ifaces/base_iface.py
+++ b/libnmstate/ifaces/base_iface.py
@@ -403,6 +403,10 @@ class BaseIface:
     def match(self, other):
         self_state = self.state_for_verify()
         other_state = other.state_for_verify()
+        for family in (Interface.IPV4, Interface.IPV6):
+            apply_allow_extra_address(
+                self_state.get(family, {}), other_state.get(family, {})
+            )
         return state_match(self_state, other_state)
 
     def state_for_verify(self):
@@ -537,3 +541,19 @@ def _convert_ovs_external_ids_values_to_string(iface_info):
     )
     for key, value in external_ids.items():
         external_ids[key] = str(value)
+
+
+# When `ALLOW_EXTRA_ADDRESS:True`, we should remove extra IP address in
+# current.
+def apply_allow_extra_address(desire_ip_state, current_ip_state):
+    # By default, we allow extra IP found during verification stage in order
+    # to make the life of OpenshiftSDN easier for this corner case.
+    if desire_ip_state.get(InterfaceIP.ALLOW_EXTRA_ADDRESS, True):
+        desire_addresses = desire_ip_state.get(InterfaceIP.ADDRESS, [])
+        new_cur_addresses = [
+            addr
+            for addr in current_ip_state.get(InterfaceIP.ADDRESS, [])
+            if addr in desire_addresses
+        ]
+        current_ip_state[InterfaceIP.ADDRESS] = new_cur_addresses
+        desire_ip_state.pop(InterfaceIP.ALLOW_EXTRA_ADDRESS, None)
diff --git a/libnmstate/schema.py b/libnmstate/schema.py
index 17daf8f1..76418bf0 100644
--- a/libnmstate/schema.py
+++ b/libnmstate/schema.py
@@ -142,6 +142,7 @@ class InterfaceIP:
     ADDRESS = "address"
     ADDRESS_IP = "ip"
     ADDRESS_PREFIX_LENGTH = "prefix-length"
+    ALLOW_EXTRA_ADDRESS = "allow-extra-address"
     DHCP = "dhcp"
     AUTO_DNS = "auto-dns"
     AUTO_GATEWAY = "auto-gateway"
-- 
2.37.3