mirror of
				https://github.com/CumulusNetworks/ifupdown2.git
				synced 2024-05-06 15:54:50 +00:00 
			
		
		
		
	Ticket: None Reviewed By: Testing Done: Signed-off-by: Julien Fortin <julien@cumulusnetworks.com>
		
			
				
	
	
		
			1749 lines
		
	
	
		
			70 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			1749 lines
		
	
	
		
			70 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| #!/usr/bin/python
 | |
| #
 | |
| # Copyright 2014 Cumulus Networks, Inc. All rights reserved.
 | |
| # 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
 | |
| import ifupdown.statemanager as statemanager
 | |
| import ifupdown.ifupdownconfig as ifupdownConfig
 | |
| import ifupdown.ifupdownflags as ifupdownflags
 | |
| from networkinterfaces import *
 | |
| from iface import *
 | |
| from scheduler import *
 | |
| from collections import deque
 | |
| from collections import OrderedDict
 | |
| from graph import *
 | |
| from sets import Set
 | |
| 
 | |
| """
 | |
| .. module:: ifupdownmain
 | |
| :synopsis: main module for ifupdown package
 | |
| 
 | |
| .. moduleauthor:: Roopa Prabhu <roopa@cumulusnetworks.com>
 | |
| 
 | |
| """
 | |
| 
 | |
| _tickmark = u'\u2713'
 | |
| _crossmark = u'\u2717'
 | |
| _success_sym = '(%s)' %_tickmark
 | |
| _error_sym = '(%s)' %_crossmark
 | |
| 
 | |
| class ifupdownMainFlags():
 | |
|     IFACE_CLASS = False
 | |
|     COMPAT_EXEC_SCRIPTS = False
 | |
|     STATEMANAGER_ENABLE = True
 | |
|     STATEMANAGER_UPDATE = True
 | |
|     ADDONS_ENABLE = False
 | |
|     DELETE_DEPENDENT_IFACES_WITH_NOCONFIG = False
 | |
|     SCHED_SKIP_CHECK_UPPERIFACES = False
 | |
|     CHECK_SHARED_DEPENDENTS = True
 | |
| 
 | |
| class ifacePrivFlags():
 | |
|     # priv flags to mark iface objects
 | |
|     BUILTIN = False
 | |
|     NOCONFIG = False
 | |
| 
 | |
|     def __init__(self, builtin=False, noconfig=False):
 | |
|         self.BUILTIN = builtin
 | |
|         self.NOCONFIG = noconfig
 | |
|     
 | |
| class ifupdownMain(ifupdownBase):
 | |
|     """ ifupdown2 main class """
 | |
| 
 | |
|     scripts_dir='/etc/network'
 | |
|     addon_modules_dir='/usr/share/ifupdown2/addons'
 | |
|     addon_modules_configfile='/etc/network/ifupdown2/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):
 | |
|         # Skip link sets on ifaceobjs of type 'vlan' (used for l2 attrs).
 | |
|         # there is no real interface behind it
 | |
|         if ifaceobj.type == ifaceType.BRIDGE_VLAN:
 | |
|             return
 | |
|         if ((ifaceobj.link_kind & ifaceLinkKind.VRF) or
 | |
|             (ifaceobj.link_privflags & ifaceLinkPrivFlags.VRF_SLAVE)):
 | |
|             return
 | |
|         if (ifaceobj.addr_method and
 | |
|             ifaceobj.addr_method == 'manual'):
 | |
|             return
 | |
|         if self._delay_admin_state:
 | |
|             self._delay_admin_state_iface_queue.append(ifaceobj.name)
 | |
|             return
 | |
|         # If this object is a link slave, ie its link is controlled
 | |
|         # by its link master interface, then dont set the link state.
 | |
|         # But do allow user to change state of the link if the interface
 | |
|         # is already with its link master (hence the master check).
 | |
|         if ifaceobj.link_type == ifaceLinkType.LINK_SLAVE:
 | |
|             return
 | |
|         if not self.link_exists(ifaceobj.name):
 | |
|            return
 | |
|         self.link_up(ifaceobj.name)
 | |
| 
 | |
|     def run_down(self, ifaceobj):
 | |
|         if ((ifaceobj.link_kind & ifaceLinkKind.VRF) or
 | |
|             (ifaceobj.link_privflags & ifaceLinkPrivFlags.VRF_SLAVE)):
 | |
|             return
 | |
|         # Skip link sets on ifaceobjs of type 'vlan' (used for l2 attrs)
 | |
|         # there is no real interface behind it
 | |
|         if ifaceobj.type == ifaceType.BRIDGE_VLAN:
 | |
|             return
 | |
|         if (ifaceobj.addr_method and
 | |
|             ifaceobj.addr_method == 'manual'):
 | |
|             return
 | |
|         if self._delay_admin_state:
 | |
|             self._delay_admin_state_iface_queue.append(ifaceobj.name)
 | |
|             return
 | |
|         # If this object is a link slave, ie its link is controlled
 | |
|         # by its link master interface, then dont set the link state.
 | |
|         # But do allow user to change state of the link if the interface
 | |
|         # is already with its link master (hence the master check).
 | |
|         if ifaceobj.link_type == ifaceLinkType.LINK_SLAVE:
 | |
|            return
 | |
|         if not self.link_exists(ifaceobj.name):
 | |
|            return
 | |
|         self.link_down(ifaceobj.name)
 | |
| 
 | |
|     # 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 and (ifaceobj.priv_flags.BUILTIN or
 | |
|             ifaceobj.priv_flags.NOCONFIG)):
 | |
|             return
 | |
|         if self.flags.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',
 | |
|                  withdefaults=False):
 | |
|         """This member function initializes the ifupdownmain object.
 | |
| 
 | |
|         Kwargs:
 | |
|             config (dict):  config dict from /etc/network/ifupdown2/ifupdown2.conf
 | |
|             force (bool): force interface configuration
 | |
|             dryrun (bool): dryrun interface configuration
 | |
|             withdepends (bool): apply interface configuration on all depends
 | |
|             interfacesfile (str): interfaces file. default is /etc/network/interfaces
 | |
|             interfacesfileformat (str): default is 'native'. Other choices are 'json'
 | |
| 
 | |
|         Raises:
 | |
|             AttributeError, KeyError """
 | |
| 
 | |
|         self.logger = logging.getLogger('ifupdown')
 | |
|         ifupdownflags.flags.FORCE = force
 | |
|         ifupdownflags.flags.DRYRUN = dryrun
 | |
|         ifupdownflags.flags.WITHDEFAULTS = withdefaults
 | |
|         ifupdownflags.flags.NOWAIT = nowait
 | |
|         ifupdownflags.flags.PERFMODE = perfmode
 | |
|         ifupdownflags.flags.CACHE = cache
 | |
|         ifupdownflags.flags.WITH_DEPENDS = withdepends
 | |
| 
 | |
|         # Can be used to provide hints for caching
 | |
|         ifupdownflags.flags.CACHE_FLAGS = 0x0
 | |
| 
 | |
|         self.flags = ifupdownMainFlags()
 | |
| 
 | |
|         self.flags.STATEMANAGER_ENABLE = statemanager_enable
 | |
|         self.interfacesfile = interfacesfile
 | |
