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

A whole lot of fixes and some new code (needs some cleanup which will be

part of subsequent checkins)

Ticket: CM-1438
Reviewed By:
Testing Done: Tested ifup, ifdown and ifquery

Conflicts:
	packages/ifupdown2-addons/addons/ifenslave.py
This commit is contained in:
roopa
2014-01-16 06:46:17 -08:00
parent f407f5cfe8
commit 739f665baa
9 changed files with 498 additions and 115 deletions

9
README
View File

@ -54,3 +54,12 @@ install instructions
dpkg -i python-ifupdown2-addons-<ver>.deb dpkg -i python-ifupdown2-addons-<ver>.deb
extra packages to use addional packages:
======================================
To use templates install python-mako (from wheezy):
apt-get install python-mako
To generate dot files install python-gvgen (from wheezy):
apt-get install python-gvgen

View File

@ -51,6 +51,7 @@ case "$1" in
[ -e /sbin/ifup ] || ln -s /sbin/ifupdown /sbin/ifup [ -e /sbin/ifup ] || ln -s /sbin/ifupdown /sbin/ifup
[ -e /sbin/ifdown ] || ln -s /sbin/ifupdown /sbin/ifdown [ -e /sbin/ifdown ] || ln -s /sbin/ifupdown /sbin/ifdown
[ -e /sbin/ifquery ] || ln -s /sbin/ifupdown /sbin/ifquery [ -e /sbin/ifquery ] || ln -s /sbin/ifupdown /sbin/ifquery
[ -e /sbin/ifreload ] || ln -s /sbin/ifupdown /sbin/ifreload
;; ;;
purge) purge)

View File

@ -9,6 +9,10 @@
import logging import logging
from collections import deque from collections import deque
try:
from gvgen import *
except ImportError, e:
pass
class graph(): class graph():
@ -49,3 +53,48 @@ class graph():
' (indegree %d)' %indegree) ' (indegree %d)' %indegree)
return S return S
@classmethod
def add_to_dot_old(cls, dependency_graph, gvgraph, v, parentgvitem):
dependents = dependency_graph.get(v, [])
if dependents is None:
return
if len(dependents) > 1:
# if more than one dependents .., add them to a box
box = gvgraph.newItem(v)
for d in dependents:
dnode = gvgraph.newItem(d, box)
cls.add_to_dot(dependency_graph, gvgraph, d, dnode)
if parentgvitem is not None: gvgraph.newLink(parentgvitem,
dnode)
else:
for d in dependents:
dnode = gvgraph.newItem(d)
cls.add_to_dot(dependency_graph, gvgraph, d, dnode)
if parentgvitem is not None: gvgraph.newLink(parentgvitem,
dnode)
@classmethod
def add_to_dot(cls, dependency_graph, gvgraph, v, parentgvitem):
vnode = gvgraph.newItem(v)
if parentgvitem is not None: gvgraph.newLink(parentgvitem, vnode)
dependents = dependency_graph.get(v, [])
if dependents is None:
return
for d in dependents:
cls.add_to_dot(dependency_graph, gvgraph, d, vnode)
@classmethod
def generate_dot(cls, dependency_graph, v):
gvgraph = GvGen()
cls.add_to_dot(dependency_graph, gvgraph, v, None)
gvgraph.dot(name=v)
@classmethod
def generate_dots(cls, dependency_graph, indegrees):
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)

View File

@ -31,6 +31,8 @@ class ifaceStatus():
return 'success' return 'success'
elif state == cls.ERROR: elif state == cls.ERROR:
return 'error' return 'error'
elif state == cls.NOTFOUND:
return 'not found'
@classmethod @classmethod
def from_str(cls, state_str): def from_str(cls, state_str):
@ -104,7 +106,12 @@ class iface():
self.status = ifaceStatus.UNKNOWN self.status = ifaceStatus.UNKNOWN
self.flags = 0x0 self.flags = 0x0
self.refcnt = 0 self.refcnt = 0
# dependents that are listed as in the
# config file
self.dependents = None self.dependents = None
# All dependents (includes dependents that
# are not listed in the config file)
self.realdev_dependents = None
self.auto = False self.auto = False
self.classes = [] self.classes = []
self.env = None self.env = None
@ -113,7 +120,6 @@ class iface():
self.linkstate = None self.linkstate = None
def inc_refcnt(self): def inc_refcnt(self):
#print 'inside inc_refcnt = %d' %self.refcnt
self.refcnt += 1 self.refcnt += 1
def dec_refcnt(self): def dec_refcnt(self):
@ -217,6 +223,12 @@ class iface():
def get_dependents(self): def get_dependents(self):
return self.dependents return self.dependents
def set_realdev_dependents(self, dlist):
self.realdev_dependents = dlist
def get_realdev_dependents(self):
return self.realdev_dependents
def set_linkstate(self, l): def set_linkstate(self, l):
self.linkstate = l self.linkstate = l
@ -268,7 +280,16 @@ class iface():
if len(env) > 0: if len(env) > 0:
self.set_env(env) self.set_env(env)
def update_config(self, attr_name, attr_value, attr_status=0): def update_config(self, attr_name, attr_value):
if self.config.get(attr_name) is None:
self.config[attr_name] = [attr_value]
else:
self.config[attr_name].append(attr_value)
def update_config_dict(self, attrdict):
self.config.update(attrdict)
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 = ''
@ -314,6 +335,10 @@ class iface():
else: else:
logger.info(indent + 'dependents: None') logger.info(indent + 'dependents: None')
logger.info(indent + 'realdev dependents: %s'
%str(self.get_realdev_dependents()))
logger.info(indent + 'config: ') logger.info(indent + 'config: ')
config = self.get_config() config = self.get_config()
if config is not None: if config is not None:

