1
0
mirror of https://github.com/CumulusNetworks/ifupdown2.git synced 2024-05-06 15:54:50 +00:00

More fixes and cleanup

Ticket: CM-1438
Reviewed By:
Testing Done:
This commit is contained in:
roopa
2014-02-08 09:05:32 -08:00
parent 37c0543d34
commit d08d5f5478
8 changed files with 587 additions and 537 deletions

6
TODO
View File

@@ -1,7 +1,9 @@
TODO: TODO:
==== ====
- fix service networking reload to use ifreload - dry-run improvement: It skips the cache completely. Which means It tells you the commands it would execute if the system is clean. Its not smart enought to say what it will really execute given the state of the system
- the --print-dependency=dot option currently assumes gvgen module is installed.
- included gvgen in the package. Need to check if there are any license issues
- bash completion for options
- Ifquery does not report link status, mainly because it reports only in terms of /etc/network/interfaces attributes. Plan to fix that - Ifquery does not report link status, mainly because it reports only in terms of /etc/network/interfaces attributes. Plan to fix that
- update man-pages with new options. Convert them to rst - update man-pages with new options. Convert them to rst
- Documentation - Documentation

View File

@@ -139,6 +139,5 @@ class graph():
roots = [k for k, v in indegrees.items() if v == 0] roots = [k for k, v in indegrees.items() if v == 0]
if roots is None: if roots is None:
return return
print roots
map(lambda r: cls.generate_dot(dependency_graph, r), roots) map(lambda r: cls.generate_dot(dependency_graph, r), roots)

View File