|         self.interfacesfileiobuf = interfacesfileiobuf
 | |
|         self.interfacesfileformat = interfacesfileformat
 | |
|         self.config = config
 | |
|         self.logger.debug(self.config)
 | |
|         self.blacklisted_ifaces_present = False
 | |
| 
 | |
|         self.type = ifaceType.UNKNOWN
 | |
| 
 | |
|         self.flags.DELETE_DEPENDENT_IFACES_WITH_NOCONFIG = False
 | |
|         self.flags.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.flags.COMPAT_EXEC_SCRIPTS:
 | |
|             self.load_scripts(self.scripts_dir)
 | |
|         self.dependency_graph = OrderedDict({})
 | |
| 
 | |
|         self._cache_no_repeats = {}
 | |
| 
 | |
|         if self.flags.STATEMANAGER_ENABLE:
 | |
|             try:
 | |
|                 self.statemanager = statemanager.statemanager_api
 | |
|                 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.flags.STATEMANAGER_UPDATE = False
 | |
|         self._delay_admin_state = True if self.config.get(
 | |
|                             'delay_admin_state_change', '0') == '1' else False
 | |
|         self._delay_admin_state_iface_queue = []
 | |
|         if self._delay_admin_state:
 | |
|             self.logger.info('\'delay_admin_state_change\' is set. admin ' +
 | |
|                              'state changes will be delayed till the end.')
 | |
| 
 | |
|         self._link_master_slave = True if self.config.get(
 | |
|                       'link_master_slave', '0') == '1' else False
 | |
|         if self._link_master_slave:
 | |
|             self.logger.info('\'link_master_slave\' is set. slave admin ' +
 | |
|                              'state changes will be delayed till the ' +
 | |
|                              'masters admin state change.')
 | |
| 
 | |
|         # squash iface objects for same interface both internal and
 | |
|         # external representation. It is off by default.
 | |
|         self._ifaceobj_squash = True if self.config.get(
 | |
|                             'ifaceobj_squash', '0') == '1' else False
 | |
| 
 | |
|         # squash iface objects for same interface internal
 | |
|         # representation only. External representation as seen by ifquery
 | |
|         # will continue to see multiple iface stanzas if it was specified
 | |
|         # that way by the user. It is on by default.
 | |
|         self._ifaceobj_squash_internal = True if self.config.get(
 | |
|                             'ifaceobj_squash_internal', '1') == '1' else False
 | |
| 
 | |
|         # initialize global config object with config passed by the user
 | |
|         # This makes config available to addon modules
 | |
|         ifupdownConfig.config = self.config
 | |
| 
 | |
|     def link_master_slave_ignore_error(self, errorstr):
 | |
|         # If link master slave flag is set, 
 | |
|         # there may be cases where the lowerdev may not be
 | |
|         # up resulting in 'Network is down' error
 | |
|         # This can happen if the lowerdev is a LINK_SLAVE
 | |
|         # of another interface which is not up yet
 | |
|         # example of such a case:
 | |
|         #   bringing up a vlan on a bond interface and the bond
 | |
|         #   is a LINK_SLAVE of a bridge (in other words the bond is
 | |
|         #   part of a bridge) which is not up yet
 | |
|         if self._link_master_slave:
 | |
|            if 'Network is down':
 | |
|               return True
 | |
|         return False
 | |
| 
 | |
|     def get_ifaceobjs(self, ifacename):
 | |
|         return self.ifaceobjdict.get(ifacename)
 | |
| 
 | |
|     def get_ifaceobjs_saved(self, ifacename):
 | |
|         """ Return ifaceobjects from statemanager """
 | |
|         if self.flags.STATEMANAGER_ENABLE:
 | |
|            return self.statemanager.get_ifaceobjs(ifacename)
 | |
|         else:
 | |
|            None
 | |
| 
 | |
|     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 must_follow_upperifaces(self, ifacename):
 | |
|         #
 | |
|         # XXX: This bleeds the knowledge of iface
 | |
|         # types in the infrastructure module.
 | |
|         # Cant think of a better fix at the moment.
 | |
|         # In future maybe the module can set a flag
 | |
|         # to indicate if we should follow upperifaces
 | |
|         #
 | |
|         ifaceobj = self.get_ifaceobj_first(ifacename)
 | |
|         if ifaceobj.type == ifaceType.BRIDGE_VLAN:
 | |
|             return False
 | |
|         return True
 | |
| 
 | |
|     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 not self._link_master_slave:
 | |
|             ifaceobj.link_type = ifaceLinkType.LINK_NA
 | |
|         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.type = ifaceobj.type
 | |
|         ifaceobjcurr.lowerifaces = ifaceobj.lowerifaces
 | |
