]> git.proxmox.com Git - mirror_ifupdown2.git/blobdiff - ifupdown2/ifupdown/ifupdownmain.py
ifupdownmain: detect interfaces no longer configured but pick up by regexes
[mirror_ifupdown2.git] / ifupdown2 / ifupdown / ifupdownmain.py
index ed0e155b294f86bd7eb8c94bfa323008ffe0dbb6..57b17a2743a906e0a1a69b854b6fed4f877c9986 100644 (file)
@@ -97,11 +97,6 @@ class ifupdownMain(ifupdownBase):
             (ifaceobj.link_privflags & ifaceLinkPrivFlags.VRF_SLAVE)):
             self._keep_link_down(ifaceobj)
             return
-        # if not a logical interface and addr method is manual,
-        # ignore link admin state changes
-        if (ifaceobj.addr_method == 'manual' and
-            not ifaceobj.link_kind):
-            return
         if self._delay_admin_state:
             self._delay_admin_state_iface_queue.append(ifaceobj.name)
             return
@@ -115,7 +110,13 @@ class ifupdownMain(ifupdownBase):
             return
         if self._keep_link_down(ifaceobj):
             return
-        self.link_up(ifaceobj.name)
+        try:
+            self.link_up(ifaceobj.name)
+        except:
+            if ifaceobj.addr_method == 'manual':
+                pass
+            else:
+                raise
 
     def _keep_link_down(self, ifaceobj):
         if ifaceobj.link_privflags & ifaceLinkPrivFlags.KEEP_LINK_DOWN:
@@ -134,11 +135,6 @@ class ifupdownMain(ifupdownBase):
         # there is no real interface behind it
         if ifaceobj.type == ifaceType.BRIDGE_VLAN:
             return
-        # if not a logical interface and addr method is manual,
-        # ignore link admin state changes
-        if (ifaceobj.addr_method == 'manual' and
-            not ifaceobj.link_kind):
-            return
         if self._delay_admin_state:
             self._delay_admin_state_iface_queue.append(ifaceobj.name)
             return
@@ -150,7 +146,13 @@ class ifupdownMain(ifupdownBase):
            return
         if not self.link_exists(ifaceobj.name):
            return
-        self.link_down(ifaceobj.name)
+        try:
+            self.link_down(ifaceobj.name)
+        except:
+            if ifaceobj.addr_method == 'manual':
+                pass
+            else:
+                raise
 
     # ifupdown object interface operation handlers
     ops_handlers = OrderedDict([('up', run_up),
@@ -285,6 +287,11 @@ class ifupdownMain(ifupdownBase):
 
         self._cache_no_repeats = {}
 
+        # initialize global config object with config passed by the user
+        # This makes config available to addon modules
+        ifupdownConfig.config = self.config
+        statemanager.statemanager_api.init()
+
         if self.flags.STATEMANAGER_ENABLE:
             self.statemanager = statemanager.statemanager_api
             try:
@@ -321,10 +328,6 @@ class ifupdownMain(ifupdownBase):
         self._ifaceobj_squash_internal = True if self.config.get(
                             'ifaceobj_squash_internal', '1') == '1' else False
 
-        # initialize global config object with config passed by the user
-        # This makes config available to addon modules
-        ifupdownConfig.config = self.config
-
         self.validate_keywords = {
             '<mac>': self._keyword_mac,
             '<text>': self._keyword_text,
@@ -525,13 +528,6 @@ class ifupdownMain(ifupdownBase):
         ifaceobj.role = role
 
     def _set_iface_role_n_kind(self, ifaceobj, upperifaceobj):
-
-        # If addr_method is set and link is not a logical interface,
-        # set flag KEEP_LINK_DOWN. addr_method == 'manual' only applies to
-        # logical interfaces.
-        if (ifaceobj.addr_method == 'manual' and not ifaceobj.link_kind):
-            ifaceobj.link_privflags |= ifaceLinkPrivFlags.KEEP_LINK_DOWN
-
         if (upperifaceobj.link_kind & ifaceLinkKind.BOND):
             self._set_iface_role(ifaceobj, ifaceRole.SLAVE, upperifaceobj)
             ifaceobj.link_privflags |= ifaceLinkPrivFlags.BOND_SLAVE
@@ -1804,6 +1800,9 @@ class ifupdownMain(ifupdownBase):
         if self.flags.STATEMANAGER_ENABLE and ops[0] == 'query-savedstate':
             return self.statemanager.dump_pretty(ifacenames)
         self.flags.STATEMANAGER_UPDATE = False
+
+        iface_read_ret = True
+
         if auto:
             self.logger.debug('setting flag ALL')
             ifupdownflags.flags.ALL = True
@@ -1818,7 +1817,7 @@ class ifupdownMain(ifupdownBase):
                                 ifacePrivFlags(False, True)), ifacenames)
         else:
             try:
-                self.read_iface_config()
+                iface_read_ret = self.read_iface_config()
             except Exception:
                 raise
 
@@ -1869,14 +1868,16 @@ class ifupdownMain(ifupdownBase):
         if ops[0] == 'query' and ifupdownflags.flags.WITHDEFAULTS:
             return self.print_ifaceobjs_pretty(filtered_ifacenames, format)
         elif ops[0] == 'query-checkcurr':
-            ret = self.print_ifaceobjscurr_pretty(filtered_ifacenames, format)
-            if ret != 0:
+            if self.print_ifaceobjscurr_pretty(filtered_ifacenames, format):
                 # if any of the object has an error, signal that silently
                 raise Exception('')
         elif ops[0] == 'query-running':
             self.print_ifaceobjsrunning_pretty(filtered_ifacenames, format)
             return
 
+        if not iface_read_ret or not ret:
+            raise Exception()
+
     def _reload_currentlyup(self, upops, downops, auto=False, allow=None,
             ifacenames=None, excludepats=None, usecurrentconfig=False,
             syntaxcheck=False, **extra_args):
@@ -2086,14 +2087,57 @@ class ifupdownMain(ifupdownBase):
                     not self.is_ifaceobj_builtin(newifaceobjlist[0]) and
                     lastifaceobjlist[0].is_config_present() and
                     lastifaceobjlist[0].link_kind):
