]> git.proxmox.com Git - mirror_ifupdown2.git/blame - ifupdown/scheduler.py
addons: vrf: fix check in vrf map initialization when no running vrfs present
[mirror_ifupdown2.git] / ifupdown / scheduler.py
CommitLineData
a6f80f0e 1#!/usr/bin/python
3e8ee54f 2#
904908bc 3# Copyright 2014 Cumulus Networks, Inc. All rights reserved.
3e8ee54f 4# Author: Roopa Prabhu, roopa@cumulusnetworks.com
5#
6# ifaceScheduler --
7# interface scheduler
8#
a6f80f0e 9
a6f80f0e 10from statemanager import *
fc5e1735 11import ifupdown.ifupdownflags as ifupdownflags
a6f80f0e 12from iface import *
13from graph import *
14from collections import deque
15from collections import OrderedDict
a6f80f0e 16import logging
d08d5f54 17import traceback
69f58278 18import sys
a6f80f0e 19from graph import *
20from collections import deque
21from threading import *
22from ifupdownbase import *
a9ab1b4f 23from sets import Set
a6f80f0e 24
d08d5f54 25class ifaceSchedulerFlags():
904908bc
RP
26 """ Enumerates scheduler flags """
27
c798b0f4 28 INORDER = 0x1
29 POSTORDER = 0x2
d08d5f54 30
be0b20f2 31class ifaceScheduler():
32 """ scheduler functions to schedule configuration of interfaces.
a6f80f0e 33
a6f80f0e 34 supports scheduling of interfaces serially in plain interface list
35 or dependency graph format.
99b212b0 36
a6f80f0e 37 """
38
c798b0f4 39 _STATE_CHECK = True
40
2009513f
RP
41 _SCHED_STATUS = True
42
43 @classmethod
44 def get_sched_status(cls):
45 return cls._SCHED_STATUS
5973036b 46
892c495e
RP
47 @classmethod
48 def set_sched_status(cls, state):
49 cls._SCHED_STATUS = state
50
be0b20f2 51 @classmethod
669b422a 52 def run_iface_op(cls, ifupdownobj, ifaceobj, op, withdefaults=False, cenv=None):
a6f80f0e 53 """ Runs sub operation on an interface """
62ddec8b 54 ifacename = ifaceobj.name
a6f80f0e 55
3e6ea735 56 if ifupdownobj.type and ifupdownobj.type != ifaceobj.type:
2da58137
RP
57 return
58
dbc018d3 59 if not ifupdownobj.flags.ADDONS_ENABLE: return
44a6ca06
RP
60 if op == 'query-checkcurr':
61 query_ifaceobj=ifupdownobj.create_n_save_ifaceobjcurr(ifaceobj)
16d854b4
RP
62 # If not type bridge vlan and the object does not exist,
63 # mark not found and return
64 if (not ifupdownobj.link_exists(ifaceobj.name) and
65 ifaceobj.type != ifaceType.BRIDGE_VLAN):
66 query_ifaceobj.set_state_n_status(ifaceState.from_str(op),
67 ifaceStatus.NOTFOUND)
68 return
be0b20f2 69 for mname in ifupdownobj.module_ops.get(op):
37c0543d 70 m = ifupdownobj.modules.get(mname)
a6f80f0e 71 err = 0
72 try:
d08d5f54 73 if hasattr(m, 'run'):
a690dfae 74 msg = ('%s: %s : running module %s' %(ifacename, op, mname))
739f665b 75 if op == 'query-checkcurr':
d08d5f54 76 # Dont check curr if the interface object was
37c0543d 77 # auto generated
dbc018d3
RP
78 if (ifaceobj.priv_flags and
79 ifaceobj.priv_flags.NOCONFIG):
37c0543d 80 continue
a690dfae 81 ifupdownobj.logger.debug(msg)
e1601369 82 m.run(ifaceobj, op, query_ifaceobj,
669b422a 83 ifaceobj_getfunc=ifupdownobj.get_ifaceobjs, withdefaults=withdefaults)
a6f80f0e 84 else:
a690dfae 85 ifupdownobj.logger.debug(msg)
3e6ea735 86 m.run(ifaceobj, op,
669b422a 87 ifaceobj_getfunc=ifupdownobj.get_ifaceobjs, withdefaults=withdefaults)
a6f80f0e 88 except Exception, e:
3e6ea735
RP
89 if not ifupdownobj.ignore_error(str(e)):
90 err = 1
2009513f 91 ifupdownobj.logger.error(str(e))
3e6ea735
RP
92 # Continue with rest of the modules
93 pass
a6f80f0e 94 finally:
ca105861 95 if err or ifaceobj.status == ifaceStatus.ERROR:
31a5f4c3 96 ifaceobj.set_state_n_status(ifaceState.from_str(op),
97 ifaceStatus.ERROR)
2009513f 98 if 'up' in op or 'down' in op or 'query-checkcurr' in op:
892c495e 99 cls.set_sched_status(False)
d08d5f54 100 else:
3e6ea735
RP
101 # Mark success only if the interface was not already
102 # marked with error
103 status = (ifaceobj.status
104 if ifaceobj.status == ifaceStatus.ERROR
105 else ifaceStatus.SUCCESS)
31a5f4c3 106 ifaceobj.set_state_n_status(ifaceState.from_str(op),
3e6ea735 107 status)
6bd7fc74 108
ee3fcf44 109 if ifupdownobj.config.get('addon_scripts_support', '0') == '1':
6bd7fc74 110 # execute /etc/network/ scripts
111 for mname in ifupdownobj.script_ops.get(op, []):
112 ifupdownobj.logger.debug('%s: %s : running script %s'
d08d5f54 113 %(ifacename, op, mname))
6bd7fc74 114 try:
115 ifupdownobj.exec_command(mname, cmdenv=cenv)
116 except Exception, e:
117 ifupdownobj.log_error(str(e))
37c0543d 118
be0b20f2 119 @classmethod
669b422a 120 def run_iface_list_ops(cls, ifupdownobj, ifaceobjs, ops, withdefaults=False):
923290bd 121 """ Runs all operations on a list of interface
122 configurations for the same interface
123 """
a070c90e 124
a690dfae 125 # minor optimization. If operation is 'down', proceed only
126 # if interface exists in the system
923290bd 127 ifacename = ifaceobjs[0].name
8c13865c 128 ifupdownobj.logger.info('%s: running ops ...' %ifacename)
16d854b4
RP
129 if ('down' in ops[0] and
130 ifaceobjs[0].type != ifaceType.BRIDGE_VLAN and
923290bd 131 not ifupdownobj.link_exists(ifacename)):
525f0a30 132 ifupdownobj.logger.debug('%s: does not exist' %ifacename)
923290bd 133 # run posthook before you get out of here, so that
134 # appropriate cleanup is done
135 posthookfunc = ifupdownobj.sched_hooks.get('posthook')
136 if posthookfunc:
137 for ifaceobj in ifaceobjs:
138 ifaceobj.status = ifaceStatus.SUCCESS
139 posthookfunc(ifupdownobj, ifaceobj, 'down')
a690dfae 140 return
923290bd 141 for op in ops:
142 # first run ifupdownobj handlers. This is good enough
143 # for the first object in the list
144 handler = ifupdownobj.ops_handlers.get(op)
145 if handler:
a070c90e
RP
146 try:
147 handler(ifupdownobj, ifaceobjs[0])
148 except Exception, e:
61c4d724
RP
149 if not ifupdownobj.link_master_slave_ignore_error(str(e)):
150 ifupdownobj.logger.warn('%s: %s'
151 %(ifaceobjs[0].name, str(e)))
a070c90e 152 pass
923290bd 153 for ifaceobj in ifaceobjs:
669b422a 154 cls.run_iface_op(ifupdownobj, ifaceobj, op, withdefaults,
923290bd 155 cenv=ifupdownobj.generate_running_env(ifaceobj, op)
ee3fcf44
RP
156 if ifupdownobj.config.get('addon_scripts_support',
157 '0') == '1' else None)
158 posthookfunc = ifupdownobj.sched_hooks.get('posthook')
159 if posthookfunc:
40ed8c4d
RP
160 try:
161 [posthookfunc(ifupdownobj, ifaceobj, ops[0])
162 for ifaceobj in ifaceobjs]
163 except Exception, e:
164 ifupdownobj.logger.warn('%s' %str(e))
165 pass
21c7daa7 166
167 @classmethod
fa3da4be 168 def _check_upperifaces(cls, ifupdownobj, ifaceobj, ops, parent,
169 followdependents=False):
99b212b0 170 """ Check if upperifaces are hanging off us and help caller decide
171 if he can proceed with the ops on this device
21c7daa7 172
99b212b0 173 Returns True or False indicating the caller to proceed with the
174 operation.
175 """
86fc62e2 176 # proceed only for down operation
177 if 'down' not in ops[0]:
178 return True
179
dbc018d3
RP
180 if (ifupdownobj.flags.SCHED_SKIP_CHECK_UPPERIFACES):
181 return True
182
fc5e1735 183 if (ifupdownflags.flags.FORCE or
dbc018d3 184 not ifupdownobj.flags.ADDONS_ENABLE or
86fc62e2 185 (not ifupdownobj.is_ifaceobj_noconfig(ifaceobj) and
33e106da 186 ifupdownobj.config.get('warn_on_ifdown', '0') == '0' and
dbc018d3 187 not ifupdownobj.flags.ALL)):
99b212b0 188 return True
65c48517 189
62ddec8b 190 ulist = ifaceobj.upperifaces
99b212b0 191 if not ulist:
192 return True
33e106da 193
99b212b0 194 # Get the list of upper ifaces other than the parent
195 tmpulist = ([u for u in ulist if u != parent] if parent
196 else ulist)
197 if not tmpulist:
198 return True
199 # XXX: This is expensive. Find a cheaper way to do this.
200 # if any of the upperdevs are present,
201 # return false to the caller to skip this interface
202 for u in tmpulist:
203 if ifupdownobj.link_exists(u):
dbc018d3 204 if not ifupdownobj.flags.ALL:
86fc62e2 205 if ifupdownobj.is_ifaceobj_noconfig(ifaceobj):
206 ifupdownobj.logger.info('%s: skipping interface down,'
207 %ifaceobj.name + ' upperiface %s still around ' %u)
208 else:
209 ifupdownobj.logger.warn('%s: skipping interface down,'
210 %ifaceobj.name + ' upperiface %s still around ' %u)
99b212b0 211 return False
21c7daa7 212 return True
213
be0b20f2 214 @classmethod
669b422a
RP
215 def run_iface_graph(cls, ifupdownobj, ifacename, ops, withdefaults=False,
216 parent=None, order=ifaceSchedulerFlags.POSTORDER,
d08d5f54 217 followdependents=True):
6ef5bfa2 218 """ runs interface by traversing all nodes rooted at itself """
219
d08d5f54 220 # Each ifacename can have a list of iface objects
31a5f4c3 221 ifaceobjs = ifupdownobj.get_ifaceobjs(ifacename)
222 if not ifaceobjs:
d08d5f54 223 raise Exception('%s: not found' %ifacename)
a6f80f0e 224
a070c90e
RP
225 # Check state of the dependent. If it is already brought up, return
226 if (cls._STATE_CHECK and
227 (ifaceobjs[0].state == ifaceState.from_str(ops[-1]))):
228 ifupdownobj.logger.debug('%s: already processed' %ifacename)
229 return
230
d08d5f54 231 for ifaceobj in ifaceobjs:
ca3f4fc7 232 if not cls._check_upperifaces(ifupdownobj, ifaceobj,
233 ops, parent, followdependents):
a070c90e 234 return
f3215127 235
923290bd 236 # If inorder, run the iface first and then its dependents
237 if order == ifaceSchedulerFlags.INORDER:
669b422a 238 cls.run_iface_list_ops(ifupdownobj, ifaceobjs, ops, False)
923290bd 239
240 for ifaceobj in ifaceobjs:
f3215127 241 # Run lowerifaces or dependents
62ddec8b 242 dlist = ifaceobj.lowerifaces
f3215127 243 if dlist:
fa3da4be 244 ifupdownobj.logger.debug('%s: found dependents %s'
245 %(ifacename, str(dlist)))
d08d5f54 246 try:
247 if not followdependents:
248 # XXX: this is yet another extra step,
249 # but is needed for interfaces that are
f3215127 250 # implicit dependents. even though we are asked to
251 # not follow dependents, we must follow the ones
252 # that dont have user given config. Because we own them
d08d5f54 253 new_dlist = [d for d in dlist
923290bd 254 if ifupdownobj.is_iface_noconfig(d)]
6ef5bfa2 255 if new_dlist:
be0b20f2 256 cls.run_iface_list(ifupdownobj, new_dlist, ops,
669b422a
RP
257 withdefaults, ifacename, order,
258 followdependents,
923290bd 259 continueonfailure=False)
d08d5f54 260 else:
be0b20f2 261 cls.run_iface_list(ifupdownobj, dlist, ops,
669b422a 262 withdefaults, ifacename, order,
f3215127 263 followdependents,
6ef5bfa2 264 continueonfailure=False)
d08d5f54 265 except Exception, e:
be0b20f2 266 if (ifupdownobj.ignore_error(str(e))):
d08d5f54 267 pass
268 else:
269 # Dont bring the iface up if children did not come up
a690dfae 270 ifaceobj.set_state_n_status(ifaceState.NEW,
923290bd 271 ifaceStatus.ERROR)
d08d5f54 272 raise
923290bd 273 if order == ifaceSchedulerFlags.POSTORDER:
669b422a 274 cls.run_iface_list_ops(ifupdownobj, ifaceobjs, ops, withdefaults)
a6f80f0e 275
be0b20f2 276 @classmethod
669b422a
RP
277 def run_iface_list(cls, ifupdownobj, ifacenames, ops, withdefaults=False,
278 parent=None, order=ifaceSchedulerFlags.POSTORDER,
6ef5bfa2 279 followdependents=True, continueonfailure=True):
d08d5f54 280 """ Runs interface list """
d08d5f54 281 for ifacename in ifacenames:
a6f80f0e 282 try:
669b422a
RP
283 cls.run_iface_graph(ifupdownobj, ifacename, ops, withdefaults,
284 parent, order, followdependents)
a6f80f0e 285 except Exception, e:
6ef5bfa2 286 if continueonfailure:
69f58278 287 if ifupdownobj.logger.isEnabledFor(logging.DEBUG):
288 traceback.print_tb(sys.exc_info()[2])
be0b20f2 289 ifupdownobj.logger.error('%s : %s' %(ifacename, str(e)))
d08d5f54 290 pass
291 else:
be0b20f2 292 if (ifupdownobj.ignore_error(str(e))):
6ef5bfa2 293 pass
294 else:
9dce3561 295 raise Exception('%s : (%s)' %(ifacename, str(e)))
d08d5f54 296
be0b20f2 297 @classmethod
c798b0f4 298 def run_iface_graph_upper(cls, ifupdownobj, ifacename, ops, parent=None,
299 followdependents=True, skip_root=False):
300 """ runs interface by traversing all nodes rooted at itself """
301
302 # Each ifacename can have a list of iface objects
303 ifaceobjs = ifupdownobj.get_ifaceobjs(ifacename)
304 if not ifaceobjs:
305 raise Exception('%s: not found' %ifacename)
306
a070c90e
RP
307 if (cls._STATE_CHECK and
308 (ifaceobjs[0].state == ifaceState.from_str(ops[-1]))):
309 ifupdownobj.logger.debug('%s: already processed' %ifacename)
310 return
311
923290bd 312 if not skip_root:
313 # run the iface first and then its upperifaces
669b422a 314 cls.run_iface_list_ops(ifupdownobj, ifaceobjs, ops, False)
c798b0f4 315 for ifaceobj in ifaceobjs:
c798b0f4 316 # Run upperifaces
62ddec8b 317 ulist = ifaceobj.upperifaces
c798b0f4 318 if ulist:
fa3da4be 319 ifupdownobj.logger.debug('%s: found upperifaces %s'
320 %(ifacename, str(ulist)))
c798b0f4 321 try:
322 cls.run_iface_list_upper(ifupdownobj, ulist, ops,
323 ifacename,
324 followdependents,
325 continueonfailure=True)
326 except Exception, e:
327 if (ifupdownobj.ignore_error(str(e))):
328 pass
329 else:
330 raise
331
332 @classmethod
333 def run_iface_list_upper(cls, ifupdownobj, ifacenames,
334 ops, parent=None, followdependents=True,
335 continueonfailure=True, skip_root=False):
336 """ Runs interface list """
337
338 for ifacename in ifacenames:
339 try:
340 cls.run_iface_graph_upper(ifupdownobj, ifacename, ops, parent,
341 followdependents, skip_root)
342 except Exception, e:
09a304ca
RP
343 if ifupdownobj.logger.isEnabledFor(logging.DEBUG):
344 traceback.print_tb(sys.exc_info()[2])
345 ifupdownobj.logger.warn('%s : %s' %(ifacename, str(e)))
346 pass
c798b0f4 347
a9ab1b4f
RP
348 @classmethod
349 def _get_valid_upperifaces(cls, ifupdownobj, ifacenames,
350 allupperifacenames):
351 """ Recursively find valid upperifaces
352
353 valid upperifaces are:
354 - An upperiface which had no user config (example builtin
355 interfaces. usually vlan interfaces.)
356 - or had config and previously up
357 - and interface currently does not exist
358 - or is a bridge (because if your upperiface was a bridge
359 - u will have to execute up on the bridge
360 to enslave the port and apply bridge attributes to the port) """
361
362 upperifacenames = []
363 for ifacename in ifacenames:
364 # get upperifaces
365 ifaceobj = ifupdownobj.get_ifaceobj_first(ifacename)
366 if not ifaceobj:
367 continue
368 ulist = Set(ifaceobj.upperifaces).difference(upperifacenames)
369 nulist = []
370 for u in ulist:
371 uifaceobj = ifupdownobj.get_ifaceobj_first(u)
372 if not uifaceobj:
373 continue
dbc018d3
RP
374 has_config = not (uifaceobj.priv_flags and
375 uifaceobj.priv_flags.NOCONFIG)
a9ab1b4f
RP
376 if (((has_config and ifupdownobj.get_ifaceobjs_saved(u)) or
377 not has_config) and (not ifupdownobj.link_exists(u)
65e0c276
RP
378 # Do this always for a bridge. Note that this is
379 # not done for a vlan aware bridge because,
380 # in the vlan aware bridge case, the bridge module
381 # applies the bridge port configuration on the port
382 # when up is scheduled on the port.
383 or (uifaceobj.link_kind == ifaceLinkKind.BRIDGE))):
a9ab1b4f
RP
384 nulist.append(u)
385 upperifacenames.extend(nulist)
386 allupperifacenames.extend(upperifacenames)
387 if upperifacenames:
388 cls._get_valid_upperifaces(ifupdownobj, upperifacenames,
389 allupperifacenames)
390 return
391
392 @classmethod
393 def run_upperifaces(cls, ifupdownobj, ifacenames, ops,
394 continueonfailure=True):
395 """ Run through valid upperifaces """
396 upperifaces = []
397
398 cls._get_valid_upperifaces(ifupdownobj, ifacenames, upperifaces)
399 if not upperifaces:
400 return
401 # dump valid upperifaces
402 ifupdownobj.logger.debug(upperifaces)
403 for u in upperifaces:
404 try:
405 ifaceobjs = ifupdownobj.get_ifaceobjs(u)
406 if not ifaceobjs:
407 continue
669b422a 408 cls.run_iface_list_ops(ifupdownobj, ifaceobjs, ops, False)
a9ab1b4f
RP
409 except Exception, e:
410 if continueonfailure:
411 self.logger.warn('%s' %str(e))
412
5ee3e1a8
RP
413 @classmethod
414 def get_sorted_iface_list(cls, ifupdownobj, ifacenames, ops,
415 dependency_graph, indegrees=None):
416 if len(ifacenames) == 1:
417 return ifacenames
418 # Get a sorted list of all interfaces
419 if not indegrees:
420 indegrees = OrderedDict()
421 for ifacename in dependency_graph.keys():
422 indegrees[ifacename] = ifupdownobj.get_iface_refcnt(ifacename)
423 ifacenames_all_sorted = graph.topological_sort_graphs_all(
424 dependency_graph, indegrees)
425 # if ALL was set, return all interfaces
dbc018d3 426 if ifupdownobj.flags.ALL:
5ee3e1a8
RP
427 return ifacenames_all_sorted
428
429 # else return ifacenames passed as argument in sorted order
430 ifacenames_sorted = []
431 [ifacenames_sorted.append(ifacename)
432 for ifacename in ifacenames_all_sorted
433 if ifacename in ifacenames]
434 return ifacenames_sorted
435
c798b0f4 436 @classmethod
669b422a 437 def sched_ifaces(cls, ifupdownobj, ifacenames, ops, withdefaults=False,
c798b0f4 438 dependency_graph=None, indegrees=None,
d08d5f54 439 order=ifaceSchedulerFlags.POSTORDER,
e308cb82 440 followdependents=True, skipupperifaces=False, sort=False):
2c0ad8b3
RP
441 """ runs interface configuration modules on interfaces passed as
442 argument. Runs topological sort on interface dependency graph.
443
444 Args:
904908bc
RP
445 **ifupdownobj** (object): ifupdownMain object
446
447 **ifacenames** (list): list of interface names
448
449 **ops** : list of operations to perform eg ['pre-up', 'up', 'post-up']
450
451 **dependency_graph** (dict): dependency graph in adjacency list format
2c0ad8b3
RP
452
453 Kwargs:
904908bc
RP
454 **indegrees** (dict): indegree array of the dependency graph
455
456 **order** (int): ifaceSchedulerFlags (POSTORDER, INORDER)
457
458 **followdependents** (bool): follow dependent interfaces if true
2c0ad8b3 459
e308cb82
RP
460 **sort** (bool): sort ifacelist in the case where ALL is not set
461
d08d5f54 462 """
5ee3e1a8
RP
463 #
464 # Algo:
465 # if ALL/auto interfaces are specified,
466 # - walk the dependency tree in postorder or inorder depending
467 # on the operation.
468 # (This is to run interfaces correctly in order)
469 # else:
470 # - sort iface list if the ifaces belong to a "class"
471 # - else just run iface list in the order they were specified
472 #
473 # Run any upperifaces if available
474 #
8c13865c 475 followupperifaces = False
5ee3e1a8
RP
476 run_queue = []
477 skip_ifacesort = int(ifupdownobj.config.get('skip_ifacesort', '0'))
478 if not skip_ifacesort and not indegrees:
479 indegrees = OrderedDict()
480 for ifacename in dependency_graph.keys():
481 indegrees[ifacename] = ifupdownobj.get_iface_refcnt(ifacename)
c798b0f4 482
dbc018d3 483 if not ifupdownobj.flags.ALL:
e308cb82
RP
484 if 'up' in ops[0]:
485 # If there is any interface that does not exist, maybe it
486 # is a logical interface and we have to followupperifaces
487 # when it comes up, so lets get that list.
488 if any([True for i in ifacenames
489 if ifupdownobj.must_follow_upperifaces(i)]):
490 followupperifaces = (True if
ca3f4fc7 491 [i for i in ifacenames
923290bd 492 if not ifupdownobj.link_exists(i)]
493 else False)
e308cb82
RP
494 # sort interfaces only if the caller asked to sort
495 # and skip_ifacesort is not on.
496 if not skip_ifacesort and sort:
5ee3e1a8
RP
497 run_queue = cls.get_sorted_iface_list(ifupdownobj, ifacenames,
498 ops, dependency_graph, indegrees)
499 if run_queue and 'up' in ops[0]:
500 run_queue.reverse()
ba7b1d60 501 else:
e308cb82
RP
502 # if -a is set, we pick the interfaces
503 # that have no parents and use a sorted list of those
5ee3e1a8
RP
504 if not skip_ifacesort:
505 sorted_ifacenames = cls.get_sorted_iface_list(ifupdownobj,
506 ifacenames, ops, dependency_graph,
507 indegrees)
508 if sorted_ifacenames:
509 # pick interfaces that user asked
510 # and those that dont have any dependents first
511 [run_queue.append(ifacename)
512 for ifacename in sorted_ifacenames
513 if ifacename in ifacenames and
514 not indegrees.get(ifacename)]
515 ifupdownobj.logger.debug('graph roots (interfaces that ' +
516 'dont have dependents):' + ' %s' %str(run_queue))
517 else:
518 ifupdownobj.logger.warn('interface sort returned None')
519
e308cb82
RP
520 # If queue not present, just run interfaces that were asked by the
521 # user
5ee3e1a8
RP
522 if not run_queue:
523 run_queue = list(ifacenames)
e308cb82
RP
524 # if we are taking the order of interfaces as specified
525 # in the interfaces file, we should reverse the list if we
526 # want to down. This can happen if 'skip_ifacesort'
527 # is been specified.
5ee3e1a8
RP
528 if 'down' in ops[0]:
529 run_queue.reverse()
530
531 # run interface list
669b422a 532 cls.run_iface_list(ifupdownobj, run_queue, ops, withdefaults,
5ee3e1a8
RP
533 parent=None, order=order,
534 followdependents=followdependents)
892c495e 535 if not cls.get_sched_status():
2009513f 536 return
09a304ca 537
ad25e7bb
RP
538 if (not skipupperifaces and
539 ifupdownobj.config.get('skip_upperifaces', '0') == '0' and
dbc018d3 540 ((not ifupdownobj.flags.ALL and followdependents) or
5ee3e1a8
RP
541 followupperifaces) and
542 'up' in ops[0]):
543 # If user had given a set of interfaces to bring up
544 # try and execute 'up' on the upperifaces
09a304ca
RP
545 ifupdownobj.logger.info('running upperifaces (parent interfaces) ' +
546 'if available ..')
892c495e
RP
547 try:
548 cls._STATE_CHECK = False
549 cls.run_upperifaces(ifupdownobj, ifacenames, ops)
550 cls._STATE_CHECK = True
551 finally:
552 # upperiface bringup is best effort, so dont propagate errors
553 # reset scheduler status to True
554 cls.set_sched_status(True)