View File

@ -56,7 +56,8 @@ class ifupdownBase(object):
def log_error(self, str): def log_error(self, str):
if self.ignore_error(str) == False: if self.ignore_error(str) == False:
raise Exception(str) raise
#raise Exception(str)
else: else:
pass pass

View File

@ -53,6 +53,12 @@ class ifupdownMain():
OrderedDict([('pre-up', OrderedDict({})), OrderedDict([('pre-up', OrderedDict({})),
('up' , OrderedDict({})), ('up' , OrderedDict({})),
('post-up' , OrderedDict({}))]), ('post-up' , OrderedDict({}))]),
'query-checkcurr' :
OrderedDict([('query-checkcurr', OrderedDict({}))]),
'query-running' :
OrderedDict([('query-running', OrderedDict({}))]),
'down' : 'down' :
OrderedDict([('pre-down', OrderedDict({})), OrderedDict([('pre-down', OrderedDict({})),
('down' , OrderedDict({})), ('down' , OrderedDict({})),
@ -60,7 +66,8 @@ class ifupdownMain():
def __init__(self, force=False, dryrun=False, nowait=False, def __init__(self, force=False, dryrun=False, nowait=False,
perfmode=False, nodepends=False, njobs=1): perfmode=False, nodepends=False, njobs=1,
format='nwifaces', cache=False):
self.logger = logging.getLogger('ifupdown') self.logger = logging.getLogger('ifupdown')
self.FORCE = force self.FORCE = force
@ -68,6 +75,8 @@ class ifupdownMain():
self.NOWAIT = nowait self.NOWAIT = nowait
self.PERFMODE = perfmode self.PERFMODE = perfmode
self.NODEPENDS = nodepends self.NODEPENDS = nodepends
self.CACHE = cache
self._DELETE_DEPENDENT_IFACES_WITH_NOCONFIG = True
self.ifaces = OrderedDict() self.ifaces = OrderedDict()
self.njobs = njobs self.njobs = njobs
@ -114,6 +123,16 @@ class ifupdownMain():
def get_dryrun(self): def get_dryrun(self):
return self.DRYRUN return self.DRYRUN
def get_cache(self):
return self.CACHE
def get_ifaceobjdict(self):
return self.ifaceobjdict
def set_ifaceobjdict(self, ifaceobjdict):
del self.ifaceobjdict
self.ifaceobjdict = ifaceobjdict
def set_perfmode(self, perfmode): def set_perfmode(self, perfmode):
if perfmode == True: if perfmode == True:
self.logger.debug('setting perfmode to true') self.logger.debug('setting perfmode to true')
@ -161,20 +180,26 @@ class ifupdownMain():
def get_iface_obj_last(self, ifacename): def get_iface_obj_last(self, ifacename):
return self.ifaceobjdict.get(ifacename)[-1] return self.ifaceobjdict.get(ifacename)[-1]
def create_ifaceobjcurr(self, ifacename): def create_ifaceobjcurr(self, ifaceobj):
ifaceobj = self.get_ifaceobjcurr(ifacename) ifacename = ifaceobj.get_name()
if ifaceobj is not None: ifaceobjcurr = self.get_ifaceobjcurr(ifacename)
return ifaceobj if ifaceobjcurr is not None:
return ifaceobjcurr
ifaceobj = iface() ifaceobjcurr = iface()
ifaceobj.set_name(ifacename) ifaceobjcurr.set_name(ifacename)
self.ifaceobjcurrdict[ifacename] = ifaceobj ifaceobjcurr.set_dependents(ifaceobj.get_dependents())
self.ifaceobjcurrdict[ifacename] = ifaceobjcurr
return ifaceobj return ifaceobj
def get_ifaceobjcurr(self, ifacename): def get_ifaceobjcurr(self, ifacename):
return self.ifaceobjcurrdict.get(ifacename) return self.ifaceobjcurrdict.get(ifacename)
def get_ifaceobjrunning(self, ifacename):
return self.ifaceobjrunningdict.get(ifacename)
def get_iface_status(self, ifacename): def get_iface_status(self, ifacename):
ifaceobjs = self.get_iface_objs(ifacename) ifaceobjs = self.get_iface_objs(ifacename)
for i in ifaceobjs: for i in ifaceobjs:
@ -191,19 +216,16 @@ class ifupdownMain():
max = i.get_refcnt() max = i.get_refcnt()
return max return max
def create_fake_vlan_iface(self, vlan_ifname, op): def create_n_save_ifaceobj(self, ifacename, increfcnt=False):
""" creates and returns a fake vlan iface object. """ creates and returns a fake vlan iface object.
This was added to support creation of simple vlan
This was added to support creation of simple vlan devices without any devices without any user specified configuration.
user specified configuration.
""" """
ifaceobj = iface()
# XXX: Ideally this should be a call-back into the vlan module. ifaceobj.set_name(ifacename)
vlan_iface_obj = iface() if increfcnt == True:
vlan_iface_obj.set_name(vlan_ifname) ifaceobj.inc_refcnt()
self.ifaceobjdict[ifacename] = [ifaceobj]
return vlan_iface_obj
def is_vlan_device(self, ifacename): def is_vlan_device(self, ifacename):
""" Returns true if iface name is a vlan interface. """ Returns true if iface name is a vlan interface.
@ -216,20 +238,31 @@ class ifupdownMain():
return False return False
def preprocess_dependency_list(self, dlist, op): def preprocess_dependency_list(self, dlist, op):
""" We go through the dependency list and
delete or add interfaces from the interfaces dict by
applying the following rules:
if flag _DELETE_DEPENDENT_IFACES_WITH_NOCONFIG is True:
we only consider devices whose configuration was
specified in the network interfaces file. We delete
any interface whose config was not specified except
for vlan devices. vlan devices get special treatment.
Even if they are not present they are created and added
to the ifacesdict
elif flag _DELETE_DEPENDENT_IFACES_WITH_NOCONFIG is False:
we create objects for all dependent devices that are not
present in the ifacesdict
"""
del_list = [] del_list = []
create_list = []
self.logger.debug('pre-processing dependency list: %s' %list(dlist)) self.logger.debug('pre-processing dependency list: %s' %list(dlist))
for d in dlist: for d in dlist:
dilist = self.get_iface_objs(d) dilist = self.get_iface_objs(d)
if dilist == None: if dilist == None:
if self.is_vlan_device(d) == True: if (self.is_vlan_device(d) == True or
vlan_iface_obj = self.create_fake_vlan_iface(d, op) self._DELETE_DEPENDENT_IFACES_WITH_NOCONFIG == False):
create_list.append(d)
# Add face vlan device to ifaceobjdict dict
vlan_iface_obj.inc_refcnt()
self.save_iface(vlan_iface_obj)
else: else:
# Remove the device from the list
del_list.append(d) del_list.append(d)
else: else:
for di in dilist: for di in dilist:
@ -238,10 +271,13 @@ class ifupdownMain():
for d in del_list: for d in del_list:
dlist.remove(d) dlist.remove(d)
# create fake devices to all dependents that dont have config
map(lambda i: self.create_n_save_ifaceobj(i, increfcnt=True),
create_list)
self.logger.debug('After Processing dependency list: %s' self.logger.debug('After Processing dependency list: %s'
%list(dlist)) %list(dlist))
def get_dependents(self, ifaceobj, op): def get_dependents(self, ifaceobj, op):
""" Gets iface dependents by calling into respective modules """ """ Gets iface dependents by calling into respective modules """
dlist = None dlist = None
@ -254,16 +290,23 @@ class ifupdownMain():
for mname, mdata in mdict.items(): for mname, mdata in mdict.items():
if mdata.get('ftype') == 'pmodule': if mdata.get('ftype') == 'pmodule':
module = mdata.get('module') module = mdata.get('module')
if (hasattr(module, if op == 'query-running':
'get_dependent_ifacenames') == False): if (hasattr(module,
continue 'get_dependent_ifacenames_running') == False):
dlist = module.get_dependent_ifacenames(ifaceobj, continue
self.ifaceobjdict.keys()) dlist = module.get_dependent_ifacenames_running(
ifaceobj)
else:
if (hasattr(module,
'get_dependent_ifacenames') == False):
continue
dlist = module.get_dependent_ifacenames(ifaceobj,
self.ifaceobjdict.keys())
if dlist is not None: if dlist is not None:
ifaceobj.set_realdev_dependents(dlist[:])
self.logger.debug('%s: ' %ifaceobj.get_name() + self.logger.debug('%s: ' %ifaceobj.get_name() +
'got dependency list: %s' %str(dlist)) 'got dependency list: %s' %str(dlist))
break break
return dlist return dlist
def generate_dependency_info(self, ifacenames, dependency_graph, op): def generate_dependency_info(self, ifacenames, dependency_graph, op):
@ -290,8 +333,7 @@ class ifupdownMain():
if dlist is not None: if dlist is not None:
self.preprocess_dependency_list(dlist, op) self.preprocess_dependency_list(dlist, op)
ifaceobj.set_dependents(dlist) ifaceobj.set_dependents(dlist)
for d in dlist: [iqueue.append(d) for d in dlist]
iqueue.append(d)
if dependency_graph.get(i) is None: if dependency_graph.get(i) is None:
dependency_graph[i] = dlist dependency_graph[i] = dlist
@ -330,7 +372,12 @@ class ifupdownMain():
""" """
mmetadata = self.operations[mkind][msubkind].get(mname) try:
mmetadata = self.operations[mkind][msubkind].get(mname)
except KeyError:
self.logger.warn('unsupported module type %s' %mname)
return
if mmetadata is None or mmetadata.get('ftype') != 'pmodule': if mmetadata is None or mmetadata.get('ftype') != 'pmodule':
mmetadata = {} mmetadata = {}
mmetadata['ftype'] = mftype mmetadata['ftype'] = mftype
@ -373,15 +420,20 @@ class ifupdownMain():
minstance = mclass(force=self.get_force(), minstance = mclass(force=self.get_force(),
dryrun=self.get_dryrun(), dryrun=self.get_dryrun(),
nowait=self.get_nowait(), nowait=self.get_nowait(),
perfmode=self.get_perfmode()) perfmode=self.get_perfmode(),
cache=self.get_cache())
ops = minstance.get_ops() ops = minstance.get_ops()
for op in ops: for op in ops:
if re.search('up', op) is not None: if re.search('query', op) is not None:
self.save_module(op, op, mname, 'pmodule',
minstance)
elif re.search('up', op) is not None:
self.save_module('up', op, mname, 'pmodule', self.save_module('up', op, mname, 'pmodule',
minstance) minstance)
else: else:
self.save_module('down', op, mname, 'pmodule', self.save_module('down', op, mname,
minstance) 'pmodule', minstance)
except: except:
raise raise
@ -396,6 +448,9 @@ class ifupdownMain():
self.logger.info('loading user modules from %s' %modules_dir) self.logger.info('loading user modules from %s' %modules_dir)
for op, subops in self.operations.items(): for op, subops in self.operations.items():
if re.search('query', op) is not None:
continue
for subop in subops.keys(): for subop in subops.keys():
msubdir = modules_dir + '/if-%s.d' %subop msubdir = modules_dir + '/if-%s.d' %subop
self.logger.info('loading modules under %s ...' %msubdir) self.logger.info('loading modules under %s ...' %msubdir)
@ -475,11 +530,27 @@ class ifupdownMain():
ret = ifaceSched.run_iface_dependency_graph_parallel(self, ret = ifaceSched.run_iface_dependency_graph_parallel(self,
dependency_graph, op) dependency_graph, op)
else: else:
ret = ifaceSched.run_iface_dependency_graph(self, dependency_graph, ret = ifaceSched.run_iface_dependency_graph(self,
op) dependency_graph, op)
return ret return ret
def print_dependency(self, op, ifacenames, format):
dependency_graph = {}
if ifacenames is None:
ifacenames = self.ifaceobjdict.keys()
# generate dependency graph of interfaces
self._DELETE_DEPENDENT_IFACES_WITH_NOCONFIG = False
self.generate_dependency_info(ifacenames, dependency_graph, op)
if format == 'list':
self.pp.pprint(dependency_graph)
elif format == 'dot':
indegrees = {}
map(lambda i: indegrees.update({i :
self.get_iface_refcnt(i)}),
dependency_graph.keys())
graph.generate_dots(dependency_graph, indegrees)
def validate_ifaces(self, ifacenames): def validate_ifaces(self, ifacenames):
""" validates interface list for config existance. """ validates interface list for config existance.
@ -539,10 +610,8 @@ class ifupdownMain():
return True return True
def generate_running_env(self, ifaceobj, op): def generate_running_env(self, ifaceobj, op):
""" Generates a dictionary with env variables required for an interface. """ Generates a dictionary with env variables required for
an interface. Used to support script execution for interfaces.
Used to support script execution for interfaces.
""" """
cenv = None cenv = None
@ -560,8 +629,8 @@ class ifupdownMain():
def run(self, op, auto=False, allow_classes=None, def run(self, op, auto=False, allow_classes=None,
ifacenames=None, query_state=None, excludepats=None, ifacenames=None, excludepats=None,
format=None): format=None, printdependency=None):
""" main ifupdown run method """ """ main ifupdown run method """
if auto == True: if auto == True:
@ -571,12 +640,15 @@ class ifupdownMain():
# Only read new iface config for 'up' # Only read new iface config for 'up'
# operations. For 'downs' we only rely on # operations. For 'downs' we only rely on
# old state # old state
if op == 'up' or op == 'query': if op == 'query-running':
# create fake devices to all dependents that dont have config
map(lambda i: self.create_n_save_ifaceobj(i), ifacenames)
elif op == 'up' or op[:5] == 'query':
try: try:
self.read_iface_config() self.read_iface_config()
except Exception, e: except Exception, e:
raise raise
else: elif op == 'down':
# for down we need to look at old state # for down we need to look at old state
self.logger.debug('down op, looking at old state ..') self.logger.debug('down op, looking at old state ..')
@ -584,18 +656,19 @@ class ifupdownMain():
self.read_old_iface_config() self.read_old_iface_config()
elif self.FORCE == True: elif self.FORCE == True:
# If no old state available # If no old state available
self.logger.info('old state not available. Force option ' + self.logger.info('old state not available. ' +
'set. Loading new iface config file') 'Force option set. Loading new iface config file')
try: try:
self.read_iface_config() self.read_iface_config()
except Exception, e: except Exception, e:
raise Exception('error reading iface config (%s)' %str(e)) raise Exception('error reading iface config (%s)'
%str(e))
else: else:
raise Exception('old state not available...aborting.' + raise Exception('old state not available...aborting.' +
' try running with --force option') ' try running with --force option')
if ifacenames is not None: if ifacenames is not None and op != 'query-running':
# If iface list is given, always check if iface is present # If iface list is given, always check if iface is present
if self.validate_ifaces(ifacenames) != 0: if self.validate_ifaces(ifacenames) != 0:
raise Exception('all or some interfaces not found') raise Exception('all or some interfaces not found')
@ -604,36 +677,45 @@ class ifupdownMain():
if ifacenames is None: ifacenames = self.ifaceobjdict.keys() if ifacenames is None: ifacenames = self.ifaceobjdict.keys()
# filter interfaces based on auto and allow classes # filter interfaces based on auto and allow classes
filtered_ifacenames = [i for i in ifacenames if op == 'query-running':
if self.iface_whitelisted(auto, allow_classes, excludepats, filtered_ifacenames = ifacenames
i) == True] else:
filtered_ifacenames = [i for i in ifacenames
if self.iface_whitelisted(auto, allow_classes,
excludepats, i) == True]
if len(filtered_ifacenames) == 0: if len(filtered_ifacenames) == 0:
raise Exception('no ifaces found matching ' + raise Exception('no ifaces found matching ' +
'given allow lists') 'given allow lists')
if op == 'query': if op == 'query':
if query_state == None: return self.print_ifaceobjs_raw(filtered_ifacenames)
return self.print_ifaceobjs_pretty(filtered_ifacenames) elif op == 'query-presumed':
elif query_state == 'presumed': return self.print_ifaceobjs_saved_state_pretty(
return self.print_ifaceobjs_saved_state_pretty(
filtered_ifacenames) filtered_ifacenames)
elif query_state == 'presumeddetailed': elif op == 'query-presumeddetailed':
return self.print_ifaceobjs_saved_state_detailed_pretty( return self.print_ifaceobjs_saved_state_detailed_pretty(
filtered_ifacenames) filtered_ifacenames)
if op == 'query' or self.NODEPENDS == True: if printdependency is not None:
self.print_dependency(op, filtered_ifacenames, printdependency)
return
#if op.split('-')[0] == 'query' or self.NODEPENDS == True:
if op.split('-')[0] == 'query' or self.NODEPENDS == True:
self.run_without_dependents(op, filtered_ifacenames) self.run_without_dependents(op, filtered_ifacenames)
else: else:
self.run_with_dependents(op, filtered_ifacenames) self.run_with_dependents(op, filtered_ifacenames)
if op == 'query': if op == 'query-checkcurr':
if query_state == 'curr': # print curr state of all interfaces
# print curr state of all interfaces ret = self.print_ifaceobjscurr_pretty(filtered_ifacenames)
ret = self.print_ifaceobjscurr_pretty(filtered_ifacenames) if ret != 0:
if ret != 0: # if any of the object has an error, signal that silently
# if any of the object has an error, signal that silently raise Exception('')
raise Exception('') elif op == 'query-running':
# print curr state of all interfaces
self.print_ifaceobjsrunning_pretty(filtered_ifacenames)
return return
# Update persistant iface states # Update persistant iface states
@ -649,17 +731,162 @@ class ifupdownMain():
self.logger.warning('error saving state (%s)' %str(e)) self.logger.warning('error saving state (%s)' %str(e))
def up(self, auto=False, allow=None, ifacenames=None, excludepats=None): def up(self, auto=False, allow=None, ifacenames=None,
return self.run('up', auto, allow, ifacenames, excludepats=excludepats) excludepats=None, printdependency=None):
return self.run('up', auto, allow, ifacenames,
excludepats=excludepats,
printdependency=printdependency)
def down(self, auto=False, allow=None, ifacenames=None, excludepats=None): def down(self, auto=False, allow=None, ifacenames=None, excludepats=None):
return self.run('down', auto, allow, ifacenames, return self.run('down', auto, allow, ifacenames,
excludepats=excludepats); excludepats=excludepats);
def query(self, auto=False, allow=None, ifacenames=None, def query(self, op, auto=False, allow_classes=None, ifacenames=None,
query_state=False, excludepats=None): excludepats=None, printdependency=None,
return self.run('query', auto, allow, ifacenames, format=None):
query_state=query_state, excludepats=excludepats); """ main ifupdown run method """
if auto == True:
self.logger.debug('setting flag ALL')
self.ALL = True
if op == 'query-running':
self._DELETE_DEPENDENT_IFACES_WITH_NOCONFIG = False
# create fake devices to all dependents that dont have config
map(lambda i: self.create_n_save_ifaceobj(i), ifacenames)
else:
try:
self.read_iface_config()
except Exception:
raise
if ifacenames is not None and op != 'query-running':
# If iface list is given, always check if iface is present
if self.validate_ifaces(ifacenames) != 0:
raise Exception('all or some interfaces not found')
# if iface list not given by user, assume all from config file
if ifacenames is None: ifacenames = self.ifaceobjdict.keys()
# filter interfaces based on auto and allow classes
if op == 'query-running':
filtered_ifacenames = ifacenames
else:
filtered_ifacenames = [i for i in ifacenames
if self.iface_whitelisted(auto, allow_classes,
excludepats, i) == True]
if len(filtered_ifacenames) == 0:
raise Exception('no ifaces found matching ' +
'given allow lists')
if op == 'query':
return self.print_ifaceobjs_raw(filtered_ifacenames)
elif op == 'query-presumed':
return self.print_ifaceobjs_saved_state_pretty(
filtered_ifacenames)
elif op == 'query-presumeddetailed':
return self.print_ifaceobjs_saved_state_detailed_pretty(
filtered_ifacenames)
if printdependency is not None:
self.print_dependency(op, filtered_ifacenames, printdependency)
return
if self.NODEPENDS == True:
self.run_without_dependents(op, filtered_ifacenames)
else:
self.run_with_dependents(op, filtered_ifacenames)
if op == 'query-checkcurr':
ret = self.print_ifaceobjscurr_pretty(filtered_ifacenames)
if ret != 0:
# if any of the object has an error, signal that silently
raise Exception('')
elif op == 'query-running':
self.print_ifaceobjsrunning_pretty(filtered_ifacenames)
return
def reload(self, auto=False, allow=None,
ifacenames=None, excludepats=None):
""" main ifupdown run method """
allow_classes = []
self.logger.debug('reloading interface config ..')
if auto == True:
self.logger.debug('setting flag ALL')
self.ALL = True
try:
self.read_iface_config()
except Exception, e:
raise
# Save a copy of new iface objects
new_ifaceobjdict = self.get_ifaceobjdict()
if len(self.statemanager.get_ifaceobjdict()) > 0:
# if old state is present, read old state and mark op for 'down'
# followed by 'up' aka: reload
self.read_old_iface_config()
op = 'reload'
else:
# oldconfig not available, continue with 'up' with new config
op = 'up'
if ifacenames is None: ifacenames = self.ifaceobjdict.keys()
if (op == 'reload' and ifacenames is not None and
len(ifacenames) != 0):
filtered_ifacenames = [i for i in ifacenames
if self.iface_whitelisted(auto, allow_classes,
excludepats, i) == True]
ifacedownlist = Set(filtered_ifacenames).difference(
Set(new_ifaceobjdict.keys()))
if ifacedownlist is not None and len(ifacedownlist) > 0:
self.logger.debug('bringing down interfaces: %s'
%str(ifacedownlist))
if self.NODEPENDS == True:
self.run_without_dependents('down', ifacedownlist)
else:
self.run_with_dependents('down', ifacedownlist)
# Update persistant iface states
try:
if self.ALL == True:
self.statemanager.flush_state(self.ifaceobjdict)
else:
self.statemanager.flush_state()
except Exception, e:
if self.logger.isEnabledFor(logging.DEBUG):
t = sys.exc_info()[2]
traceback.print_tb(t)
self.logger.warning('error saving state (%s)' %str(e))
# Now, run up with new dict
self.set_ifaceobjdict(new_ifaceobjdict)
ifacenames = self.ifaceobjdict.keys()
filtered_ifacenames = [i for i in ifacenames
if self.iface_whitelisted(auto, allow_classes,
excludepats, i) == True]
self.logger.debug('bringing up interfaces: %s'
%str(filtered_ifacenames))
if self.NODEPENDS == True:
self.run_without_dependents('up', filtered_ifacenames)
else:
self.run_with_dependents('up', filtered_ifacenames)
# Update persistant iface states
try:
if self.ALL == True:
self.statemanager.flush_state(self.get_ifaceobjdict())
else:
self.statemanager.flush_state()
except Exception, e:
if self.logger.isEnabledFor(logging.DEBUG):
t = sys.exc_info()[2]
traceback.print_tb(t)
self.logger.warning('error saving state (%s)' %str(e))
def dump(self): def dump(self):
""" all state dump """ """ all state dump """
@ -672,24 +899,37 @@ class ifupdownMain():
def print_state(self, ifacenames=None): def print_state(self, ifacenames=None):
self.statemanager.dump(ifacenames) self.statemanager.dump(ifacenames)
def print_ifaceobjs_raw(self, ifacenames):
for i in ifacenames:
ifaceobjs = self.get_iface_objs(i)
for i in ifaceobjs:
i.dump_raw(self.logger)
print '\n'
def print_ifaceobjs_pretty(self, ifacenames): def print_ifaceobjs_pretty(self, ifacenames):
for i in ifacenames: for i in ifacenames:
ifaceobjs = self.get_iface_objs(i) ifaceobjs = self.get_iface_objs(i)
for io in ifaceobjs: for i in ifaceobjs:
io.dump_raw(self.logger) i.dump_pretty(self.logger)
print '\n' print '\n'
def print_ifaceobjscurr_pretty(self, ifacenames, format): def dump_ifaceobjs(self, ifacenames):
for i in ifacenames:
ifaceobjs = self.get_iface_objs(i)
for i in ifaceobjs:
i.dump(self.logger)
print '\n'
def print_ifaceobjscurr_pretty(self, ifacenames, format=None):
""" Dumps current running state of interfaces. """ Dumps current running state of interfaces.
returns 1 if any of the interface has an error, returns 1 if any of the interface has an error,
else returns 0 else returns 0
""" """
ret = 0 ret = 0
for i in ifacenames: for i in ifacenames:
ifaceobj = self.get_ifaceobjcurr(i) ifaceobj = self.get_ifaceobjcurr(i)
if ifaceobj is None: continue
if ifaceobj.get_status() == ifaceStatus.NOTFOUND: if ifaceobj.get_status() == ifaceStatus.NOTFOUND:
print 'iface %s' %ifaceobj.get_name() + ' (not found)' print 'iface %s' %ifaceobj.get_name() + ' (not found)'
ret = 1 ret = 1
@ -701,8 +941,29 @@ class ifupdownMain():
else: else:
ifaceobj.dump_json(self.logger) ifaceobj.dump_json(self.logger)
dlist = ifaceobj.get_dependents()
if dlist is None or len(dlist) == 0: continue
self.print_ifaceobjscurr_pretty(dlist, format)
return ret return ret
def print_ifaceobjsrunning_pretty(self, ifacenames, format=None):
for i in ifacenames:
ifaceobj = self.get_iface_obj_first(i)
if ifaceobj.get_status() == ifaceStatus.NOTFOUND:
print 'iface %s' %ifaceobj.get_name() + ' (not found)'
continue
if format is None or format == 'nwifaces':
ifaceobj.dump_pretty(self.logger)
elif format == 'json':
ifaceobj.dump_json(self.logger)
dlist = ifaceobj.get_dependents()
if dlist is None or len(dlist) == 0: continue
self.print_ifaceobjsrunning_pretty(dlist, format)
return
def print_ifaceobjs_saved_state_pretty(self, ifacenames): def print_ifaceobjs_saved_state_pretty(self, ifacenames):
self.statemanager.print_state_pretty(ifacenames, self.logger) self.statemanager.print_state_pretty(ifacenames, self.logger)

View File

@ -10,6 +10,7 @@
import collections import collections
import logging import logging
import glob import glob
import re
from iface import * from iface import *
class networkInterfaces(): class networkInterfaces():
@ -95,6 +96,7 @@ class networkInterfaces():
iface_line = lines[cur_idx].strip('\n ') iface_line = lines[cur_idx].strip('\n ')
iface_attrs = iface_line.split() iface_attrs = iface_line.split()
ifacename = iface_attrs[1]
ifaceobj.raw_lines.append(iface_line) ifaceobj.raw_lines.append(iface_line)
@ -111,6 +113,9 @@ class networkInterfaces():
ifaceobj.raw_lines.append(l) ifaceobj.raw_lines.append(l)
# preprocess vars (XXX: only preprocesses $IFACE for now)
l = re.sub(r'\$IFACE', ifacename, l)
attrs = l.split(' ', 1) attrs = l.split(' ', 1)
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))
@ -124,7 +129,7 @@ class networkInterfaces():
lines_consumed = line_idx - cur_idx lines_consumed = line_idx - cur_idx
# Create iface object # Create iface object
ifaceobj.set_name(iface_attrs[1]) ifaceobj.set_name(ifacename)
ifaceobj.set_config(iface_config) ifaceobj.set_config(iface_config)
ifaceobj.generate_env() ifaceobj.generate_env()
if len(iface_attrs) > 2: if len(iface_attrs) > 2:

View File

@ -50,10 +50,10 @@ class ifaceScheduler(ifupdownBase):
self.logger.debug('%s: ' %ifaceobj.get_name() + self.logger.debug('%s: ' %ifaceobj.get_name() +
'running module %s' %mname + 'running module %s' %mname +
' op %s' %op + ' subop %s' %subop) ' op %s' %op + ' subop %s' %subop)
if op == 'query': if op == 'query-checkcurr':
m.run(ifaceobj, subop, query=True, m.run(ifaceobj, subop, query_check=True,
query_ifaceobj=ifupdownobj.create_ifaceobjcurr( query_ifaceobj=ifupdownobj.create_ifaceobjcurr(
ifaceobj.get_name())) ifaceobj))
else: else:
m.run(ifaceobj, subop) m.run(ifaceobj, subop)
else: else:
@ -65,7 +65,7 @@ class ifaceScheduler(ifupdownBase):
err = 1 err = 1
self.log_error(str(e)) self.log_error(str(e))
finally: finally:
if op != 'query': if op[:5] != 'query':
if err == 1: if err == 1:
ifupdownobj.set_iface_state(ifaceobj, ifupdownobj.set_iface_state(ifaceobj,
ifaceState.from_str(subop), ifaceState.from_str(subop),
@ -135,7 +135,6 @@ class ifaceScheduler(ifupdownBase):
""" 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' %op) self.logger.debug('running sub operation %s on all given interfaces' %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 == 'up':

View File

@ -15,42 +15,58 @@ def run(args, op):
logger.debug('args = %s' %str(args)) logger.debug('args = %s' %str(args))
try: try:
logger.debug('creating ifupdown object ..')
if op == 'up' or op == 'down':
ifupdown_handle = ifupdownMain(force=args.force,
nodepends=args.nodepends,
perfmode=args.perfmode,
njobs=args.jobs,
dryrun=args.noact)
elif op == 'query':
ifupdown_handle = ifupdownMain(nodepends=args.nodepends,
perfmode=args.perfmode,
njobs=args.jobs,
format=args.format)
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 else True
logger.debug('creating ifupdown object ..')
if op == 'up' or op == 'down' or op == 'reload':
ifupdown_handle = ifupdownMain(force=args.force,
nodepends=args.nodepends,
perfmode=args.perfmode,
njobs=args.jobs,
dryrun=args.noact,
cache=cachearg)
elif op == 'query':
ifupdown_handle = ifupdownMain(nodepends=args.nodepends,
perfmode=args.perfmode,
njobs=args.jobs,
format=args.format,
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(args.all, args.CLASS, iflist,
excludepats=args.excludepats) excludepats=args.excludepats,
printdependency=args.printdependency)
elif op == 'down': elif op == 'down':
ifupdown_handle.down(args.all, args.CLASS, iflist, ifupdown_handle.down(args.all, args.CLASS, iflist,
excludepats=args.excludepats) excludepats=args.excludepats)
elif op == 'query': elif op == 'query':
if args.curstate == True: if args.checkcurstate == True:
qstate='curr' qtype='query-checkcurr'
elif args.presumedstate == True: elif args.presumedstate == True:
qstate='presumed' qtype='query-presumed'
elif args.presumedstatedetailed == True: elif args.presumedstatedetailed == True:
qstate='presumeddetailed' qtype='query-presumeddetailed'
elif args.runningstate == True:
if iflist is None:
iflist = [i for i in os.listdir('/sys/class/net/')
if os.path.isdir('/sys/class/net/%s' %i) == True]
print iflist
qtype='query-running'
else: else:
qstate=None qtype='query'
ifupdown_handle.query(args.all, args.CLASS, iflist,
query_state=qstate, ifupdown_handle.query(qtype, args.all, args.CLASS, iflist,
excludepats=args.excludepats) excludepats=args.excludepats)
elif op == 'reload':
if iflist is not None:
raise Exception('iflist is currently not supported with reload')
ifupdown_handle.reload(args.all, args.CLASS, iflist,
excludepats=args.excludepats)
except: except:
raise raise
@ -77,6 +93,7 @@ def deinit():
{} {}
def update_argparser(argparser): def update_argparser(argparser):
""" base parser """
argparser.add_argument('iflist', metavar='IFACE', argparser.add_argument('iflist', metavar='IFACE',
nargs='*', help='interfaces list') nargs='*', help='interfaces list')
argparser.add_argument('-v', '--verbose', dest='verbose', argparser.add_argument('-v', '--verbose', dest='verbose',
@ -95,6 +112,11 @@ def update_argparser(argparser):
action='store_true', help=argparse.SUPPRESS) action='store_true', help=argparse.SUPPRESS)
argparser.add_argument('-j', '--jobs', dest='jobs', type=int, argparser.add_argument('-j', '--jobs', dest='jobs', type=int,
default=-1, choices=range(1,12), help=argparse.SUPPRESS) default=-1, choices=range(1,12), help=argparse.SUPPRESS)
argparser.add_argument('--nocache', dest='nocache', action='store_true',
help=argparse.SUPPRESS)
argparser.add_argument('--print-dependency',
dest='printdependency', choices=['list', 'dot'],
help=argparse.SUPPRESS)
argparser.add_argument('-X', '--exclude', dest='excludepats', argparser.add_argument('-X', '--exclude', dest='excludepats',
action='append', help='exclude interfaces from the list of ' action='append', help='exclude interfaces from the list of '
+ 'interfaces to operate on by a PATTERN ' + 'interfaces to operate on by a PATTERN '
@ -121,10 +143,14 @@ def update_ifquery_argparser(argparser):
argparser.add_argument('-l', '--list', action='store_true', dest='all', argparser.add_argument('-l', '--list', action='store_true', dest='all',
help='process all interfaces marked \"auto\"') help='process all interfaces marked \"auto\"')
group = argparser.add_mutually_exclusive_group(required=False) group = argparser.add_mutually_exclusive_group(required=False)
group.add_argument('-r', '--running-state', dest='curstate', 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',
action='store_true',
help='check running state of an interface')
# presumed-state is state maintained by ifupdown # presumed-state is state maintained by ifupdown
group.add_argument('--presumed-state', dest='presumedstate', group.add_argument('--presumed-state', dest='presumedstate',
action='store_true', help=argparse.SUPPRESS) action='store_true', help=argparse.SUPPRESS)
@ -138,6 +164,8 @@ def update_ifquery_argparser(argparser):
group.add_argument('--format', dest='format', default='nwifaces', group.add_argument('--format', dest='format', default='nwifaces',
choices=['nwifaces', 'json'], help=argparse.SUPPRESS) choices=['nwifaces', 'json'], help=argparse.SUPPRESS)
def update_ifreload_argparser(argparser):
update_ifupdown_argparser(argparser)
def parse_args(argsv, op): def parse_args(argsv, op):
descr = 'interface management' descr = 'interface management'
@ -150,6 +178,8 @@ def parse_args(argsv, op):
update_ifdown_argparser(argparser) update_ifdown_argparser(argparser)
elif op == 'query': elif op == 'query':
update_ifquery_argparser(argparser) update_ifquery_argparser(argparser)
elif op == 'reload':
update_ifreload_argparser(argparser)
return argparser.parse_args(argsv) return argparser.parse_args(argsv)
@ -163,6 +193,8 @@ def main(argv):
op = 'down' op = 'down'
elif re.search(r'ifquery', argv[0]) != None: elif re.search(r'ifquery', argv[0]) != None:
op = 'query' op = 'query'
elif re.search(r'ifreload', argv[0]) != None:
op = 'reload'
else: else:
print ('Unexpected executable.' + print ('Unexpected executable.' +
' Should be \'ifup\' or \'ifdown\' or \'ifquery\'') ' Should be \'ifup\' or \'ifdown\' or \'ifquery\'')
@ -171,7 +203,7 @@ def main(argv):
# 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 is True: if len(args.iflist) > 0 and args.all is True:
print 'interface list and \'-a\' are mutually exclusive' print 'interface list cannot be specified with all option'
exit(1) exit(1)
init(args) init(args)
@ -184,6 +216,7 @@ def main(argv):
raise raise
else: else:
logger.error(str(e)) logger.error(str(e))
print '\nRerun the command with \'-d\' for a detailed errormsg'
exit(1) exit(1)
finally: finally:
deinit() deinit()