@@ -6,18 +6,19 @@
# iface -- # iface --
# interface object # interface object
# #
from collections import OrderedDict from collections import OrderedDict
import logging #from json import *
import json import json
import logging
tickmark = ' (' + u'\u2713'.encode('utf8') + ')'
crossmark = ' (' + u'\u2717'.encode('utf8') + ')'
class ifaceFlags(): class ifaceFlags():
NONE = 0x1 NONE = 0x1
FOLLOW_DEPENDENTS = 0x2 FOLLOW_DEPENDENTS = 0x2
class ifaceStatus(): class ifaceStatus():
"""iface status """ """iface status """
UNKNOWN = 0x1 UNKNOWN = 0x1
SUCCESS = 0x2 SUCCESS = 0x2
@@ -56,6 +57,10 @@ class ifaceState():
DOWN = 0x7 DOWN = 0x7
POST_DOWN = 0x8 POST_DOWN = 0x8
# Pseudo states
QUERY_CHECKCURR = 0x9
QUERY_RUNNING = 0xa
@classmethod @classmethod
def to_str(cls, state): def to_str(cls, state):
if state == cls.UNKNOWN: if state == cls.UNKNOWN:
@@ -70,8 +75,14 @@ class ifaceState():
return 'post-up' return 'post-up'
elif state == cls.PRE_DOWN: elif state == cls.PRE_DOWN:
return 'pre-down' return 'pre-down'
elif state == cls.DOWN:
return 'down'
elif state == cls.POST_DOWN: elif state == cls.POST_DOWN:
return 'post-down' return 'post-down'
elif state == cls.QUERY_CHECKCURR:
return 'query-checkcurr'
elif state == cls.QUERY_RUNNING:
return 'query-running'
@classmethod @classmethod
def from_str(cls, state_str): def from_str(cls, state_str):
@@ -87,10 +98,23 @@ class ifaceState():
return cls.POST_UP return cls.POST_UP
elif state_str == 'pre-down': elif state_str == 'pre-down':
return cls.PRE_DOWN return cls.PRE_DOWN
elif state_str == 'down':
return cls.DOWN
elif state_str == 'post-down': elif state_str == 'post-down':
return cls.POST_DOWN return cls.POST_DOWN
elif state_str == 'query-checkcurr':
return cls.QUERY_CHECKCURR
elif state_str == 'query-running':
return cls.QUERY_RUNNING
class ifaceJsonEncoder(json.JSONEncoder):
def default(self, o):
return {'addr_method' : o.addr_method,
'addr_family' : o.addr_family,
'auto' : o.auto,
'config' : o.config}
class iface(): class iface():
""" config flags """ """ config flags """
AUTO = 0x1 AUTO = 0x1
@@ -98,15 +122,14 @@ class iface():
version = '0.1' version = '0.1'
def __init__(self): def __init__(self):
self.name = None self.name = None
self.addr_family = None self.addr_family = None
self.addr_method = None self.addr_method = None
self.config = OrderedDict() self.config = OrderedDict()
self.children = []
self.state = ifaceState.NEW self.state = ifaceState.NEW
self.status = ifaceStatus.UNKNOWN self.status = ifaceStatus.UNKNOWN
self.errstr = ''
self.flags = 0x0 self.flags = 0x0
self.priv_flags = 0x0 self.priv_flags = 0x0
self.refcnt = 0 self.refcnt = 0
@@ -203,9 +226,6 @@ class iface():
return False return False
def add_child(self, child_iface_obj):
self.children.append(child_iface_obj)
def get_state(self): def get_state(self):
return self.state return self.state
@@ -258,11 +278,9 @@ class iface():
def get_attr_value_first(self, attr_name): def get_attr_value_first(self, attr_name):
config = self.get_config() config = self.get_config()
attr_value_list = config.get(attr_name) attr_value_list = config.get(attr_name)
if attr_value_list is not None: if attr_value_list is not None:
return attr_value_list[0] return attr_value_list[0]
return None return None
def get_attr_value_n(self, attr_name, attr_index): def get_attr_value_n(self, attr_name, attr_index):
@@ -308,26 +326,17 @@ class iface():
def update_config_with_status(self, attr_name, attr_value, attr_status=0): def update_config_with_status(self, attr_name, attr_value, attr_status=0):
if attr_value is None: if attr_value is None:
attr_value = '' attr_value = ''
if attr_status:
if attr_status != 0:
self.set_status(ifaceStatus.ERROR) self.set_status(ifaceStatus.ERROR)
new_attr_value = '%s (%s)' %(attr_value, crossmark)
else: else:
new_attr_value = '%s (%s)' %(attr_value, tickmark)
if self.get_status() != ifaceStatus.ERROR: if self.get_status() != ifaceStatus.ERROR:
self.set_status(ifaceStatus.SUCCESS) self.set_status(ifaceStatus.SUCCESS)
if self.config.get(attr_name) is not None: if self.config.get(attr_name) is not None:
self.config[attr_name].append(attr_value) self.config[attr_name].append(new_attr_value)
else: else:
self.config[attr_name] = [attr_value] self.config[attr_name] = [new_attr_value]
""" XXX: If status needs to be encoded in the query string
if attr_status == 0:
self.set_status(attr
attr_status_str = ''
elif attr_status == 0:
attr_status_str = ' (success)'
elif attr_status != 0:
attr_status_str = ' (error)'
self.config[attr_name] = attr_value + attr_status_str """
def is_different(self, dstiface): def is_different(self, dstiface):
if self.name != dstiface.name: return True if self.name != dstiface.name: return True
@@ -342,9 +351,27 @@ class iface():
if any(True for k,v in self.config.items() if any(True for k,v in self.config.items()
if v != dstiface.config.get(k)): return True if v != dstiface.config.get(k)): return True
return False return False
def __getstate__(self):
odict = self.__dict__.copy()
del odict['state']
del odict['status']
del odict['dependents']
del odict['realdev_dependents']
del odict['refcnt']
return odict
def __setstate__(self, dict):
self.__dict__.update(dict)
self.state = ifaceState.NEW
self.status = ifaceStatus.UNKNOWN
self.refcnt = 0
self.dependents = None
self.realdev_dependents = None
self.linkstate = None
def dump_raw(self, logger): def dump_raw(self, logger):
indent = ' ' indent = ' '
print (self.raw_lines[0]) print (self.raw_lines[0])
@@ -376,7 +403,7 @@ class iface():
logger.info(indent + indent + str(config)) logger.info(indent + indent + str(config))
logger.info('}') logger.info('}')
def dump_pretty(self, logger): def dump_pretty(self):
indent = '\t' indent = '\t'
outbuf = '' outbuf = ''
if self.get_auto(): if self.get_auto():
@@ -396,10 +423,7 @@ class iface():
for cv in cvaluelist: for cv in cvaluelist:
outbuf += indent + '%s' %cname + ' %s\n' %cv outbuf += indent + '%s' %cname + ' %s\n' %cv
#outbuf += ('%s' %indent + '%s' %self.get_state_str() +
# ' %s' %self.get_status_str())
print outbuf print outbuf
def dump_json(self, logger): def dump_json(self):
json.dumps(self) print json.dumps(self, cls=ifaceJsonEncoder)

File diff suppressed because it is too large Load Diff

View File