|         ifaceobjcurr.priv_flags = copy.deepcopy(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>
 | |
|         """
 | |
|         if (ifaceobj.priv_flags and ifaceobj.priv_flags.BUILTIN):
 | |
|             return True
 | |
|         return False
 | |
| 
 | |
|     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 and ifaceobj.priv_flags.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 check_shared_dependents(self, ifaceobj, dlist):
 | |
|         """ ABSOLETE: Check if dlist intersects with any other
 | |
|             interface with slave dependents.
 | |
|             example: bond and bridges.
 | |
|             This function logs such errors """
 | |
|         setdlist = Set(dlist)
 | |
|         for ifacename, ifacedlist in self.dependency_graph.items():
 | |
|             if not ifacedlist:
 | |
|                 continue
 | |
|             check_depends = False
 | |
|             iobjs = self.get_ifaceobjs(ifacename)
 | |
|             if not iobjs:
 | |
|                 continue
 | |
|             for i in iobjs:
 | |
|                 if (i.dependency_type == ifaceDependencyType.MASTER_SLAVE):
 | |
|                     check_depends = True
 | |
|             if check_depends:
 | |
|                 common = Set(ifacedlist).intersection(setdlist)
 | |
|                 if common:
 | |
|                     self.logger.error('misconfig..?. iface %s and %s '
 | |
|                             %(ifaceobj.name, ifacename) +
 | |
|                             'seem to share dependents/ports %s' %str(list(common)))
 | |
| 
 | |
|     def _set_iface_role(self, ifaceobj, role, upperifaceobj):
 | |
|         if (self.flags.CHECK_SHARED_DEPENDENTS and
 | |
|             (ifaceobj.role & ifaceRole.SLAVE) and
 | |
|             (role == ifaceRole.SLAVE) and (upperifaceobj.role == ifaceRole.MASTER)):
 | |
| 		self.logger.error("misconfig..? %s %s is enslaved to multiple interfaces %s"
 | |
|                                   %(ifaceobj.name,
 | |
|                                     ifaceLinkPrivFlags.get_all_str(ifaceobj.link_privflags), str(ifaceobj.upperifaces)))
 | |
|                 ifaceobj.set_status(ifaceStatus.ERROR)
 | |
|                 return
 | |
|         ifaceobj.role = role
 | |
| 
 | |
|     def _set_iface_role_n_kind(self, ifaceobj, upperifaceobj):
 | |
| 
 | |
|         if (upperifaceobj.link_kind & ifaceLinkKind.BOND):
 | |
|             self._set_iface_role(ifaceobj, ifaceRole.SLAVE, upperifaceobj)
 | |
|             ifaceobj.link_privflags |= ifaceLinkPrivFlags.BOND_SLAVE
 | |
| 
 | |
|         if (upperifaceobj.link_kind & ifaceLinkKind.BRIDGE):
 | |
|             self._set_iface_role(ifaceobj, ifaceRole.SLAVE, upperifaceobj)
 | |
|             ifaceobj.link_privflags |= ifaceLinkPrivFlags.BRIDGE_PORT
 | |
| 
 | |
|         if (ifaceobj.link_kind & ifaceLinkKind.VXLAN) \
 | |
|                 and (upperifaceobj.link_kind & ifaceLinkKind.BRIDGE):
 | |
|             upperifaceobj.link_privflags |= ifaceLinkPrivFlags.BRIDGE_VXLAN
 | |
| 
 | |
|         # vrf masters get processed after slaves, which means
 | |
|         # check both link_kind vrf and vrf slave
 | |
|         if ((upperifaceobj.link_kind & ifaceLinkKind.VRF) or
 | |
|             (ifaceobj.link_privflags & ifaceLinkPrivFlags.VRF_SLAVE)):
 | |
|             self._set_iface_role(ifaceobj, ifaceRole.SLAVE, upperifaceobj)
 | |
|             ifaceobj.link_privflags |= ifaceLinkPrivFlags.VRF_SLAVE
 | |
|         if self._link_master_slave:
 | |
|             if upperifaceobj.link_type == ifaceLinkType.LINK_MASTER:
 | |
|                 ifaceobj.link_type = ifaceLinkType.LINK_SLAVE
 | |
|         else:
 | |
|             upperifaceobj.link_type = ifaceLinkType.LINK_NA
 | |
|             ifaceobj.link_type = ifaceLinkType.LINK_NA
 | |
| 
 | |
|     def dump_iface_dependency_info(self):
 | |
|         """ debug funtion to print raw dependency 
 | |
|         info - lower and upper devices"""
 | |
| 
 | |
|         for ifacename, ifaceobjs in self.ifaceobjdict.iteritems():
 | |
|             iobj = ifaceobjs[0]
 | |
|             self.logger.info("%s: refcnt: %d, lower: %s, upper: %s" %(ifacename,
 | |
|                              self.get_iface_refcnt(ifacename),
 | |
|                              str(iobj.lowerifaces) if iobj.lowerifaces else [],
 | |
|                              str(iobj.upperifaces) if iobj.upperifaces else []))
 | |
| 
 | |
| 
 | |
|     def preprocess_dependency_list(self, upperifaceobj, 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:
 | |
|                 ni = None
 | |
|                 if self.is_iface_builtin_byname(d):
 | |
|                     ni = self.create_n_save_ifaceobj(d,
 | |
|                             ifacePrivFlags(True, True), True)
 | |
|                 elif not self.flags.DELETE_DEPENDENT_IFACES_WITH_NOCONFIG:
 | |
|                     ni = self.create_n_save_ifaceobj(d,
 | |
|                                     ifacePrivFlags(False, True), True)
 | |
|                 else:
 | |
|                     del_list.append(d)
 | |
|                 if ni:
 | |
|                     ni.add_to_upperifaces(upperifaceobj.name)
 | |
|                     self._set_iface_role_n_kind(ni, upperifaceobj)
 | |
|             else:
 | |
|                 for di in dilist:
 | |
|                     di.inc_refcnt()
 | |
|                     di.add_to_upperifaces(upperifaceobj.name)
 | |
|                     self._set_iface_role_n_kind(di, upperifaceobj)
 | |
|         for d in del_list:
 | |
|             dlist.remove(d)
 | |
| 
 | |
|     def preprocess_upperiface(self, lowerifaceobj, ulist, ops):
 | |
|         for u in ulist:
 | |
|             if (lowerifaceobj.upperifaces and
 | |
|                 u in lowerifaceobj.upperifaces):
 | |
|                 continue
 | |
|             lowerifaceobj.add_to_upperifaces(u)
 | |
|             uifacelist = self.get_ifaceobjs(u)
 | |
|             if uifacelist:
 | |
|                 for ui in uifacelist:
 | |
|                     lowerifaceobj.inc_refcnt()
 | |
|                     self._set_iface_role_n_kind(lowerifaceobj, ui)
 | |
|                     ui.add_to_lowerifaces(lowerifaceobj.name)
 | |
| 
 | |
|     def query_lowerifaces(self, ifaceobj, ops, ifacenames, type=None):
 | |
|         """ Gets iface dependents by calling into respective modules """
 | |
|         ret_dlist = []
 | |
| 
 | |
|         # Get dependents for interface by querying respective modules
 | |
|         for module in self.modules.values():
 | |
|             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,
 | |
|                                         ifacenames)
 | |
|             except Exception, e:
 | |
|                 self.logger.warn('%s: error getting dependent interfaces (%s)'
 | |
|                         %(ifaceobj.name, str(e)))
 | |
|                 dlist = None
 | |
|                 pass
 | |
|             if dlist: ret_dlist.extend(dlist)
 | |
|         return list(set(ret_dlist))
 | |
| 
 | |
|     def query_upperifaces(self, ifaceobj, ops, ifacenames, type=None):
 | |
|         """ Gets iface upperifaces by calling into respective modules """
 | |
|         ret_ulist = []
 | |
| 
 | |
|         # Get upperifaces for interface by querying respective modules
 | |
|         for module in self.modules.values():
 | |
|             try:
 | |
|                 if ops[0] == 'query-running':
 | |
|                     if (not hasattr(module,
 | |
|                         'get_upper_ifacenames_running')):
 | |
|                         continue
 | |
|                     ulist = module.get_upper_ifacenames_running(ifaceobj)
 | |
|                 else:
 | |
|                     if (not hasattr(module, 'get_upper_ifacenames')):
 | |
|                         continue
 | |
|                     ulist = module.get_upper_ifacenames(ifaceobj, ifacenames)
 | |
|             except Exception, e:
 | |
|                 self.logger.warn('%s: error getting upper interfaces (%s)'
 | |
|                                  %(ifaceobj.name, str(e)))
 | |
|                 ulist = None
 | |
|                 pass
 | |
|             if ulist: ret_ulist.extend(ulist)
 | |
|         return list(set(ret_ulist))
 | |
| 
 | |
|     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
 | |
|             ulist = None
 | |
|             ifaceobjs = self.get_ifaceobjs(i)
 | |
|             if not ifaceobjs:
 | |
|                 continue
 | |
|             dependents_processed = False
 | |
| 
 | |
|             # Store all dependency info in the first ifaceobj
 | |
|             # but get dependency info from all ifaceobjs
 | |
|             ifaceobj = ifaceobjs[0]
 | |
|             for iobj in ifaceobjs:
 | |
|                 ulist = self.query_upperifaces(iobj, ops, ifacenames)
 | |
|                 if iobj.lowerifaces:
 | |
|                     dependents_processed = True
 | |
|                     break
 | |
|                 dlist = self.query_lowerifaces(iobj, ops, ifacenames)
 | |
|                 if dlist:
 | |
|                    break
 | |
|             if ulist:
 | |
|                 self.preprocess_upperiface(ifaceobj, ulist, ops)
 | |
|             if dependents_processed:
 | |
|                 continue
 | |
|             if dlist:
 | |
|                 self.preprocess_dependency_list(ifaceobj,
 | |
|                                                 dlist, ops)
 | |
|                 ifaceobj.lowerifaces = dlist
 | |
|                 [iqueue.append(d) for d in dlist]
 | |
|             #if not self.dependency_graph.get(i):
 | |
|             #    self.dependency_graph[i] = dlist
 | |
| 
 | |
|         for i in self.ifaceobjdict.keys():
 | |
|             iobj = self.get_ifaceobj_first(i)
 | |
|             if iobj.lowerifaces:
 | |
|                 self.dependency_graph[i] = iobj.lowerifaces
 | |
|             else:
 | |
|                 self.dependency_graph[i] = []
 | |
| 
 | |
|         if not self.blacklisted_ifaces_present:
 | |
|             return
 | |
| 
 | |
|         # Walk through the dependency graph and remove blacklisted
 | |
|         # interfaces that were picked up as dependents
 | |
|         for i in self.dependency_graph.keys():
 | |
|             ifaceobj = self.get_ifaceobj_first(i)
 | |
|             if not ifaceobj:
 | |
|                 continue
 | |
| 
 | |
|             if ifaceobj.blacklisted and not ifaceobj.upperifaces:
 | |
|                 # if blacklisted and was not picked up as a
 | |
|                 # dependent of a upper interface, delete the
 | |
|                 # interface from the dependency graph
 | |
|                 dlist = ifaceobj.lowerifaces
 | |
|                 if dlist:
 | |
|                     for d in dlist:
 | |
|                         difaceobjs = self.get_ifaceobjs(d)
 | |
|                         if not difaceobjs:
 | |
|                             continue
 | |
|                         try:
 | |
|                             for d in difaceobjs:
 | |
|                                 d.dec_refcnt()
 | |
|                                 d.upperifaces.remove(i)
 | |
|                         except:
 | |
|                             self.logger.debug('error removing %s from %s upperifaces' %(i, d))
 | |
|                             pass
 | |
|                 self.logger.debug("populate_dependency_info: deleting blacklisted interface %s" %i)
 | |
|                 del self.dependency_graph[i]
 | |
|                 continue
 | |
| 
 | |
|     def _check_config_no_repeats(self, ifaceobj):
 | |
|         """ check if object has an attribute that is
 | |
|         restricted to a single object in the system.
 | |
|         if yes, warn and return """
 | |
|         for k,v in self._cache_no_repeats.items():
 | |
|             iv = ifaceobj.config.get(k)
 | |
|             if iv and iv[0] == v:
 | |
|                 self.logger.error('ignoring interface %s. ' %ifaceobj.name +
 | |
|                         'Only one object with attribute ' +
 | |
|                         '\'%s %s\' allowed.' %(k, v))
 | |
|                 return True
 | |
|         for k, v in self.config.get('no_repeats', {}).items():
 | |
|             iv = ifaceobj.config.get(k)
 | |
|             if iv and iv[0] == v:
 | |
|                 self._cache_no_repeats[k] = v
 | |
|         return False
 | |
| 
 | |
|     def _save_iface_squash(self, ifaceobj):
 | |
|         """ squash ifaceobjects belonging to same iface
 | |
|         into a single object """
 | |
|         if self._check_config_no_repeats(ifaceobj):
 | |
|            return
 | |
|         ifaceobj.priv_flags = ifacePrivFlags()
 | |
|         if not self._link_master_slave:
 | |
|            ifaceobj.link_type = ifaceLinkType.LINK_NA
 | |
|         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
 | |
|         if ifaceobj.type == ifaceType.BRIDGE_VLAN:
 | |
|             self.ifaceobjdict[ifaceobj.name].append(ifaceobj)
 | |
|         else:
 | |
|             currentifaceobjlist[0].squash(ifaceobj)
 | |
| 
 | |
|     def _save_iface(self, ifaceobj):
 | |
|         if self._check_config_no_repeats(ifaceobj):
 | |
|            return
 | |
|         ifaceobj.priv_flags = ifacePrivFlags()
 | |
|         if not self._link_master_slave:
 | |
|            ifaceobj.link_type = ifaceLinkType.LINK_NA
 | |
|         currentifaceobjlist = self.ifaceobjdict.get(ifaceobj.name)
 | |
|         if not currentifaceobjlist:
 | |
|             self.ifaceobjdict[ifaceobj.name]= [ifaceobj]
 | |
|             if not self._ifaceobj_squash:
 | |
|                 ifaceobj.flags |= ifaceobj.YOUNGEST_SIBLING
 | |
|             return
 | |
|         if ifaceobj.compare(currentifaceobjlist[0]):
 | |
|             self.logger.warn('duplicate interface %s found' %ifaceobj.name)
 | |
|             return
 | |
|         if currentifaceobjlist[0].type == ifaceobj.type:
 | |
|             currentifaceobjlist[0].flags |= ifaceobj.HAS_SIBLINGS
 | |
|             ifaceobj.flags |= ifaceobj.HAS_SIBLINGS
 | |
|         # clear the OLDEST_SIBLING from all the siblings
 | |
|         for iface in self.ifaceobjdict[ifaceobj.name]:
 | |
|             iface.flags &= ~ifaceobj.OLDEST_SIBLING
 | |
|         # current sibling is the oldest
 | |
|         ifaceobj.flags |= ifaceobj.OLDEST_SIBLING
 | |
|         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:
 | |
|                 a = attrsdict.get(attrname)
 | |
|                 if a:
 | |
|                     if a.get('deprecated'):
 | |
|                         newa = a.get('new-attribute')
 | |
|                         if newa:
 | |
|                             self.logger.warn('attribute %s is deprecated. use %s instead.' %(attrname, newa))
 | |
|                         else:
 | |
|                             self.logger.warn('attribute %s is deprecated.'
 | |
|                                              %attrname)
 | |
|                     return True
 | |
|             except AttributeError:
 | |
|                 pass
 | |
|         return False
 | |
| 
 | |
|     def _ifaceobj_syntax_checker(self, ifaceobj):
 | |
|         ret = True
 | |
|         for attrname, attrvalue in ifaceobj.config.items():
 | |
|             found = False
 | |
|             for k, v in self.module_attrs.items():
 | |
|                 if v and v.get('attrs', {}).get(attrname):
 | |
|                     found = True
 | |
|                     break
 | |
|             if not found:
 | |
|                 ret = False
 | |
|                 self.logger.warn('%s: unsupported attribute \'%s\'' \
 | |
|                                  % (ifaceobj.name, attrname))
 | |
|                 continue
 | |
|         return ret
 | |
| 
 | |
|     def read_iface_config(self):
 | |
|         """ Reads default network interface config /etc/network/interfaces. """
 | |
|         ret = True
 | |
|         nifaces = networkInterfaces(self.interfacesfile,
 | |
|                         self.interfacesfileiobuf,
 | |
|                         self.interfacesfileformat,
 | |
|                         template_engine=self.config.get('template_engine'),
 | |
|                 template_lookuppath=self.config.get('template_lookuppath'))
 | |
|         if self._ifaceobj_squash or self._ifaceobj_squash_internal:
 | |
|             nifaces.subscribe('iface_found', self._save_iface_squash)
 | |
|         else:
 | |
|             nifaces.subscribe('iface_found', self._save_iface)
 | |
|         nifaces.subscribe('validateifaceattr',
 | |
|                           self._iface_configattr_syntax_checker)
 | |
|         nifaces.subscribe('validateifaceobj', self._ifaceobj_syntax_checker)
 | |
|         nifaces.load()
 | |
|         if nifaces.errors or nifaces.warns:
 | |
|             ret = False
 | |
|         return ret
 | |
| 
 | |
|     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:
 | |
|                 try:
 | |
|                     litems = l.strip(' \n\t\r').split(',')
 | |
|                     if not litems or len(litems) < 2:
 | |
|                         continue
 | |
|                     operation = litems[0]
 | |
|                     mname = litems[1]
 | |
|                     self.module_ops[operation].append(mname)
 | |
|                 except Exception, e:
 | |
|                     self.logger.warn('error reading line \'%s\' %s:' %(l, str(e)))
 | |
|                     continue
 | |
| 
 | |
|     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()
 | |
|                         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: %s-%s'
 | |
|                               %(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, skipupperifaces=False,
 | |
|                       followdependents=True, sort=False):
 | |
|         self.logger.debug('scheduling \'%s\' for %s'
 | |
|                           %(str(ops), str(ifacenames)))
 | |
|         self._pretty_print_ordered_dict('dependency graph',
 | |
|                     self.dependency_graph)
 | |
|         ifaceScheduler.sched_ifaces(self, ifacenames, ops,
 | |
|                         dependency_graph=self.dependency_graph,
 | |
|                         order=ifaceSchedulerFlags.INORDER
 | |
|                             if 'down' in ops[0]
 | |
|                                 else ifaceSchedulerFlags.POSTORDER,
 | |
|                         followdependents=followdependents,
 | |
|                         skipupperifaces=skipupperifaces,
 | |
|                         sort=True if (sort or self.flags.IFACE_CLASS) else False)
 | |
|         return ifaceScheduler.get_sched_status()
 | |
| 
 | |
|     def _render_ifacename(self, ifacename):
 | |
|         new_ifacenames = []
 | |
|         vlan_match = re.match("^([\d]+)-([\d]+)", ifacename)
 | |
|         if vlan_match:
 | |
|             vlan_groups = vlan_match.groups()
 | |
|             if vlan_groups[0] and vlan_groups[1]:
 | |
|                 [new_ifacenames.append('%d' %v)
 | |
|                     for v in range(int(vlan_groups[0]),
 | |
|                             int(vlan_groups[1])+1)]
 | |
|         return new_ifacenames
 | |
| 
 | |
|     def _preprocess_ifacenames(self, ifacenames):
 | |
|         """ validates interface list for config existance.
 | |
|        
 | |
|         returns -1 if one or more interface not found. else, returns 0
 | |
| 
 | |
|         """
 | |
|         new_ifacenames = []
 | |
|         err_iface = ''
 | |
|         for i in ifacenames:
 | |
|             ifaceobjs = self.get_ifaceobjs(i)
 | |
|             if not ifaceobjs:
 | |
|                 # if name not available, render interface name and check again
 | |
|                 rendered_ifacenames = utils.expand_iface_range(i)
 | |
|                 if rendered_ifacenames:
 | |
|                     for ri in rendered_ifacenames:
 | |
|                         ifaceobjs = self.get_ifaceobjs(ri)
 | |
|                         if not ifaceobjs:
 | |
|                             err_iface += ' ' + ri
 | |
|                         else:
 | |
|                             new_ifacenames.append(ri)
 | |
|                 else:
 | |
|                     err_iface += ' ' + i
 | |
|             else:
 | |
|                 new_ifacenames.append(i)
 | |
|         if err_iface:
 | |
|             raise Exception('cannot find interfaces:%s' %err_iface)
 | |
|         return new_ifacenames 
 | |
| 
 | |
|     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.
 | |
| 
 | |
|         """
 | |
| 
 | |
|         ret = True
 | |
| 
 | |
| 	    # Check if interface matches the exclude patter
 | |
|         if excludepats:
 | |
|             for e in excludepats:
 | |
|                 if re.search(e, ifacename):
 | |
|                     ret = False
 | |
|         ifaceobjs = self.get_ifaceobjs(ifacename)
 | |
|         if not ifaceobjs:
 | |
|             if ret:
 | |
|                 self.logger.debug('iface %s' %ifacename + ' not found')
 | |
|             return ret
 | |
|         # If matched exclude pattern, return false
 | |
|         if not ret:
 | |
|             for i in ifaceobjs:
 | |
|                 i.blacklisted = True
 | |
|                 self.blacklisted_ifaces_present = True
 | |
|             return ret
 | |
|         # Check if interface belongs to the class
 | |
|         # the user is interested in, if not return false
 | |
|         if allow_classes:
 | |
|             ret = False
 | |
|             for i in ifaceobjs:
 | |
|                 if i.classes:
 | |
|                     common = Set([allow_classes]).intersection(
 | |
|                                 Set(i.classes))
 | |
|                     if common:
 | |
|                         ret = True
 | |
|             if not ret:
 | |
|                 # If a class was requested and interface does not belong
 | |
|                 # to the class, only then mark the ifaceobjs as blacklisted
 | |
|                 self.blacklisted_ifaces_present = True
 | |
|                 for i in ifaceobjs:
 | |
|                     i.blacklisted = True
 | |
|             return ret
 | |
|         # If the user has requested auto class, check if the interface
 | |
|         # is marked auto
 | |
|         if auto:
 | |
|             ret = False
 | |
|             for i in ifaceobjs:
 | |
|                 if i.auto:
 | |
|                     ret = True
 | |
|             if not ret:
 | |
|                 # If auto was requested and interface was not marked auto,
 | |
|                 # only then mark all of them as blacklisted
 | |
|                 self.blacklisted_ifaces_present = True
 | |
|                 for i in ifaceobjs:
 | |
|                     i.blacklisted = True
 | |
|         return ret
 | |
| 
 | |
|     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.flags.STATEMANAGER_ENABLE or
 | |
|             not self.flags.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 set_type(self, type):
 | |
|         if type == 'iface':
 | |
|             self.type = ifaceType.IFACE
 | |
|         elif type == 'vlan':
 | |
|             self.type = ifaceType.BRIDGE_VLAN
 | |
|         else:
 | |
|             self.type = ifaceType.UNKNOWN
 | |
| 
 | |
|     def _process_delay_admin_state_queue(self, op):
 | |
|         if not self._delay_admin_state_iface_queue:
 | |
|            return
 | |
|         if op == 'up':
 | |
|            func = self.link_up
 | |
|         elif op == 'down':
 | |
|            func = self.link_down
 | |
|         else:
 | |
|            return
 | |
|         for i in self._delay_admin_state_iface_queue:
 | |
|             try:
 | |
|                 if self.link_exists(i):
 | |
|                    func(i)
 | |
|             except Exception, e:
 | |
|                 self.logger.warn(str(e))
 | |
|                 pass
 | |
| 
 | |
|     def up(self, ops, auto=False, allow_classes=None, ifacenames=None,
 | |
|            excludepats=None, printdependency=None, syntaxcheck=False,
 | |
|            type=None, skipupperifaces=False):
 | |
|         """This brings the interface(s) up
 | |
|         
 | |
|         Args:
 | |
|             ops (list): list of ops to perform on the interface(s).
 | |
|             Eg: ['pre-up', 'up', 'post-up'
 | |
| 
 | |
|         Kwargs:
 | |
|             auto (bool): act on interfaces marked auto
 | |
|             allow_classes (list): act on interfaces belonging to classes in the list
 | |
|             ifacenames (list): act on interfaces specified in this list
 | |
|             excludepats (list): list of patterns of interfaces to exclude
 | |
|             syntaxcheck (bool): only perform syntax check
 | |
|         """
 | |
| 
 | |
|         self.set_type(type)
 | |
| 
 | |
|         if allow_classes:
 | |
|             self.flags.IFACE_CLASS = True
 | |
|         if not self.flags.ADDONS_ENABLE:
 | |
|             self.flags.STATEMANAGER_UPDATE = False
 | |
|         if auto:
 | |
|             ifupdownflags.flags.ALL = True
 | |
|             ifupdownflags.flags.WITH_DEPENDS = True
 | |
|         try:
 | |
|             iface_read_ret = self.read_iface_config()
 | |
|         except Exception:
 | |
|             raise
 | |
| 
 | |
|         if ifacenames:
 | |
|             ifacenames = self._preprocess_ifacenames(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)
 | |
| 
 | |
|         # If only syntax check was requested, return here.
 | |
|         # return here because we want to make sure most
 | |
|         # errors above are caught and reported.
 | |
|         if syntaxcheck:
 | |
|             if not iface_read_ret:
 | |
|                 raise Exception()
 | |
|             elif self._any_iface_errors(filtered_ifacenames):
 | |
|                 raise Exception()
 | |
|             return
 | |
| 
 | |
|         ret = None
 | |
|         try:
 | |
|             ret = self._sched_ifaces(filtered_ifacenames, ops,
 | |
|                                      skipupperifaces=skipupperifaces,
 | |
|                                      followdependents=True
 | |
|                                      if ifupdownflags.flags.WITH_DEPENDS
 | |
|                                      else False)
 | |
|         finally:
 | |
|             self._process_delay_admin_state_queue('up')
 | |
|             if not ifupdownflags.flags.DRYRUN and self.flags.ADDONS_ENABLE:
 | |
|                 self._save_state()
 | |
| 
 | |
|         if not iface_read_ret or not ret:
 | |
|             raise Exception()
 | |
| 
 | |
|     def down(self, ops, auto=False, allow_classes=None, ifacenames=None,
 | |
|              excludepats=None, printdependency=None, usecurrentconfig=False,
 | |
|              type=None):
 | |
|         """ down an interface """
 | |
| 
 | |
|         self.set_type(type)
 | |
| 
 | |
|         if allow_classes:
 | |
|             self.flags.IFACE_CLASS = True
 | |
|         if not self.flags.ADDONS_ENABLE:
 | |
|             self.flags.STATEMANAGER_UPDATE = False
 | |
|         if auto:
 | |
|             ifupdownflags.flags.ALL = True
 | |
|             ifupdownflags.flags.WITH_DEPENDS = True
 | |
|         # For down we need to look at old state, unless usecurrentconfig
 | |
|         # is set
 | |
|         if (not usecurrentconfig and self.flags.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:
 | |
|                ifacenames = self._preprocess_ifacenames(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 ' +
 | |
|                     '(or interfaces were probably never up ?)')
 | |
| 
 | |
|         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,
 | |
|                                followdependents=True
 | |
|                                if ifupdownflags.flags.WITH_DEPENDS else False)
 | |
|         finally:
 | |
|             self._process_delay_admin_state_queue('down')
 | |
|             if not ifupdownflags.flags.DRYRUN and self.flags.ADDONS_ENABLE:
 | |
|                 self._save_state()
 | |
| 
 | |
|     def query(self, ops, auto=False, format_list=False, allow_classes=None,
 | |
|               ifacenames=None,
 | |
|               excludepats=None, printdependency=None,
 | |
|               format='native', type=None):
 | |
|         """ query an interface """
 | |
| 
 | |
|         self.set_type(type)
 | |
| 
 | |
|         # Let us forget internal squashing when it comes to 
 | |
|         # ifquery. It can surprise people relying of ifquery
 | |
|         # output
 | |
|         self._ifaceobj_squash_internal = False
 | |
| 
 | |
|         if allow_classes:
 | |
|             self.flags.IFACE_CLASS = True
 | |
|         if self.flags.STATEMANAGER_ENABLE and ops[0] == 'query-savedstate':
 | |
|             return self.statemanager.dump_pretty(ifacenames)
 | |
|         self.flags.STATEMANAGER_UPDATE = False
 | |
|         if auto:
 | |
|             self.logger.debug('setting flag ALL')
 | |
|             ifupdownflags.flags.ALL = True
 | |
|             ifupdownflags.flags.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,
 | |
|                                 ifacePrivFlags(False, True)), 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
 | |