-                    self.logger.warn('%s: misconfig ? removed but still exists '
-                                     'as a dependency of %s.\nPlease remove '
-                                     'the dependency manually `ifdown %s` if '
-                                     'it is being picked up as part of a regex'
-                                     % (newifaceobjlist[objidx].name,
-                                        str(newifaceobjlist[objidx].upperifaces),
-                                        newifaceobjlist[objidx].name))
-                if (lastifaceobjlist[0].link_kind and
+
+                    # Check if interface is picked up by a regex in the upperifaces.
+                    print_warning = True
+
+                    for upper in newifaceobjlist[objidx].upperifaces or []:
+                        slaves = []
+                        for upper_ifaceobj in self.ifaceobjdict.get(upper):
+                            slaves.extend(upper_ifaceobj.get_attr_value("bond-slaves") or [])
+                            slaves.extend(upper_ifaceobj.get_attr_value("bridge-ports") or [])
+                        slaves_string = " ".join(slaves)
+                        if newifaceobjlist[objidx].name not in slaves_string:
+                            print_warning = "regex" not in slaves_string
+                            if not print_warning:
+                                break
+                    ###############################################################
+
+                    warning_no_config_regex = (
+                        "%s: misconfig ? removed but still exists as a dependency of %s.\n"
+                        "Please remove the dependency manually `ifdown %s` if it is being "
+                        "picked up as part of a regex" % (
+                            newifaceobjlist[objidx].name,
+                            str(newifaceobjlist[objidx].upperifaces),
+                            newifaceobjlist[objidx].name
+                        )
+                    )
+
+                    if print_warning:
+                        self.logger.warn(warning_no_config_regex)
+                    else:
+                        # The warning shouldn't be printed because we've detected that this
+                        # interface was pick up as part of a regex but the config doesn't
+                        # exist anymore. It was most likely removed from the config file itself
+                        # We should down this interface and remove it from the ifaceobjdict
+                        # and dependency graph used for the following ifreload.
+                        ifname_to_remove = newifaceobjlist[objidx].name
+                        ifacedownlist.append(ifname_to_remove)
+
+                        try:
+                            if new_ifaceobjdict:
+                                del new_ifaceobjdict[ifname_to_remove]
+
+                            for k, v in new_dependency_graph.iteritems():
+                                if ifname_to_remove in v:
+                                    v.remove(ifname_to_remove)
+                            del new_dependency_graph[ifname_to_remove]
+                        except Exception as e:
+                            self.logger.warning(warning_no_config_regex)
+                            self.logger.warning("while trying to fix this situation "
+                                                "we ran into the following issues: %s" % str(e))
+
+                elif (lastifaceobjlist[0].link_kind and
                     not newifaceobjlist[0].link_kind):
                     self.logger.warn('%s: moved from being a %s to a'
                                      ' physical interface (non-logical interface).'