]> git.proxmox.com Git - mirror_ifupdown2.git/blame - pkg/scheduler.py
cleanup (mostly cosmetic)
[mirror_ifupdown2.git] / pkg / scheduler.py
CommitLineData
a6f80f0e 1#!/usr/bin/python
3e8ee54f 2#
3# Copyright 2013. Cumulus Networks, Inc.
4# Author: Roopa Prabhu, roopa@cumulusnetworks.com
5#
6# ifaceScheduler --
7# interface scheduler
8#
a6f80f0e 9
a6f80f0e 10from statemanager import *
11from iface import *
12from graph import *
13from collections import deque
14from collections import OrderedDict
a6f80f0e 15import logging
d08d5f54 16import traceback
69f58278 17import sys
a6f80f0e 18from graph import *
19from collections import deque
20from threading import *
21from ifupdownbase import *
22
d08d5f54 23class ifaceSchedulerFlags():
c798b0f4 24 INORDER = 0x1
25 POSTORDER = 0x2
d08d5f54 26
be0b20f2 27class ifaceScheduler():
28 """ scheduler functions to schedule configuration of interfaces.
a6f80f0e 29
a6f80f0e 30 supports scheduling of interfaces serially in plain interface list
31 or dependency graph format.
32 """
33
c798b0f4 34 _STATE_CHECK = True
35
be0b20f2 36 token_pool = None
d08d5f54 37
be0b20f2 38 @classmethod
39 def run_iface_op(cls, ifupdownobj, ifaceobj, op, cenv):
a6f80f0e 40 """ Runs sub operation on an interface """
62ddec8b 41 ifacename = ifaceobj.name
a6f80f0e 42
c798b0f4 43 if (cls._STATE_CHECK and
62ddec8b 44 (ifaceobj.state >= ifaceState.from_str(op)) and
45 (ifaceobj.status == ifaceStatus.SUCCESS)):
be0b20f2 46 ifupdownobj.logger.debug('%s: already in state %s' %(ifacename, op))
d08d5f54 47 return
a6f80f0e 48
be0b20f2 49 # first run ifupdownobj handlers
50 handler = ifupdownobj.ops_handlers.get(op)
51 if handler:
62ddec8b 52 if not ifaceobj.addr_method or (ifaceobj.addr_method and
53 ifaceobj.addr_method != 'manual'):
be0b20f2 54 handler(ifupdownobj, ifaceobj)
55
20dd6242 56 if not ifupdownobj.ADDONS_ENABLE: return
57
be0b20f2 58 for mname in ifupdownobj.module_ops.get(op):
37c0543d 59 m = ifupdownobj.modules.get(mname)
a6f80f0e 60 err = 0
61 try:
d08d5f54 62 if hasattr(m, 'run'):
a690dfae 63 msg = ('%s: %s : running module %s' %(ifacename, op, mname))
739f665b 64 if op == 'query-checkcurr':
d08d5f54 65 # Dont check curr if the interface object was
37c0543d 66 # auto generated
d08d5f54 67 if (ifaceobj.priv_flags & ifupdownobj.NOCONFIG):
37c0543d 68 continue
a690dfae 69 ifupdownobj.logger.debug(msg)
d08d5f54 70 m.run(ifaceobj, op,
71 query_ifaceobj=ifupdownobj.create_n_save_ifaceobjcurr(ifaceobj))
a6f80f0e 72 else:
a690dfae 73 ifupdownobj.logger.debug(msg)
d08d5f54 74 m.run(ifaceobj, op)
a6f80f0e 75 except Exception, e:
76 err = 1
be0b20f2 77 ifupdownobj.log_error(str(e))
a6f80f0e 78 finally:
31a5f4c3 79 if err:
80 ifaceobj.set_state_n_status(ifaceState.from_str(op),
81 ifaceStatus.ERROR)
d08d5f54 82 else:
31a5f4c3 83 ifaceobj.set_state_n_status(ifaceState.from_str(op),
84 ifaceStatus.SUCCESS)
6bd7fc74 85
86 if ifupdownobj.COMPAT_EXEC_SCRIPTS:
87 # execute /etc/network/ scripts
88 for mname in ifupdownobj.script_ops.get(op, []):
89 ifupdownobj.logger.debug('%s: %s : running script %s'
d08d5f54 90 %(ifacename, op, mname))
6bd7fc74 91 try:
92 ifupdownobj.exec_command(mname, cmdenv=cenv)
93 except Exception, e:
94 ifupdownobj.log_error(str(e))
37c0543d 95
be0b20f2 96 @classmethod
97 def run_iface_ops(cls, ifupdownobj, ifaceobj, ops):
31a5f4c3 98 """ Runs all operations on an interface """
62ddec8b 99 ifacename = ifaceobj.name
a690dfae 100 # minor optimization. If operation is 'down', proceed only
101 # if interface exists in the system
102 if 'down' in ops[0] and not ifupdownobj.link_exists(ifacename):
103 ifupdownobj.logger.info('%s: does not exist' %ifacename)
104 return
6bd7fc74 105 cenv=None
6bd7fc74 106 if ifupdownobj.COMPAT_EXEC_SCRIPTS:
107 # For backward compatibility generate env variables
108 # for attributes
109 cenv = ifupdownobj.generate_running_env(ifaceobj, ops[0])
6bd7fc74 110 map(lambda op: cls.run_iface_op(ifupdownobj, ifaceobj, op, cenv), ops)
31a5f4c3 111 posthookfunc = ifupdownobj.sched_hooks.get('posthook')
112 if posthookfunc:
113 posthookfunc(ifupdownobj, ifaceobj)
a6f80f0e 114
21c7daa7 115
116 @classmethod
c798b0f4 117 def _check_upperifaces(cls, ifupdownobj, ifaceobj, ops, parent, followdependents=False):
21c7daa7 118 """ Check if conflicting upper ifaces are around and warn if required
119
120 Returns False if this interface needs to be skipped, else return True """
121
c798b0f4 122 if 'up' in ops[0] and followdependents:
123 return True
124
62ddec8b 125 ifacename = ifaceobj.name
21c7daa7 126 # Deal with upperdevs first
62ddec8b 127 ulist = ifaceobj.upperifaces
21c7daa7 128 if ulist:
129 tmpulist = ([u for u in ulist if u != parent] if parent
130 else ulist)
131 if not tmpulist:
21c7daa7 132 return True
133 if 'down' in ops[0]:
134 # XXX: This is expensive. Find a cheaper way to do this
135 # if any of the upperdevs are present,
136 # dont down this interface
137 for u in tmpulist:
138 if ifupdownobj.link_exists(u):
139 if not ifupdownobj.FORCE and not ifupdownobj.ALL:
140 ifupdownobj.logger.warn('%s: ' %ifacename +
141 ' skip interface down,' +
142 ' upperiface %s still around' %u)
143 return False
144 elif 'up' in ops[0] and not ifupdownobj.ALL:
145 # For 'up', just warn that there is an upperdev which is
146 # probably not up
147 for u in tmpulist:
148 if not ifupdownobj.link_exists(u):
149 ifupdownobj.logger.warn('%s: upper iface %s '
150 %(ifacename, u) + 'does not exist')
151 return True
152
be0b20f2 153 @classmethod
154 def run_iface_graph(cls, ifupdownobj, ifacename, ops, parent=None,
d08d5f54 155 order=ifaceSchedulerFlags.POSTORDER,
156 followdependents=True):
6ef5bfa2 157 """ runs interface by traversing all nodes rooted at itself """
158
d08d5f54 159 # Each ifacename can have a list of iface objects
31a5f4c3 160 ifaceobjs = ifupdownobj.get_ifaceobjs(ifacename)
161 if not ifaceobjs:
d08d5f54 162 raise Exception('%s: not found' %ifacename)
a6f80f0e 163
d08d5f54 164 for ifaceobj in ifaceobjs:
c798b0f4 165 if not cls._check_upperifaces(ifupdownobj, ifaceobj, ops, parent,
166 followdependents):
21c7daa7 167 return
d08d5f54 168 if order == ifaceSchedulerFlags.INORDER:
f3215127 169 # If inorder, run the iface first and then its dependents
be0b20f2 170 cls.run_iface_ops(ifupdownobj, ifaceobj, ops)
f3215127 171
172 # Run lowerifaces or dependents
62ddec8b 173 dlist = ifaceobj.lowerifaces
f3215127 174 if dlist:
20dd6242 175 ifupdownobj.logger.debug('%s:' %ifacename +
d08d5f54 176 ' found dependents: %s' %str(dlist))
177 try:
178 if not followdependents:
179 # XXX: this is yet another extra step,
180 # but is needed for interfaces that are
f3215127 181 # implicit dependents. even though we are asked to
182 # not follow dependents, we must follow the ones
183 # that dont have user given config. Because we own them
d08d5f54 184 new_dlist = [d for d in dlist
185 if ifupdownobj.is_iface_noconfig(d)]
6ef5bfa2 186 if new_dlist:
be0b20f2 187 cls.run_iface_list(ifupdownobj, new_dlist, ops,
f3215127 188 ifacename, order,
189 followdependents,
6ef5bfa2 190 continueonfailure=False)
d08d5f54 191 else:
be0b20f2 192 cls.run_iface_list(ifupdownobj, dlist, ops,
f3215127 193 ifacename, order,
194 followdependents,
6ef5bfa2 195 continueonfailure=False)
d08d5f54 196 except Exception, e:
be0b20f2 197 if (ifupdownobj.ignore_error(str(e))):
d08d5f54 198 pass
199 else:
200 # Dont bring the iface up if children did not come up
a690dfae 201 ifaceobj.set_state_n_status(ifaceState.NEW,
202 ifaceStatus.ERROR)
d08d5f54 203 raise
d08d5f54 204 if order == ifaceSchedulerFlags.POSTORDER:
be0b20f2 205 cls.run_iface_ops(ifupdownobj, ifaceobj, ops)
a6f80f0e 206
be0b20f2 207 @classmethod
208 def run_iface_list(cls, ifupdownobj, ifacenames,
f3215127 209 ops, parent=None, order=ifaceSchedulerFlags.POSTORDER,
6ef5bfa2 210 followdependents=True, continueonfailure=True):
d08d5f54 211 """ Runs interface list """
a6f80f0e 212
d08d5f54 213 for ifacename in ifacenames:
a6f80f0e 214 try:
be0b20f2 215 cls.run_iface_graph(ifupdownobj, ifacename, ops, parent,
d08d5f54 216 order, followdependents)
a6f80f0e 217 except Exception, e:
6ef5bfa2 218 if continueonfailure:
69f58278 219 if ifupdownobj.logger.isEnabledFor(logging.DEBUG):
220 traceback.print_tb(sys.exc_info()[2])
be0b20f2 221 ifupdownobj.logger.error('%s : %s' %(ifacename, str(e)))
d08d5f54 222 pass
223 else:
be0b20f2 224 if (ifupdownobj.ignore_error(str(e))):
6ef5bfa2 225 pass
226 else:
227 raise Exception('error running iface %s (%s)'
228 %(ifacename, str(e)))
d08d5f54 229
be0b20f2 230 @classmethod
c798b0f4 231 def run_iface_graph_upper(cls, ifupdownobj, ifacename, ops, parent=None,
232 followdependents=True, skip_root=False):
233 """ runs interface by traversing all nodes rooted at itself """
234
235 # Each ifacename can have a list of iface objects
236 ifaceobjs = ifupdownobj.get_ifaceobjs(ifacename)
237 if not ifaceobjs:
238 raise Exception('%s: not found' %ifacename)
239
240 for ifaceobj in ifaceobjs:
241 if not skip_root:
242 # run the iface first and then its upperifaces
243 cls.run_iface_ops(ifupdownobj, ifaceobj, ops)
244
245 # Run upperifaces
62ddec8b 246 ulist = ifaceobj.upperifaces
c798b0f4 247 if ulist:
248 ifupdownobj.logger.debug('%s:' %ifacename +
249 ' found upperifaces: %s' %str(ulist))
250 try:
251 cls.run_iface_list_upper(ifupdownobj, ulist, ops,
252 ifacename,
253 followdependents,
254 continueonfailure=True)
255 except Exception, e:
256 if (ifupdownobj.ignore_error(str(e))):
257 pass
258 else:
259 raise
260
261 @classmethod
262 def run_iface_list_upper(cls, ifupdownobj, ifacenames,
263 ops, parent=None, followdependents=True,
264 continueonfailure=True, skip_root=False):
265 """ Runs interface list """
266
267 for ifacename in ifacenames:
268 try:
269 cls.run_iface_graph_upper(ifupdownobj, ifacename, ops, parent,
270 followdependents, skip_root)
271 except Exception, e:
272 if continueonfailure:
273 if ifupdownobj.logger.isEnabledFor(logging.DEBUG):
274 traceback.print_tb(sys.exc_info()[2])
275 ifupdownobj.logger.error('%s : %s' %(ifacename, str(e)))
276 pass
277 else:
278 if (ifupdownobj.ignore_error(str(e))):
279 pass
280 else:
281 raise Exception('error running iface %s (%s)'
282 %(ifacename, str(e)))
283
284 @classmethod
285 def sched_ifaces(cls, ifupdownobj, ifacenames, ops,
286 dependency_graph=None, indegrees=None,
d08d5f54 287 order=ifaceSchedulerFlags.POSTORDER,
288 followdependents=True):
289 """ Runs iface dependeny graph by visiting all the nodes
290
291 Parameters:
292 -----------
293 ifupdownobj : ifupdown object (used for getting and updating iface
294 object state)
295 dependency_graph : dependency graph in adjacency list
296 format (contains more than one dependency graph)
297 ops : list of operations to perform eg ['pre-up', 'up', 'post-up']
298
299 indegrees : indegree array if present is used to determine roots
300 of the graphs in the dependency_graph
301 """
c798b0f4 302
303 if not ifupdownobj.ALL or not followdependents or len(ifacenames) == 1:
304 cls.run_iface_list(ifupdownobj, ifacenames, ops,
305 parent=None,order=order,
306 followdependents=followdependents)
307 if not ifupdownobj.ALL and followdependents and 'up' in ops[0]:
308 # If user had given a set of interfaces to bring up
309 # try and execute 'up' on the upperifaces
310 ifupdownobj.logger.info('running upperifaces if available')
311 cls._STATE_CHECK = False
312 cls.run_iface_list_upper(ifupdownobj, ifacenames, ops,
313 skip_root=True)
314 cls._STATE_CHECK = True
315 return
d08d5f54 316 run_queue = []
f3215127 317
c798b0f4 318 # Get a sorted list of all interfaces
20dd6242 319 if not indegrees:
f3215127 320 indegrees = OrderedDict()
d08d5f54 321 for ifacename in dependency_graph.keys():
f3215127 322 indegrees[ifacename] = ifupdownobj.get_iface_refcnt(ifacename)
f3215127 323 sorted_ifacenames = graph.topological_sort_graphs_all(dependency_graph,
324 dict(indegrees))
be0b20f2 325 ifupdownobj.logger.debug('sorted ifacenames %s : '
326 %str(sorted_ifacenames))
f3215127 327
c798b0f4 328 # From the sorted list, pick interfaces that user asked
329 # and those that dont have any dependents first
330 [run_queue.append(ifacename)
331 for ifacename in sorted_ifacenames
332 if ifacename in ifacenames and
333 not indegrees.get(ifacename)]
d08d5f54 334
20dd6242 335 ifupdownobj.logger.debug('graph roots (interfaces that dont have '
336 'dependents):' + ' %s' %str(run_queue))
c798b0f4 337 cls.run_iface_list(ifupdownobj, run_queue, ops,
be0b20f2 338 parent=None,order=order,
339 followdependents=followdependents)
d08d5f54 340
be0b20f2 341 @classmethod
342 def run_iface(cls, ifupdownobj, ifacename, ops):
d08d5f54 343 """ Runs operation on an interface """
344
31a5f4c3 345 ifaceobjs = ifupdownobj.get_ifaceobjs(ifacename)
d08d5f54 346 for i in ifaceobjs:
be0b20f2 347 cls.run_iface_ops(ifupdownobj, i, ops)
d08d5f54 348
be0b20f2 349 @classmethod
350 def run_iface_list_op(cls, ifupdownobj, ifacenames, op,
351 sorted_by_dependency=False):
a6f80f0e 352 """ Runs interface list through sub operation handler. """
353
be0b20f2 354 ifupdownobj.logger.debug('running operation %s on all given interfaces'
355 %op)
a6f80f0e 356 iface_run_queue = deque(ifacenames)
357 for i in range(0, len(iface_run_queue)):
d08d5f54 358 if op.endswith('up'):
a6f80f0e 359 # XXX: simplify this
d08d5f54 360 if sorted_by_dependency:
a6f80f0e 361 ifacename = iface_run_queue.pop()
362 else:
363 ifacename = iface_run_queue.popleft()
364 else:
d08d5f54 365 if sorted_by_dependency:
a6f80f0e 366 ifacename = iface_run_queue.popleft()
367 else:
368 ifacename = iface_run_queue.pop()
369
370 try:
31a5f4c3 371 ifaceobjs = ifupdownobj.get_ifaceobjs(ifacename)
a6f80f0e 372 for ifaceobj in ifaceobjs:
a6f80f0e 373 cenv = ifupdownobj.generate_running_env(ifaceobj, op)
be0b20f2 374 cls.run_iface_op(ifupdownobj, ifaceobj, op, cenv)
a6f80f0e 375 except Exception, e:
be0b20f2 376 ifupdownobj.log_error(str(e))
a6f80f0e 377
be0b20f2 378 @classmethod
379 def run_iface_list_ops(cls, ifupdownobj, ifacenames, ops,
380 sorted_by_dependency=False):
a6f80f0e 381 """ Runs interface list through sub operations handler
382
383 Unlike run_iface_list, this method executes a sub operation on the
384 entire interface list before proceeding to the next sub-operation.
385 ie operation 'pre-up' is run through the entire interface list before
386 'up'
387 """
a6f80f0e 388 # Each sub operation has a module list
be0b20f2 389 [cls.run_iface_list_op(ifupdownobj, ifacenames, op,
d08d5f54 390 sorted_by_dependency) for op in ops]
a6f80f0e 391
be0b20f2 392 @classmethod
393 def run_iface_dependency_graphs_sorted(cls, ifupdownobj,
394 dependency_graphs,
395 ops, indegrees=None,
396 graphsortall=False):
d08d5f54 397 """ runs interface dependency graph by topologically sorting the interfaces """
a6f80f0e 398
37c0543d 399 if indegrees is None:
400 indegrees = OrderedDict()
401 for ifacename in dependency_graphs.keys():
402 indegrees[ifacename] = ifupdownobj.get_iface_refcnt(ifacename)
a6f80f0e 403
be0b20f2 404 ifupdownobj.logger.debug('indegree array :')
405 ifupdownobj.logger.debug(ifupdownobj.pp.pformat(indegrees))
a6f80f0e 406
407 try:
be0b20f2 408 ifupdownobj.logger.debug('calling topological sort on the graph ' +
409 '...')
d08d5f54 410 if graphsortall:
37c0543d 411 sorted_ifacenames = graph.topological_sort_graphs_all(
412 dependency_graphs, indegrees)
413 else:
414 sorted_ifacenames = graph.topological_sort_graphs(
415 dependency_graphs, indegrees)
cca03c30 416 except Exception:
a6f80f0e 417 raise
418
be0b20f2 419 ifupdownobj.logger.debug('sorted iface list = %s' %sorted_ifacenames)
420 cls.run_iface_list_ops(ifupdownobj, sorted_ifacenames, ops,
421 sorted_by_dependency=True)
a6f80f0e 422
423
d08d5f54 424 """ Methods to execute interfaces in parallel """
be0b20f2 425 @classmethod
426 def init_tokens(cls, count):
427 cls.token_pool = BoundedSemaphore(count)
a6f80f0e 428
be0b20f2 429 @classmethod
430 def accquire_token(cls, logprefix=''):
431 cls.token_pool.acquire()
a6f80f0e 432
be0b20f2 433 @classmethod
434 def release_token(cls, logprefix=''):
435 cls.token_pool.release()
a6f80f0e 436
be0b20f2 437 @classmethod
438 def run_iface_parallel(cls, ifupdownobj, ifacename, op):
a6f80f0e 439 """ Configures interface in parallel.
440
441 Executes all its direct dependents in parallel
442
443 """
444
be0b20f2 445 ifupdownobj.logger.debug('%s:' %ifacename + ' %s' %op)
446 cls.accquire_token(iface)
a6f80f0e 447
448 # Each iface can have a list of objects
31a5f4c3 449 ifaceobjs = ifupdownobj.get_ifaceobjs(ifacename)
a6f80f0e 450 if ifaceobjs is None:
be0b20f2 451 ifupdownobj.logger.warning('%s: ' %ifacename + 'not found')
452 cls.release_token(ifacename)
a6f80f0e 453 return -1
454
455 for ifaceobj in ifaceobjs:
456 # Run dependents
62ddec8b 457 dlist = ifaceobj.lowerifaces
be0b20f2 458 if dlist:
459 ifupdownobj.logger.debug('%s:' %ifacename +
a6f80f0e 460 ' found dependents: %s' %str(dlist))
461 try:
be0b20f2 462 cls.release_token(ifacename)
463 cls.run_iface_list_parallel(ifacename, ifupdownobj,
a6f80f0e 464 dlist, op)
be0b20f2 465 cls.accquire_token(ifacename)
a6f80f0e 466 except Exception, e:
be0b20f2 467 if ifupdownobj.ignore_error(str(e)):
a6f80f0e 468 pass
469 else:
470 # Dont bring the iface up if children did not come up
be0b20f2 471 ifupdownobj.logger.debug('%s:' %ifacename +
a6f80f0e 472 ' there was an error bringing %s' %op +
473 ' dependents (%s)', str(e))
474 ifupdownobj.set_iface_state(ifaceobj,
d08d5f54 475 ifaceState.from_str(ops[0]),
a6f80f0e 476 ifaceStatus.ERROR)
477 return -1
478
a6f80f0e 479 # Run all sub operations sequentially
480 try:
be0b20f2 481 ifupdownobj.logger.debug('%s:' %ifacename +
482 ' running sub-operations')
483 cls.run_iface_ops(ifupdownobj, ifaceobj, op)
a6f80f0e 484 except Exception, e:
be0b20f2 485 ifupdownobj.logger.error('%s:' %ifacename +
a6f80f0e 486 ' error running sub operations (%s)' %str(e))
487
be0b20f2 488 cls.release_token(ifacename)
a6f80f0e 489
be0b20f2 490 @classmethod
491 def run_iface_list_parallel(cls, parent, ifupdownobj, ifacenames, op):
a6f80f0e 492 """ Runs interface list in parallel """
493
494 running_threads = OrderedDict()
495 err = 0
496
497 for ifacename in ifacenames:
498 try:
be0b20f2 499 cls.accquire_token(parent)
a6f80f0e 500 running_threads[ifacename] = Thread(None,
be0b20f2 501 cls.run_iface_parallel, ifacename,
a6f80f0e 502 args=(ifupdownobj, ifacename, op))
503 running_threads[ifacename].start()
be0b20f2 504 cls.release_token(parent)
a6f80f0e 505 except Exception, e:
be0b20f2 506 cls.release_token(parent)
d08d5f54 507 if ifupdownobj.ignore_error(str(e)):
a6f80f0e 508 pass
509 else:
510 raise Exception('error starting thread for iface %s'
511 %ifacename)
512
513
be0b20f2 514 ifupdownobj.logger.debug('%s ' %parent +
515 'waiting for all the threads ...')
a6f80f0e 516 for ifacename, t in running_threads.items():
517 t.join()
518 if ifupdownobj.get_iface_status(ifacename) != ifaceStatus.SUCCESS:
519 err += 1
520
521 return err
522
be0b20f2 523 @classmethod
524 def run_iface_graphs_parallel(cls, parent, ifupdownobj, ifacenames, op):
a6f80f0e 525 """ Runs iface graphs in parallel """
526
527 running_threads = OrderedDict()
528 err = 0
529
530 for ifacename in ifacenames:
531 try:
be0b20f2 532 cls.accquire_graph_token(parent)
a6f80f0e 533 running_threads[ifacename] = Thread(None,
be0b20f2 534 cls.run_iface_parallel, ifacename,
a6f80f0e 535 args=(ifupdownobj, ifacename, op))
536 running_threads[ifacename].start()
be0b20f2 537 cls.release_graph_token(parent)
a6f80f0e 538 except Exception, e:
be0b20f2 539 cls.release_graph_token(parent)
d08d5f54 540 if ifupdownobj.ignore_error(str(e)):
a6f80f0e 541 pass
542 else:
543 raise Exception('error starting thread for iface %s'
544 %ifacename)
545
be0b20f2 546 ifupdownobj.logger.info('%s ' %parent +
547 'waiting for all the threads ...')
548 for ifacename, t in running_threads.items():
a6f80f0e 549 t.join()
550 # Check status of thread
551 # XXX: Check all objs
552 if ifupdownobj.get_iface_status(ifacename) != ifaceStatus.SUCCESS:
553 err += 1
a6f80f0e 554 return err
555
be0b20f2 556 @classmethod
557 def run_iface_dependency_graph_parallel(cls, ifupdownobj, dependency_graph,
a6f80f0e 558 operation):
559 """ Runs iface dependeny graph in parallel.
560
561 arguments:
562 ifupdownobj -- ifupdown object (used for getting and updating iface
563 object state)
564 dependency_graph -- dependency graph with
565 operation -- 'up' or 'down' or 'query'
566
567 """
568
be0b20f2 569 ifupdownobj.logger.debug('running dependency graph in parallel ..')
a6f80f0e 570 run_queue = []
a6f80f0e 571 # Build a list of ifaces that dont have any dependencies
572 for ifacename in dependency_graph.keys():
573 if ifupdownobj.get_iface_refcnt(ifacename) == 0:
574 run_queue.append(ifacename)
575
be0b20f2 576 ifupdownobj.logger.debug('graph roots (interfaces that dont'
d08d5f54 577 ' have dependents):' + ' %s' %str(run_queue))
be0b20f2 578 cls.init_tokens(ifupdownobj.get_njobs())
579 return cls.run_iface_list_parallel('main', ifupdownobj, run_queue,
a6f80f0e 580 operation)
581
582 # OR
583 # Run one graph at a time
584 #for iface in run_queue:
585 # self.run_iface_list_parallel('main', ifupdownobj, [iface],
586 # operation)
587