|            ifacenames = self._preprocess_ifacenames(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)
 | |
|         if ops[0] == 'query-dependency' and printdependency:
 | |
|             self.print_dependency(filtered_ifacenames, printdependency)
 | |
|             return
 | |
| 
 | |
|         if format_list and (ops[0] == 'query' or ops[0] == 'query-raw'):
 | |
|             return self.print_ifaceobjs_list(filtered_ifacenames)
 | |
| 
 | |
|         if ops[0] == 'query' and not ifupdownflags.flags.WITHDEFAULTS:
 | |
|             return self.print_ifaceobjs_pretty(filtered_ifacenames, format)
 | |
|         elif ops[0] == 'query-raw':
 | |
|             return self.print_ifaceobjs_raw(filtered_ifacenames)
 | |
| 
 | |
|         ret = self._sched_ifaces(filtered_ifacenames, ops,
 | |
|                            followdependents=True
 | |
|                            if ifupdownflags.flags.WITH_DEPENDS else False)
 | |
| 
 | |
|         if ops[0] == 'query' and ifupdownflags.flags.WITHDEFAULTS:
 | |
|             return self.print_ifaceobjs_pretty(filtered_ifacenames, format)
 | |
|         elif 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_currentlyup(self, upops, downops, auto=False, allow=None,
 | |
|             ifacenames=None, excludepats=None, usecurrentconfig=False,
 | |
|             syntaxcheck=False, **extra_args):
 | |
