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