From d2b357167d55b49d572f0a4de09632e4f8e5d470 Mon Sep 17 00:00:00 2001 From: Roopa Prabhu Date: Fri, 13 May 2016 22:44:50 -0700 Subject: [PATCH] addons: vrf: vrf_slave: up vrf dev only when all interfaces are being brought up Ticket: CM-10954, CM-10953 Reviewed By: julien Testing Done: ran ifupdown2 smoke and vrf ifup/ifdown testing - vrf master if not around is brought up when the first slave is brought up by design (because we want the slaves to be enslaved to a vrf master before addresses are configured). and master is not brought up by first because interfaces are brought up down to top in the dependency tree. - This patch makes sure a slave brings up a vrf master only when all interfaces are specified. When an individual interface is brought up, skip master bring up and throw an error. - Since the addon modules also need to use the ALL and WITH_DEPENDS flags, this patch moves them to the existing global ifupdownflags class - vrf module uses the ifupdownflags.ALL flag to not bring up the master when only the slave is being brought up example: ifup # brings up the vrf device ifup --with-depends # brings up the vrf dev and # its slaves ifup # if vrf master is not around, # an error is thrown ifup --with-depends # will still not bring up the vrf master ifdown # deletes vrf dev and flushes the # addresses on vrf slaves ifup # brings up vrf dev and does not # up the adresses on the slaves ifup --with-depends # will bring up vrf and reapply config # on slaves (including addresses) Signed-off-by: Roopa Prabhu --- addons/vrf.py | 13 ++++++++-- ifupdown/ifupdownflags.py | 1 + ifupdown/ifupdownmain.py | 51 +++++++++++++++++++++------------------ ifupdown/scheduler.py | 10 ++++---- 4 files changed, 45 insertions(+), 30 deletions(-) diff --git a/addons/vrf.py b/addons/vrf.py index fddbae7..3cf7e2c 100644 --- a/addons/vrf.py +++ b/addons/vrf.py @@ -351,15 +351,22 @@ class vrf(moduleBase): def _up_vrf_slave(self, ifacename, vrfname, ifaceobj=None, ifaceobj_getfunc=None, vrf_exists=False): try: + master_exists = True if vrf_exists or self.ipcmd.link_exists(vrfname): upper = self.ipcmd.link_get_upper(ifacename) if not upper or upper != vrfname: self._handle_existing_connections(ifaceobj, vrfname) self.ipcmd.link_set(ifacename, 'master', vrfname) - elif ifaceobj: + elif ifupdownflags.flags.ALL and ifaceobj: self._up_vrf_slave_without_master(ifacename, vrfname, ifaceobj, ifaceobj_getfunc) - rtnetlink_api.rtnl_api.link_set(ifacename, "up") + else: + master_exists = False + if master_exists: + rtnetlink_api.rtnl_api.link_set(ifacename, "up") + else: + self.log_error('vrf %s not around, skipping vrf config' + %(vrfname)) except Exception, e: self.log_error('%s: %s' %(ifacename, str(e))) @@ -455,6 +462,8 @@ class vrf(moduleBase): if add_slaves: for s in add_slaves: try: + if not self.ipcmd.link_exists(s): + continue sobj = None if ifaceobj_getfunc: sobj = ifaceobj_getfunc(s) diff --git a/ifupdown/ifupdownflags.py b/ifupdown/ifupdownflags.py index 08ad3ec..58ca55e 100644 --- a/ifupdown/ifupdownflags.py +++ b/ifupdown/ifupdownflags.py @@ -9,6 +9,7 @@ class ifupdownFlags(): def __init__(self): + self.ALL = False self.FORCE = False self.DRYRUN = False self.NOWAIT = False diff --git a/ifupdown/ifupdownmain.py b/ifupdown/ifupdownmain.py index 0595679..66e5093 100644 --- a/ifupdown/ifupdownmain.py +++ b/ifupdown/ifupdownmain.py @@ -40,8 +40,6 @@ _success_sym = '(%s)' %_tickmark _error_sym = '(%s)' %_crossmark class ifupdownMainFlags(): - WITH_DEPENDS = False - ALL = False IFACE_CLASS = False COMPAT_EXEC_SCRIPTS = False STATEMANAGER_ENABLE = True @@ -112,7 +110,8 @@ class ifupdownMain(ifupdownBase): # there is no real interface behind it if ifaceobj.type == ifaceType.BRIDGE_VLAN: return - if ifaceobj.link_kind & ifaceLinkKind.VRF: + if ((ifaceobj.link_kind & ifaceLinkKind.VRF) or + (ifaceobj.link_privflags & ifaceLinkPrivFlags.VRF_SLAVE)): return if (ifaceobj.addr_method and ifaceobj.addr_method == 'manual'): @@ -131,7 +130,8 @@ class ifupdownMain(ifupdownBase): self.link_up(ifaceobj.name) def run_down(self, ifaceobj): - if ifaceobj.link_kind & ifaceLinkKind.VRF: + if ((ifaceobj.link_kind & ifaceLinkKind.VRF) or + (ifaceobj.link_privflags & ifaceLinkPrivFlags.VRF_SLAVE)): return # Skip link sets on ifaceobjs of type 'vlan' (used for l2 attrs) # there is no real interface behind it @@ -195,13 +195,13 @@ class ifupdownMain(ifupdownBase): ifupdownflags.flags.NOWAIT = nowait ifupdownflags.flags.PERFMODE = perfmode ifupdownflags.flags.CACHE = cache + ifupdownflags.flags.WITH_DEPENDS = withdepends # Can be used to provide hints for caching ifupdownflags.flags.CACHE_FLAGS = 0x0 self.flags = ifupdownMainFlags() - self.flags.WITH_DEPENDS = withdepends self.flags.STATEMANAGER_ENABLE = statemanager_enable self.interfacesfile = interfacesfile self.interfacesfileiobuf = interfacesfileiobuf @@ -1103,8 +1103,8 @@ class ifupdownMain(ifupdownBase): if not self.flags.ADDONS_ENABLE: self.flags.STATEMANAGER_UPDATE = False if auto: - self.flags.ALL = True - self.flags.WITH_DEPENDS = True + ifupdownflags.flags.ALL = True + ifupdownflags.flags.WITH_DEPENDS = True try: iface_read_ret = self.read_iface_config() except Exception: @@ -1143,7 +1143,8 @@ class ifupdownMain(ifupdownBase): ret = self._sched_ifaces(filtered_ifacenames, ops, skipupperifaces=skipupperifaces, followdependents=True - if self.flags.WITH_DEPENDS else False) + if ifupdownflags.flags.WITH_DEPENDS + else False) finally: self._process_delay_admin_state_queue('up') if not ifupdownflags.flags.DRYRUN and self.flags.ADDONS_ENABLE: @@ -1164,8 +1165,8 @@ class ifupdownMain(ifupdownBase): if not self.flags.ADDONS_ENABLE: self.flags.STATEMANAGER_UPDATE = False if auto: - self.flags.ALL = True - self.flags.WITH_DEPENDS = True + ifupdownflags.flags.ALL = True + ifupdownflags.flags.WITH_DEPENDS = True # For down we need to look at old state, unless usecurrentconfig # is set if (not usecurrentconfig and self.flags.STATEMANAGER_ENABLE and @@ -1210,7 +1211,7 @@ class ifupdownMain(ifupdownBase): try: self._sched_ifaces(filtered_ifacenames, ops, followdependents=True - if self.flags.WITH_DEPENDS else False) + if ifupdownflags.flags.WITH_DEPENDS else False) finally: self._process_delay_admin_state_queue('down') if not ifupdownflags.flags.DRYRUN and self.flags.ADDONS_ENABLE: @@ -1236,8 +1237,8 @@ class ifupdownMain(ifupdownBase): self.flags.STATEMANAGER_UPDATE = False if auto: self.logger.debug('setting flag ALL') - self.flags.ALL = True - self.flags.WITH_DEPENDS = True + ifupdownflags.flags.ALL = True + ifupdownflags.flags.WITH_DEPENDS = True if ops[0] == 'query-syntax': self._modules_help() @@ -1285,7 +1286,7 @@ class ifupdownMain(ifupdownBase): ret = self._sched_ifaces(filtered_ifacenames, ops, followdependents=True - if self.flags.WITH_DEPENDS else False) + if ifupdownflags.flags.WITH_DEPENDS else False) if ops[0] == 'query' and ifupdownflags.flags.WITHDEFAULTS: return self.print_ifaceobjs_pretty(filtered_ifacenames, format) @@ -1371,8 +1372,8 @@ class ifupdownMain(ifupdownBase): # Now, run 'up' with new config dict # reset statemanager update flag to default if auto: - self.flags.ALL = True - self.flags.WITH_DEPENDS = True + ifupdownflags.flags.ALL = True + ifupdownflags.flags.WITH_DEPENDS = True if new_ifaceobjdict: # and now, ifaceobjdict is back to current config self.ifaceobjdict = new_ifaceobjdict @@ -1384,7 +1385,7 @@ class ifupdownMain(ifupdownBase): %str(interfaces_to_up)) ret = self._sched_ifaces(interfaces_to_up, upops, followdependents=True - if self.flags.WITH_DEPENDS else False) + if ifupdownflags.flags.WITH_DEPENDS else False) if ifupdownflags.flags.DRYRUN: return self._save_state() @@ -1557,8 +1558,8 @@ class ifupdownMain(ifupdownBase): return if auto: - self.flags.ALL = True - self.flags.WITH_DEPENDS = True + ifupdownflags.flags.ALL = True + ifupdownflags.flags.WITH_DEPENDS = True # and now, we are back to the current config in ifaceobjdict self.ifaceobjdict = new_ifaceobjdict self.dependency_graph = new_dependency_graph @@ -1569,7 +1570,8 @@ class ifupdownMain(ifupdownBase): try: ret = self._sched_ifaces(new_filtered_ifacenames, upops, followdependents=True - if self.flags.WITH_DEPENDS else False) + if ifupdownflags.flags.WITH_DEPENDS + else False) except Exception, e: ret = None self.logger.error(str(e)) @@ -1625,7 +1627,8 @@ class ifupdownMain(ifupdownBase): continue ifaceobj.dump_raw(self.logger) print '\n' - if self.flags.WITH_DEPENDS and not self.flags.ALL: + if (ifupdownflags.flags.WITH_DEPENDS and + not ifupdownflags.flags.ALL): dlist = ifaceobj.lowerifaces if not dlist: continue self.print_ifaceobjs_raw(dlist) @@ -1639,7 +1642,8 @@ class ifupdownMain(ifupdownBase): (running and not ifaceobj.is_config_present())): continue ifaceobjs.append(ifaceobj) - if self.flags.WITH_DEPENDS and not self.flags.ALL: + if (ifupdownflags.flags.WITH_DEPENDS and + not ifupdownflags.flags.ALL): dlist = ifaceobj.lowerifaces if not dlist: continue self._get_ifaceobjs_pretty(dlist, ifaceobjs, running) @@ -1675,7 +1679,8 @@ class ifupdownMain(ifupdownBase): if self.is_ifaceobj_noconfig(ifaceobj): continue ifaceobjs.append(ifaceobj) - if self.flags.WITH_DEPENDS and not self.flags.ALL: + if (ifupdownflags.flags.WITH_DEPENDS and + not ifupdownflags.flags.ALL): dlist = ifaceobj.lowerifaces if not dlist: continue dret = self._get_ifaceobjscurr_pretty(dlist, ifaceobjs) diff --git a/ifupdown/scheduler.py b/ifupdown/scheduler.py index 3202f9b..1d0d92d 100644 --- a/ifupdown/scheduler.py +++ b/ifupdown/scheduler.py @@ -184,7 +184,7 @@ class ifaceScheduler(): not ifupdownobj.flags.ADDONS_ENABLE or (not ifupdownobj.is_ifaceobj_noconfig(ifaceobj) and ifupdownobj.config.get('warn_on_ifdown', '0') == '0' and - not ifupdownobj.flags.ALL)): + not ifupdownflags.flags.ALL)): return True ulist = ifaceobj.upperifaces @@ -201,7 +201,7 @@ class ifaceScheduler(): # return false to the caller to skip this interface for u in tmpulist: if ifupdownobj.link_exists(u): - if not ifupdownobj.flags.ALL: + if not ifupdownflags.flags.ALL: if ifupdownobj.is_ifaceobj_noconfig(ifaceobj): ifupdownobj.logger.info('%s: skipping interface down,' %ifaceobj.name + ' upperiface %s still around ' %u) @@ -423,7 +423,7 @@ class ifaceScheduler(): ifacenames_all_sorted = graph.topological_sort_graphs_all( dependency_graph, indegrees) # if ALL was set, return all interfaces - if ifupdownobj.flags.ALL: + if ifupdownflags.flags.ALL: return ifacenames_all_sorted # else return ifacenames passed as argument in sorted order @@ -480,7 +480,7 @@ class ifaceScheduler(): for ifacename in dependency_graph.keys(): indegrees[ifacename] = ifupdownobj.get_iface_refcnt(ifacename) - if not ifupdownobj.flags.ALL: + if not ifupdownflags.flags.ALL: if 'up' in ops[0]: # If there is any interface that does not exist, maybe it # is a logical interface and we have to followupperifaces @@ -537,7 +537,7 @@ class ifaceScheduler(): if (not skipupperifaces and ifupdownobj.config.get('skip_upperifaces', '0') == '0' and - ((not ifupdownobj.flags.ALL and followdependents) or + ((not ifupdownflags.flags.ALL and followdependents) or followupperifaces) and 'up' in ops[0]): # If user had given a set of interfaces to bring up