|         """ reload currently up interfaces """
 | |
|         new_ifaceobjdict = {}
 | |
| 
 | |
|         self.logger.info('reloading interfaces that are currently up ..')
 | |
| 
 | |
|         try:
 | |
|             iface_read_ret = self.read_iface_config()
 | |
|         except:
 | |
|             raise
 | |
|         if not self.ifaceobjdict:
 | |
|             self.logger.warn("nothing to reload ..exiting.")
 | |
|             return
 | |
|         already_up_ifacenames = []
 | |
|         if not ifacenames: ifacenames = self.ifaceobjdict.keys()
 | |
| 
 | |
|         if (not usecurrentconfig and self.flags.STATEMANAGER_ENABLE
 | |
|                 and self.statemanager.ifaceobjdict):
 | |
|             already_up_ifacenames = self.statemanager.ifaceobjdict.keys()
 | |
| 
 | |
|         # Get already up interfaces that still exist in the interfaces file
 | |
|         already_up_ifacenames_not_present = Set(
 | |
|                         already_up_ifacenames).difference(ifacenames)
 | |
|         already_up_ifacenames_still_present = Set(
 | |
|                         already_up_ifacenames).difference(
 | |
|                         already_up_ifacenames_not_present)
 | |
| 
 | |
|         interfaces_to_up = already_up_ifacenames_still_present
 | |
