From 72edab395316ba1ae69ea4d788b0572c935759ac Mon Sep 17 00:00:00 2001 From: Fernando Fernandez Mancera 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 Signed-off-by: Gris Ge --- 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