From a9ab1b4f1098fd3fce2e9a826fce83c65c7a9fc5 Mon Sep 17 00:00:00 2001 From: Roopa Prabhu Date: Wed, 24 Dec 2014 12:14:30 -0800 Subject: [PATCH] Rework bridge upperiface handling (to fix some problems with the new bridge driver and svi config) Ticket: CM-3346 Reviewed By: Testing Done: Tested upper interface handling during ifup of bonds/bridges/svis --- addons/bridge.py | 1 + ifupdown/iface.py | 8 +++++ ifupdown/ifupdownmain.py | 8 +++++ ifupdown/scheduler.py | 64 ++++++++++++++++++++++++++++++++++++++-- 4 files changed, 79 insertions(+), 2 deletions(-) diff --git a/addons/bridge.py b/addons/bridge.py index 61a7ad1..59c5f70 100644 --- a/addons/bridge.py +++ b/addons/bridge.py @@ -220,6 +220,7 @@ class bridge(moduleBase): return None if ifaceobj.link_type != ifaceLinkType.LINK_NA: ifaceobj.link_type = ifaceLinkType.LINK_MASTER + ifaceobj.link_kind = ifaceLinkKind.BRIDGE return self.parse_port_list(ifaceobj.get_attr_value_first( 'bridge-ports'), ifacenames_all) diff --git a/ifupdown/iface.py b/ifupdown/iface.py index a1cabe5..bba303a 100644 --- a/ifupdown/iface.py +++ b/ifupdown/iface.py @@ -22,6 +22,11 @@ class ifaceType(): IFACE = 0x1 BRIDGE_VLAN = 0x2 +class ifaceLinkKind(): + UNKNOWN = 0x0 + BRIDGE = 0x1 + BOND = 0x2 + class ifaceLinkType(): LINK_UNKNOWN = 0x0 LINK_SLAVE = 0x1 @@ -223,6 +228,7 @@ class iface(): self.priv_data = None self.realname = None self.link_type = ifaceLinkType.LINK_UNKNOWN + self.link_kind = ifaceLinkKind.BRIDGE def _set_attrs_from_dict(self, attrdict): self.auto = attrdict.get('auto', False) @@ -407,6 +413,7 @@ class iface(): del odict['linkstate'] del odict['env'] del odict['link_type'] + del odict['link_kind'] return odict def __setstate__(self, dict): @@ -424,6 +431,7 @@ class iface(): self.raw_config = [] self.flags |= self._PICKLED self.link_type = ifaceLinkType.LINK_UNKNOWN + self.link_kind = ifaceLinkKind.UNKNOWN def dump_raw(self, logger): indent = ' ' diff --git a/ifupdown/ifupdownmain.py b/ifupdown/ifupdownmain.py index 6346740..07c0802 100644 --- a/ifupdown/ifupdownmain.py +++ b/ifupdown/ifupdownmain.py @@ -241,6 +241,13 @@ class ifupdownMain(ifupdownBase): def get_ifaceobjs(self, ifacename): return self.ifaceobjdict.get(ifacename) + def get_ifaceobjs_saved(self, ifacename): + """ Return ifaceobjects from statemanager """ + if self.STATEMANAGER_ENABLE: + return self.statemanager.get_ifaceobjs(ifacename) + else: + None + def get_ifaceobj_first(self, ifacename): ifaceobjs = self.get_ifaceobjs(ifacename) if ifaceobjs: @@ -253,6 +260,7 @@ class ifupdownMain(ifupdownBase): def get_iface_obj_last(self, ifacename): return self.ifaceobjdict.get(ifacename)[-1] + def must_follow_upperifaces(self, ifacename): # # XXX: This bleeds the knowledge of iface diff --git a/ifupdown/scheduler.py b/ifupdown/scheduler.py index a634586..794c552 100644 --- a/ifupdown/scheduler.py +++ b/ifupdown/scheduler.py @@ -19,6 +19,7 @@ from graph import * from collections import deque from threading import * from ifupdownbase import * +from sets import Set class ifaceSchedulerFlags(): """ Enumerates scheduler flags """ @@ -330,6 +331,66 @@ class ifaceScheduler(): ifupdownobj.logger.warn('%s : %s' %(ifacename, str(e))) pass + @classmethod + def _get_valid_upperifaces(cls, ifupdownobj, ifacenames, + allupperifacenames): + """ Recursively find valid upperifaces + + valid upperifaces are: + - An upperiface which had no user config (example builtin + interfaces. usually vlan interfaces.) + - or had config and previously up + - and interface currently does not exist + - or is a bridge (because if your upperiface was a bridge + - u will have to execute up on the bridge + to enslave the port and apply bridge attributes to the port) """ + + upperifacenames = [] + for ifacename in ifacenames: + # get upperifaces + ifaceobj = ifupdownobj.get_ifaceobj_first(ifacename) + if not ifaceobj: + continue + ulist = Set(ifaceobj.upperifaces).difference(upperifacenames) + nulist = [] + for u in ulist: + uifaceobj = ifupdownobj.get_ifaceobj_first(u) + if not uifaceobj: + continue + has_config = not bool(uifaceobj.priv_flags + & ifupdownobj.NOCONFIG) + if (((has_config and ifupdownobj.get_ifaceobjs_saved(u)) or + not has_config) and (not ifupdownobj.link_exists(u) + or uifaceobj.link_kind == ifaceLinkKind.BRIDGE)): + nulist.append(u) + upperifacenames.extend(nulist) + allupperifacenames.extend(upperifacenames) + if upperifacenames: + cls._get_valid_upperifaces(ifupdownobj, upperifacenames, + allupperifacenames) + return + + @classmethod + def run_upperifaces(cls, ifupdownobj, ifacenames, ops, + continueonfailure=True): + """ Run through valid upperifaces """ + upperifaces = [] + + cls._get_valid_upperifaces(ifupdownobj, ifacenames, upperifaces) + if not upperifaces: + return + # dump valid upperifaces + ifupdownobj.logger.debug(upperifaces) + for u in upperifaces: + try: + ifaceobjs = ifupdownobj.get_ifaceobjs(u) + if not ifaceobjs: + continue + cls.run_iface_list_ops(ifupdownobj, ifaceobjs, ops) + except Exception, e: + if continueonfailure: + self.logger.warn('%s' %str(e)) + @classmethod def get_sorted_iface_list(cls, ifupdownobj, ifacenames, ops, dependency_graph, indegrees=None): @@ -457,6 +518,5 @@ class ifaceScheduler(): ifupdownobj.logger.info('running upperifaces (parent interfaces) ' + 'if available ..') cls._STATE_CHECK = False - cls.run_iface_list_upper(ifupdownobj, ifacenames, ops, - skip_root=True) + cls.run_upperifaces(ifupdownobj, ifacenames, ops) cls._STATE_CHECK = True