Blob Blame History Raw
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