| 
 | |
|         # generate dependency graph of interfaces
 | |
|         self.populate_dependency_info(upops, interfaces_to_up)
 | |
| 
 | |
|         # If only syntax check was requested, return here.
 | |
|         # return here because we want to make sure most
 | |
|         # errors above are caught and reported.
 | |
|         if syntaxcheck:
 | |
|             if not iface_read_ret:
 | |
|                 raise Exception()
 | |
|             elif self._any_iface_errors(interfaces_to_up):
 | |
|                 raise Exception()
 | |
|             return
 | |
| 
 | |
|         if (already_up_ifacenames_not_present and
 | |
|                 self.config.get('ifreload_currentlyup_down_notpresent') == '1'):
 | |
|            self.logger.info('reload: schedule down on interfaces: %s'
 | |
|                             %str(already_up_ifacenames_not_present))
 | |
| 
 | |
|            # Save a copy of new iface objects and dependency_graph
 | |
|            new_ifaceobjdict = dict(self.ifaceobjdict)
 | |
|            new_dependency_graph = dict(self.dependency_graph)
 | |
| 
 | |
|            # old interface config is read into self.ifaceobjdict
 | |
|            self.read_old_iface_config()
 | |
| 
 | |
|            # reinitialize dependency graph 
 | |
|            self.dependency_graph = OrderedDict({})
 | |
