From 7444feea6ddbfbfe766087d12937cf45583c5a60 Mon Sep 17 00:00:00 2001 From: Sam Tannous Date: Tue, 20 Oct 2015 13:49:07 -0400 Subject: [PATCH] ifupdown2 should allow speed setting even with duplicate iface stanzas Ticket: CM-6740 Reviewed By: roopa Testing Done: tested multiple ifreloads with various test cases In the case of duplicate iface stanzas where one of the stanzas sets the link attributes, ifupdown2 was confused because the absence of link attributes forced it to reset them to default values (when they existed). This patch tracks link changes and prevents resetting to defaults only if there are no explicit settings configured. Furthermore, only the last interface processed (from the duplicates) will take care of resetting to defaults. --- addons/ethtool.py | 29 +++++++++++++++++++++++++++++ ifupdown/iface.py | 5 +++-- ifupdown/ifupdownmain.py | 9 +++++++-- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/addons/ethtool.py b/addons/ethtool.py index 06cad88..f69574b 100644 --- a/addons/ethtool.py +++ b/addons/ethtool.py @@ -39,6 +39,8 @@ class ethtool(moduleBase,utilsBase): def __init__(self, *args, **kargs): moduleBase.__init__(self, *args, **kargs) self.ipcmd = None + # keep a list of iface objects who have modified link attributes + self.ifaceobjs_modified_configs = [] def _post_up(self, ifaceobj, operation='post_up'): """ @@ -62,12 +64,36 @@ class ethtool(moduleBase,utilsBase): continue # check running values running_val = self.get_running_attr(attr, ifaceobj) + # we need to track if an interface has a configured value + # this will be used if there are duplicate iface stanza and + # the configured interface will always take precedence. + # so even if we do not change the settings because they match + # what is configured, we need to append it here so that later duplicate + # ifaces will see that we had a configured iface and not change things. if config_val and config_val == running_val: # running value is what is configured, do nothing + # this prevents unconfigured ifaces from resetting to default + self.ifaceobjs_modified_configs.append(ifaceobj.name) continue + if not config_val and default_val and default_val == running_val: # nothing configured but the default is running continue + # if we are the oldest sibling, we have to reset to defaults + # unless a previous sibling had link attr configured and made changes + if ((ifaceobj.flags & iface.HAS_SIBLINGS) and + (ifaceobj.flags & iface.OLDEST_SIBLING) and + (ifaceobj.name in self.ifaceobjs_modified_configs)): + continue + + # if we are not the oldest and we have no configs, do not change anything + # the only way a non-oldest sibling would change values is if it + # had configured settings + if (not ((ifaceobj.flags & iface.HAS_SIBLINGS) and + (ifaceobj.flags & iface.OLDEST_SIBLING)) and + not config_val): + continue + # if we got this far, we need to change it if config_val and (config_val != running_val): # if the configured value is not set, set it @@ -83,6 +109,9 @@ class ethtool(moduleBase,utilsBase): # we should only be calling ethtool if there # is a speed set or we can find a default speed # because we should only be calling ethtool on swp ports + # we also need to set this here in case we changed + # something. this prevents unconfigured ifaces from resetting to default + self.ifaceobjs_modified_configs.append(ifaceobj.name) cmd = 'ethtool -s %s %s' %(ifaceobj.name, cmd) self.exec_command(cmd) except Exception, e: diff --git a/ifupdown/iface.py b/ifupdown/iface.py index e6a1807..aed4b78 100644 --- a/ifupdown/iface.py +++ b/ifupdown/iface.py @@ -291,10 +291,11 @@ class iface(): """ # flag to indicate that the object was created from pickled state - _PICKLED = 0x00000001 - HAS_SIBLINGS = 0x00000010 + _PICKLED = 0x00000001 + HAS_SIBLINGS = 0x00000010 IFACERANGE_ENTRY = 0x00000100 IFACERANGE_START = 0x00001000 + OLDEST_SIBLING = 0x00010000 version = '0.1' diff --git a/ifupdown/ifupdownmain.py b/ifupdown/ifupdownmain.py index f94acfb..c02ff7e 100644 --- a/ifupdown/ifupdownmain.py +++ b/ifupdown/ifupdownmain.py @@ -574,8 +574,13 @@ class ifupdownMain(ifupdownBase): self.logger.warn('duplicate interface %s found' %ifaceobj.name) return if currentifaceobjlist[0].type == ifaceobj.type: - currentifaceobjlist[0].flags |= iface.HAS_SIBLINGS - ifaceobj.flags |= iface.HAS_SIBLINGS + currentifaceobjlist[0].flags |= ifaceobj.HAS_SIBLINGS + ifaceobj.flags |= ifaceobj.HAS_SIBLINGS + # clear the OLDEST_SIBLING from all the siblings + for iface in self.ifaceobjdict[ifaceobj.name]: + iface.flags &= ~ifaceobj.OLDEST_SIBLING + # current sibling is the oldest + ifaceobj.flags |= ifaceobj.OLDEST_SIBLING self.ifaceobjdict[ifaceobj.name].append(ifaceobj) def _iface_configattr_syntax_checker(self, attrname, attrval):