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:
6
TODO
6
TODO
@@ -1,7 +1,9 @@
|
||||
TODO:
|
||||
====
|
||||
- fix service networking reload to use ifreload
|
||||
- the --print-dependency=dot option currently assumes gvgen module is installed.
|
||||
- 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
|
||||
|
||||
- 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
|
||||
- update man-pages with new options. Convert them to rst
|
||||
- Documentation
|
||||
|
@@ -139,6 +139,5 @@ class graph():
|
||||
roots = [k for k, v in indegrees.items() if v == 0]
|
||||
if roots is None:
|
||||
return
|
||||
print roots
|
||||
map(lambda r: cls.generate_dot(dependency_graph, r), roots)
|
||||
|
||||
|
88
pkg/iface.py
88
pkg/iface.py
@@ -6,18 +6,19 @@
|
||||
# iface --
|
||||
# interface object
|
||||
#
|
||||
|
||||
from collections import OrderedDict
|
||||
import logging
|
||||
#from json import *
|
||||
import json
|
||||
import logging
|
||||
|
||||
tickmark = ' (' + u'\u2713'.encode('utf8') + ')'
|
||||
crossmark = ' (' + u'\u2717'.encode('utf8') + ')'
|
||||
|
||||
class ifaceFlags():
|
||||
|
||||
NONE = 0x1
|
||||
FOLLOW_DEPENDENTS = 0x2
|
||||
|
||||
class ifaceStatus():
|
||||
|
||||
"""iface status """
|
||||
UNKNOWN = 0x1
|
||||
SUCCESS = 0x2
|
||||
@@ -56,6 +57,10 @@ class ifaceState():
|
||||
DOWN = 0x7
|
||||
POST_DOWN = 0x8
|
||||
|
||||
# Pseudo states
|
||||
QUERY_CHECKCURR = 0x9
|
||||
QUERY_RUNNING = 0xa
|
||||
|
||||
@classmethod
|
||||
def to_str(cls, state):
|
||||
if state == cls.UNKNOWN:
|
||||
@@ -70,8 +75,14 @@ class ifaceState():
|
||||
return 'post-up'
|
||||
elif state == cls.PRE_DOWN:
|
||||
return 'pre-down'
|
||||
elif state == cls.DOWN:
|
||||
return 'down'
|
||||
elif state == cls.POST_DOWN:
|
||||
return 'post-down'
|
||||
elif state == cls.QUERY_CHECKCURR:
|
||||
return 'query-checkcurr'
|
||||
elif state == cls.QUERY_RUNNING:
|
||||
return 'query-running'
|
||||
|
||||
@classmethod
|
||||
def from_str(cls, state_str):
|
||||
@@ -87,10 +98,23 @@ class ifaceState():
|
||||
return cls.POST_UP
|
||||
elif state_str == 'pre-down':
|
||||
return cls.PRE_DOWN
|
||||
elif state_str == 'down':
|
||||
return cls.DOWN
|
||||
elif state_str == '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():
|
||||
""" config flags """
|
||||
AUTO = 0x1
|
||||
@@ -98,15 +122,14 @@ class iface():
|
||||
|
||||
version = '0.1'
|
||||
|
||||
|
||||
def __init__(self):
|
||||
self.name = None
|
||||
self.addr_family = None
|
||||
self.addr_method = None
|
||||
self.config = OrderedDict()
|
||||
self.children = []
|
||||
self.state = ifaceState.NEW
|
||||
self.status = ifaceStatus.UNKNOWN
|
||||
self.errstr = ''
|
||||
self.flags = 0x0
|
||||
self.priv_flags = 0x0
|
||||
self.refcnt = 0
|
||||
@@ -203,9 +226,6 @@ class iface():
|
||||
|
||||
return False
|
||||
|
||||
def add_child(self, child_iface_obj):
|
||||
self.children.append(child_iface_obj)
|
||||
|
||||
def get_state(self):
|
||||
return self.state
|
||||
|
||||
@@ -258,11 +278,9 @@ class iface():
|
||||
|
||||
def get_attr_value_first(self, attr_name):
|
||||
config = self.get_config()
|
||||
|
||||
attr_value_list = config.get(attr_name)
|
||||
if attr_value_list is not None:
|
||||
return attr_value_list[0]
|
||||
|
||||
return None
|
||||
|
||||
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):
|
||||
if attr_value is None:
|
||||
attr_value = ''
|
||||
|
||||
if attr_status != 0:
|
||||
if attr_status:
|
||||
self.set_status(ifaceStatus.ERROR)
|
||||
new_attr_value = '%s (%s)' %(attr_value, crossmark)
|
||||
else:
|
||||
new_attr_value = '%s (%s)' %(attr_value, tickmark)
|
||||
if self.get_status() != ifaceStatus.ERROR:
|
||||
self.set_status(ifaceStatus.SUCCESS)
|
||||
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:
|
||||
self.config[attr_name] = [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 """
|
||||
self.config[attr_name] = [new_attr_value]
|
||||
|
||||
def is_different(self, dstiface):
|
||||
if self.name != dstiface.name: return True
|
||||
@@ -342,9 +351,27 @@ class iface():
|
||||
if any(True for k,v in self.config.items()
|
||||
if v != dstiface.config.get(k)): return True
|
||||
|
||||
|
||||
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):
|
||||
indent = ' '
|
||||
print (self.raw_lines[0])
|
||||
@@ -376,7 +403,7 @@ class iface():
|
||||
logger.info(indent + indent + str(config))
|
||||
logger.info('}')
|
||||
|
||||
def dump_pretty(self, logger):
|
||||
def dump_pretty(self):
|
||||
indent = '\t'
|
||||
outbuf = ''
|
||||
if self.get_auto():
|
||||
@@ -396,10 +423,7 @@ class iface():
|
||||
for cv in cvaluelist:
|
||||
outbuf += indent + '%s' %cname + ' %s\n' %cv
|
||||
|
||||
#outbuf += ('%s' %indent + '%s' %self.get_state_str() +
|
||||
# ' %s' %self.get_status_str())
|
||||
|
||||
print outbuf
|
||||
|
||||
def dump_json(self, logger):
|
||||
json.dumps(self)
|
||||
def dump_json(self):
|
||||
print json.dumps(self, cls=ifaceJsonEncoder)
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -24,7 +24,8 @@ class networkInterfaces():
|
||||
def __init__(self):
|
||||
self.logger = logging.getLogger('ifupdown.' +
|
||||
self.__class__.__name__)
|
||||
self.callbacks = {'iface_found' : None}
|
||||
self.callbacks = {'iface_found' : None,
|
||||
'validate' : None}
|
||||
self.allow_classes = {}
|
||||
|
||||
|
||||
@@ -118,11 +119,18 @@ class networkInterfaces():
|
||||
if len(attrs) < 2:
|
||||
self.logger.warn('invalid syntax at line %d' %(line_idx + 1))
|
||||
continue
|
||||
|
||||
if iface_config.get(attrs[0]) == None:
|
||||
iface_config[attrs[0]] = [attrs[1].strip(' ')]
|
||||
attrname = attrs[0]
|
||||
attrval = 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:
|
||||
iface_config[attrs[0]].append(attrs[1].strip(' '))
|
||||
iface_config[attrname].append(attrval)
|
||||
|
||||
lines_consumed = line_idx - cur_idx
|
||||
|
||||
@@ -148,7 +156,6 @@ class networkInterfaces():
|
||||
ifaceobj.set_class(c)
|
||||
|
||||
# Call iface found callback
|
||||
#self.logger.debug('saving interface %s' %ifaceobj.get_name())
|
||||
self.callbacks.get('iface_found')(ifaceobj)
|
||||
|
||||
return lines_consumed # Return next index
|
||||
|
290
pkg/scheduler.py
290
pkg/scheduler.py
@@ -7,21 +7,22 @@
|
||||
# interface scheduler
|
||||
#
|
||||
|
||||
import os
|
||||
import re
|
||||
from statemanager import *
|
||||
from iface import *
|
||||
from graph import *
|
||||
from collections import deque
|
||||
from collections import OrderedDict
|
||||
import imp
|
||||
import pprint
|
||||
import logging
|
||||
import traceback
|
||||
from graph import *
|
||||
from collections import deque
|
||||
from threading import *
|
||||
from ifupdownbase import *
|
||||
|
||||
class ifaceSchedulerFlags():
|
||||
INORDER = 1
|
||||
POSTORDER = 2
|
||||
|
||||
class ifaceScheduler(ifupdownBase):
|
||||
""" scheduler to schedule configuration of interfaces.
|
||||
|
||||
@@ -30,132 +31,206 @@ class ifaceScheduler(ifupdownBase):
|
||||
or dependency graph format.
|
||||
"""
|
||||
|
||||
|
||||
def __init__(self, force=False):
|
||||
self.logger = logging.getLogger('ifupdown.' +
|
||||
self.__class__.__name__)
|
||||
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 """
|
||||
ifacename = ifaceobj.get_name()
|
||||
|
||||
self.logger.debug('%s: ' %ifaceobj.get_name() + 'op %s' %op +
|
||||
' subop = %s' %subop)
|
||||
if (ifaceobj.get_state() >= ifaceState.from_str(op) and
|
||||
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)
|
||||
err = 0
|
||||
try:
|
||||
if hasattr(m, 'run') == True:
|
||||
if hasattr(m, 'run'):
|
||||
self.logger.debug('%s: %s : running module %s'
|
||||
%(ifaceobj.get_name(), subop, mname))
|
||||
%(ifacename, op, mname))
|
||||
if op == 'query-checkcurr':
|
||||
# Dont check state if the interface object was
|
||||
# Dont check curr if the interface object was
|
||||
# auto generated
|
||||
if ((ifaceobj.priv_flags & ifupdownobj.BUILTIN) != 0 or
|
||||
(ifaceobj.priv_flags & ifupdownobj.NOCONFIG) != 0):
|
||||
if (ifaceobj.priv_flags & ifupdownobj.NOCONFIG):
|
||||
continue
|
||||
m.run(ifaceobj, subop,
|
||||
query_ifaceobj=ifupdownobj.create_ifaceobjcurr(
|
||||
ifaceobj))
|
||||
m.run(ifaceobj, op,
|
||||
query_ifaceobj=ifupdownobj.create_n_save_ifaceobjcurr(ifaceobj))
|
||||
else:
|
||||
m.run(ifaceobj, subop)
|
||||
m.run(ifaceobj, op)
|
||||
except Exception, e:
|
||||
err = 1
|
||||
self.log_error(str(e))
|
||||
finally:
|
||||
if op[:5] != 'query':
|
||||
if err == 1:
|
||||
ifupdownobj.set_iface_state(ifaceobj,
|
||||
ifaceState.from_str(subop),
|
||||
if err == 1:
|
||||
ifupdownobj.set_iface_state(ifaceobj,
|
||||
ifaceState.from_str(op),
|
||||
ifaceStatus.ERROR)
|
||||
else:
|
||||
ifupdownobj.set_iface_state(ifaceobj,
|
||||
ifaceState.from_str(subop),
|
||||
else:
|
||||
ifupdownobj.set_iface_state(ifaceobj,
|
||||
ifaceState.from_str(op),
|
||||
ifaceStatus.SUCCESS)
|
||||
|
||||
# execute /etc/network/ scripts
|
||||
subop_dict = ifupdownobj.operations_compat.get(op)
|
||||
if subop_dict is None: return
|
||||
for mname in subop_dict.get(subop):
|
||||
mlist = ifupdownobj.operations_compat.get(op)
|
||||
if not mlist:
|
||||
return
|
||||
for mname in mlist:
|
||||
self.logger.debug('%s: %s : running script %s'
|
||||
%(ifaceobj.get_name(), subop, mname))
|
||||
%(ifacename, op, mname))
|
||||
try:
|
||||
self.exec_command(mname, cmdenv=cenv)
|
||||
except Exception, e:
|
||||
err = 1
|
||||
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 """
|
||||
|
||||
# For backward compatibility execute scripts with
|
||||
# environent set
|
||||
cenv = ifupdownobj.generate_running_env(ifaceobj, op)
|
||||
cenv = ifupdownobj.generate_running_env(ifaceobj, ops[0])
|
||||
|
||||
# Each sub operation has a module list
|
||||
subopdict = ifupdownobj.operations.get(op)
|
||||
for subop, mlist in subopdict.items():
|
||||
self.run_iface_subop(ifupdownobj, ifaceobj, op, subop, mlist, cenv)
|
||||
[self.run_iface_op(ifupdownobj, ifaceobj, op, cenv)
|
||||
for op in ops]
|
||||
|
||||
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 """
|
||||
|
||||
ifaceobjs = ifupdownobj.get_iface_objs(ifacename)
|
||||
for i in ifaceobjs:
|
||||
if (op != 'query' and ifupdownobj.STATE_CHECK == True and
|
||||
ifupdownobj.is_valid_state_transition(i, op) == False and
|
||||
ifupdownobj.FORCE == False):
|
||||
self.logger.warning('%s' %ifacename +
|
||||
' already %s' %op)
|
||||
continue
|
||||
self.run_iface_ops(ifupdownobj, i, ops)
|
||||
|
||||
self.run_iface_subops(ifupdownobj, i, 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,
|
||||
def run_iface_list_op(self, ifupdownobj, ifacenames, op,
|
||||
sorted_by_dependency=False):
|
||||
""" Runs interface list through sub operation handler. """
|
||||
|
||||
self.logger.debug('running sub operation %s on all given interfaces'
|
||||
%subop)
|
||||
self.logger.debug('running operation %s on all given interfaces'
|
||||
%op)
|
||||
iface_run_queue = deque(ifacenames)
|
||||
for i in range(0, len(iface_run_queue)):
|
||||
if op == 'up':
|
||||
if op.endswith('up'):
|
||||
# XXX: simplify this
|
||||
if sorted_by_dependency == True:
|
||||
if sorted_by_dependency:
|
||||
ifacename = iface_run_queue.pop()
|
||||
else:
|
||||
ifacename = iface_run_queue.popleft()
|
||||
else:
|
||||
if sorted_by_dependency == True:
|
||||
if sorted_by_dependency:
|
||||
ifacename = iface_run_queue.popleft()
|
||||
else:
|
||||
ifacename = iface_run_queue.pop()
|
||||
@@ -163,21 +238,12 @@ class ifaceScheduler(ifupdownBase):
|
||||
try:
|
||||
ifaceobjs = ifupdownobj.get_iface_objs(ifacename)
|
||||
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)
|
||||
self.run_iface_subop(ifupdownobj, ifaceobj, op, subop,
|
||||
mdict, cenv)
|
||||
self.run_iface_op(ifupdownobj, ifaceobj, op, cenv)
|
||||
except Exception, 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):
|
||||
""" Runs interface list through sub operations handler
|
||||
|
||||
@@ -188,30 +254,27 @@ class ifaceScheduler(ifupdownBase):
|
||||
"""
|
||||
|
||||
# Each sub operation has a module list
|
||||
subopdict = ifupdownobj.operations.get(op)
|
||||
for subop, mdict in subopdict.items():
|
||||
self.run_iface_list_subop(ifupdownobj, ifacenames, op, subop, mdict,
|
||||
sorted_by_dependency)
|
||||
[self.run_iface_list_op(ifupdownobj, ifacenames, op,
|
||||
sorted_by_dependency) for op in ops]
|
||||
|
||||
|
||||
def run_iface_dependency_graph(self, ifupdownobj, dependency_graphs,
|
||||
operation, indegrees=None,
|
||||
def run_iface_dependency_graphs_sorted(self, ifupdownobj,
|
||||
dependency_graphs,
|
||||
ops, indegrees=None,
|
||||
graphsortall=False):
|
||||
""" runs interface dependency graph """
|
||||
|
||||
""" runs interface dependency graph by topologically sorting the interfaces """
|
||||
|
||||
if indegrees is None:
|
||||
indegrees = OrderedDict()
|
||||
for ifacename in dependency_graphs.keys():
|
||||
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(ifupdownobj.pp.pformat(indegrees))
|
||||
|
||||
try:
|
||||
self.logger.debug('calling topological sort on the graph ...')
|
||||
if graphsortall == True:
|
||||
if graphsortall:
|
||||
sorted_ifacenames = graph.topological_sort_graphs_all(
|
||||
dependency_graphs, indegrees)
|
||||
else:
|
||||
@@ -221,14 +284,11 @@ class ifaceScheduler(ifupdownBase):
|
||||
raise
|
||||
|
||||
self.logger.debug('sorted iface list = %s' %sorted_ifacenames)
|
||||
|
||||
#self.run_iface_list(ifupdownobj, sorted_ifacenames, operation,
|
||||
# sorted_by_dependency=True)
|
||||
|
||||
self.run_iface_list_stages(ifupdownobj, sorted_ifacenames, operation,
|
||||
sorted_by_dependency=True)
|
||||
self.run_iface_list_ops(ifupdownobj, sorted_ifacenames, ops,
|
||||
sorted_by_dependency=True)
|
||||
|
||||
|
||||
""" Methods to execute interfaces in parallel """
|
||||
def init_tokens(self, count):
|
||||
self.token_pool = BoundedSemaphore(count)
|
||||
self.logger.debug('initialized bounded semaphore with %d' %count)
|
||||
@@ -270,7 +330,7 @@ class ifaceScheduler(ifupdownBase):
|
||||
dlist, op)
|
||||
self.accquire_token(ifacename)
|
||||
except Exception, e:
|
||||
if (self.ignore_error(str(e)) == True):
|
||||
if self.ignore_error(str(e)):
|
||||
pass
|
||||
else:
|
||||
# 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 +
|
||||
' dependents (%s)', str(e))
|
||||
ifupdownobj.set_iface_state(ifaceobj,
|
||||
ifaceState.from_str(
|
||||
ifupdownobj.get_subops(op)[0]),
|
||||
ifaceState.from_str(ops[0]),
|
||||
ifaceStatus.ERROR)
|
||||
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
|
||||
try:
|
||||
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:
|
||||
self.logger.error('%s:' %ifacename +
|
||||
' error running sub operations (%s)' %str(e))
|
||||
@@ -317,7 +369,7 @@ class ifaceScheduler(ifupdownBase):
|
||||
self.release_token(parent)
|
||||
except Exception, e:
|
||||
self.release_token(parent)
|
||||
if (ifupdownobj.ignore_error(str(e)) == True):
|
||||
if ifupdownobj.ignore_error(str(e)):
|
||||
pass
|
||||
else:
|
||||
raise Exception('error starting thread for iface %s'
|
||||
@@ -348,7 +400,7 @@ class ifaceScheduler(ifupdownBase):
|
||||
self.release_graph_token(parent)
|
||||
except Exception, e:
|
||||
self.release_graph_token(parent)
|
||||
if (ifupdownobj.ignore_error(str(e)) == True):
|
||||
if ifupdownobj.ignore_error(str(e)):
|
||||
pass
|
||||
else:
|
||||
raise Exception('error starting thread for iface %s'
|
||||
@@ -385,8 +437,8 @@ class ifaceScheduler(ifupdownBase):
|
||||
if ifupdownobj.get_iface_refcnt(ifacename) == 0:
|
||||
run_queue.append(ifacename)
|
||||
|
||||
self.logger.debug('graph roots (interfaces that dont have dependents):' +
|
||||
' %s' %str(run_queue))
|
||||
self.logger.debug('graph roots (interfaces that dont'
|
||||
' have dependents):' + ' %s' %str(run_queue))
|
||||
|
||||
self.init_tokens(ifupdownobj.get_njobs())
|
||||
|
||||
|
@@ -70,8 +70,8 @@ class stateManager():
|
||||
# Read all ifaces from file
|
||||
for ifaceobj in pickling.load(pickle_filename):
|
||||
self.save_ifaceobj(ifaceobj)
|
||||
ifaceobj.set_refcnt(0)
|
||||
ifaceobj.set_dependents(None)
|
||||
#ifaceobj.set_refcnt(0)
|
||||
#ifaceobj.set_dependents(None)
|
||||
|
||||
return 0
|
||||
|
||||
|
@@ -18,14 +18,11 @@ def run(args, op):
|
||||
iflist = args.iflist
|
||||
if len(args.iflist) == 0:
|
||||
iflist = None
|
||||
|
||||
cachearg=(False if (iflist is not None or
|
||||
args.nocache == True or
|
||||
args.perfmode == True)
|
||||
else True)
|
||||
|
||||
logger.debug('creating ifupdown object ..')
|
||||
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,
|
||||
withdepends=args.withdepends,
|
||||
perfmode=args.perfmode,
|
||||
@@ -33,40 +30,45 @@ def run(args, op):
|
||||
dryrun=args.noact,
|
||||
cache=cachearg)
|
||||
elif op == 'query':
|
||||
cachearg=(False if (iflist or args.nocache or
|
||||
args.perfmode or args.syntaxhelp) else True)
|
||||
ifupdown_handle = ifupdownMain(withdepends=args.withdepends,
|
||||
perfmode=args.perfmode,
|
||||
njobs=args.jobs,
|
||||
format=args.format,
|
||||
cache=cachearg)
|
||||
|
||||
logger.debug('calling \'%s\'' %op + ' for all interfaces ..')
|
||||
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,
|
||||
printdependency=args.printdependency)
|
||||
elif op == 'down':
|
||||
ifupdown_handle.down(args.all, args.CLASS, iflist,
|
||||
excludepats=args.excludepats)
|
||||
ifupdown_handle.down(['pre-down', 'down', 'post-down'],
|
||||
args.all, args.CLASS, iflist,
|
||||
excludepats=args.excludepats,
|
||||
printdependency=args.printdependency)
|
||||
elif op == 'query':
|
||||
if args.checkcurstate == True:
|
||||
qtype='query-checkcurr'
|
||||
elif args.presumedstate == True:
|
||||
qtype='query-presumed'
|
||||
elif args.presumedstatedetailed == True:
|
||||
qtype='query-presumeddetailed'
|
||||
elif args.runningstate == True:
|
||||
if args.checkcurstate:
|
||||
qop='query-checkcurr'
|
||||
elif args.runningstate:
|
||||
if iflist is None:
|
||||
iflist = [i for i in os.listdir('/sys/class/net/')
|
||||
if os.path.isdir('/sys/class/net/%s' %i) == True]
|
||||
qtype='query-running'
|
||||
elif args.pretty == True:
|
||||
qtype='query-pretty'
|
||||
if os.path.isdir('/sys/class/net/%s' %i)]
|
||||
qop='query-running'
|
||||
elif args.raw:
|
||||
qop='query-raw'
|
||||
elif args.syntaxhelp:
|
||||
qop = 'query-syntax'
|
||||
elif args.printdependency:
|
||||
qop = 'query-dependency'
|
||||
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,
|
||||
printdependency=args.printdependency)
|
||||
printdependency=args.printdependency,
|
||||
format=args.format)
|
||||
elif op == 'reload':
|
||||
if iflist is not None:
|
||||
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',
|
||||
action='store_true',
|
||||
help='query running state of an interface')
|
||||
|
||||
group.add_argument('-c', '--check-state', dest='checkcurstate',
|
||||
action='store_true',
|
||||
help='check running against config of an interface')
|
||||
|
||||
# presumed-state is state maintained by ifupdown
|
||||
group.add_argument('--presumed-state', dest='presumedstate',
|
||||
action='store_true', 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')
|
||||
|
||||
group.add_argument('--raw', action='store_true', dest='raw',
|
||||
help='print raw config file entries')
|
||||
argparser.add_argument('--format', dest='format', default='native',
|
||||
choices=['native', 'json'], help=argparse.SUPPRESS)
|
||||
argparser.add_argument('--print-dependency',
|
||||
dest='printdependency', choices=['list', 'dot'],
|
||||
help=argparse.SUPPRESS)
|
||||
dest='printdependency', choices=['list', 'dot'],
|
||||
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):
|
||||
update_ifupdown_argparser(argparser)
|
||||
|
||||
argparser.add_argument('--down-changediface', dest='downchangediface',
|
||||
action='store_true',
|
||||
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)'
|
||||
else:
|
||||
descr = 'interface management'
|
||||
|
||||
argparser = argparse.ArgumentParser(description=descr)
|
||||
update_argparser(argparser)
|
||||
if op == 'up':
|
||||
@@ -205,7 +194,6 @@ def parse_args(argsv, op):
|
||||
update_ifquery_argparser(argparser)
|
||||
elif op == 'reload':
|
||||
update_ifreload_argparser(argparser)
|
||||
|
||||
return argparser.parse_args(argsv)
|
||||
|
||||
def main(argv):
|
||||
@@ -224,28 +212,25 @@ def main(argv):
|
||||
print ('Unexpected executable.' +
|
||||
' Should be \'ifup\' or \'ifdown\' or \'ifquery\'')
|
||||
exit(1)
|
||||
|
||||
# Command line arg parser
|
||||
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'
|
||||
exit(1)
|
||||
|
||||
if len(args.iflist) > 0 and args.all is True:
|
||||
if len(args.iflist) and args.all:
|
||||
print '\'-a\' option and interface list are mutually exclusive'
|
||||
exit(1)
|
||||
|
||||
init(args)
|
||||
run(args, op)
|
||||
except Exception, e:
|
||||
if str(e) == '':
|
||||
exit(1)
|
||||
|
||||
if args.debug == True:
|
||||
if args.debug:
|
||||
raise
|
||||
else:
|
||||
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)
|
||||
finally:
|
||||
deinit()
|
||||
|
Reference in New Issue
Block a user