1
0
mirror of https://github.com/CumulusNetworks/ifupdown2.git synced 2024-05-06 15:54:50 +00:00
CumulusNetworks-ifupdown2/pkg/ifupdownmain.py
roopa 923290bd42 Fix bug during handling multiple iface sections for same interface
Ticket: CM-1438
Reviewed By:
Testing Done: Tested ifupdown2 sanity + multiple iface sections for an
interface

- This patch fixes a few shortcomings in the multiple iface sections
for same interface (partly because i was only covering
backward compatibility cases earlier)
- Since this is a very common configuration pattern, this patch cleans
  it up
- also restructures some code
- main change is:
    before:
        for iface in ifaces:
            for op in ops:
                run op on iface

    after:
        for op in ops:
            for iface in ifaces:
                run op on iface
2014-05-26 09:03:29 -07:00

1009 lines
38 KiB
Python

#!/usr/bin/python
#
# Copyright 2013. Cumulus Networks, Inc.
# Author: Roopa Prabhu, roopa@cumulusnetworks.com
#
# ifupdownMain --
# ifupdown main module
#
import os
import re
import imp
import pprint
import logging
import sys, traceback
import copy
import json
from statemanager import *
from networkinterfaces import *
from iface import *
from scheduler import *
from collections import deque
from collections import OrderedDict
from graph import *
from sets import Set
_tickmark = u'\u2713'
_crossmark = u'\u2717'
_success_sym = _tickmark
_error_sym = _crossmark
class ifupdownMain(ifupdownBase):
""" ifupdown2 main class """
# Flags
WITH_DEPENDS = False
ALL = False
COMPAT_EXEC_SCRIPTS = False
STATEMANAGER_ENABLE = True
STATEMANAGER_UPDATE = True
ADDONS_ENABLE = False
# priv flags to mark iface objects
BUILTIN = 0x1
NOCONFIG = 0x2
scripts_dir='/etc/network'
addon_modules_dir='/usr/share/ifupdownaddons'
addon_modules_configfile='/var/lib/ifupdownaddons/addons.conf'
# iface dictionary in the below format:
# { '<ifacename>' : [<ifaceobject1>, <ifaceobject2> ..] }
# eg:
# { 'swp1' : [<iface swp1>, <iface swp2> ..] }
#
# Each ifaceobject corresponds to a configuration block for
# that interface
# The value in the dictionary is a list because the network
# interface configuration file supports more than one iface section
# in the interfaces file
ifaceobjdict = OrderedDict()
# iface dictionary representing the curr running state of an iface
# in the below format:
# {'<ifacename>' : <ifaceobject>}
ifaceobjcurrdict = OrderedDict()
# Dictionary representing operation and modules
# for every operation
module_ops = OrderedDict([('pre-up', []),
('up' , []),
('post-up' , []),
('query-checkcurr', []),
('query-running', []),
('query-dependency', []),
('query', []),
('query-raw', []),
('pre-down', []),
('down' , []),
('post-down' , [])])
# For old style /etc/network/ bash scripts
script_ops = OrderedDict([('pre-up', []),
('up' , []),
('post-up' , []),
('pre-down', []),
('down' , []),
('post-down' , [])])
# Handlers for ops that ifupdown2 owns
def run_up(self, ifaceobj):
ifacename = ifaceobj.name
if self.link_exists(ifacename):
self.link_up(ifacename)
def run_down(self, ifaceobj):
ifacename = ifaceobj.name
if self.link_exists(ifacename):
self.link_down(ifacename)
# ifupdown object interface operation handlers
ops_handlers = OrderedDict([('up', run_up),
('down', run_down)])
def run_sched_ifaceobj_posthook(self, ifaceobj, op):
if ((ifaceobj.priv_flags & self.BUILTIN) or
(ifaceobj.priv_flags & self.NOCONFIG)):
return
if self.STATEMANAGER_UPDATE:
self.statemanager.ifaceobj_sync(ifaceobj, op)
# ifupdown object interface scheduler pre and posthooks
sched_hooks = {'posthook' : run_sched_ifaceobj_posthook}
def __init__(self, config={},
force=False, dryrun=False, nowait=False,
perfmode=False, withdepends=False, njobs=1,
cache=False, addons_enable=True, statemanager_enable=True,
interfacesfile='/etc/network/interfaces',
interfacesfileiobuf=None,
interfacesfileformat='native'):
self.logger = logging.getLogger('ifupdown')
self.FORCE = force
self.DRYRUN = dryrun
self.NOWAIT = nowait
self.PERFMODE = perfmode
self.WITH_DEPENDS = withdepends
self.STATEMANAGER_ENABLE = statemanager_enable
self.CACHE = cache
self.interfacesfile = interfacesfile
self.interfacesfileiobuf = interfacesfileiobuf
self.interfacesfileformat = interfacesfileformat
self.config = config
self.logger.debug(self.config)
# Can be used to provide hints for caching
self.CACHE_FLAGS = 0x0
self._DELETE_DEPENDENT_IFACES_WITH_NOCONFIG = False
self.ADDONS_ENABLE = addons_enable
self.ifaces = OrderedDict()
self.njobs = njobs
self.pp = pprint.PrettyPrinter(indent=4)
self.modules = OrderedDict({})
self.module_attrs = {}
self.load_addon_modules(self.addon_modules_dir)
if self.COMPAT_EXEC_SCRIPTS:
self.load_scripts(self.scripts_dir)
self.dependency_graph = OrderedDict({})
if self.STATEMANAGER_ENABLE:
try:
self.statemanager = stateManager()
self.statemanager.read_saved_state()
except Exception, e:
# XXX Maybe we should continue by ignoring old state
self.logger.warning('error reading state (%s)' %str(e))
raise
else:
self.STATEMANAGER_UPDATE = False
def get_ifaceobjs(self, ifacename):
return self.ifaceobjdict.get(ifacename)
def get_ifaceobj_first(self, ifacename):
ifaceobjs = self.get_ifaceobjs(ifacename)
if ifaceobjs:
return ifaceobjs[0]
return None
def get_ifacenames(self):
return self.ifaceobjdict.keys()
def get_iface_obj_last(self, ifacename):
return self.ifaceobjdict.get(ifacename)[-1]
def create_n_save_ifaceobj(self, ifacename, priv_flags=None,
increfcnt=False):
""" creates a iface object and adds it to the iface dictionary """
ifaceobj = iface()
ifaceobj.name = ifacename
ifaceobj.priv_flags = priv_flags
ifaceobj.auto = True
if increfcnt:
ifaceobj.inc_refcnt()
self.ifaceobjdict[ifacename] = [ifaceobj]
return ifaceobj
def create_n_save_ifaceobjcurr(self, ifaceobj):
""" creates a copy of iface object and adds it to the iface
dict containing current iface objects
"""
ifaceobjcurr = iface()
ifaceobjcurr.name = ifaceobj.name
ifaceobjcurr.lowerifaces = ifaceobj.lowerifaces
ifaceobjcurr.priv_flags = ifaceobj.priv_flags
ifaceobjcurr.auto = ifaceobj.auto
self.ifaceobjcurrdict.setdefault(ifaceobj.name,
[]).append(ifaceobjcurr)
return ifaceobjcurr
def get_ifaceobjcurr(self, ifacename, idx=0):
ifaceobjlist = self.ifaceobjcurrdict.get(ifacename)
if not ifaceobjlist:
return None
if not idx:
return ifaceobjlist
else:
return ifaceobjlist[idx]
def get_ifaceobjrunning(self, ifacename):
return self.ifaceobjrunningdict.get(ifacename)
def get_iface_refcnt(self, ifacename):
""" Return iface ref count """
max = 0
ifaceobjs = self.get_ifaceobjs(ifacename)
if not ifaceobjs:
return 0
for i in ifaceobjs:
if i.refcnt > max:
max = i.refcnt
return max
def is_iface_builtin_byname(self, ifacename):
""" Returns true if iface name is a builtin interface.
A builtin interface is an interface which ifupdown understands.
The following are currently considered builtin ifaces:
- vlan interfaces in the format <ifacename>.<vlanid>
"""
return '.' in ifacename
def is_ifaceobj_builtin(self, ifaceobj):
""" Returns true if iface name is a builtin interface.
A builtin interface is an interface which ifupdown understands.
The following are currently considered builtin ifaces:
- vlan interfaces in the format <ifacename>.<vlanid>
"""
return (ifaceobj.priv_flags & self.BUILTIN)
def is_ifaceobj_noconfig(self, ifaceobj):
""" Returns true if iface object did not have a user defined config.
These interfaces appear only when they are dependents of interfaces
which have user defined config
"""
return (ifaceobj.priv_flags & self.NOCONFIG)
def is_iface_noconfig(self, ifacename):
""" Returns true if iface has no config """
ifaceobj = self.get_ifaceobj_first(ifacename)
if not ifaceobj: return True
return self.is_ifaceobj_noconfig(ifaceobj)
def preprocess_dependency_list(self, upperifacename, dlist, ops):
""" 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 = []
for d in dlist:
dilist = self.get_ifaceobjs(d)
if not dilist:
if self.is_iface_builtin_byname(d):
self.create_n_save_ifaceobj(d, self.BUILTIN | self.NOCONFIG,
True).add_to_upperifaces(upperifacename)
elif not self._DELETE_DEPENDENT_IFACES_WITH_NOCONFIG:
self.create_n_save_ifaceobj(d, self.NOCONFIG,
True).add_to_upperifaces(upperifacename)
else:
del_list.append(d)
else:
for di in dilist:
di.inc_refcnt()
di.add_to_upperifaces(upperifacename)
for d in del_list:
dlist.remove(d)
def query_dependents(self, ifaceobj, ops):
""" Gets iface dependents by calling into respective modules """
dlist = None
# Get dependents for interface by querying respective modules
for mname, module in self.modules.items():
module = self.modules.get(mname)
try:
if ops[0] == 'query-running':
if (not hasattr(module,
'get_dependent_ifacenames_running')):
continue
dlist = module.get_dependent_ifacenames_running(ifaceobj)
else:
if (not hasattr(module, 'get_dependent_ifacenames')):
continue
dlist = module.get_dependent_ifacenames(ifaceobj,
self.ifaceobjdict.keys())
except Exception, e:
self.logger.warn('%s: error getting dependent interfaces (%s)'
%(ifaceobj.name, str(e)))
dlist = None
pass
if dlist:
break
return dlist
def populate_dependency_info(self, ops, ifacenames=None):
""" recursive function to generate iface dependency info """
if not ifacenames:
ifacenames = self.ifaceobjdict.keys()
iqueue = deque(ifacenames)
while iqueue:
i = iqueue.popleft()
# Go through all modules and find dependent ifaces
dlist = None
ifaceobj = self.get_ifaceobj_first(i)
if not ifaceobj:
continue
dlist = ifaceobj.lowerifaces
if not dlist:
dlist = self.query_dependents(ifaceobj, ops)
else:
continue
if dlist:
self.preprocess_dependency_list(ifaceobj.name,
dlist, ops)
ifaceobj.lowerifaces = dlist
[iqueue.append(d) for d in dlist]
if not self.dependency_graph.get(i):
self.dependency_graph[i] = dlist
def _save_iface(self, ifaceobj):
currentifaceobjlist = self.ifaceobjdict.get(ifaceobj.name)
if not currentifaceobjlist:
self.ifaceobjdict[ifaceobj.name]= [ifaceobj]
return
if ifaceobj.compare(currentifaceobjlist[0]):
self.logger.warn('duplicate interface %s found' %ifaceobj.name)
return
currentifaceobjlist[0].flags |= iface.HAS_SIBLINGS
ifaceobj.flags |= iface.HAS_SIBLINGS
self.ifaceobjdict[ifaceobj.name].append(ifaceobj)
def _iface_configattr_syntax_checker(self, attrname, attrval):
for m, mdict in self.module_attrs.items():
if not mdict:
continue
attrsdict = mdict.get('attrs')
try:
if attrsdict.get(attrname):
return True
except AttributeError:
pass
return False
def _ifaceobj_syntax_checker(self, ifaceobj):
err = False
for attrname in ifaceobj.config:
found = False
for k, v in self.module_attrs.items():
if v and v.get('attrs', {}).get(attrname):
found = True
break
if not found:
err = True
self.logger.warn('%s: unsupported attribute \'%s\'' %attrname)
continue
return err
def read_iface_config(self):
""" Reads default network interface config /etc/network/interfaces. """
nifaces = networkInterfaces(self.interfacesfile,
self.interfacesfileiobuf,
self.interfacesfileformat,
template_engine=self.config.get('template_engine'),
template_lookuppath=self.config.get('template_lookuppath'))
nifaces.subscribe('iface_found', self._save_iface)
nifaces.subscribe('validateifaceattr',
self._iface_configattr_syntax_checker)
nifaces.subscribe('validateifaceobj', self._ifaceobj_syntax_checker)
nifaces.load()
def read_old_iface_config(self):
""" Reads the saved iface config instead of default iface config.
And saved iface config is already read by the statemanager """
self.ifaceobjdict = copy.deepcopy(self.statemanager.ifaceobjdict)
def _load_addon_modules_config(self):
""" Load addon modules config file """
with open(self.addon_modules_configfile, 'r') as f:
lines = f.readlines()
for l in lines:
litems = l.rstrip(' \n').split(',')
operation = litems[0]
mname = litems[1]
self.module_ops[operation].append(mname)
def load_addon_modules(self, modules_dir):
""" load python modules from modules_dir
Default modules_dir is /usr/share/ifupdownmodules
"""
self.logger.info('loading builtin modules from %s' %modules_dir)
self._load_addon_modules_config()
if not modules_dir in sys.path:
sys.path.append(modules_dir)
try:
for op, mlist in self.module_ops.items():
for mname in mlist:
if self.modules.get(mname):
continue
mpath = modules_dir + '/' + mname + '.py'
if os.path.exists(mpath):
try:
m = __import__(mname)
mclass = getattr(m, mname)
except:
raise
minstance = mclass(force=self.FORCE,
dryrun=self.DRYRUN,
nowait=self.NOWAIT,
perfmode=self.PERFMODE,
cache=self.CACHE,
cacheflags=self.CACHE_FLAGS)
self.modules[mname] = minstance
try:
self.module_attrs[mname] = minstance.get_modinfo()
except:
pass
except:
raise
# Assign all modules to query operations
self.module_ops['query-checkcurr'] = self.modules.keys()
self.module_ops['query-running'] = self.modules.keys()
self.module_ops['query-dependency'] = self.modules.keys()
self.module_ops['query'] = self.modules.keys()
self.module_ops['query-raw'] = self.modules.keys()
def _modules_help(self):
""" Prints addon modules supported syntax """
indent = ' '
for m, mdict in self.module_attrs.items():
if not mdict:
continue
print('%s: %s' %(m, mdict.get('mhelp')))
attrdict = mdict.get('attrs')
if not attrdict:
continue
try:
for attrname, attrvaldict in attrdict.items():
if attrvaldict.get('compat', False):
continue
print('%s%s' %(indent, attrname))
print('%shelp: %s' %(indent + ' ',
attrvaldict.get('help', '')))
print ('%srequired: %s' %(indent + ' ',
attrvaldict.get('required', False)))
default = attrvaldict.get('default')
if default:
print('%sdefault: %s' %(indent + ' ', default))
validrange = attrvaldict.get('validrange')
if validrange:
print('%svalidrange: %d-%d'
%(indent + ' ', validrange[0], validrange[1]))
validvals = attrvaldict.get('validvals')
if validvals:
print('%svalidvals: %s'
%(indent + ' ', ','.join(validvals)))
examples = attrvaldict.get('example')
if not examples:
continue
print '%sexample:' %(indent + ' ')
for e in examples:
print '%s%s' %(indent + ' ', e)
except:
pass
print ''
def load_scripts(self, modules_dir):
""" loading user modules from /etc/network/.
Note that previously loaded python modules override modules found
under /etc/network if any
"""
self.logger.info('looking for user scripts under %s' %modules_dir)
for op, mlist in self.script_ops.items():
msubdir = modules_dir + '/if-%s.d' %op
self.logger.info('loading scripts under %s ...' %msubdir)
try:
module_list = os.listdir(msubdir)
for module in module_list:
if self.modules.get(module) is not None:
continue
self.script_ops[op].append(
msubdir + '/' + module)
except:
# continue reading
pass
def _sched_ifaces(self, ifacenames, ops):
self.logger.debug('scheduling \'%s\' for %s'
%(str(ops), str(ifacenames)))
self._pretty_print_ordered_dict('dependency graph',
self.dependency_graph)
return ifaceScheduler.sched_ifaces(self, ifacenames, ops,
dependency_graph=self.dependency_graph,
order=ifaceSchedulerFlags.INORDER
if 'down' in ops[0]
else ifaceSchedulerFlags.POSTORDER,
followdependents=True if self.WITH_DEPENDS else False)
def _validate_ifaces(self, ifacenames):
""" validates interface list for config existance.
returns -1 if one or more interface not found. else, returns 0
"""
err_iface = ''
for i in ifacenames:
ifaceobjs = self.get_ifaceobjs(i)
if not ifaceobjs:
err_iface += ' ' + i
if err_iface:
raise Exception('cannot find interfaces:%s' %err_iface)
return True
def _iface_whitelisted(self, auto, allow_classes, excludepats, ifacename):
""" Checks if interface is whitelisted depending on set of parameters.
interfaces are checked against the allow_classes and auto lists.
"""
if excludepats:
for e in excludepats:
if re.search(e, ifacename):
return False
ifaceobjs = self.get_ifaceobjs(ifacename)
if not ifaceobjs:
self.logger.debug('iface %s' %ifacename + ' not found')
return False
# We check classes first
if allow_classes:
for i in ifaceobjs:
if i.classes:
common = Set([allow_classes]).intersection(
Set(i.classes))
if common:
return True
return False
if auto:
for i in ifaceobjs:
if i.auto:
return True
return False
return True
def _compat_conv_op_to_mode(self, op):
""" Returns old op name to work with existing scripts """
if op == 'pre-up':
return 'start'
elif op == 'pre-down':
return 'stop'
else:
return op
def generate_running_env(self, ifaceobj, op):
""" Generates a dictionary with env variables required for
an interface. Used to support script execution for interfaces.
"""
cenv = None
iface_env = ifaceobj.env
if iface_env:
cenv = os.environ
if cenv:
cenv.update(iface_env)
else:
cenv = iface_env
cenv['MODE'] = self._compat_conv_op_to_mode(op)
return cenv
def _save_state(self):
if not self.STATEMANAGER_ENABLE or not self.STATEMANAGER_UPDATE:
return
try:
# Update persistant iface states
self.statemanager.save_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 up(self, ops, auto=False, allow_classes=None, ifacenames=None,
excludepats=None, printdependency=None, syntaxcheck=False):
""" up an interface """
if not self.ADDONS_ENABLE: self.STATEMANAGER_UPDATE = False
if auto:
self.ALL = True
self.WITH_DEPENDS = True
try:
self.read_iface_config()
except Exception:
raise
# If only syntax check was requested, return here
if syntaxcheck:
return
if ifacenames:
# If iface list is given by the caller, always check if iface
# is present
self._validate_ifaces(ifacenames)
# if iface list not given by user, assume all from config file
if not ifacenames: ifacenames = self.ifaceobjdict.keys()
# filter interfaces based on auto and allow classes
filtered_ifacenames = [i for i in ifacenames
if self._iface_whitelisted(auto, allow_classes,
excludepats, i)]
if not filtered_ifacenames:
raise Exception('no ifaces found matching given allow lists')
if printdependency:
self.populate_dependency_info(ops, filtered_ifacenames)
self.print_dependency(filtered_ifacenames, printdependency)
return
else:
self.populate_dependency_info(ops)
try:
self._sched_ifaces(filtered_ifacenames, ops)
finally:
if not self.DRYRUN and self.ADDONS_ENABLE:
self._save_state()
def down(self, ops, auto=False, allow_classes=None, ifacenames=None,
excludepats=None, printdependency=None, usecurrentconfig=False):
""" down an interface """
if not self.ADDONS_ENABLE: self.STATEMANAGER_UPDATE = False
if auto:
self.ALL = True
self.WITH_DEPENDS = True
# For down we need to look at old state, unless usecurrentconfig
# is set
if (not usecurrentconfig and self.STATEMANAGER_ENABLE and
self.statemanager.ifaceobjdict):
# Since we are using state manager objects,
# skip the updating of state manager objects
self.logger.debug('Looking at old state ..')
self.read_old_iface_config()
else:
# If no old state available
try:
self.read_iface_config()
except Exception, e:
raise Exception('error reading iface config (%s)' %str(e))
if ifacenames:
# If iface list is given by the caller, always check if iface
# is present
try:
self._validate_ifaces(ifacenames)
except Exception, e:
raise Exception('%s' %str(e) +
' (interface was probably never up ?)')
# if iface list not given by user, assume all from config file
if not ifacenames: ifacenames = self.ifaceobjdict.keys()
# filter interfaces based on auto and allow classes
filtered_ifacenames = [i for i in ifacenames
if self._iface_whitelisted(auto, allow_classes,
excludepats, i)]
if not filtered_ifacenames:
raise Exception('no ifaces found matching given allow lists')
if printdependency:
self.populate_dependency_info(ops, filtered_ifacenames)
self.print_dependency(filtered_ifacenames, printdependency)
return
else:
self.populate_dependency_info(ops)
try:
self._sched_ifaces(filtered_ifacenames, ops)
finally:
if not self.DRYRUN and self.ADDONS_ENABLE:
self._save_state()
def query(self, ops, auto=False, allow_classes=None, ifacenames=None,
excludepats=None, printdependency=None,
format='native'):
""" query an interface """
if self.STATEMANAGER_ENABLE and ops[0] == 'query-savedstate':
return self.statemanager.dump_pretty(ifacenames)
self.STATEMANAGER_UPDATE = False
if auto:
self.logger.debug('setting flag ALL')
self.ALL = True
self.WITH_DEPENDS = True
if ops[0] == 'query-syntax':
self._modules_help()
return
elif ops[0] == 'query-running':
# create fake devices to all dependents that dont have config
map(lambda i: self.create_n_save_ifaceobj(i, self.NOCONFIG),
ifacenames)
else:
try:
self.read_iface_config()
except Exception:
raise
if ifacenames and ops[0] != 'query-running':
# If iface list is given, always check if iface is present
self._validate_ifaces(ifacenames)
# if iface list not given by user, assume all from config file
if not ifacenames: ifacenames = self.ifaceobjdict.keys()
# filter interfaces based on auto and allow classes
if ops[0] == 'query-running':
filtered_ifacenames = ifacenames
else:
filtered_ifacenames = [i for i in ifacenames
if self._iface_whitelisted(auto, allow_classes,
excludepats, i)]
if not filtered_ifacenames:
raise Exception('no ifaces found matching ' +
'given allow lists')
self.populate_dependency_info(ops, filtered_ifacenames)
if ops[0] == 'query-dependency' and printdependency:
self.print_dependency(filtered_ifacenames, printdependency)
return
if ops[0] == 'query':
return self.print_ifaceobjs_pretty(filtered_ifacenames, format)
elif ops[0] == 'query-raw':
return self.print_ifaceobjs_raw(filtered_ifacenames)
self._sched_ifaces(filtered_ifacenames, ops)
if ops[0] == 'query-checkcurr':
ret = self.print_ifaceobjscurr_pretty(filtered_ifacenames, format)
if ret != 0:
# if any of the object has an error, signal that silently
raise Exception('')
elif ops[0] == 'query-running':
self.print_ifaceobjsrunning_pretty(filtered_ifacenames, format)
return
def reload(self, upops, downops, auto=False, allow=None,
ifacenames=None, excludepats=None, usecurrentconfig=False):
""" reload interface config """
allow_classes = []
self.logger.debug('reloading interface config ..')
if auto:
self.ALL = True
self.WITH_DEPENDS = True
try:
self.read_iface_config()
except:
raise
# generate dependency graph of interfaces
self.populate_dependency_info(upops)
if (not usecurrentconfig and self.STATEMANAGER_ENABLE
and self.statemanager.ifaceobjdict):
# Save a copy of new iface objects and dependency_graph
new_ifaceobjdict = dict(self.ifaceobjdict)
new_dependency_graph = dict(self.dependency_graph)
# if old state is present, read old state and mark op for 'down'
# followed by 'up' aka: reload
# old interface config is read into self.ifaceobjdict
self.read_old_iface_config()
op = 'reload'
else:
# oldconfig not available, continue with 'up' with new config
op = 'up'
if not ifacenames: ifacenames = self.ifaceobjdict.keys()
if op == 'reload' and ifacenames:
filtered_ifacenames = [i for i in ifacenames
if self._iface_whitelisted(auto, allow_classes,
excludepats, i)]
# Generate the interface down list
# Interfaces that go into the down list:
# - interfaces that were present in last config and are not
# present in the new config
# - interfaces that were changed between the last and current
# config
#
ifacedownlist = []
for ifname, lastifaceobjlist in self.ifaceobjdict.items():
objidx = 0
# If interface is not present in the new file
# append it to the down list
newifaceobjlist = new_ifaceobjdict.get(ifname)
if not newifaceobjlist:
ifacedownlist.append(ifname)
continue
# If interface has changed between the current file
# and the last installed append it to the down list
if len(newifaceobjlist) != len(lastifaceobjlist):
ifacedownlist.append(ifname)
continue
# compare object list
for objidx in range(0, len(lastifaceobjlist)):
oldobj = lastifaceobjlist[objidx]
newobj = newifaceobjlist[objidx]
if not newobj.compare(oldobj):
ifacedownlist.append(ifname)
continue
if ifacedownlist:
self.logger.info('Executing down on interfaces: %s'
%str(ifacedownlist))
# reinitialize dependency graph
self.dependency_graph = OrderedDict({})
# Generate dependency info for old config
self.populate_dependency_info(downops, ifacedownlist)
self._sched_ifaces(ifacedownlist, downops)
else:
self.logger.debug('no interfaces to down ..')
# Now, run 'up' with new config dict
# reset statemanager update flag to default
self.ifaceobjdict = new_ifaceobjdict
self.dependency_graph = new_dependency_graph
ifacenames = self.ifaceobjdict.keys()
filtered_ifacenames = [i for i in ifacenames
if self._iface_whitelisted(auto, allow_classes,
excludepats, i)]
self.logger.info('Scheduling up on interfaces: %s'
%str(filtered_ifacenames))
self._sched_ifaces(filtered_ifacenames, upops)
if self.DRYRUN:
return
self._save_state()
def _pretty_print_ordered_dict(self, prefix, argdict):
outbuf = prefix + ' {\n'
for k, vlist in argdict.items():
outbuf += '\t%s : %s\n' %(k, str(vlist))
self.logger.debug(outbuf + '}')
def print_dependency(self, ifacenames, format):
""" prints iface dependency information """
if not ifacenames:
ifacenames = self.ifaceobjdict.keys()
if format == 'list':
for k,v in self.dependency_graph.items():
print '%s : %s' %(k, str(v))
elif format == 'dot':
indegrees = {}
map(lambda i: indegrees.update({i :
self.get_iface_refcnt(i)}),
self.dependency_graph.keys())
graph.generate_dots(self.dependency_graph, indegrees)
def print_ifaceobjs_raw(self, ifacenames):
""" prints raw lines for ifaces from config file """
for i in ifacenames:
for ifaceobj in self.get_ifaceobjs(i):
if (self.is_ifaceobj_builtin(ifaceobj) or
not ifaceobj.is_config_present()):
continue
ifaceobj.dump_raw(self.logger)
print '\n'
if self.WITH_DEPENDS and not self.ALL:
dlist = ifaceobj.lowerifaces
if not dlist: continue
self.print_ifaceobjs_raw(dlist)
def _get_ifaceobjs_pretty(self, ifacenames, ifaceobjs, running=False):
""" returns iface obj list """
for i in ifacenames:
for ifaceobj in self.get_ifaceobjs(i):
if ((not running and self.is_ifaceobj_noconfig(ifaceobj)) or
(running and not ifaceobj.is_config_present())):
continue
ifaceobjs.append(ifaceobj)
if self.WITH_DEPENDS and not self.ALL:
dlist = ifaceobj.lowerifaces
if not dlist: continue
self._get_ifaceobjs_pretty(dlist, ifaceobjs, running)
def print_ifaceobjs_pretty(self, ifacenames, format='native'):
""" pretty prints iface in format given by keyword arg format """
ifaceobjs = []
self._get_ifaceobjs_pretty(ifacenames, ifaceobjs)
if not ifaceobjs: return
if format == 'json':
print json.dumps(ifaceobjs, cls=ifaceJsonEncoder,
indent=4, separators=(',', ': '))
else:
map(lambda i: i.dump_pretty(), ifaceobjs)
def _get_ifaceobjscurr_pretty(self, ifacenames, ifaceobjs):
ret = 0
for i in ifacenames:
ifaceobjscurr = self.get_ifaceobjcurr(i)
if not ifaceobjscurr: continue
for ifaceobj in ifaceobjscurr:
if (ifaceobj.status == ifaceStatus.NOTFOUND or
ifaceobj.status == ifaceStatus.ERROR):
ret = 1
if self.is_ifaceobj_noconfig(ifaceobj):
continue
ifaceobjs.append(ifaceobj)
if self.WITH_DEPENDS and not self.ALL:
dlist = ifaceobj.lowerifaces
if not dlist: continue
dret = self._get_ifaceobjscurr_pretty(dlist, ifaceobjs)
if dret: ret = 1
return ret
def print_ifaceobjscurr_pretty(self, ifacenames, format='native'):
""" pretty prints current running state of interfaces with status.
returns 1 if any of the interface has an error,
else returns 0
"""
ifaceobjs = []
ret = self._get_ifaceobjscurr_pretty(ifacenames, ifaceobjs)
if not ifaceobjs: return
self.logger.debug(ifaceobjs)
if format == 'json':
print json.dumps(ifaceobjs, cls=ifaceJsonEncoder, indent=2,
separators=(',', ': '))
else:
map(lambda i: i.dump_pretty(with_status=True,
successstr=self.config.get('check_success_str',
_success_sym),
errorstr=self.config.get('check_error_str', _error_sym)),
ifaceobjs)
return ret
def print_ifaceobjsrunning_pretty(self, ifacenames, format='native'):
""" pretty prints iface running state """
ifaceobjs = []
self._get_ifaceobjs_pretty(ifacenames, ifaceobjs, running=True)
if not ifaceobjs: return
if format == 'json':
print json.dumps(ifaceobjs, cls=ifaceJsonEncoder, indent=2,
separators=(',', ': '))
else:
map(lambda i: i.dump_pretty(), ifaceobjs)
def _dump(self):
print 'ifupdown main object dump'
print self.pp.pprint(self.modules)
print self.pp.pprint(self.ifaceobjdict)
def _dump_ifaceobjs(self, ifacenames):
for i in ifacenames:
ifaceobjs = self.get_ifaceobjs(i)
for i in ifaceobjs:
i.dump(self.logger)
print '\n'