@@ -24,7 +24,8 @@ class networkInterfaces():
def __init__(self): def __init__(self):
self.logger = logging.getLogger('ifupdown.' + self.logger = logging.getLogger('ifupdown.' +
self.__class__.__name__) self.__class__.__name__)
self.callbacks = {'iface_found' : None} self.callbacks = {'iface_found' : None,
'validate' : None}
self.allow_classes = {} self.allow_classes = {}
@@ -118,11 +119,18 @@ class networkInterfaces():
if len(attrs) < 2: if len(attrs) < 2:
self.logger.warn('invalid syntax at line %d' %(line_idx + 1)) self.logger.warn('invalid syntax at line %d' %(line_idx + 1))
continue continue
attrname = attrs[0]
if iface_config.get(attrs[0]) == None: attrval = attrs[1].strip(' ')
iface_config[attrs[0]] = [attrs[1].strip(' ')] try:
if not self.callbacks.get('validate')(attrname, attrval):
self.logger.warn('unsupported keyword (%s) at line %d'
%(l, line_idx + 1))
except:
pass
if not iface_config.get(attrname):
iface_config[attrname] = [attrval]
else: else:
iface_config[attrs[0]].append(attrs[1].strip(' ')) iface_config[attrname].append(attrval)
lines_consumed = line_idx - cur_idx lines_consumed = line_idx - cur_idx
@@ -148,7 +156,6 @@ class networkInterfaces():
ifaceobj.set_class(c) ifaceobj.set_class(c)
# Call iface found callback # Call iface found callback
#self.logger.debug('saving interface %s' %ifaceobj.get_name())
self.callbacks.get('iface_found')(ifaceobj) self.callbacks.get('iface_found')(ifaceobj)
return lines_consumed # Return next index return lines_consumed # Return next index

View File