|            falready_up_ifacenames_not_present = [i for i in
 | |
|                                     already_up_ifacenames_not_present
 | |
|                                     if self._iface_whitelisted(auto, allow,
 | |
|                                     excludepats, i)]
 | |
|            self.populate_dependency_info(downops,
 | |
|                                          falready_up_ifacenames_not_present)
 | |
|            self._sched_ifaces(falready_up_ifacenames_not_present, downops,
 | |
|                               followdependents=False, sort=True)
 | |
|         else:
 | |
|            self.logger.info('no interfaces to down ..')
 | |
| 
 | |
|         # Now, run 'up' with new config dict
 | |
|         # reset statemanager update flag to default
 | |
|         if auto:
 | |
|             ifupdownflags.flags.ALL = True
 | |
|             ifupdownflags.flags.WITH_DEPENDS = True
 | |
|         if new_ifaceobjdict:
 | |
|             # and now, ifaceobjdict is back to current config
 | |
|             self.ifaceobjdict = new_ifaceobjdict
 | |
|             self.dependency_graph = new_dependency_graph
 | |
| 
 | |
|         if not self.ifaceobjdict:
 | |
|             self.logger.info('no interfaces to up')
 | |
|             return
 | |
|         self.logger.info('reload: scheduling up on interfaces: %s'
 | |
|                          %str(interfaces_to_up))
 | |
|         ret = self._sched_ifaces(interfaces_to_up, upops,
 | |
|                                  followdependents=True
 | |
|                                  if ifupdownflags.flags.WITH_DEPENDS else False)
 | |
|         if ifupdownflags.flags.DRYRUN:
 | |
|             return
 | |
|         self._save_state()
 | |
| 
 | |
|         if not iface_read_ret or not ret:
 | |
|             raise Exception()
 | |
| 
 | |
|     def _reload_default(self, upops, downops, auto=False, allow=None,
 | |
|             ifacenames=None, excludepats=None, usecurrentconfig=False,
 | |
|             syntaxcheck=False, **extra_args):
 | |
|         """ reload interface config """
 | |
|         new_ifaceobjdict = {}
 | |
| 
 | |
|         try:
 | |
|             iface_read_ret = self.read_iface_config()
 | |
|         except:
 | |
|             raise
 | |
| 
 | |
|         if not self.ifaceobjdict:
 | |
|             self.logger.warn("nothing to reload ..exiting.")
 | |
|             return
 | |
| 
 | |
|         if not ifacenames: ifacenames = self.ifaceobjdict.keys()
 | |
|         new_filtered_ifacenames = [i for i in ifacenames
 | |
|                                if self._iface_whitelisted(auto, allow,
 | |
|                                excludepats, i)]
 | |
|         # generate dependency graph of interfaces
 | |
|         self.populate_dependency_info(upops)
 | |
| 
 | |
|         # If only syntax check was requested, return here.
 | |
|         # return here because we want to make sure most
 | |
|         # errors above are caught and reported.
 | |
|         if syntaxcheck:
 | |
|             if not iface_read_ret:
 | |
|                 raise Exception()
 | |
|             elif self._any_iface_errors(new_filtered_ifacenames):
 | |
|                 raise Exception()
 | |
|             return
 | |
| 
 | |
|         if (not usecurrentconfig and self.flags.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)
 | |
| 
 | |
|             self.ifaceobjdict = OrderedDict({})
 | |
|             self.dependency_graph = OrderedDict({})
 | |
| 
 | |
|             # 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'
 | |
|             new_ifaceobjdict = self.ifaceobjdict
 | |
|             new_dependency_graph = self.dependency_graph
 | |
| 
 | |
|         if op == 'reload' and ifacenames:
 | |
|             ifacenames = self.ifaceobjdict.keys()
 | |
|             old_filtered_ifacenames = [i for i in ifacenames
 | |
|                                if self._iface_whitelisted(auto, allow,
 | |
|                                excludepats, i)]
 | |
| 
 | |
|             # generate dependency graph of old interfaces,
 | |
|             # This should make sure built in interfaces are
 | |
|             # populated. disable check shared dependents as an optimization.
 | |
|             # these are saved interfaces and dependency for these
 | |
|             # have been checked before they became part of saved state.
 | |
|             try:
 | |
|                 self.flags.CHECK_SHARED_DEPENDENTS = False 
 | |
|                 self.populate_dependency_info(upops)
 | |
|                 self.flags.CHECK_SHARED_DEPENDENTS = True
 | |
|             except Exception, e:
 | |
|                 self.logger.info("error generating dependency graph for "
 | |
|                                  "saved interfaces (%s)" %str(e))
 | |
|                 pass
 | |
|             
 | |
|             # make sure we pick up built-in interfaces
 | |
|             # if config file had 'ifreload_down_changed' variable
 | |
|             # set, also look for interfaces that changed to down them
 | |
|             down_changed = int(self.config.get('ifreload_down_changed', '1'))
 | |
| 
 | |
|             # 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 in self.ifaceobjdict.keys():
 | |
|                 lastifaceobjlist = self.ifaceobjdict.get(ifname)
 | |
|                 if not self.is_ifaceobj_builtin(lastifaceobjlist[0]):
 | |
