]> git.proxmox.com Git - mirror_ifupdown2.git/blame - ifupdown2/ifupdown/scheduler.py
netlink: nlpacket AttributeMACAddress
[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)
16d854b4
RP
147 if ('down' in ops[0] and
148 ifaceobjs[0].type != ifaceType.BRIDGE_VLAN and
923290bd 149 not ifupdownobj.link_exists(ifacename)):
525f0a30 150 ifupdownobj.logger.debug('%s: does not exist' %ifacename)
923290bd 151 # run posthook before you get out of here, so that
152 # appropriate cleanup is done
153 posthookfunc = ifupdownobj.sched_hooks.get('posthook')
154 if posthookfunc:
155 for ifaceobj in ifaceobjs:
156 ifaceobj.status = ifaceStatus.SUCCESS
157 posthookfunc(ifupdownobj, ifaceobj, 'down')
d486dd0d 158 return
923290bd 159 for op in ops:
160 # first run ifupdownobj handlers. This is good enough
161 # for the first object in the list
162 handler = ifupdownobj.ops_handlers.get(op)
163 if handler:
a070c90e
RP
164 try:
165 handler(ifupdownobj, ifaceobjs[0])
166 except Exception, e:
61c4d724
RP
167 if not ifupdownobj.link_master_slave_ignore_error(str(e)):
168 ifupdownobj.logger.warn('%s: %s'
169 %(ifaceobjs[0].name, str(e)))
a070c90e 170 pass
923290bd 171 for ifaceobj in ifaceobjs:
6e16e5ae 172 cls.run_iface_op(ifupdownobj, ifaceobj, op,
923290bd 173 cenv=ifupdownobj.generate_running_env(ifaceobj, op)
ee3fcf44
RP
174 if ifupdownobj.config.get('addon_scripts_support',
175 '0') == '1' else None)
176 posthookfunc = ifupdownobj.sched_hooks.get('posthook')
177 if posthookfunc:
40ed8c4d
RP
178 try:
179 [posthookfunc(ifupdownobj, ifaceobj, ops[0])
180 for ifaceobj in ifaceobjs]
181 except Exception, e:
182 ifupdownobj.logger.warn('%s' %str(e))
183 pass
21c7daa7 184
185 @classmethod
fa3da4be 186 def _check_upperifaces(cls, ifupdownobj, ifaceobj, ops, parent,
187 followdependents=False):
99b212b0 188 """ Check if upperifaces are hanging off us and help caller decide
189 if he can proceed with the ops on this device
21c7daa7 190
99b212b0 191 Returns True or False indicating the caller to proceed with the
192 operation.
193 """
86fc62e2 194 # proceed only for down operation
195 if 'down' not in ops[0]:
196 return True
197
dbc018d3
RP
198 if (ifupdownobj.flags.SCHED_SKIP_CHECK_UPPERIFACES):
199 return True
200
fc5e1735 201 if (ifupdownflags.flags.FORCE or
dbc018d3 202 not ifupdownobj.flags.ADDONS_ENABLE or
86fc62e2 203 (not ifupdownobj.is_ifaceobj_noconfig(ifaceobj) and
33e106da 204 ifupdownobj.config.get('warn_on_ifdown', '0') == '0' and
d2b35716 205 not ifupdownflags.flags.ALL)):
99b212b0 206 return True
65c48517 207
62ddec8b 208 ulist = ifaceobj.upperifaces
99b212b0 209 if not ulist:
210 return True
33e106da 211
99b212b0 212 # Get the list of upper ifaces other than the parent
213 tmpulist = ([u for u in ulist if u != parent] if parent
214 else ulist)
215 if not tmpulist:
216 return True
217 # XXX: This is expensive. Find a cheaper way to do this.
218 # if any of the upperdevs are present,
219 # return false to the caller to skip this interface
220 for u in tmpulist:
221 if ifupdownobj.link_exists(u):
d2b35716 222 if not ifupdownflags.flags.ALL:
86fc62e2 223 if ifupdownobj.is_ifaceobj_noconfig(ifaceobj):
224 ifupdownobj.logger.info('%s: skipping interface down,'
225 %ifaceobj.name + ' upperiface %s still around ' %u)
226 else:
227 ifupdownobj.logger.warn('%s: skipping interface down,'
228 %ifaceobj.name + ' upperiface %s still around ' %u)
99b212b0 229 return False
21c7daa7 230 return True
231
be0b20f2 232 @classmethod
6e16e5ae
N
233 def run_iface_graph(cls, ifupdownobj, ifacename, ops, parent=None,
234 order=ifaceSchedulerFlags.POSTORDER,
d08d5f54 235 followdependents=True):
6ef5bfa2 236 """ runs interface by traversing all nodes rooted at itself """
237
d08d5f54 238 # Each ifacename can have a list of iface objects
31a5f4c3 239 ifaceobjs = ifupdownobj.get_ifaceobjs(ifacename)
240 if not ifaceobjs:
d08d5f54 241 raise Exception('%s: not found' %ifacename)
a6f80f0e 242
a070c90e
RP
243 # Check state of the dependent. If it is already brought up, return
244 if (cls._STATE_CHECK and
245 (ifaceobjs[0].state == ifaceState.from_str(ops[-1]))):
246 ifupdownobj.logger.debug('%s: already processed' %ifacename)
247 return
248
d08d5f54 249 for ifaceobj in ifaceobjs:
ca3f4fc7 250 if not cls._check_upperifaces(ifupdownobj, ifaceobj,
251 ops, parent, followdependents):
a070c90e 252 return
f3215127 253
923290bd 254 # If inorder, run the iface first and then its dependents
255 if order == ifaceSchedulerFlags.INORDER:
6e16e5ae 256 cls.run_iface_list_ops(ifupdownobj, ifaceobjs, ops)
923290bd 257
258 for ifaceobj in ifaceobjs:
f3215127 259 # Run lowerifaces or dependents
62ddec8b 260 dlist = ifaceobj.lowerifaces
f3215127 261 if dlist:
fa3da4be 262 ifupdownobj.logger.debug('%s: found dependents %s'
263 %(ifacename, str(dlist)))
d08d5f54 264 try:
265 if not followdependents:
266 # XXX: this is yet another extra step,
267 # but is needed for interfaces that are
f3215127 268 # implicit dependents. even though we are asked to
269 # not follow dependents, we must follow the ones
270 # that dont have user given config. Because we own them
d08d5f54 271 new_dlist = [d for d in dlist
923290bd 272 if ifupdownobj.is_iface_noconfig(d)]
6ef5bfa2 273 if new_dlist:
be0b20f2 274 cls.run_iface_list(ifupdownobj, new_dlist, ops,
6e16e5ae 275 ifacename, order, followdependents,
923290bd 276 continueonfailure=False)
d08d5f54 277 else:
be0b20f2 278 cls.run_iface_list(ifupdownobj, dlist, ops,
6e16e5ae 279 ifacename, order,
f3215127 280 followdependents,
6ef5bfa2 281 continueonfailure=False)
d08d5f54 282 except Exception, e:
be0b20f2 283 if (ifupdownobj.ignore_error(str(e))):
d08d5f54 284 pass
285 else:
286 # Dont bring the iface up if children did not come up
a690dfae 287 ifaceobj.set_state_n_status(ifaceState.NEW,
923290bd 288 ifaceStatus.ERROR)
d08d5f54 289 raise
923290bd 290 if order == ifaceSchedulerFlags.POSTORDER:
6e16e5ae 291 cls.run_iface_list_ops(ifupdownobj, ifaceobjs, ops)
a6f80f0e 292
be0b20f2 293 @classmethod
6e16e5ae
N
294 def run_iface_list(cls, ifupdownobj, ifacenames,
295 ops, parent=None, order=ifaceSchedulerFlags.POSTORDER,
6ef5bfa2 296 followdependents=True, continueonfailure=True):
d08d5f54 297 """ Runs interface list """
6e16e5ae 298
d08d5f54 299 for ifacename in ifacenames:
a6f80f0e 300 try:
6e16e5ae
N
301 cls.run_iface_graph(ifupdownobj, ifacename, ops, parent,
302 order, followdependents)
a6f80f0e 303 except Exception, e:
6ef5bfa2 304 if continueonfailure:
69f58278 305 if ifupdownobj.logger.isEnabledFor(logging.DEBUG):
306 traceback.print_tb(sys.exc_info()[2])
be0b20f2 307 ifupdownobj.logger.error('%s : %s' %(ifacename, str(e)))
d08d5f54 308 pass
309 else:
be0b20f2 310 if (ifupdownobj.ignore_error(str(e))):
6ef5bfa2 311 pass
312 else:
9dce3561 313 raise Exception('%s : (%s)' %(ifacename, str(e)))
d08d5f54 314
be0b20f2 315 @classmethod
c798b0f4 316 def run_iface_graph_upper(cls, ifupdownobj, ifacename, ops, parent=None,
317 followdependents=True, skip_root=False):
318 """ runs interface by traversing all nodes rooted at itself """
319
320 # Each ifacename can have a list of iface objects
321 ifaceobjs = ifupdownobj.get_ifaceobjs(ifacename)
322 if not ifaceobjs:
323 raise Exception('%s: not found' %ifacename)
324
a070c90e
RP
325 if (cls._STATE_CHECK and
326 (ifaceobjs[0].state == ifaceState.from_str(ops[-1]))):
327 ifupdownobj.logger.debug('%s: already processed' %ifacename)
328 return
329
923290bd 330 if not skip_root:
331 # run the iface first and then its upperifaces
6e16e5ae 332 cls.run_iface_list_ops(ifupdownobj, ifaceobjs, ops)
c798b0f4 333 for ifaceobj in ifaceobjs:
c798b0f4 334 # Run upperifaces
62ddec8b 335 ulist = ifaceobj.upperifaces
c798b0f4 336 if ulist:
fa3da4be 337 ifupdownobj.logger.debug('%s: found upperifaces %s'
338 %(ifacename, str(ulist)))
c798b0f4 339 try:
340 cls.run_iface_list_upper(ifupdownobj, ulist, ops,
341 ifacename,
342 followdependents,
343 continueonfailure=True)
344 except Exception, e:
345 if (ifupdownobj.ignore_error(str(e))):
346 pass
347 else:
348 raise
349
350 @classmethod
351 def run_iface_list_upper(cls, ifupdownobj, ifacenames,
352 ops, parent=None, followdependents=True,
353 continueonfailure=True, skip_root=False):
354 """ Runs interface list """
355
356 for ifacename in ifacenames:
357 try:
358 cls.run_iface_graph_upper(ifupdownobj, ifacename, ops, parent,
359 followdependents, skip_root)
360 except Exception, e:
09a304ca
RP
361 if ifupdownobj.logger.isEnabledFor(logging.DEBUG):
362 traceback.print_tb(sys.exc_info()[2])
363 ifupdownobj.logger.warn('%s : %s' %(ifacename, str(e)))
364 pass
c798b0f4 365
a9ab1b4f
RP
366 @classmethod
367 def _get_valid_upperifaces(cls, ifupdownobj, ifacenames,
368 allupperifacenames):
369 """ Recursively find valid upperifaces
370
371 valid upperifaces are:
372 - An upperiface which had no user config (example builtin
373 interfaces. usually vlan interfaces.)
374 - or had config and previously up
375 - and interface currently does not exist
376 - or is a bridge (because if your upperiface was a bridge
377 - u will have to execute up on the bridge
378 to enslave the port and apply bridge attributes to the port) """
379
380 upperifacenames = []
381 for ifacename in ifacenames:
382 # get upperifaces
383 ifaceobj = ifupdownobj.get_ifaceobj_first(ifacename)
384 if not ifaceobj:
385 continue
386 ulist = Set(ifaceobj.upperifaces).difference(upperifacenames)
387 nulist = []
388 for u in ulist:
389 uifaceobj = ifupdownobj.get_ifaceobj_first(u)
390 if not uifaceobj:
391 continue
dbc018d3
RP
392 has_config = not (uifaceobj.priv_flags and
393 uifaceobj.priv_flags.NOCONFIG)
a9ab1b4f
RP
394 if (((has_config and ifupdownobj.get_ifaceobjs_saved(u)) or
395 not has_config) and (not ifupdownobj.link_exists(u)
65e0c276
RP
396 # Do this always for a bridge. Note that this is
397 # not done for a vlan aware bridge because,
398 # in the vlan aware bridge case, the bridge module
399 # applies the bridge port configuration on the port
400 # when up is scheduled on the port.
401 or (uifaceobj.link_kind == ifaceLinkKind.BRIDGE))):
a9ab1b4f
RP
402 nulist.append(u)
403 upperifacenames.extend(nulist)
404 allupperifacenames.extend(upperifacenames)
405 if upperifacenames:
406 cls._get_valid_upperifaces(ifupdownobj, upperifacenames,
407 allupperifacenames)
408 return
409
410 @classmethod
411 def run_upperifaces(cls, ifupdownobj, ifacenames, ops,
412 continueonfailure=True):
d486dd0d 413 """ Run through valid upperifaces """
a9ab1b4f
RP
414 upperifaces = []
415
416 cls._get_valid_upperifaces(ifupdownobj, ifacenames, upperifaces)
417 if not upperifaces:
418 return
419 # dump valid upperifaces
420 ifupdownobj.logger.debug(upperifaces)
421 for u in upperifaces:
422 try:
423 ifaceobjs = ifupdownobj.get_ifaceobjs(u)
424 if not ifaceobjs:
425 continue
6e16e5ae 426 cls.run_iface_list_ops(ifupdownobj, ifaceobjs, ops)
a9ab1b4f
RP
427 except Exception, e:
428 if continueonfailure:
afe51251 429 ifupdownobj.logger.warn('%s' %str(e))
a9ab1b4f 430
54ebaf3e
RP
431 @classmethod
432 def _dump_dependency_info(cls, ifupdownobj, ifacenames,
433 dependency_graph=None, indegrees=None):
434 ifupdownobj.logger.info('{\n')
435 ifupdownobj.logger.info('\nifaceobjs:')
436 for iname in ifacenames:
437 iobjs = ifupdownobj.get_ifaceobjs(iname)
438 for iobj in iobjs:
439 iobj.dump(ifupdownobj.logger)
440 if (dependency_graph):
441 ifupdownobj.logger.info('\nDependency Graph:')
442 ifupdownobj.logger.info(dependency_graph)
443 if (indegrees):
444 ifupdownobj.logger.info('\nIndegrees:')
445 ifupdownobj.logger.info(indegrees)
446 ifupdownobj.logger.info('}\n')
447
5ee3e1a8
RP
448 @classmethod
449 def get_sorted_iface_list(cls, ifupdownobj, ifacenames, ops,
450 dependency_graph, indegrees=None):
451 if len(ifacenames) == 1:
452 return ifacenames
453 # Get a sorted list of all interfaces
454 if not indegrees:
455 indegrees = OrderedDict()
456 for ifacename in dependency_graph.keys():
457 indegrees[ifacename] = ifupdownobj.get_iface_refcnt(ifacename)
54ebaf3e
RP
458
459 #cls._dump_dependency_info(ifupdownobj, ifacenames,
460 # dependency_graph, indegrees)
461
5ee3e1a8
RP
462 ifacenames_all_sorted = graph.topological_sort_graphs_all(
463 dependency_graph, indegrees)
464 # if ALL was set, return all interfaces
d2b35716 465 if ifupdownflags.flags.ALL:
5ee3e1a8
RP
466 return ifacenames_all_sorted
467
468 # else return ifacenames passed as argument in sorted order
469 ifacenames_sorted = []
470 [ifacenames_sorted.append(ifacename)
471 for ifacename in ifacenames_all_sorted
472 if ifacename in ifacenames]
473 return ifacenames_sorted
474
c798b0f4 475 @classmethod
6e16e5ae 476 def sched_ifaces(cls, ifupdownobj, ifacenames, ops,
c798b0f4 477 dependency_graph=None, indegrees=None,
d08d5f54 478 order=ifaceSchedulerFlags.POSTORDER,
e308cb82 479 followdependents=True, skipupperifaces=False, sort=False):
2c0ad8b3
RP
480 """ runs interface configuration modules on interfaces passed as
481 argument. Runs topological sort on interface dependency graph.
482
483 Args:
d486dd0d 484 **ifupdownobj** (object): ifupdownMain object
904908bc
RP
485
486 **ifacenames** (list): list of interface names
487
488 **ops** : list of operations to perform eg ['pre-up', 'up', 'post-up']
489
490 **dependency_graph** (dict): dependency graph in adjacency list format
2c0ad8b3
RP
491
492 Kwargs:
904908bc
RP
493 **indegrees** (dict): indegree array of the dependency graph
494
495 **order** (int): ifaceSchedulerFlags (POSTORDER, INORDER)
496
497 **followdependents** (bool): follow dependent interfaces if true
2c0ad8b3 498
e308cb82
RP
499 **sort** (bool): sort ifacelist in the case where ALL is not set
500
d08d5f54 501 """
5ee3e1a8
RP
502 #
503 # Algo:
504 # if ALL/auto interfaces are specified,
505 # - walk the dependency tree in postorder or inorder depending
506 # on the operation.
507 # (This is to run interfaces correctly in order)
508 # else:
509 # - sort iface list if the ifaces belong to a "class"
510 # - else just run iface list in the order they were specified
511 #
512 # Run any upperifaces if available
513 #
8c13865c 514 followupperifaces = False
5ee3e1a8
RP
515 run_queue = []
516 skip_ifacesort = int(ifupdownobj.config.get('skip_ifacesort', '0'))
517 if not skip_ifacesort and not indegrees:
518 indegrees = OrderedDict()
519 for ifacename in dependency_graph.keys():
520 indegrees[ifacename] = ifupdownobj.get_iface_refcnt(ifacename)
c798b0f4 521
d2b35716 522 if not ifupdownflags.flags.ALL:
e308cb82
RP
523 if 'up' in ops[0]:
524 # If there is any interface that does not exist, maybe it
525 # is a logical interface and we have to followupperifaces
526 # when it comes up, so lets get that list.
527 if any([True for i in ifacenames
528 if ifupdownobj.must_follow_upperifaces(i)]):
529 followupperifaces = (True if
ca3f4fc7 530 [i for i in ifacenames
923290bd 531 if not ifupdownobj.link_exists(i)]
532 else False)
e308cb82
RP
533 # sort interfaces only if the caller asked to sort
534 # and skip_ifacesort is not on.
535 if not skip_ifacesort and sort:
5ee3e1a8
RP
536 run_queue = cls.get_sorted_iface_list(ifupdownobj, ifacenames,
537 ops, dependency_graph, indegrees)
538 if run_queue and 'up' in ops[0]:
539 run_queue.reverse()
ba7b1d60 540 else:
e308cb82
RP
541 # if -a is set, we pick the interfaces
542 # that have no parents and use a sorted list of those
5ee3e1a8
RP
543 if not skip_ifacesort:
544 sorted_ifacenames = cls.get_sorted_iface_list(ifupdownobj,
545 ifacenames, ops, dependency_graph,
546 indegrees)
547 if sorted_ifacenames:
548 # pick interfaces that user asked
549 # and those that dont have any dependents first
550 [run_queue.append(ifacename)
551 for ifacename in sorted_ifacenames
552 if ifacename in ifacenames and
553 not indegrees.get(ifacename)]
554 ifupdownobj.logger.debug('graph roots (interfaces that ' +
555 'dont have dependents):' + ' %s' %str(run_queue))
556 else:
557 ifupdownobj.logger.warn('interface sort returned None')
558
e308cb82
RP
559 # If queue not present, just run interfaces that were asked by the
560 # user
5ee3e1a8
RP
561 if not run_queue:
562 run_queue = list(ifacenames)
e308cb82
RP
563 # if we are taking the order of interfaces as specified
564 # in the interfaces file, we should reverse the list if we
565 # want to down. This can happen if 'skip_ifacesort'
566 # is been specified.
5ee3e1a8
RP
567 if 'down' in ops[0]:
568 run_queue.reverse()
569
570 # run interface list
6e16e5ae 571 cls.run_iface_list(ifupdownobj, run_queue, ops,
5ee3e1a8
RP
572 parent=None, order=order,
573 followdependents=followdependents)
892c495e 574 if not cls.get_sched_status():
2009513f 575 return
09a304ca 576
ad25e7bb
RP
577 if (not skipupperifaces and
578 ifupdownobj.config.get('skip_upperifaces', '0') == '0' and
d2b35716 579 ((not ifupdownflags.flags.ALL and followdependents) or
d486dd0d 580 followupperifaces) and
5ee3e1a8
RP
581 'up' in ops[0]):
582 # If user had given a set of interfaces to bring up
583 # try and execute 'up' on the upperifaces
09a304ca
RP
584 ifupdownobj.logger.info('running upperifaces (parent interfaces) ' +
585 'if available ..')
892c495e 586 try:
3fb52fa3
RP
587 # upperiface bring up is best effort.
588 # eg case: if we are bringing up a bridge port
589 # this section does an 'ifup on the bridge'
590 # so that the recently up'ed bridge port gets enslaved
591 # to the bridge. But the up on the bridge may
592 # throw out more errors if the bridge is not
593 # in the correct state. Lets not surprise
594 # the user with such errors when he has
595 # only requested to bring up the bridge port.
892c495e 596 cls._STATE_CHECK = False
3fb52fa3 597 ifupdownflags.flags.IGNORE_ERRORS = True
892c495e 598 cls.run_upperifaces(ifupdownobj, ifacenames, ops)
892c495e 599 finally:
3fb52fa3
RP
600 ifupdownflags.flags.IGNORE_ERRORS = False
601 cls._STATE_CHECK = True
892c495e
RP
602 # upperiface bringup is best effort, so dont propagate errors
603 # reset scheduler status to True
604 cls.set_sched_status(True)