@@ -7,21 +7,22 @@
# interface scheduler # interface scheduler
# #
import os
import re
from statemanager import * from statemanager import *
from iface import * from iface import *
from graph import * from graph import *
from collections import deque from collections import deque
from collections import OrderedDict from collections import OrderedDict
import imp
import pprint
import logging import logging
import traceback
from graph import * from graph import *
from collections import deque from collections import deque
from threading import * from threading import *
from ifupdownbase import * from ifupdownbase import *
class ifaceSchedulerFlags():
INORDER = 1
POSTORDER = 2
class ifaceScheduler(ifupdownBase): class ifaceScheduler(ifupdownBase):
""" scheduler to schedule configuration of interfaces. """ scheduler to schedule configuration of interfaces.
@@ -30,132 +31,206 @@ class ifaceScheduler(ifupdownBase):
or dependency graph format. or dependency graph format.
""" """
def __init__(self, force=False): def __init__(self, force=False):
self.logger = logging.getLogger('ifupdown.' + self.logger = logging.getLogger('ifupdown.' +
self.__class__.__name__) self.__class__.__name__)
self.FORCE = force self.FORCE = force
def run_iface_subop(self, ifupdownobj, ifaceobj, op, subop, mlist, cenv): def run_iface_op(self, ifupdownobj, ifaceobj, op, cenv):
""" Runs sub operation on an interface """ """ Runs sub operation on an interface """
ifacename = ifaceobj.get_name()
self.logger.debug('%s: ' %ifaceobj.get_name() + 'op %s' %op + if (ifaceobj.get_state() >= ifaceState.from_str(op) and
' subop = %s' %subop) ifaceobj.get_status() == ifaceStatus.SUCCESS):
self.logger.debug('%s: already in state %s' %(ifacename, op))
return
for mname in mlist: for mname in ifupdownobj.operations.get(op):
m = ifupdownobj.modules.get(mname) m = ifupdownobj.modules.get(mname)
err = 0 err = 0
try: try:
if hasattr(m, 'run') == True: if hasattr(m, 'run'):
self.logger.debug('%s: %s : running module %s' self.logger.debug('%s: %s : running module %s'
%(ifaceobj.get_name(), subop, mname)) %(ifacename, op, mname))
if op == 'query-checkcurr': if op == 'query-checkcurr':
# Dont check state if the interface object was # Dont check curr if the interface object was
# auto generated # auto generated
if ((ifaceobj.priv_flags & ifupdownobj.BUILTIN) != 0 or if (ifaceobj.priv_flags & ifupdownobj.NOCONFIG):
(ifaceobj.priv_flags & ifupdownobj.NOCONFIG) != 0):
continue continue
m.run(ifaceobj, subop, m.run(ifaceobj, op,
query_ifaceobj=ifupdownobj.create_ifaceobjcurr( query_ifaceobj=ifupdownobj.create_n_save_ifaceobjcurr(ifaceobj))
ifaceobj))
else: else:
m.run(ifaceobj, subop) m.run(ifaceobj, op)
except Exception, e: except Exception, e:
err = 1 err = 1
self.log_error(str(e)) self.log_error(str(e))
finally: finally:
if op[:5] != 'query': if err == 1:
if err == 1: ifupdownobj.set_iface_state(ifaceobj,
ifupdownobj.set_iface_state(ifaceobj, ifaceState.from_str(op),
ifaceState.from_str(subop),
ifaceStatus.ERROR) ifaceStatus.ERROR)
else: else:
ifupdownobj.set_iface_state(ifaceobj, ifupdownobj.set_iface_state(ifaceobj,
ifaceState.from_str(subop), ifaceState.from_str(op),
ifaceStatus.SUCCESS) ifaceStatus.SUCCESS)
# execute /etc/network/ scripts # execute /etc/network/ scripts
subop_dict = ifupdownobj.operations_compat.get(op) mlist = ifupdownobj.operations_compat.get(op)
if subop_dict is None: return if not mlist:
for mname in subop_dict.get(subop): return
for mname in mlist:
self.logger.debug('%s: %s : running script %s' self.logger.debug('%s: %s : running script %s'
%(ifaceobj.get_name(), subop, mname)) %(ifacename, op, mname))
try: try:
self.exec_command(mname, cmdenv=cenv) self.exec_command(mname, cmdenv=cenv)
except Exception, e: except Exception, e:
err = 1 err = 1
self.log_error(str(e)) self.log_error(str(e))
def run_iface_subops(self, ifupdownobj, ifaceobj, op):
def run_iface_ops(self, ifupdownobj, ifaceobj, ops):
""" Runs all sub operations on an interface """ """ Runs all sub operations on an interface """
# For backward compatibility execute scripts with # For backward compatibility execute scripts with
# environent set # environent set
cenv = ifupdownobj.generate_running_env(ifaceobj, op) cenv = ifupdownobj.generate_running_env(ifaceobj, ops[0])
# Each sub operation has a module list # Each sub operation has a module list
subopdict = ifupdownobj.operations.get(op) [self.run_iface_op(ifupdownobj, ifaceobj, op, cenv)
for subop, mlist in subopdict.items(): for op in ops]
self.run_iface_subop(ifupdownobj, ifaceobj, op, subop, mlist, cenv)
def run_iface_graph(self, ifupdownobj, ifacename, ops,
order=ifaceSchedulerFlags.POSTORDER,
followdependents=True):
""" runs interface by traversing its dependents first """
# Each ifacename can have a list of iface objects
ifaceobjs = ifupdownobj.get_iface_objs(ifacename)
if ifaceobjs is None:
raise Exception('%s: not found' %ifacename)
def run_iface(self, ifupdownobj, ifacename, op): for ifaceobj in ifaceobjs:
if order == ifaceSchedulerFlags.INORDER:
# Run all sub operations sequentially
try:
self.run_iface_ops(ifupdownobj, ifaceobj, ops)
except Exception, e:
raise Exception(str(e))
# Run dependents
dlist = ifaceobj.get_dependents()
if dlist and len(dlist):
self.logger.debug('%s:' %ifacename +
' found dependents: %s' %str(dlist))
try:
if not followdependents:
# XXX: this is yet another extra step,
# but is needed for interfaces that are
# implicit dependents
# up without dependents, but
new_dlist = [d for d in dlist
if ifupdownobj.is_iface_noconfig(d)]
if not new_dlist: continue
self.run_iface_list(ifupdownobj, new_dlist, ops,
order, followdependents)
else:
self.run_iface_list(ifupdownobj, dlist, ops,
order, followdependents)
except Exception, e:
if (self.ignore_error(str(e))):
pass
else:
# Dont bring the iface up if children did not come up
ifaceobj.set_state(ifaceState.NEW)
ifaceobj.set_status(ifaceStatus.ERROR)
raise
if order == ifaceSchedulerFlags.POSTORDER:
try:
self.run_iface_ops(ifupdownobj, ifaceobj, ops)
except Exception, e:
raise Exception(str(e))
def run_iface_list(self, ifupdownobj, ifacenames,
ops, order=ifaceSchedulerFlags.POSTORDER,
followdependents=True):
""" Runs interface list """
for ifacename in ifacenames:
try:
self.run_iface_graph(ifupdownobj, ifacename, ops,
order, followdependents)
except Exception, e:
if (self.ignore_error(str(e))):
pass
else:
traceback.print_stack()
raise Exception('error running iface %s (%s)'
%(ifacename, str(e)))
def run_iface_dependency_graphs(self, ifupdownobj,
dependency_graph, ops, indegrees=None,
order=ifaceSchedulerFlags.POSTORDER,
followdependents=True):
""" Runs iface dependeny graph by visiting all the nodes
Parameters:
-----------
ifupdownobj : ifupdown object (used for getting and updating iface
object state)
dependency_graph : dependency graph in adjacency list
format (contains more than one dependency graph)
ops : list of operations to perform eg ['pre-up', 'up', 'post-up']
indegrees : indegree array if present is used to determine roots
of the graphs in the dependency_graph
"""
self.logger.debug('running dependency graph serially ..')
run_queue = []
# Build a list of ifaces that dont have any dependencies
if indegrees:
# use indegrees array if specified
for ifacename, degree in indegrees.items():
if not indegrees.get(ifacename):
run_queue.append(ifacename)
else:
for ifacename in dependency_graph.keys():
if not ifupdownobj.get_iface_refcnt(ifacename):
run_queue.append(ifacename)
self.logger.debug('graph roots (interfaces that dont have '
'dependents):' + ' %s' %str(run_queue))
return self.run_iface_list(ifupdownobj, run_queue, ops, order,
followdependents)
def run_iface(self, ifupdownobj, ifacename, ops):
""" Runs operation on an interface """ """ Runs operation on an interface """
ifaceobjs = ifupdownobj.get_iface_objs(ifacename) ifaceobjs = ifupdownobj.get_iface_objs(ifacename)
for i in ifaceobjs: for i in ifaceobjs:
if (op != 'query' and ifupdownobj.STATE_CHECK == True and self.run_iface_ops(ifupdownobj, i, ops)
ifupdownobj.is_valid_state_transition(i, op) == False and
ifupdownobj.FORCE == False):
self.logger.warning('%s' %ifacename +
' already %s' %op)
continue
self.run_iface_subops(ifupdownobj, i, op) def run_iface_list_op(self, ifupdownobj, ifacenames, op,
def run_iface_list(self, ifupdownobj, ifacenames, operation,
sorted_by_dependency=False):
""" Runs interface list serially executing all sub operations on
each interface at a time. """
self.logger.debug('run_iface_list: running interface list for ' +
'operation %s' %operation)
iface_run_queue = deque(ifacenames)
for i in range(0, len(iface_run_queue)):
if operation == 'up':
# XXX: simplify this
if sorted_by_dependency == True:
ifacename = iface_run_queue.pop()
else:
ifacename = iface_run_queue.popleft()
else:
if sorted_by_dependency == True:
ifacename = iface_run_queue.popleft()
else:
ifacename = iface_run_queue.pop()
try:
self.run_iface(ifupdownobj, ifacename, operation)
except Exception, e:
self.log_error(str(e))
def run_iface_list_subop(self, ifupdownobj, ifacenames, op, subop, mdict,
sorted_by_dependency=False): sorted_by_dependency=False):
""" Runs interface list through sub operation handler. """ """ Runs interface list through sub operation handler. """
self.logger.debug('running sub operation %s on all given interfaces' self.logger.debug('running operation %s on all given interfaces'
%subop) %op)
iface_run_queue = deque(ifacenames) iface_run_queue = deque(ifacenames)
for i in range(0, len(iface_run_queue)): for i in range(0, len(iface_run_queue)):
if op == 'up': if op.endswith('up'):
# XXX: simplify this # XXX: simplify this
if sorted_by_dependency == True: if sorted_by_dependency:
ifacename = iface_run_queue.pop() ifacename = iface_run_queue.pop()
else: else:
ifacename = iface_run_queue.popleft() ifacename = iface_run_queue.popleft()
else: else:
if sorted_by_dependency == True: if sorted_by_dependency:
ifacename = iface_run_queue.popleft() ifacename = iface_run_queue.popleft()
else: else:
ifacename = iface_run_queue.pop() ifacename = iface_run_queue.pop()
@@ -163,21 +238,12 @@ class ifaceScheduler(ifupdownBase):
try: try:
ifaceobjs = ifupdownobj.get_iface_objs(ifacename) ifaceobjs = ifupdownobj.get_iface_objs(ifacename)
for ifaceobj in ifaceobjs: for ifaceobj in ifaceobjs:
if (op != 'query' and ifupdownobj.STATE_CHECK == True and
ifupdownobj.is_valid_state_transition(ifaceobj,
op) == False and ifupdownobj.FORCE == False):
if subop == 'post-down' or subop == 'post-up':
self.logger.warning('%s: ' %ifacename +
' already %s' %op)
continue
cenv = ifupdownobj.generate_running_env(ifaceobj, op) cenv = ifupdownobj.generate_running_env(ifaceobj, op)
self.run_iface_subop(ifupdownobj, ifaceobj, op, subop, self.run_iface_op(ifupdownobj, ifaceobj, op, cenv)
mdict, cenv)
except Exception, e: except Exception, e:
self.log_error(str(e)) self.log_error(str(e))
def run_iface_list_stages(self, ifupdownobj, ifacenames, op, def run_iface_list_ops(self, ifupdownobj, ifacenames, ops,
sorted_by_dependency=False): sorted_by_dependency=False):
""" Runs interface list through sub operations handler """ Runs interface list through sub operations handler
@@ -188,30 +254,27 @@ class ifaceScheduler(ifupdownBase):
""" """
# Each sub operation has a module list # Each sub operation has a module list
subopdict = ifupdownobj.operations.get(op) [self.run_iface_list_op(ifupdownobj, ifacenames, op,
for subop, mdict in subopdict.items(): sorted_by_dependency) for op in ops]
self.run_iface_list_subop(ifupdownobj, ifacenames, op, subop, mdict,
sorted_by_dependency)
def run_iface_dependency_graphs_sorted(self, ifupdownobj,
def run_iface_dependency_graph(self, ifupdownobj, dependency_graphs, dependency_graphs,
operation, indegrees=None, ops, indegrees=None,
graphsortall=False): graphsortall=False):
""" runs interface dependency graph """ """ runs interface dependency graph by topologically sorting the interfaces """
if indegrees is None: if indegrees is None:
indegrees = OrderedDict() indegrees = OrderedDict()
for ifacename in dependency_graphs.keys(): for ifacename in dependency_graphs.keys():
indegrees[ifacename] = ifupdownobj.get_iface_refcnt(ifacename) indegrees[ifacename] = ifupdownobj.get_iface_refcnt(ifacename)
if self.logger.isEnabledFor(logging.DEBUG) == True: if self.logger.isEnabledFor(logging.DEBUG):
self.logger.debug('indegree array :') self.logger.debug('indegree array :')
self.logger.debug(ifupdownobj.pp.pformat(indegrees)) self.logger.debug(ifupdownobj.pp.pformat(indegrees))
try: try:
self.logger.debug('calling topological sort on the graph ...') self.logger.debug('calling topological sort on the graph ...')
if graphsortall == True: if graphsortall:
sorted_ifacenames = graph.topological_sort_graphs_all( sorted_ifacenames = graph.topological_sort_graphs_all(
dependency_graphs, indegrees) dependency_graphs, indegrees)
else: else:
@@ -221,14 +284,11 @@ class ifaceScheduler(ifupdownBase):
raise raise
self.logger.debug('sorted iface list = %s' %sorted_ifacenames) self.logger.debug('sorted iface list = %s' %sorted_ifacenames)
self.run_iface_list_ops(ifupdownobj, sorted_ifacenames, ops,
#self.run_iface_list(ifupdownobj, sorted_ifacenames, operation, sorted_by_dependency=True)
# sorted_by_dependency=True)
self.run_iface_list_stages(ifupdownobj, sorted_ifacenames, operation,
sorted_by_dependency=True)
""" Methods to execute interfaces in parallel """
def init_tokens(self, count): def init_tokens(self, count):
self.token_pool = BoundedSemaphore(count) self.token_pool = BoundedSemaphore(count)
self.logger.debug('initialized bounded semaphore with %d' %count) self.logger.debug('initialized bounded semaphore with %d' %count)
@@ -270,7 +330,7 @@ class ifaceScheduler(ifupdownBase):
dlist, op) dlist, op)
self.accquire_token(ifacename) self.accquire_token(ifacename)
except Exception, e: except Exception, e:
if (self.ignore_error(str(e)) == True): if self.ignore_error(str(e)):
pass pass
else: else:
# Dont bring the iface up if children did not come up # Dont bring the iface up if children did not come up
@@ -278,22 +338,14 @@ class ifaceScheduler(ifupdownBase):
' there was an error bringing %s' %op + ' there was an error bringing %s' %op +
' dependents (%s)', str(e)) ' dependents (%s)', str(e))
ifupdownobj.set_iface_state(ifaceobj, ifupdownobj.set_iface_state(ifaceobj,
ifaceState.from_str( ifaceState.from_str(ops[0]),
ifupdownobj.get_subops(op)[0]),
ifaceStatus.ERROR) ifaceStatus.ERROR)
return -1 return -1
if (op != 'query' and ifupdownobj.STATE_CHECK == True and
ifupdownobj.is_valid_state_transition(ifaceobj,
op) == False and ifupdownobj.FORCE == False):
self.logger.warning('%s:' %ifacename + ' already %s' %op)
continue
# Run all sub operations sequentially # Run all sub operations sequentially
try: try:
self.logger.debug('%s:' %ifacename + ' running sub-operations') self.logger.debug('%s:' %ifacename + ' running sub-operations')
self.run_iface_subops(ifupdownobj, ifaceobj, op) self.run_iface_ops(ifupdownobj, ifaceobj, op)
except Exception, e: except Exception, e:
self.logger.error('%s:' %ifacename + self.logger.error('%s:' %ifacename +
' error running sub operations (%s)' %str(e)) ' error running sub operations (%s)' %str(e))
@@ -317,7 +369,7 @@ class ifaceScheduler(ifupdownBase):
self.release_token(parent) self.release_token(parent)
except Exception, e: except Exception, e:
self.release_token(parent) self.release_token(parent)
if (ifupdownobj.ignore_error(str(e)) == True): if ifupdownobj.ignore_error(str(e)):
pass pass
else: else:
raise Exception('error starting thread for iface %s' raise Exception('error starting thread for iface %s'
@@ -348,7 +400,7 @@ class ifaceScheduler(ifupdownBase):
self.release_graph_token(parent) self.release_graph_token(parent)
except Exception, e: except Exception, e:
self.release_graph_token(parent) self.release_graph_token(parent)
if (ifupdownobj.ignore_error(str(e)) == True): if ifupdownobj.ignore_error(str(e)):
pass pass
else: else:
raise Exception('error starting thread for iface %s' raise Exception('error starting thread for iface %s'
@@ -385,8 +437,8 @@ class ifaceScheduler(ifupdownBase):
if ifupdownobj.get_iface_refcnt(ifacename) == 0: if ifupdownobj.get_iface_refcnt(ifacename) == 0:
run_queue.append(ifacename) run_queue.append(ifacename)
self.logger.debug('graph roots (interfaces that dont have dependents):' + self.logger.debug('graph roots (interfaces that dont'
' %s' %str(run_queue)) ' have dependents):' + ' %s' %str(run_queue))
self.init_tokens(ifupdownobj.get_njobs()) self.init_tokens(ifupdownobj.get_njobs())

View File

@@ -70,8 +70,8 @@ class stateManager():
# Read all ifaces from file # Read all ifaces from file
for ifaceobj in pickling.load(pickle_filename): for ifaceobj in pickling.load(pickle_filename):
self.save_ifaceobj(ifaceobj) self.save_ifaceobj(ifaceobj)
ifaceobj.set_refcnt(0) #ifaceobj.set_refcnt(0)
ifaceobj.set_dependents(None) #ifaceobj.set_dependents(None)
return 0 return 0

View File

@@ -18,14 +18,11 @@ def run(args, op):
iflist = args.iflist iflist = args.iflist
if len(args.iflist) == 0: if len(args.iflist) == 0:
iflist = None iflist = None
cachearg=(False if (iflist is not None or
args.nocache == True or
args.perfmode == True)
else True)
logger.debug('creating ifupdown object ..') logger.debug('creating ifupdown object ..')
if op == 'up' or op == 'down' or op == 'reload': if op == 'up' or op == 'down' or op == 'reload':
cachearg=(False if (iflist or args.nocache or
args.perfmode or args.noact)
else True)
ifupdown_handle = ifupdownMain(force=args.force, ifupdown_handle = ifupdownMain(force=args.force,
withdepends=args.withdepends, withdepends=args.withdepends,
perfmode=args.perfmode, perfmode=args.perfmode,
@@ -33,40 +30,45 @@ def run(args, op):
dryrun=args.noact, dryrun=args.noact,
cache=cachearg) cache=cachearg)
elif op == 'query': elif op == 'query':
cachearg=(False if (iflist or args.nocache or
args.perfmode or args.syntaxhelp) else True)
ifupdown_handle = ifupdownMain(withdepends=args.withdepends, ifupdown_handle = ifupdownMain(withdepends=args.withdepends,
perfmode=args.perfmode, perfmode=args.perfmode,
njobs=args.jobs, njobs=args.jobs,
format=args.format,
cache=cachearg) cache=cachearg)
logger.debug('calling \'%s\'' %op + ' for all interfaces ..') logger.debug('calling \'%s\'' %op + ' for all interfaces ..')
if op == 'up': if op == 'up':
ifupdown_handle.up(args.all, args.CLASS, iflist, ifupdown_handle.up(['pre-up', 'up', 'post-up'],
args.all, args.CLASS, iflist,
excludepats=args.excludepats, excludepats=args.excludepats,
printdependency=args.printdependency) printdependency=args.printdependency)
elif op == 'down': elif op == 'down':
ifupdown_handle.down(args.all, args.CLASS, iflist, ifupdown_handle.down(['pre-down', 'down', 'post-down'],
excludepats=args.excludepats) args.all, args.CLASS, iflist,
excludepats=args.excludepats,
printdependency=args.printdependency)
elif op == 'query': elif op == 'query':
if args.checkcurstate == True: if args.checkcurstate:
qtype='query-checkcurr' qop='query-checkcurr'
elif args.presumedstate == True: elif args.runningstate:
qtype='query-presumed'
elif args.presumedstatedetailed == True:
qtype='query-presumeddetailed'
elif args.runningstate == True:
if iflist is None: if iflist is None:
iflist = [i for i in os.listdir('/sys/class/net/') iflist = [i for i in os.listdir('/sys/class/net/')
if os.path.isdir('/sys/class/net/%s' %i) == True] if os.path.isdir('/sys/class/net/%s' %i)]
qtype='query-running' qop='query-running'
elif args.pretty == True: elif args.raw:
qtype='query-pretty' qop='query-raw'
elif args.syntaxhelp:
qop = 'query-syntax'
elif args.printdependency:
qop = 'query-dependency'
else: else:
qtype='query' qop='query'
ifupdown_handle.query(qtype, args.all, args.CLASS, iflist, ifupdown_handle.query([qop], args.all, args.CLASS, iflist,
excludepats=args.excludepats, excludepats=args.excludepats,
printdependency=args.printdependency) printdependency=args.printdependency,
format=args.format)
elif op == 'reload': elif op == 'reload':
if iflist is not None: if iflist is not None:
raise Exception('iflist is currently not supported with reload') raise Exception('iflist is currently not supported with reload')
@@ -157,34 +159,22 @@ def update_ifquery_argparser(argparser):
group.add_argument('-r', '--running-state', dest='runningstate', group.add_argument('-r', '--running-state', dest='runningstate',
action='store_true', action='store_true',
help='query running state of an interface') help='query running state of an interface')
group.add_argument('-c', '--check-state', dest='checkcurstate', group.add_argument('-c', '--check-state', dest='checkcurstate',
action='store_true', action='store_true',
help='check running against config of an interface') help='check running against config of an interface')
group.add_argument('--raw', action='store_true', dest='raw',
# presumed-state is state maintained by ifupdown help='print raw config file entries')
group.add_argument('--presumed-state', dest='presumedstate', argparser.add_argument('--format', dest='format', default='native',
action='store_true', help=argparse.SUPPRESS) choices=['native', 'json'], help=argparse.SUPPRESS)
# presumed-state-detailed prints all details about the object stored
# by ifupdown
group.add_argument('--presumed-state-detailed',
dest='presumedstatedetailed',
action='store_true', help=argparse.SUPPRESS)
group.add_argument('--format', dest='format', default='nwifaces',
choices=['nwifaces', 'json'], help=argparse.SUPPRESS)
group.add_argument('--pretty', action='store_true', dest='pretty',
help='pretty print config file entries')
argparser.add_argument('--print-dependency', argparser.add_argument('--print-dependency',
dest='printdependency', choices=['list', 'dot'], dest='printdependency', choices=['list', 'dot'],
help=argparse.SUPPRESS) help='print interface dependency')
argparser.add_argument('--syntax-help', action='store_true',
dest='syntaxhelp',
help='print supported interface config syntax')
def update_ifreload_argparser(argparser): def update_ifreload_argparser(argparser):
update_ifupdown_argparser(argparser) update_ifupdown_argparser(argparser)
argparser.add_argument('--down-changediface', dest='downchangediface', argparser.add_argument('--down-changediface', dest='downchangediface',
action='store_true', action='store_true',
help='down interfaces that have changed before bringing them up') help='down interfaces that have changed before bringing them up')
@@ -194,7 +184,6 @@ def parse_args(argsv, op):
descr = 'query interfaces (all or interface list)' descr = 'query interfaces (all or interface list)'
else: else:
descr = 'interface management' descr = 'interface management'
argparser = argparse.ArgumentParser(description=descr) argparser = argparse.ArgumentParser(description=descr)
update_argparser(argparser) update_argparser(argparser)
if op == 'up': if op == 'up':
@@ -205,7 +194,6 @@ def parse_args(argsv, op):
update_ifquery_argparser(argparser) update_ifquery_argparser(argparser)
elif op == 'reload': elif op == 'reload':
update_ifreload_argparser(argparser) update_ifreload_argparser(argparser)
return argparser.parse_args(argsv) return argparser.parse_args(argsv)
def main(argv): def main(argv):
@@ -224,28 +212,25 @@ def main(argv):
print ('Unexpected executable.' + print ('Unexpected executable.' +
' Should be \'ifup\' or \'ifdown\' or \'ifquery\'') ' Should be \'ifup\' or \'ifdown\' or \'ifquery\'')
exit(1) exit(1)
# Command line arg parser # Command line arg parser
args = parse_args(argv[1:], op) args = parse_args(argv[1:], op)
if len(args.iflist) == 0 and args.all == False: if not len(args.iflist) and not args.all and not args.syntaxhelp:
print '\'-a\' option or interface list are required' print '\'-a\' option or interface list are required'
exit(1) exit(1)
if len(args.iflist) and args.all:
if len(args.iflist) > 0 and args.all is True:
print '\'-a\' option and interface list are mutually exclusive' print '\'-a\' option and interface list are mutually exclusive'
exit(1) exit(1)
init(args) init(args)
run(args, op) run(args, op)
except Exception, e: except Exception, e:
if str(e) == '': if str(e) == '':
exit(1) exit(1)
if args.debug:
if args.debug == True:
raise raise
else: else:
logger.error(str(e)) logger.error(str(e))
print '\nRerun the command with \'-d\' for a detailed errormsg' if not args.debug:
print '\nRerun the command with \'-d\' for a detailed errormsg'
exit(1) exit(1)
finally: finally:
deinit() deinit()