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