|                     # if interface is not built-in and is not in
 | |
|                     # old filtered ifacenames
 | |
|                     if ifname not in old_filtered_ifacenames:
 | |
|                         continue
 | |
|                 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 ifaceobj was present in the old interfaces file,
 | |
|                 # and does not have a config in the new interfaces file
 | |
|                 # but has been picked up as a dependent of another
 | |
|                 # interface, catch it here. This catches a common error
 | |
|                 # for example: remove a bond section from the interfaces
 | |
|                 # file, but leave it around as a bridge port
 | |
|                 # XXX: Ideally its better to just add it to the
 | |
|                 # ifacedownlist. But we will be cautious here 
 | |
|                 # and just print a warning
 | |
|                 if (self.is_ifaceobj_noconfig(newifaceobjlist[0]) and
 | |
|                     not self.is_ifaceobj_builtin(newifaceobjlist[0]) and
 | |
|                     lastifaceobjlist[0].is_config_present() and
 | |
|                     lastifaceobjlist[0].link_kind):
 | |
|                     self.logger.warn('%s: misconfig ? removed but still exists as a dependency of %s' %(newifaceobjlist[objidx].name, str(newifaceobjlist[objidx].upperifaces)))
 | |
|                 if not down_changed:
 | |
|                     continue
 | |
|                 if len(newifaceobjlist) != len(lastifaceobjlist):
 | |
|                     ifacedownlist.append(ifname)
 | |
|                     continue
 | |
| 
 | |
|                 # If interface has changed between the current file
 | |
|                 # and the last installed append it to the down list
 | |
|                 # 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('reload: scheduling down on interfaces: %s'
 | |
|                                   %str(ifacedownlist))
 | |
|                 # reinitialize dependency graph 
 | |
|                 self.dependency_graph = OrderedDict({})
 | |
| 
 | |
|                 # Generate dependency info for old config
 | |
|                 self.flags.CHECK_SHARED_DEPENDENTS = False
 | |
|                 self.populate_dependency_info(downops, ifacedownlist)
 | |
|                 self.flags.CHECK_SHARED_DEPENDENTS = True
 | |
| 
 | |
|                 try:
 | |
|                     # XXX: Hack to skip checking upperifaces during down.
 | |
|                     # the dependency list is not complete here
 | |
|                     # and we dont want to down the upperiface.
 | |
|                     # Hence during reload, set  this to true.
 | |
|                     # This is being added to avoid a failure in
 | |
|                     # scheduler._check_upperifaces when we are dowing
 | |
|                     # a builtin bridge port 
 | |
|                     self.flags.SCHED_SKIP_CHECK_UPPERIFACES = True
 | |
|                     self._sched_ifaces(ifacedownlist, downops,
 | |
|                                        followdependents=False,
 | |
|                                        sort=True)
 | |
|                 except Exception, e:
 | |
|                     self.logger.error(str(e))
 | |
|                     pass
 | |
|                 finally:
 | |
|                     self.flags.SCHED_SKIP_CHECK_UPPERIFACES = False
 | |
|                     self._process_delay_admin_state_queue('down')
 | |
|             else:
 | |
|                 self.logger.info('no interfaces to down ..')
 | |
| 
 | |
|         # Now, run 'up' with new config dict
 | |
|         # reset statemanager update flag to default
 | |
|         if not new_ifaceobjdict:
 | |
|             self.logger.debug('no interfaces to up')
 | |
|             return
 | |
| 
 | |
|         if auto:
 | |
|             ifupdownflags.flags.ALL = True
 | |
|             ifupdownflags.flags.WITH_DEPENDS = True
 | |
|         # and now, we are back to the current config in ifaceobjdict
 | |
|         self.ifaceobjdict = new_ifaceobjdict
 | |
|         self.dependency_graph = new_dependency_graph
 | |
| 
 | |
|         self.logger.info('reload: scheduling up on interfaces: %s'
 | |
|                          %str(new_filtered_ifacenames))
 | |
|         ifupdownflags.flags.CACHE = True
 | |
|         try:
 | |
|             ret = self._sched_ifaces(new_filtered_ifacenames, upops,
 | |
|                                      followdependents=True
 | |
|                                      if ifupdownflags.flags.WITH_DEPENDS
 | |
|                                      else False)
 | |
|         except Exception, e:
 | |
|             ret = None
 | |
|             self.logger.error(str(e))
 | |
|         finally:
 | |
|             self._process_delay_admin_state_queue('up')
 | |
|         if ifupdownflags.flags.DRYRUN:
 | |
|             return
 | |
|         self._save_state()
 | |
| 
 | |
|         if not iface_read_ret or not ret:
 | |
|             raise Exception()
 | |
| 
 | |
|     def reload(self, *args, **kargs):
 | |
|         """ reload interface config """
 | |
|         self.logger.debug('reloading interface config ..')
 | |
|         if kargs.get('currentlyup', False):
 | |
|             self._reload_currentlyup(*args, **kargs)
 | |
|         else:
 | |
|             self._reload_default(*args, **kargs)
 | |
| 
 | |
|     def _any_iface_errors(self, ifacenames):
 | |
|         for i in ifacenames:
 | |
|             ifaceobjs = self.get_ifaceobjs(i)
 | |
|             if not ifaceobjs: continue
 | |
|             for ifaceobj in ifaceobjs:
 | |
|                 if (ifaceobj.status == ifaceStatus.NOTFOUND or
 | |
|                     ifaceobj.status == ifaceStatus.ERROR):
 | |
|                     return True
 | |
|         return False
 | |
| 
 | |
|     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_list(self, ifacenames):
 | |
|         for i in ifacenames:
 | |
|             print i
 | |
| 
 | |
|     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 (ifupdownflags.flags.WITH_DEPENDS and
 | |
|                     not ifupdownflags.flags.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 (ifupdownflags.flags.WITH_DEPENDS and
 | |
|                     not ifupdownflags.flags.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:
 | |
|             expand = int(self.config.get('ifquery_ifacename_expand_range', '0'))
 | |
|             for i in ifaceobjs:
 | |
|                 if not expand and (i.flags & iface.IFACERANGE_ENTRY):
 | |
|                     # print only the first one
 | |
|                     if i.flags & iface.IFACERANGE_START:
 | |
|                        i.dump_pretty(use_realname=True)
 | |
|                 else:
 | |
|                     i.dump_pretty()
 | |
| 
 | |
|     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 (ifupdownflags.flags.WITH_DEPENDS and
 | |
|                     not ifupdownflags.flags.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
 | |
| 
 | |
|         # override ifaceStatusUserStrs
 | |
|         ifaceStatusUserStrs.SUCCESS = self.config.get('ifquery_check_success_str', _success_sym)
 | |
|         ifaceStatusUserStrs.ERROR = self.config.get('ifquery_check_error_str', _error_sym)
 | |
|         ifaceStatusUserStrs.UNKNOWN = self.config.get('ifquery_check_unknown_str', '')
 | |
|         if format == 'json':
 | |
|             print json.dumps(ifaceobjs, cls=ifaceJsonEncoderWithStatus,
 | |
|                              indent=2, separators=(',', ': '))
 | |
|         else:
 | |
|             map(lambda i: i.dump_pretty(with_status=True), 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'
 |