return S
- @classmethod
- def topological_sort_graph(cls, dependency_graph, indegrees, rootifname):
- S = []
- Q = deque()
-
- Q.append(rootifname)
-
- while len(Q):
- # initialize queue
- x = Q.popleft()
-
- # Get dependents of x
- dlist = dependency_graph.get(x)
- if not dlist:
- S.append(x)
- continue
-
- for y in dlist:
- indegrees[y] = indegrees.get(y) - 1
- if indegrees.get(y) == 0:
- Q.append(y)
-
- S.append(x)
-
- return S
-
- @classmethod
- def topological_sort_graphs(cls, dependency_graphs, indegrees):
- """ Sorts graph one at a time merges all the sorted graph
- lists and returns a combined list
-
- """
- sorted_graphs_list = []
- for ifname,indegree in indegrees.items():
- if indegree == 0:
- sorted_graphs_list += cls.topological_sort_graph(
- dependency_graphs, indegrees, ifname)
- # If some indegrees are non zero, we have a cycle
- for ifname,indegree in indegrees.items():
- if indegree != 0:
- raise Exception('cycle found involving iface %s' %ifname +
- ' (indegree %d)' %indegree)
-
- return sorted_graphs_list
-
@classmethod
def generate_dots(cls, dependency_graph, indegrees):
gvgraph = GvGen()
del odict['state']
del odict['status']
del odict['lowerifaces']
+ del odict['upperifaces']
del odict['refcnt']
del odict['config_status']
del odict['flags']
self.refcnt = 0
self.flags = 0
self.lowerifaces = None
+ self.upperifaces = None
self.linkstate = None
self.env = None
self.priv_flags = 0
# Flags
WITH_DEPENDS = False
ALL = False
- STATE_CHECK = False
COMPAT_EXEC_SCRIPTS = False
STATEMANAGER_ENABLE = True
STATEMANAGER_UPDATE = True
return ifaceobjs[0]
return None
+ def get_ifacenames(self):
+ return self.ifaceobjdict.keys()
+
def get_iface_obj_last(self, ifacename):
return self.ifaceobjdict.get(ifacename)[-1]
break
return dlist
- def populate_dependency_info(self, ifacenames, ops):
+ def populate_dependency_info(self, ops, ifacenames=None):
""" recursive function to generate iface dependency info """
if not ifacenames:
ifacenames = self.ifaceobjdict.keys()
+
self.logger.debug('populating dependency info for %s' %str(ifacenames))
iqueue = deque(ifacenames)
while iqueue:
iface_objs.append(iface_obj)
return iface_objs
-
- def run_without_dependents(self, ops, ifacenames):
- """ Run interface list without their dependents """
- if not ifacenames:
- raise ifupdownInvalidValue('no interfaces found')
-
- self.logger.debug('run_without_dependents for ops %s for %s'
- %(str(ops), str(ifacenames)))
-
- ifaceScheduler.run_iface_list(self, ifacenames, ops, parent=None,
- order=ifaceSchedulerFlags.INORDER
- if 'down' in ops[0]
- else ifaceSchedulerFlags.POSTORDER,
- followdependents=False)
-
def _pretty_print_ordered_dict(self, argdict):
for k, vlist in argdict.items():
self.logger.info('%s : %s' %(k, str(vlist)))
- def run_with_dependents(self, ops, ifacenames):
- ret = 0
- self.logger.debug('running \'%s\' with dependents for %s'
+ def sched_ifaces(self, ifacenames, ops):
+ self.logger.debug('scheduling \'%s\' for %s'
%(str(ops), str(ifacenames)))
- if not ifacenames:
- ifacenames = self.ifaceobjdict.keys()
-
self.logger.info('dependency graph:')
self._pretty_print_ordered_dict(self.dependency_graph)
- if self.njobs > 1:
- ret = ifaceScheduler.run_iface_dependency_graph_parallel(self,
- self.dependency_graph, ops)
- else:
- ret = ifaceScheduler.run_iface_dependency_graphs(self,
- self.dependency_graph, ops,
+ return ifaceScheduler.sched_ifaces(self, ifacenames, ops,
+ dependency_graph=self.dependency_graph,
order=ifaceSchedulerFlags.INORDER
if 'down' in ops[0]
- else ifaceSchedulerFlags.POSTORDER)
- return ret
+ else ifaceSchedulerFlags.POSTORDER,
+ followdependents=True if self.WITH_DEPENDS else False)
def print_dependency(self, ifacenames, format):
- if ifacenames is None:
+ if not ifacenames:
ifacenames = self.ifaceobjdict.keys()
if format == 'list':
if not filtered_ifacenames:
raise Exception('no ifaces found matching given allow lists')
- self.populate_dependency_info(filtered_ifacenames, ops)
-
if printdependency:
+ self.populate_dependency_info(ops, filtered_ifacenames)
self.print_dependency(filtered_ifacenames, printdependency)
return
-
- if self.WITH_DEPENDS:
- self.run_with_dependents(ops, filtered_ifacenames)
else:
- self.run_without_dependents(ops, filtered_ifacenames)
+ self.populate_dependency_info(ops)
+
+ self.sched_ifaces(filtered_ifacenames, ops)
if self.DRYRUN and self.ADDONS_ENABLE:
return
if not filtered_ifacenames:
raise Exception('no ifaces found matching given allow lists')
- self.populate_dependency_info(filtered_ifacenames, ops)
if printdependency:
+ self.populate_dependency_info(ops, filtered_ifacenames)
self.print_dependency(filtered_ifacenames, printdependency)
return
-
- if self.WITH_DEPENDS:
- self.run_with_dependents(ops, filtered_ifacenames)
else:
- self.run_without_dependents(ops, filtered_ifacenames)
+ self.populate_dependency_info(ops)
+ self.sched_ifaces(filtered_ifacenames, ops)
if self.DRYRUN and self.ADDONS_ENABLE:
return
raise Exception('no ifaces found matching ' +
'given allow lists')
- self.populate_dependency_info(filtered_ifacenames, ops)
if ops[0] == 'query-dependency' and printdependency:
+ self.populate_dependency_info(ops, filtered_ifacenames)
self.print_dependency(filtered_ifacenames, printdependency)
return
+ else:
+ self.populate_dependency_info(ops)
if ops[0] == 'query':
return self.print_ifaceobjs_pretty(filtered_ifacenames, format)
elif ops[0] == 'query-raw':
return self.print_ifaceobjs_raw(filtered_ifacenames)
- if self.WITH_DEPENDS:
- self.run_with_dependents(ops, filtered_ifacenames)
- else:
- self.run_without_dependents(ops, filtered_ifacenames)
+ self.sched_ifaces(filtered_ifacenames, ops)
if ops[0] == 'query-checkcurr':
ret = self.print_ifaceobjscurr_pretty(filtered_ifacenames, format)
raise
# generate dependency graph of interfaces
- self.populate_dependency_info(ifacenames, upops)
+ self.populate_dependency_info(upops)
# Save a copy of new iface objects and dependency_graph
new_ifaceobjdict = dict(self.get_ifaceobjdict())
# reinitialize dependency graph
self.dependency_graph = OrderedDict({})
# Generate dependency info for old config
- self.populate_dependency_info(ifacedownlist, downops)
- self.run_with_dependents(downops, ifacedownlist)
+ self.populate_dependency_info(downops)
+ self.sched_ifaces(ifacedownlist, downops)
else:
self.logger.debug('no interfaces to down ..')
excludepats, i)]
self.logger.info('Executing up on interfaces: %s'
%str(filtered_ifacenames))
- if self.WITH_DEPENDS:
- self.run_with_dependents(upops, filtered_ifacenames)
- else:
- self.run_without_dependents(upops, filtered_ifacenames)
+
+ self.sched_ifaces(filtered_ifacenames, upops)
if self.DRYRUN:
return
+
self.save_state()
def dump(self):
print 'ifupdown object dump'
print self.pp.pprint(self.modules)
- print self.pp.pprint(self.ifaces)
- self.state_manager.dump()
+ print self.pp.pprint(self.ifaceobjdict)
+ #self.state_manager.dump()
def print_state(self, ifacenames=None):
self.statemanager.dump(ifacenames)
from ifupdownbase import *
class ifaceSchedulerFlags():
- INORDER = 1
- POSTORDER = 2
+ INORDER = 0x1
+ POSTORDER = 0x2
class ifaceScheduler():
""" scheduler functions to schedule configuration of interfaces.
or dependency graph format.
"""
+ _STATE_CHECK = True
+
token_pool = None
@classmethod
""" Runs sub operation on an interface """
ifacename = ifaceobj.get_name()
- if (ifaceobj.get_state() >= ifaceState.from_str(op) and
- ifaceobj.get_status() == ifaceStatus.SUCCESS):
+ if (cls._STATE_CHECK and
+ (ifaceobj.get_state() >= ifaceState.from_str(op)) and
+ (ifaceobj.get_status() == ifaceStatus.SUCCESS)):
ifupdownobj.logger.debug('%s: already in state %s' %(ifacename, op))
return
@classmethod
- def _check_upperifaces(cls, ifupdownobj, ifaceobj, ops, parent):
+ def _check_upperifaces(cls, ifupdownobj, ifaceobj, ops, parent, followdependents=False):
""" Check if conflicting upper ifaces are around and warn if required
Returns False if this interface needs to be skipped, else return True """
+ if 'up' in ops[0] and followdependents:
+ return True
+
ifacename = ifaceobj.get_name()
# Deal with upperdevs first
ulist = ifaceobj.get_upperifaces()
raise Exception('%s: not found' %ifacename)
for ifaceobj in ifaceobjs:
- if not cls._check_upperifaces(ifupdownobj, ifaceobj, ops, parent):
+ if not cls._check_upperifaces(ifupdownobj, ifaceobj, ops, parent,
+ followdependents):
return
if order == ifaceSchedulerFlags.INORDER:
# If inorder, run the iface first and then its dependents
%(ifacename, str(e)))
@classmethod
- def run_iface_dependency_graphs(cls, ifupdownobj,
- dependency_graph, ops, indegrees=None,
+ def run_iface_graph_upper(cls, ifupdownobj, ifacename, ops, parent=None,
+ followdependents=True, skip_root=False):
+ """ runs interface by traversing all nodes rooted at itself """
+
+ # Each ifacename can have a list of iface objects
+ ifaceobjs = ifupdownobj.get_ifaceobjs(ifacename)
+ if not ifaceobjs:
+ raise Exception('%s: not found' %ifacename)
+
+ for ifaceobj in ifaceobjs:
+ if not skip_root:
+ # run the iface first and then its upperifaces
+ cls.run_iface_ops(ifupdownobj, ifaceobj, ops)
+
+ # Run upperifaces
+ ulist = ifaceobj.get_upperifaces()
+ if ulist:
+ ifupdownobj.logger.debug('%s:' %ifacename +
+ ' found upperifaces: %s' %str(ulist))
+ try:
+ cls.run_iface_list_upper(ifupdownobj, ulist, ops,
+ ifacename,
+ followdependents,
+ continueonfailure=True)
+ except Exception, e:
+ if (ifupdownobj.ignore_error(str(e))):
+ pass
+ else:
+ raise
+
+ @classmethod
+ def run_iface_list_upper(cls, ifupdownobj, ifacenames,
+ ops, parent=None, followdependents=True,
+ continueonfailure=True, skip_root=False):
+ """ Runs interface list """
+
+ for ifacename in ifacenames:
+ try:
+ cls.run_iface_graph_upper(ifupdownobj, ifacename, ops, parent,
+ followdependents, skip_root)
+ except Exception, e:
+ if continueonfailure:
+ if ifupdownobj.logger.isEnabledFor(logging.DEBUG):
+ traceback.print_tb(sys.exc_info()[2])
+ ifupdownobj.logger.error('%s : %s' %(ifacename, str(e)))
+ pass
+ else:
+ if (ifupdownobj.ignore_error(str(e))):
+ pass
+ else:
+ raise Exception('error running iface %s (%s)'
+ %(ifacename, str(e)))
+
+ @classmethod
+ def sched_ifaces(cls, ifupdownobj, ifacenames, ops,
+ dependency_graph=None, indegrees=None,
order=ifaceSchedulerFlags.POSTORDER,
followdependents=True):
""" Runs iface dependeny graph by visiting all the nodes
indegrees : indegree array if present is used to determine roots
of the graphs in the dependency_graph
"""
+
+ if not ifupdownobj.ALL or not followdependents or len(ifacenames) == 1:
+ cls.run_iface_list(ifupdownobj, ifacenames, ops,
+ parent=None,order=order,
+ followdependents=followdependents)
+ if not ifupdownobj.ALL and followdependents and 'up' in ops[0]:
+ # If user had given a set of interfaces to bring up
+ # try and execute 'up' on the upperifaces
+ ifupdownobj.logger.info('running upperifaces if available')
+ cls._STATE_CHECK = False
+ cls.run_iface_list_upper(ifupdownobj, ifacenames, ops,
+ skip_root=True)
+ cls._STATE_CHECK = True
+ return
run_queue = []
+ # Get a sorted list of all interfaces
if not indegrees:
indegrees = OrderedDict()
for ifacename in dependency_graph.keys():
indegrees[ifacename] = ifupdownobj.get_iface_refcnt(ifacename)
-
sorted_ifacenames = graph.topological_sort_graphs_all(dependency_graph,
dict(indegrees))
ifupdownobj.logger.debug('sorted ifacenames %s : '
%str(sorted_ifacenames))
- # Build a list of ifaces that dont have any dependencies
- for ifacename in sorted_ifacenames:
- if not indegrees.get(ifacename):
- run_queue.append(ifacename)
+ # From the sorted list, pick interfaces that user asked
+ # and those that dont have any dependents first
+ [run_queue.append(ifacename)
+ for ifacename in sorted_ifacenames
+ if ifacename in ifacenames and
+ not indegrees.get(ifacename)]
ifupdownobj.logger.debug('graph roots (interfaces that dont have '
'dependents):' + ' %s' %str(run_queue))
-
- return cls.run_iface_list(ifupdownobj, run_queue, ops,
+ cls.run_iface_list(ifupdownobj, run_queue, ops,
parent=None,order=order,
followdependents=followdependents)
if args.checkcurr:
qop='query-checkcurr'
elif args.running:
- if not iflist:
- iflist = [i for i in os.listdir('/sys/class/net/')
- if os.path.isdir('/sys/class/net/%s' %i)]
qop='query-running'
elif args.raw:
qop='query-raw'
args.perfmode or args.syntaxhelp or
(qop != 'query-checkcurr' and
qop != 'query-running')) else True)
+ if not iflist and qop == 'query-running':
+ iflist = [i for i in os.listdir('/sys/class/net/')
+ if os.path.isdir('/sys/class/net/%s' %i)]
logger.debug('creating ifupdown object ..')
ifupdown_handle = ifupdownMain(withdepends=args.withdepends,
perfmode=args.perfmode,