2013-11-04 06:06:11 -08:00
#!/usr/bin/python
2013-11-13 16:07:15 -08:00
#
2014-07-22 11:15:56 -07:00
# Copyright 2014 Cumulus Networks, Inc. All rights reserved.
2013-11-13 16:07:15 -08:00
# Author: Roopa Prabhu, roopa@cumulusnetworks.com
#
# ifupdownMain --
# ifupdown main module
#
2013-11-04 06:06:11 -08:00
import os
import re
2013-11-13 16:07:15 -08:00
import imp
import pprint
import logging
import sys , traceback
2014-03-30 22:38:00 -07:00
import copy
2014-04-22 21:55:11 -07:00
import json
2015-07-23 15:43:45 -04:00
import ifupdown . statemanager as statemanager
2015-11-16 21:00:40 -08:00
import ifupdown . ifupdownconfig as ifupdownConfig
2016-04-14 14:45:47 -07:00
import ifupdown . ifupdownflags as ifupdownflags
2013-11-04 06:06:11 -08:00
from networkinterfaces import *
from iface import *
from scheduler import *
from collections import deque
from collections import OrderedDict
from graph import *
2013-11-13 16:07:15 -08:00
from sets import Set
2013-11-04 06:06:11 -08:00
2014-07-17 11:44:36 -07:00
"""
. . module : : ifupdownmain
: synopsis : main module for ifupdown package
. . moduleauthor : : Roopa Prabhu < roopa @cumulusnetworks.com >
"""
2014-05-09 09:10:49 -07:00
_tickmark = u ' \u2713 '
_crossmark = u ' \u2717 '
2014-10-12 13:50:05 -07:00
_success_sym = ' ( %s ) ' % _tickmark
_error_sym = ' ( %s ) ' % _crossmark
2014-05-09 09:10:49 -07:00
2016-02-25 17:10:33 -08:00
class ifupdownMainFlags ( ) :
2014-06-25 15:23:04 -07:00
IFACE_CLASS = False
2014-02-20 09:07:55 -08:00
COMPAT_EXEC_SCRIPTS = False
2014-02-26 08:09:44 -08:00
STATEMANAGER_ENABLE = True
STATEMANAGER_UPDATE = True
ADDONS_ENABLE = False
2016-02-25 17:10:33 -08:00
DELETE_DEPENDENT_IFACES_WITH_NOCONFIG = False
SCHED_SKIP_CHECK_UPPERIFACES = False
CHECK_SHARED_DEPENDENTS = True
2013-11-04 06:06:11 -08:00
2016-02-25 17:10:33 -08:00
class ifacePrivFlags ( ) :
2014-01-30 22:36:41 -08:00
# priv flags to mark iface objects
2016-02-25 17:10:33 -08:00
BUILTIN = False
NOCONFIG = False
def __init__ ( self , builtin = False , noconfig = False ) :
self . BUILTIN = builtin
self . NOCONFIG = noconfig
class ifupdownMain ( ifupdownBase ) :
""" ifupdown2 main class """
2014-01-30 22:36:41 -08:00
scripts_dir = ' /etc/network '
2015-12-20 23:03:05 -08:00
addon_modules_dir = ' /usr/share/ifupdown2/addons '
addon_modules_configfile = ' /etc/network/ifupdown2/addons.conf '
2013-11-04 06:06:11 -08:00
# iface dictionary in the below format:
# { '<ifacename>' : [<ifaceobject1>, <ifaceobject2> ..] }
# eg:
2014-03-25 15:21:19 -07:00
# { 'swp1' : [<iface swp1>, <iface swp2> ..] }
2013-11-04 06:06:11 -08:00
#
# Each ifaceobject corresponds to a configuration block for
# that interface
2014-03-25 15:21:19 -07:00
# The value in the dictionary is a list because the network
# interface configuration file supports more than one iface section
# in the interfaces file
2013-11-04 06:06:11 -08:00
ifaceobjdict = OrderedDict ( )
# iface dictionary representing the curr running state of an iface
# in the below format:
# {'<ifacename>' : <ifaceobject>}
ifaceobjcurrdict = OrderedDict ( )
2014-02-17 19:01:37 -08:00
# Dictionary representing operation and modules
# for every operation
module_ops = OrderedDict ( [ ( ' pre-up ' , [ ] ) ,
2014-02-08 09:05:32 -08:00
( ' up ' , [ ] ) ,
( ' post-up ' , [ ] ) ,
( ' query-checkcurr ' , [ ] ) ,
( ' query-running ' , [ ] ) ,
( ' query-dependency ' , [ ] ) ,
2014-02-11 06:00:07 -08:00
( ' query ' , [ ] ) ,
( ' query-raw ' , [ ] ) ,
2014-02-08 09:05:32 -08:00
( ' pre-down ' , [ ] ) ,
( ' down ' , [ ] ) ,
( ' post-down ' , [ ] ) ] )
2014-01-30 22:36:41 -08:00
# For old style /etc/network/ bash scripts
2014-02-17 19:01:37 -08:00
script_ops = OrderedDict ( [ ( ' pre-up ' , [ ] ) ,
2014-02-08 09:05:32 -08:00
( ' up ' , [ ] ) ,
( ' post-up ' , [ ] ) ,
( ' pre-down ' , [ ] ) ,
( ' down ' , [ ] ) ,
( ' post-down ' , [ ] ) ] )
2013-11-04 06:06:11 -08:00
2014-02-17 19:01:37 -08:00
# Handlers for ops that ifupdown2 owns
def run_up ( self , ifaceobj ) :
2015-02-10 11:28:53 -08:00
# 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
2016-05-13 22:44:50 -07:00
if ( ( ifaceobj . link_kind & ifaceLinkKind . VRF ) or
( ifaceobj . link_privflags & ifaceLinkPrivFlags . VRF_SLAVE ) ) :
2016-04-23 22:57:41 -07:00
return
2014-12-17 12:39:38 -08:00
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
2014-12-08 17:15:57 -08:00
# 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).
2014-12-26 09:21:50 -08:00
if ifaceobj . link_type == ifaceLinkType . LINK_SLAVE :
2014-12-08 17:15:57 -08:00
return
2014-12-17 12:39:38 -08:00
if not self . link_exists ( ifaceobj . name ) :
2014-12-26 09:21:50 -08:00
return
2014-12-17 12:39:38 -08:00
self . link_up ( ifaceobj . name )
2014-02-17 19:01:37 -08:00
def run_down ( self , ifaceobj ) :
2016-05-13 22:44:50 -07:00
if ( ( ifaceobj . link_kind & ifaceLinkKind . VRF ) or
( ifaceobj . link_privflags & ifaceLinkPrivFlags . VRF_SLAVE ) ) :
2016-03-24 21:55:58 -07:00
return
2016-03-30 23:32:59 -07:00
# Skip link sets on ifaceobjs of type 'vlan' (used for l2 attrs)
# there is no real interface behind it
2015-02-10 11:28:53 -08:00
if ifaceobj . type == ifaceType . BRIDGE_VLAN :
return
2014-12-17 12:39:38 -08:00
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
2014-12-08 17:15:57 -08:00
# 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).
2014-12-26 09:21:50 -08:00
if ifaceobj . link_type == ifaceLinkType . LINK_SLAVE :
return
2014-12-17 12:39:38 -08:00
if not self . link_exists ( ifaceobj . name ) :
2014-12-26 09:21:50 -08:00
return
2014-12-17 12:39:38 -08:00
self . link_down ( ifaceobj . name )
2014-02-17 19:01:37 -08:00
2014-02-24 11:07:59 -08:00
# ifupdown object interface operation handlers
2014-02-17 19:01:37 -08:00
ops_handlers = OrderedDict ( [ ( ' up ' , run_up ) ,
( ' down ' , run_down ) ] )
2013-11-04 06:06:11 -08:00
2014-03-30 22:38:00 -07:00
def run_sched_ifaceobj_posthook ( self , ifaceobj , op ) :
2016-02-25 17:10:33 -08:00
if ( ifaceobj . priv_flags and ( ifaceobj . priv_flags . BUILTIN or
ifaceobj . priv_flags . NOCONFIG ) ) :
2014-03-06 06:41:28 -08:00
return
2016-02-25 17:10:33 -08:00
if self . flags . STATEMANAGER_UPDATE :
2014-03-30 22:38:00 -07:00
self . statemanager . ifaceobj_sync ( ifaceobj , op )
2014-02-24 11:07:59 -08:00
# ifupdown object interface scheduler pre and posthooks
sched_hooks = { ' posthook ' : run_sched_ifaceobj_posthook }
2014-04-18 14:09:20 -07:00
def __init__ ( self , config = { } ,
force = False , dryrun = False , nowait = False ,
2014-01-17 23:10:12 -08:00
perfmode = False , withdepends = False , njobs = 1 ,
2014-04-18 14:09:20 -07:00
cache = False , addons_enable = True , statemanager_enable = True ,
2014-04-28 22:33:33 -07:00
interfacesfile = ' /etc/network/interfaces ' ,
interfacesfileiobuf = None ,
2016-04-20 03:02:26 -07:00
interfacesfileformat = ' native ' ,
withdefaults = False ) :
2014-07-17 11:44:36 -07:00
""" 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 """
2013-11-04 06:06:11 -08:00
self . logger = logging . getLogger ( ' ifupdown ' )
2016-04-14 14:45:47 -07:00
ifupdownflags . flags . FORCE = force
ifupdownflags . flags . DRYRUN = dryrun
2016-04-20 03:02:26 -07:00
ifupdownflags . flags . WITHDEFAULTS = withdefaults
2016-04-14 14:45:47 -07:00
ifupdownflags . flags . NOWAIT = nowait
ifupdownflags . flags . PERFMODE = perfmode
ifupdownflags . flags . CACHE = cache
2016-05-13 22:44:50 -07:00
ifupdownflags . flags . WITH_DEPENDS = withdepends
2016-04-14 14:45:47 -07:00
2016-02-25 17:10:33 -08:00
# Can be used to provide hints for caching
2016-04-14 14:45:47 -07:00
ifupdownflags . flags . CACHE_FLAGS = 0x0
2016-02-25 17:10:33 -08:00
self . flags = ifupdownMainFlags ( )
self . flags . STATEMANAGER_ENABLE = statemanager_enable
2014-04-18 14:09:20 -07:00
self . interfacesfile = interfacesfile
2014-04-28 22:33:33 -07:00
self . interfacesfileiobuf = interfacesfileiobuf
self . interfacesfileformat = interfacesfileformat
2014-04-18 14:09:20 -07:00
self . config = config
self . logger . debug ( self . config )
2015-10-02 13:18:03 -07:00
self . blacklisted_ifaces_present = False
2014-02-27 22:23:03 -08:00
2014-11-11 21:58:12 -08:00
self . type = ifaceType . UNKNOWN
2016-02-25 17:10:33 -08:00
self . flags . DELETE_DEPENDENT_IFACES_WITH_NOCONFIG = False
self . flags . ADDONS_ENABLE = addons_enable
2013-11-10 22:35:40 -08:00
2013-11-04 06:06:11 -08:00
self . ifaces = OrderedDict ( )
2013-11-10 22:35:40 -08:00
self . njobs = njobs
2013-11-04 06:06:11 -08:00
self . pp = pprint . PrettyPrinter ( indent = 4 )
2014-01-30 22:36:41 -08:00
self . modules = OrderedDict ( { } )
2014-02-08 09:05:32 -08:00
self . module_attrs = { }
2014-02-26 08:09:44 -08:00
2014-01-30 22:36:41 -08:00
self . load_addon_modules ( self . addon_modules_dir )
2016-02-25 17:10:33 -08:00
if self . flags . COMPAT_EXEC_SCRIPTS :
2014-02-20 13:11:22 -08:00
self . load_scripts ( self . scripts_dir )
2014-02-08 09:05:32 -08:00
self . dependency_graph = OrderedDict ( { } )
2013-11-04 06:06:11 -08:00
2014-11-03 17:55:51 -08:00
self . _cache_no_repeats = { }
2016-02-25 17:10:33 -08:00
if self . flags . STATEMANAGER_ENABLE :
2014-02-26 08:09:44 -08:00
try :
2015-07-23 15:43:45 -04:00
self . statemanager = statemanager . statemanager_api
2014-02-26 08:09:44 -08:00
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 :
2016-02-25 17:10:33 -08:00
self . flags . STATEMANAGER_UPDATE = False
2014-12-17 12:39:38 -08:00
self . _delay_admin_state = True if self . config . get (
' delay_admin_state_change ' , ' 0 ' ) == ' 1 ' else False
self . _delay_admin_state_iface_queue = [ ]
2014-12-29 22:07:49 -08:00
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 (
2014-12-17 12:39:38 -08:00
' link_master_slave ' , ' 0 ' ) == ' 1 ' else False
2014-12-29 22:07:49 -08:00
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. ' )
2013-11-04 06:06:11 -08:00
2016-03-16 18:38:43 -07:00
# squash iface objects for same interface both internal and
# external representation. It is off by default.
2016-03-08 20:40:02 -08:00
self . _ifaceobj_squash = True if self . config . get (
' ifaceobj_squash ' , ' 0 ' ) == ' 1 ' else False
2016-03-16 18:38:43 -07:00
# 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
2015-11-16 21:00:40 -08:00
# initialize global config object with config passed by the user
# This makes config available to addon modules
ifupdownConfig . config = self . config
2014-12-26 09:39:52 -08:00
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
2014-02-24 11:07:59 -08:00
def get_ifaceobjs ( self , ifacename ) :
2013-11-04 06:06:11 -08:00
return self . ifaceobjdict . get ( ifacename )
2014-12-24 12:14:30 -08:00
def get_ifaceobjs_saved ( self , ifacename ) :
""" Return ifaceobjects from statemanager """
2016-02-25 17:10:33 -08:00
if self . flags . STATEMANAGER_ENABLE :
2014-12-24 12:14:30 -08:00
return self . statemanager . get_ifaceobjs ( ifacename )
else :
None
2014-02-24 11:07:59 -08:00
def get_ifaceobj_first ( self , ifacename ) :
ifaceobjs = self . get_ifaceobjs ( ifacename )
if ifaceobjs :
2013-11-04 06:06:11 -08:00
return ifaceobjs [ 0 ]
return None
2014-03-18 16:38:00 -07:00
def get_ifacenames ( self ) :
return self . ifaceobjdict . keys ( )
2013-11-04 06:06:11 -08:00
def get_iface_obj_last ( self , ifacename ) :
return self . ifaceobjdict . get ( ifacename ) [ - 1 ]
2014-12-24 12:14:30 -08:00
2014-10-10 14:05:19 -07:00
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 )
2014-10-28 23:04:40 -07:00
if ifaceobj . type == ifaceType . BRIDGE_VLAN :
2014-10-10 14:05:19 -07:00
return False
return True
2014-03-25 15:21:19 -07:00
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
2014-12-31 13:58:25 -08:00
if not self . _link_master_slave :
ifaceobj . link_type = ifaceLinkType . LINK_NA
2014-03-25 15:21:19 -07:00
if increfcnt :
ifaceobj . inc_refcnt ( )
self . ifaceobjdict [ ifacename ] = [ ifaceobj ]
return ifaceobj
2014-02-08 09:05:32 -08:00
def create_n_save_ifaceobjcurr ( self , ifaceobj ) :
2014-05-26 09:03:29 -07:00
""" creates a copy of iface object and adds it to the iface
dict containing current iface objects
2014-03-25 15:21:19 -07:00
"""
2014-01-16 06:46:17 -08:00
ifaceobjcurr = iface ( )
2014-03-25 15:21:19 -07:00
ifaceobjcurr . name = ifaceobj . name
2014-10-28 23:04:40 -07:00
ifaceobjcurr . type = ifaceobj . type
2014-03-22 22:16:53 -07:00
ifaceobjcurr . lowerifaces = ifaceobj . lowerifaces
2016-02-25 17:10:33 -08:00
ifaceobjcurr . priv_flags = copy . deepcopy ( ifaceobj . priv_flags )
2014-04-22 21:55:11 -07:00
ifaceobjcurr . auto = ifaceobj . auto
2014-05-26 09:03:29 -07:00
self . ifaceobjcurrdict . setdefault ( ifaceobj . name ,
[ ] ) . append ( ifaceobjcurr )
2014-02-08 09:05:32 -08:00
return ifaceobjcurr
2013-11-04 06:06:11 -08:00
2014-05-26 09:03:29 -07:00
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 ]
2013-11-04 06:06:11 -08:00
2014-01-16 06:46:17 -08:00
def get_ifaceobjrunning ( self , ifacename ) :
return self . ifaceobjrunningdict . get ( ifacename )
2013-11-04 06:06:11 -08:00
def get_iface_refcnt ( self , ifacename ) :
2014-03-25 15:21:19 -07:00
""" Return iface ref count """
2013-11-04 06:06:11 -08:00
max = 0
2014-02-24 11:07:59 -08:00
ifaceobjs = self . get_ifaceobjs ( ifacename )
2014-02-26 08:09:44 -08:00
if not ifaceobjs :
return 0
2013-11-04 06:06:11 -08:00
for i in ifaceobjs :
2014-03-22 22:16:53 -07:00
if i . refcnt > max :
max = i . refcnt
2013-11-04 06:06:11 -08:00
return max
2014-02-08 09:05:32 -08:00
def is_iface_builtin_byname ( self , ifacename ) :
2014-01-17 23:10:12 -08:00
""" Returns true if iface name is a builtin interface.
2013-11-04 06:06:11 -08:00
2014-01-17 23:10:12 -08:00
A builtin interface is an interface which ifupdown understands .
The following are currently considered builtin ifaces :
- vlan interfaces in the format < ifacename > . < vlanid >
2013-11-04 06:06:11 -08:00
"""
2014-02-08 09:05:32 -08:00
return ' . ' in ifacename
2013-11-04 06:06:11 -08:00
2014-01-30 22:36:41 -08:00
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 >
"""
2016-05-07 18:27:05 -07:00
if ( ifaceobj . priv_flags and ifaceobj . priv_flags . BUILTIN ) :
return True
return False
2014-01-30 22:36:41 -08:00
def is_ifaceobj_noconfig ( self , ifaceobj ) :
2014-03-25 15:21:19 -07:00
""" Returns true if iface object did not have a user defined config.
2014-01-30 22:36:41 -08:00
These interfaces appear only when they are dependents of interfaces
which have user defined config
"""
2016-02-25 17:10:33 -08:00
return ( ifaceobj . priv_flags and ifaceobj . priv_flags . NOCONFIG )
2014-01-30 22:36:41 -08:00
2014-02-08 09:05:32 -08:00
def is_iface_noconfig ( self , ifacename ) :
""" Returns true if iface has no config """
2014-01-30 22:36:41 -08:00
2014-02-24 11:07:59 -08:00
ifaceobj = self . get_ifaceobj_first ( ifacename )
2014-02-08 09:05:32 -08:00
if not ifaceobj : return True
return self . is_ifaceobj_noconfig ( ifaceobj )
2015-04-03 21:24:25 -07:00
def check_shared_dependents ( self , ifaceobj , dlist ) :
2016-03-30 11:54:58 -07:00
""" ABSOLETE: Check if dlist intersects with any other
2015-04-03 21:24:25 -07:00
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 )
2016-02-25 17:10:33 -08:00
if not iobjs :
continue
2015-04-03 21:24:25 -07:00
for i in iobjs :
if ( i . dependency_type == ifaceDependencyType . MASTER_SLAVE ) :
check_depends = True
if check_depends :
common = Set ( ifacedlist ) . intersection ( setdlist )
if common :
2015-04-03 22:33:53 -07:00
self . logger . error ( ' misconfig..?. iface %s and %s '
2015-04-03 21:24:25 -07:00
% ( ifaceobj . name , ifacename ) +
2015-04-03 22:33:53 -07:00
' seem to share dependents/ports %s ' % str ( list ( common ) ) )
2015-04-03 21:24:25 -07:00
2016-04-04 13:24:59 -07:00
def _set_iface_role ( self , ifaceobj , role , upperifaceobj ) :
2016-03-30 11:54:58 -07:00
if ( self . flags . CHECK_SHARED_DEPENDENTS and
2016-04-04 13:24:59 -07:00
( ifaceobj . role & ifaceRole . SLAVE ) and
( role == ifaceRole . SLAVE ) and ( upperifaceobj . role == ifaceRole . MASTER ) ) :
2016-03-30 11:54:58 -07:00
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
2015-07-23 10:17:02 -07:00
def _set_iface_role_n_kind ( self , ifaceobj , upperifaceobj ) :
2016-03-30 11:54:58 -07:00
2015-07-23 10:17:02 -07:00
if ( upperifaceobj . link_kind & ifaceLinkKind . BOND ) :
2016-04-04 13:24:59 -07:00
self . _set_iface_role ( ifaceobj , ifaceRole . SLAVE , upperifaceobj )
2016-03-30 11:54:58 -07:00
ifaceobj . link_privflags | = ifaceLinkPrivFlags . BOND_SLAVE
2015-07-23 10:17:02 -07:00
if ( upperifaceobj . link_kind & ifaceLinkKind . BRIDGE ) :
2016-04-04 13:24:59 -07:00
self . _set_iface_role ( ifaceobj , ifaceRole . SLAVE , upperifaceobj )
2016-03-30 11:54:58 -07:00
ifaceobj . link_privflags | = ifaceLinkPrivFlags . BRIDGE_PORT
2016-04-25 00:32:59 +02:00
if ( ifaceobj . link_kind & ifaceLinkKind . VXLAN ) \
and ( upperifaceobj . link_kind & ifaceLinkKind . BRIDGE ) :
upperifaceobj . link_privflags | = ifaceLinkPrivFlags . BRIDGE_VXLAN
2016-03-30 11:54:58 -07:00
# 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 ) ) :
2016-04-04 13:24:59 -07:00
self . _set_iface_role ( ifaceobj , ifaceRole . SLAVE , upperifaceobj )
2016-03-30 11:54:58 -07:00
ifaceobj . link_privflags | = ifaceLinkPrivFlags . VRF_SLAVE
2016-02-26 06:32:28 -08:00
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
2015-07-23 10:17:02 -07:00
2016-02-29 22:23:24 -08:00
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 [ ] ) )
2014-12-08 17:15:57 -08:00
def preprocess_dependency_list ( self , upperifaceobj , dlist , ops ) :
2014-01-16 06:46:17 -08:00
""" We go through the dependency list and
delete or add interfaces from the interfaces dict by
applying the following rules :
2016-02-25 17:10:33 -08:00
if flag DELETE_DEPENDENT_IFACES_WITH_NOCONFIG is True :
2014-01-16 06:46:17 -08:00
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
2016-02-25 17:10:33 -08:00
elif flag DELETE_DEPENDENT_IFACES_WITH_NOCONFIG is False :
2014-01-16 06:46:17 -08:00
we create objects for all dependent devices that are not
present in the ifacesdict
"""
2013-11-04 06:06:11 -08:00
del_list = [ ]
for d in dlist :
2014-02-24 11:07:59 -08:00
dilist = self . get_ifaceobjs ( d )
2014-02-08 09:05:32 -08:00
if not dilist :
2014-12-08 17:15:57 -08:00
ni = None
2014-02-08 09:05:32 -08:00
if self . is_iface_builtin_byname ( d ) :
2014-12-17 12:39:38 -08:00
ni = self . create_n_save_ifaceobj ( d ,
2016-02-25 17:10:33 -08:00
ifacePrivFlags ( True , True ) , True )
elif not self . flags . DELETE_DEPENDENT_IFACES_WITH_NOCONFIG :
ni = self . create_n_save_ifaceobj ( d ,
ifacePrivFlags ( False , True ) , True )
2013-11-04 06:06:11 -08:00
else :
del_list . append ( d )
2014-12-08 17:15:57 -08:00
if ni :
ni . add_to_upperifaces ( upperifaceobj . name )
2015-09-04 16:12:20 -07:00
self . _set_iface_role_n_kind ( ni , upperifaceobj )
2013-11-04 06:06:11 -08:00
else :
for di in dilist :
di . inc_refcnt ( )
2014-12-08 17:15:57 -08:00
di . add_to_upperifaces ( upperifaceobj . name )
2015-09-04 16:12:20 -07:00
self . _set_iface_role_n_kind ( di , upperifaceobj )
2013-11-04 06:06:11 -08:00
for d in del_list :
dlist . remove ( d )
2016-02-25 23:55:27 -08:00
def preprocess_upperiface ( self , lowerifaceobj , ulist , ops ) :
2016-02-29 22:23:24 -08:00
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 )
2016-02-25 23:55:27 -08:00
def query_lowerifaces ( self , ifaceobj , ops , ifacenames , type = None ) :
2013-11-04 06:06:11 -08:00
""" Gets iface dependents by calling into respective modules """
2014-10-06 11:11:10 -07:00
ret_dlist = [ ]
2013-11-04 06:06:11 -08:00
2014-02-26 08:09:44 -08:00
# Get dependents for interface by querying respective modules
2014-09-26 14:23:15 -07:00
for module in self . modules . values ( ) :
2014-04-08 14:50:15 -07:00
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 ,
2014-09-26 14:23:15 -07:00
ifacenames )
2014-04-08 14:50:15 -07:00
except Exception , e :
self . logger . warn ( ' %s : error getting dependent interfaces ( %s ) '
% ( ifaceobj . name , str ( e ) ) )
dlist = None
pass
2014-10-06 11:11:10 -07:00
if dlist : ret_dlist . extend ( dlist )
2014-10-24 10:11:07 -07:00
return list ( set ( ret_dlist ) )
2014-02-26 08:09:44 -08:00
2016-02-25 23:55:27 -08:00
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 ) )
2015-04-03 21:24:25 -07:00
2014-10-28 16:10:00 -07:00
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
2016-02-25 23:55:27 -08:00
ulist = None
2015-11-28 18:30:12 -08:00
ifaceobjs = self . get_ifaceobjs ( i )
if not ifaceobjs :
2014-10-28 16:10:00 -07:00
continue
2016-02-25 23:55:27 -08:00
dependents_processed = False
2015-11-28 18:30:12 -08:00
# Store all dependency info in the first ifaceobj
# but get dependency info from all ifaceobjs
ifaceobj = ifaceobjs [ 0 ]
for iobj in ifaceobjs :
2016-02-25 23:55:27 -08:00
ulist = self . query_upperifaces ( iobj , ops , ifacenames )
2015-11-28 18:30:12 -08:00
if iobj . lowerifaces :
2016-02-25 23:55:27 -08:00
dependents_processed = True
2015-11-28 18:30:12 -08:00
break
2016-02-25 23:55:27 -08:00
dlist = self . query_lowerifaces ( iobj , ops , ifacenames )
2015-11-28 18:30:12 -08:00
if dlist :
break
2016-02-25 23:55:27 -08:00
if ulist :
self . preprocess_upperiface ( ifaceobj , ulist , ops )
if dependents_processed :
2014-10-28 16:10:00 -07:00
continue
if dlist :
2014-12-08 17:15:57 -08:00
self . preprocess_dependency_list ( ifaceobj ,
2014-10-28 16:10:00 -07:00
dlist , ops )
ifaceobj . lowerifaces = dlist
[ iqueue . append ( d ) for d in dlist ]
2016-02-25 23:55:27 -08:00
#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 ] = [ ]
2014-10-28 16:10:00 -07:00
2015-10-02 13:18:03 -07:00
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
2016-03-30 11:54:58 -07:00
2015-10-02 13:18:03 -07:00
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 :
2015-10-20 14:30:53 -07:00
difaceobjs = self . get_ifaceobjs ( d )
if not difaceobjs :
2015-10-02 13:18:03 -07:00
continue
try :
2015-10-20 14:30:53 -07:00
for d in difaceobjs :
d . dec_refcnt ( )
d . upperifaces . remove ( i )
2015-10-02 13:18:03 -07:00
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 ]
2016-03-30 11:54:58 -07:00
continue
2015-10-02 13:18:03 -07:00
2014-11-03 17:55:51 -08:00
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
2013-11-04 06:06:11 -08:00
2016-03-16 18:38:43 -07:00
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
2016-04-03 15:31:34 -07:00
if ifaceobj . type == ifaceType . BRIDGE_VLAN :
self . ifaceobjdict [ ifaceobj . name ] . append ( ifaceobj )
else :
currentifaceobjlist [ 0 ] . squash ( ifaceobj )
2016-03-16 18:38:43 -07:00
2014-10-06 11:11:10 -07:00
def _save_iface ( self , ifaceobj ) :
2014-11-03 17:55:51 -08:00
if self . _check_config_no_repeats ( ifaceobj ) :
return
2016-02-25 17:10:33 -08:00
ifaceobj . priv_flags = ifacePrivFlags ( )
2014-12-26 09:21:50 -08:00
if not self . _link_master_slave :
ifaceobj . link_type = ifaceLinkType . LINK_NA
2014-10-09 12:58:16 -07:00
currentifaceobjlist = self . ifaceobjdict . get ( ifaceobj . name )
if not currentifaceobjlist :
2016-03-08 20:40:02 -08:00
self . ifaceobjdict [ ifaceobj . name ] = [ ifaceobj ]
if not self . _ifaceobj_squash :
ifaceobj . flags | = ifaceobj . YOUNGEST_SIBLING
return
2014-10-09 12:58:16 -07:00
if ifaceobj . compare ( currentifaceobjlist [ 0 ] ) :
self . logger . warn ( ' duplicate interface %s found ' % ifaceobj . name )
return
2014-11-03 17:55:51 -08:00
if currentifaceobjlist [ 0 ] . type == ifaceobj . type :
2015-10-20 13:49:07 -04:00
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
2014-10-09 12:58:16 -07:00
self . ifaceobjdict [ ifaceobj . name ] . append ( ifaceobj )
2014-10-06 11:11:10 -07:00
2014-04-28 22:33:33 -07:00
def _iface_configattr_syntax_checker ( self , attrname , attrval ) :
2014-02-08 09:05:32 -08:00
for m , mdict in self . module_attrs . items ( ) :
2014-04-08 14:50:15 -07:00
if not mdict :
continue
2014-02-08 09:05:32 -08:00
attrsdict = mdict . get ( ' attrs ' )
2014-04-08 14:50:15 -07:00
try :
2016-03-03 16:39:59 -08:00
a = attrsdict . get ( attrname )
if a :
if a . get ( ' deprecated ' ) :
newa = a . get ( ' new-attribute ' )
if newa :
2016-05-07 19:31:16 -07:00
self . logger . warn ( ' attribute %s is deprecated. use %s instead. ' % ( attrname , newa ) )
2016-03-03 16:39:59 -08:00
else :
2016-05-07 19:31:16 -07:00
self . logger . warn ( ' attribute %s is deprecated. '
2016-03-03 16:39:59 -08:00
% attrname )
2014-04-08 14:50:15 -07:00
return True
except AttributeError :
pass
2014-02-08 09:05:32 -08:00
return False
2014-04-28 22:33:33 -07:00
def _ifaceobj_syntax_checker ( self , ifaceobj ) :
2015-11-22 16:26:14 -08:00
ret = True
2014-11-03 17:55:51 -08:00
for attrname , attrvalue in ifaceobj . config . items ( ) :
2014-04-28 22:33:33 -07:00
found = False
for k , v in self . module_attrs . items ( ) :
if v and v . get ( ' attrs ' , { } ) . get ( attrname ) :
found = True
break
if not found :
2015-11-22 16:26:14 -08:00
ret = False
2015-03-10 16:46:07 -04:00
self . logger . warn ( ' %s : unsupported attribute \' %s \' ' \
% ( ifaceobj . name , attrname ) )
2014-04-28 22:33:33 -07:00
continue
2015-11-22 16:26:14 -08:00
return ret
2014-04-28 22:33:33 -07:00
2014-04-18 14:09:20 -07:00
def read_iface_config ( self ) :
2013-11-04 06:06:11 -08:00
""" Reads default network interface config /etc/network/interfaces. """
2015-11-22 16:26:14 -08:00
ret = True
2014-04-18 14:09:20 -07:00
nifaces = networkInterfaces ( self . interfacesfile ,
2014-04-28 22:33:33 -07:00
self . interfacesfileiobuf ,
self . interfacesfileformat ,
2014-04-18 14:09:20 -07:00
template_engine = self . config . get ( ' template_engine ' ) ,
template_lookuppath = self . config . get ( ' template_lookuppath ' ) )
2016-03-16 18:38:43 -07:00
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 )
2014-04-28 22:33:33 -07:00
nifaces . subscribe ( ' validateifaceattr ' ,
self . _iface_configattr_syntax_checker )
nifaces . subscribe ( ' validateifaceobj ' , self . _ifaceobj_syntax_checker )
2013-11-04 06:06:11 -08:00
nifaces . load ( )
2015-11-22 16:26:14 -08:00
if nifaces . errors or nifaces . warns :
ret = False
return ret
2013-11-04 06:06:11 -08:00
def read_old_iface_config ( self ) :
2014-04-18 14:09:20 -07:00
""" Reads the saved iface config instead of default iface config.
And saved iface config is already read by the statemanager """
2014-03-30 22:38:00 -07:00
self . ifaceobjdict = copy . deepcopy ( self . statemanager . ifaceobjdict )
2013-11-04 06:06:11 -08:00
2014-03-25 15:21:19 -07:00
def _load_addon_modules_config ( self ) :
""" Load addon modules config file """
2013-11-04 06:06:11 -08:00
2014-01-30 22:36:41 -08:00
with open ( self . addon_modules_configfile , ' r ' ) as f :
lines = f . readlines ( )
for l in lines :
2015-01-22 12:56:56 -08:00
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 \' ' % ( l , str ( e ) ) )
continue
2014-01-30 22:36:41 -08:00
def load_addon_modules ( self , modules_dir ) :
2013-11-04 06:06:11 -08:00
""" load python modules from modules_dir
Default modules_dir is / usr / share / ifupdownmodules
"""
self . logger . info ( ' loading builtin modules from %s ' % modules_dir )
2014-03-25 15:21:19 -07:00
self . _load_addon_modules_config ( )
2013-11-04 06:06:11 -08:00
if not modules_dir in sys . path :
2014-01-30 22:36:41 -08:00
sys . path . append ( modules_dir )
2013-11-04 06:06:11 -08:00
try :
2014-02-17 19:01:37 -08:00
for op , mlist in self . module_ops . items ( ) :
2014-02-08 09:05:32 -08:00
for mname in mlist :
2014-03-25 15:21:19 -07:00
if self . modules . get ( mname ) :
2014-02-08 09:05:32 -08:00
continue
mpath = modules_dir + ' / ' + mname + ' .py '
if os . path . exists ( mpath ) :
try :
m = __import__ ( mname )
mclass = getattr ( m , mname )
except :
raise
2016-04-14 14:45:47 -07:00
minstance = mclass ( )
2014-02-08 09:05:32 -08:00
self . modules [ mname ] = minstance
2014-03-25 15:21:19 -07:00
try :
2014-02-08 09:05:32 -08:00
self . module_attrs [ mname ] = minstance . get_modinfo ( )
2014-03-25 15:21:19 -07:00
except :
pass
2013-11-04 06:06:11 -08:00
except :
raise
2014-01-30 22:36:41 -08:00
# Assign all modules to query operations
2014-02-17 19:01:37 -08:00
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 ( )
2014-02-08 09:05:32 -08:00
2014-04-18 14:09:20 -07:00
2014-03-25 15:21:19 -07:00
def _modules_help ( self ) :
""" Prints addon modules supported syntax """
2014-02-08 09:05:32 -08:00
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 ( ' %s help: %s ' % ( indent + ' ' ,
attrvaldict . get ( ' help ' , ' ' ) ) )
print ( ' %s required: %s ' % ( indent + ' ' ,
attrvaldict . get ( ' required ' , False ) ) )
default = attrvaldict . get ( ' default ' )
if default :
print ( ' %s default: %s ' % ( indent + ' ' , default ) )
validrange = attrvaldict . get ( ' validrange ' )
if validrange :
2014-06-12 06:27:29 -07:00
print ( ' %s validrange: %s - %s '
2014-04-08 14:50:15 -07:00
% ( indent + ' ' , validrange [ 0 ] , validrange [ 1 ] ) )
2014-02-08 09:05:32 -08:00
validvals = attrvaldict . get ( ' validvals ' )
if validvals :
print ( ' %s validvals: %s '
% ( indent + ' ' , ' , ' . join ( validvals ) ) )
examples = attrvaldict . get ( ' example ' )
if not examples :
continue
2013-11-04 06:06:11 -08:00
2014-02-08 09:05:32 -08:00
print ' %s example: ' % ( indent + ' ' )
for e in examples :
print ' %s %s ' % ( indent + ' ' , e )
except :
pass
print ' '
2014-01-30 22:36:41 -08:00
def load_scripts ( self , modules_dir ) :
2013-11-04 06:06:11 -08:00
""" loading user modules from /etc/network/.
Note that previously loaded python modules override modules found
under / etc / network if any
"""
2014-01-30 22:36:41 -08:00
self . logger . info ( ' looking for user scripts under %s ' % modules_dir )
2014-02-17 19:01:37 -08:00
for op , mlist in self . script_ops . items ( ) :
2014-02-08 09:05:32 -08:00
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
2014-02-17 19:01:37 -08:00
self . script_ops [ op ] . append (
2013-11-04 06:06:11 -08:00
msubdir + ' / ' + module )
2014-02-08 09:05:32 -08:00
except :
2014-02-13 21:37:26 -08:00
# continue reading
pass
2013-11-04 06:06:11 -08:00
2016-04-20 03:02:26 -07:00
def _sched_ifaces ( self , ifacenames , ops , skipupperifaces = False ,
followdependents = True , sort = False ) :
2014-03-18 16:38:00 -07:00
self . logger . debug ( ' scheduling \' %s \' for %s '
2014-02-08 09:05:32 -08:00
% ( str ( ops ) , str ( ifacenames ) ) )
2014-04-01 15:21:51 -07:00
self . _pretty_print_ordered_dict ( ' dependency graph ' ,
self . dependency_graph )
2016-04-20 03:02:26 -07:00
ifaceScheduler . sched_ifaces ( self , ifacenames , ops ,
2014-03-18 16:38:00 -07:00
dependency_graph = self . dependency_graph ,
2014-02-08 09:05:32 -08:00
order = ifaceSchedulerFlags . INORDER
if ' down ' in ops [ 0 ]
2014-03-18 16:38:00 -07:00
else ifaceSchedulerFlags . POSTORDER ,
2015-04-03 20:47:06 -07:00
followdependents = followdependents ,
2015-04-25 15:33:28 -07:00
skipupperifaces = skipupperifaces ,
2016-02-25 17:10:33 -08:00
sort = True if ( sort or self . flags . IFACE_CLASS ) else False )
2016-03-18 11:27:42 -07:00
return ifaceScheduler . get_sched_status ( )
2013-11-04 06:06:11 -08:00
2014-10-06 11:11:10 -07:00
def _render_ifacename ( self , ifacename ) :
new_ifacenames = [ ]
2014-10-09 12:58:16 -07:00
vlan_match = re . match ( " ^([ \ d]+)-([ \ d]+) " , ifacename )
2014-10-06 11:11:10 -07:00
if vlan_match :
vlan_groups = vlan_match . groups ( )
if vlan_groups [ 0 ] and vlan_groups [ 1 ] :
2014-10-09 12:58:16 -07:00
[ new_ifacenames . append ( ' %d ' % v )
2014-10-06 11:11:10 -07:00
for v in range ( int ( vlan_groups [ 0 ] ) ,
int ( vlan_groups [ 1 ] ) + 1 ) ]
return new_ifacenames
def _preprocess_ifacenames ( self , ifacenames ) :
2013-11-04 06:06:11 -08:00
""" validates interface list for config existance.
returns - 1 if one or more interface not found . else , returns 0
"""
2014-10-06 11:11:10 -07:00
new_ifacenames = [ ]
2013-11-04 06:06:11 -08:00
err_iface = ' '
for i in ifacenames :
2014-02-24 11:07:59 -08:00
ifaceobjs = self . get_ifaceobjs ( i )
if not ifaceobjs :
2014-10-06 11:11:10 -07:00
# if name not available, render interface name and check again
2014-10-09 12:58:16 -07:00
rendered_ifacenames = utils . expand_iface_range ( i )
2014-10-06 11:11:10 -07:00
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 )
2014-02-19 21:30:55 -08:00
if err_iface :
2014-05-05 13:39:00 -07:00
raise Exception ( ' cannot find interfaces: %s ' % err_iface )
2014-10-06 11:11:10 -07:00
return new_ifacenames
2013-11-04 06:06:11 -08:00
2014-03-25 15:21:19 -07:00
def _iface_whitelisted ( self , auto , allow_classes , excludepats , ifacename ) :
2013-11-04 06:06:11 -08:00
""" Checks if interface is whitelisted depending on set of parameters.
interfaces are checked against the allow_classes and auto lists .
"""
2015-10-20 08:45:20 -07:00
2015-06-21 17:37:27 -07:00
ret = True
2015-10-09 15:14:56 -07:00
# Check if interface matches the exclude patter
2014-02-19 21:30:55 -08:00
if excludepats :
2013-11-13 16:07:15 -08:00
for e in excludepats :
2014-02-08 09:05:32 -08:00
if re . search ( e , ifacename ) :
2015-06-21 17:37:27 -07:00
ret = False
2014-02-24 11:07:59 -08:00
ifaceobjs = self . get_ifaceobjs ( ifacename )
if not ifaceobjs :
2015-06-21 17:37:27 -07:00
if ret :
self . logger . debug ( ' iface %s ' % ifacename + ' not found ' )
return ret
2015-10-02 13:18:03 -07:00
# If matched exclude pattern, return false
2015-06-21 17:37:27 -07:00
if not ret :
for i in ifaceobjs :
i . blacklisted = True
2015-10-02 13:18:03 -07:00
self . blacklisted_ifaces_present = True
2015-06-21 17:37:27 -07:00
return ret
# Check if interface belongs to the class
2015-10-02 13:18:03 -07:00
# the user is interested in, if not return false
2014-02-19 21:30:55 -08:00
if allow_classes :
2015-10-09 15:14:56 -07:00
ret = False
2013-11-04 06:06:11 -08:00
for i in ifaceobjs :
2014-03-22 22:16:53 -07:00
if i . classes :
2013-11-13 16:07:15 -08:00
common = Set ( [ allow_classes ] ) . intersection (
2014-03-22 22:16:53 -07:00
Set ( i . classes ) )
2014-02-19 21:30:55 -08:00
if common :
2015-06-21 17:37:27 -07:00
ret = True
if not ret :
2015-10-09 15:14:56 -07:00
# 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
2015-10-02 13:18:03 -07:00
# If the user has requested auto class, check if the interface
# is marked auto
2014-02-08 09:05:32 -08:00
if auto :
2015-10-09 15:14:56 -07:00
ret = False
2013-11-04 06:06:11 -08:00
for i in ifaceobjs :
2014-03-22 22:16:53 -07:00
if i . auto :
2015-06-21 17:37:27 -07:00
ret = True
2015-10-09 15:14:56 -07:00
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 :
2015-06-21 17:37:27 -07:00
i . blacklisted = True
return ret
2013-11-04 06:06:11 -08:00
2014-03-25 15:21:19 -07:00
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
2013-11-04 06:06:11 -08:00
def generate_running_env ( self , ifaceobj , op ) :
2014-01-16 06:46:17 -08:00
""" Generates a dictionary with env variables required for
an interface . Used to support script execution for interfaces .
2013-11-04 06:06:11 -08:00
"""
cenv = None
2014-03-22 22:16:53 -07:00
iface_env = ifaceobj . env
if iface_env :
2013-11-04 06:06:11 -08:00
cenv = os . environ
2014-02-08 09:05:32 -08:00
if cenv :
2013-11-04 06:06:11 -08:00
cenv . update ( iface_env )
else :
cenv = iface_env
2014-03-25 15:21:19 -07:00
cenv [ ' MODE ' ] = self . _compat_conv_op_to_mode ( op )
2013-11-04 06:06:11 -08:00
return cenv
2014-03-25 15:21:19 -07:00
def _save_state ( self ) :
2016-02-25 17:10:33 -08:00
if ( not self . flags . STATEMANAGER_ENABLE or
not self . flags . STATEMANAGER_UPDATE ) :
2014-02-26 08:09:44 -08:00
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 ) )
2014-11-11 21:58:12 -08:00
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
2014-12-17 12:39:38 -08:00
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
2014-02-08 09:05:32 -08:00
def up ( self , ops , auto = False , allow_classes = None , ifacenames = None ,
2014-11-11 21:58:12 -08:00
excludepats = None , printdependency = None , syntaxcheck = False ,
2014-11-25 10:19:35 -08:00
type = None , skipupperifaces = False ) :
2014-07-17 11:44:36 -07:00
""" This brings the interface(s) up
Args :
2014-10-06 11:11:10 -07:00
ops ( list ) : list of ops to perform on the interface ( s ) .
Eg : [ ' pre-up ' , ' up ' , ' post-up '
2014-07-17 11:44:36 -07:00
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
"""
2014-03-25 15:21:19 -07:00
2014-11-11 21:58:12 -08:00
self . set_type ( type )
2014-06-25 15:23:04 -07:00
if allow_classes :
2016-02-25 17:10:33 -08:00
self . flags . IFACE_CLASS = True
if not self . flags . ADDONS_ENABLE :
self . flags . STATEMANAGER_UPDATE = False
2014-02-08 09:05:32 -08:00
if auto :
2016-05-13 22:44:50 -07:00
ifupdownflags . flags . ALL = True
ifupdownflags . flags . WITH_DEPENDS = True
2014-02-08 09:05:32 -08:00
try :
2015-11-22 16:26:14 -08:00
iface_read_ret = self . read_iface_config ( )
2014-03-22 22:16:53 -07:00
except Exception :
2014-02-08 09:05:32 -08:00
raise
2013-11-04 06:06:11 -08:00
2014-02-24 11:07:59 -08:00
if ifacenames :
2014-10-06 11:11:10 -07:00
ifacenames = self . _preprocess_ifacenames ( ifacenames )
2013-11-04 06:06:11 -08:00
# if iface list not given by user, assume all from config file
2014-02-24 11:07:59 -08:00
if not ifacenames : ifacenames = self . ifaceobjdict . keys ( )
2013-11-04 06:06:11 -08:00
# filter interfaces based on auto and allow classes
2014-01-17 23:10:12 -08:00
filtered_ifacenames = [ i for i in ifacenames
2014-03-25 15:21:19 -07:00
if self . _iface_whitelisted ( auto , allow_classes ,
2014-02-08 09:05:32 -08:00
excludepats , i ) ]
2014-02-19 21:30:55 -08:00
if not filtered_ifacenames :
2014-02-08 09:05:32 -08:00
raise Exception ( ' no ifaces found matching given allow lists ' )
2013-11-04 06:06:11 -08:00
2014-02-26 08:09:44 -08:00
if printdependency :
2014-03-18 16:38:00 -07:00
self . populate_dependency_info ( ops , filtered_ifacenames )
2014-02-08 09:05:32 -08:00
self . print_dependency ( filtered_ifacenames , printdependency )
2014-01-16 06:46:17 -08:00
return
2014-01-17 23:10:12 -08:00
else :
2014-03-18 16:38:00 -07:00
self . populate_dependency_info ( ops )
2015-11-22 16:26:14 -08:00
# If only syntax check was requested, return here.
# return here because we want to make sure most
# errors above are caught and reported.
2015-09-04 16:12:20 -07:00
if syntaxcheck :
2015-11-22 16:26:14 -08:00
if not iface_read_ret :
raise Exception ( )
2015-09-04 16:12:20 -07:00
return
2016-04-29 21:22:52 +02:00
ret = None
2014-04-04 15:00:59 -07:00
try :
2016-03-18 11:27:42 -07:00
ret = self . _sched_ifaces ( filtered_ifacenames , ops ,
skipupperifaces = skipupperifaces ,
followdependents = True
2016-05-13 22:44:50 -07:00
if ifupdownflags . flags . WITH_DEPENDS
else False )
2014-04-04 15:00:59 -07:00
finally :
2014-12-17 12:39:38 -08:00
self . _process_delay_admin_state_queue ( ' up ' )
2016-04-14 14:45:47 -07:00
if not ifupdownflags . flags . DRYRUN and self . flags . ADDONS_ENABLE :
2014-04-04 15:00:59 -07:00
self . _save_state ( )
2013-11-04 06:06:11 -08:00
2016-03-18 11:27:42 -07:00
if not iface_read_ret or not ret :
raise Exception ( )
2014-02-08 09:05:32 -08:00
def down ( self , ops , auto = False , allow_classes = None , ifacenames = None ,
2014-11-11 21:58:12 -08:00
excludepats = None , printdependency = None , usecurrentconfig = False ,
type = None ) :
2014-03-25 15:21:19 -07:00
""" down an interface """
2014-11-11 21:58:12 -08:00
self . set_type ( type )
2014-06-25 15:23:04 -07:00
if allow_classes :
2016-02-25 17:10:33 -08:00
self . flags . IFACE_CLASS = True
if not self . flags . ADDONS_ENABLE :
self . flags . STATEMANAGER_UPDATE = False
2014-02-08 09:05:32 -08:00
if auto :
2016-05-13 22:44:50 -07:00
ifupdownflags . flags . ALL = True
ifupdownflags . flags . WITH_DEPENDS = True
2014-03-06 06:41:28 -08:00
# For down we need to look at old state, unless usecurrentconfig
# is set
2016-02-25 17:10:33 -08:00
if ( not usecurrentconfig and self . flags . STATEMANAGER_ENABLE and
2014-03-25 15:21:19 -07:00
self . statemanager . ifaceobjdict ) :
2014-02-24 11:07:59 -08:00
# Since we are using state manager objects,
# skip the updating of state manager objects
2014-03-06 06:41:28 -08:00
self . logger . debug ( ' Looking at old state .. ' )
2014-02-08 09:05:32 -08:00
self . read_old_iface_config ( )
2014-02-19 21:30:55 -08:00
else :
2014-02-08 09:05:32 -08:00
# 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
2014-05-05 13:39:00 -07:00
try :
2014-10-06 11:11:10 -07:00
ifacenames = self . _preprocess_ifacenames ( ifacenames )
2014-05-05 13:39:00 -07:00
except Exception , e :
raise Exception ( ' %s ' % str ( e ) +
' (interface was probably never up ?) ' )
2014-02-08 09:05:32 -08:00
# if iface list not given by user, assume all from config file
2014-02-19 21:30:55 -08:00
if not ifacenames : ifacenames = self . ifaceobjdict . keys ( )
2014-03-25 15:21:19 -07:00
2014-02-08 09:05:32 -08:00
# filter interfaces based on auto and allow classes
filtered_ifacenames = [ i for i in ifacenames
2014-03-25 15:21:19 -07:00
if self . _iface_whitelisted ( auto , allow_classes ,
2014-02-08 09:05:32 -08:00
excludepats , i ) ]
2014-02-19 21:30:55 -08:00
if not filtered_ifacenames :
2014-06-13 06:15:40 -07:00
raise Exception ( ' no ifaces found matching given allow lists ' +
2014-10-06 11:11:10 -07:00
' (or interfaces were probably never up ?) ' )
2014-04-18 14:09:20 -07:00
2014-02-08 09:05:32 -08:00
if printdependency :
2014-04-29 21:45:57 -07:00
self . populate_dependency_info ( ops , filtered_ifacenames )
2014-02-08 09:05:32 -08:00
self . print_dependency ( filtered_ifacenames , printdependency )
return
2014-04-29 21:45:57 -07:00
else :
self . populate_dependency_info ( ops )
2014-04-04 15:00:59 -07:00
try :
2015-04-03 20:47:06 -07:00
self . _sched_ifaces ( filtered_ifacenames , ops ,
2016-02-25 17:10:33 -08:00
followdependents = True
2016-05-13 22:44:50 -07:00
if ifupdownflags . flags . WITH_DEPENDS else False )
2014-04-04 15:00:59 -07:00
finally :
2014-12-17 12:39:38 -08:00
self . _process_delay_admin_state_queue ( ' down ' )
2016-04-14 14:45:47 -07:00
if not ifupdownflags . flags . DRYRUN and self . flags . ADDONS_ENABLE :
2014-04-04 15:00:59 -07:00
self . _save_state ( )
2014-02-08 09:05:32 -08:00
2016-04-21 12:45:22 -07:00
def query ( self , ops , auto = False , format_list = False , allow_classes = None ,
ifacenames = None ,
2014-01-16 06:46:17 -08:00
excludepats = None , printdependency = None ,
2016-04-20 03:02:26 -07:00
format = ' native ' , type = None ) :
2014-03-25 15:21:19 -07:00
""" query an interface """
2014-11-11 21:58:12 -08:00
self . set_type ( type )
2016-03-16 18:38:43 -07:00
# Let us forget internal squashing when it comes to
# ifquery. It can surprise people relying of ifquery
# output
self . _ifaceobj_squash_internal = False
2014-06-25 15:23:04 -07:00
if allow_classes :
2016-02-25 17:10:33 -08:00
self . flags . IFACE_CLASS = True
if self . flags . STATEMANAGER_ENABLE and ops [ 0 ] == ' query-savedstate ' :
2014-03-06 06:41:28 -08:00
return self . statemanager . dump_pretty ( ifacenames )
2016-02-25 17:10:33 -08:00
self . flags . STATEMANAGER_UPDATE = False
2014-02-08 09:05:32 -08:00
if auto :
2014-01-16 06:46:17 -08:00
self . logger . debug ( ' setting flag ALL ' )
2016-05-13 22:44:50 -07:00
ifupdownflags . flags . ALL = True
ifupdownflags . flags . WITH_DEPENDS = True
2014-01-16 06:46:17 -08:00
2014-02-08 09:05:32 -08:00
if ops [ 0 ] == ' query-syntax ' :
2014-03-25 15:21:19 -07:00
self . _modules_help ( )
2014-02-08 09:05:32 -08:00
return
elif ops [ 0 ] == ' query-running ' :
2014-01-16 06:46:17 -08:00
# create fake devices to all dependents that dont have config
2016-02-25 17:10:33 -08:00
map ( lambda i : self . create_n_save_ifaceobj ( i ,
ifacePrivFlags ( False , True ) ) , ifacenames )
2014-01-16 06:46:17 -08:00
else :
try :
self . read_iface_config ( )
except Exception :
raise
2014-03-25 15:21:19 -07:00
if ifacenames and ops [ 0 ] != ' query-running ' :
2014-10-06 11:11:10 -07:00
# If iface list is given, always check if iface is present
ifacenames = self . _preprocess_ifacenames ( ifacenames )
2014-01-16 06:46:17 -08:00
# if iface list not given by user, assume all from config file
2014-02-24 11:07:59 -08:00
if not ifacenames : ifacenames = self . ifaceobjdict . keys ( )
2014-01-16 06:46:17 -08:00
# filter interfaces based on auto and allow classes
2014-02-08 09:05:32 -08:00
if ops [ 0 ] == ' query-running ' :
2014-01-16 06:46:17 -08:00
filtered_ifacenames = ifacenames
else :
filtered_ifacenames = [ i for i in ifacenames
2014-03-25 15:21:19 -07:00
if self . _iface_whitelisted ( auto , allow_classes ,
2014-02-08 09:05:32 -08:00
excludepats , i ) ]
2014-02-19 21:30:55 -08:00
if not filtered_ifacenames :
2014-01-16 06:46:17 -08:00
raise Exception ( ' no ifaces found matching ' +
' given allow lists ' )
2014-01-30 22:36:41 -08:00
2014-10-28 16:10:00 -07:00
self . populate_dependency_info ( ops )
2014-02-08 09:05:32 -08:00
if ops [ 0 ] == ' query-dependency ' and printdependency :
self . print_dependency ( filtered_ifacenames , printdependency )
return
2014-01-16 06:46:17 -08:00
2016-04-21 12:45:22 -07:00
if format_list and ( ops [ 0 ] == ' query ' or ops [ 0 ] == ' query-raw ' ) :
return self . print_ifaceobjs_list ( filtered_ifacenames )
2016-04-24 17:24:31 -07:00
if ops [ 0 ] == ' query ' and not ifupdownflags . flags . WITHDEFAULTS :
2014-02-11 06:00:07 -08:00
return self . print_ifaceobjs_pretty ( filtered_ifacenames , format )
elif ops [ 0 ] == ' query-raw ' :
return self . print_ifaceobjs_raw ( filtered_ifacenames )
2016-04-20 03:02:26 -07:00
ret = self . _sched_ifaces ( filtered_ifacenames , ops ,
2016-02-25 17:10:33 -08:00
followdependents = True
2016-05-13 22:44:50 -07:00
if ifupdownflags . flags . WITH_DEPENDS else False )
2014-01-16 06:46:17 -08:00
2016-04-24 17:24:31 -07:00
if ops [ 0 ] == ' query ' and ifupdownflags . flags . WITHDEFAULTS :
return self . print_ifaceobjs_pretty ( filtered_ifacenames , format )
elif ops [ 0 ] == ' query-checkcurr ' :
2014-02-08 09:05:32 -08:00
ret = self . print_ifaceobjscurr_pretty ( filtered_ifacenames , format )
2014-01-16 06:46:17 -08:00
if ret != 0 :
# if any of the object has an error, signal that silently
raise Exception ( ' ' )
2014-02-08 09:05:32 -08:00
elif ops [ 0 ] == ' query-running ' :
self . print_ifaceobjsrunning_pretty ( filtered_ifacenames , format )
2014-01-16 06:46:17 -08:00
return
2014-11-11 21:58:12 -08:00
def _reload_currentlyup ( self , upops , downops , auto = True , allow = None ,
ifacenames = None , excludepats = None , usecurrentconfig = False ,
2015-11-22 16:26:14 -08:00
syntaxcheck = False , * * extra_args ) :
2014-11-11 21:58:12 -08:00
""" reload currently up interfaces """
2014-06-13 06:15:40 -07:00
new_ifaceobjdict = { }
2014-01-16 06:46:17 -08:00
2014-11-11 21:58:12 -08:00
# Override auto to true
auto = True
try :
2015-11-22 16:26:14 -08:00
iface_read_ret = self . read_iface_config ( )
2014-11-11 21:58:12 -08:00
except :
raise
if not self . ifaceobjdict :
self . logger . warn ( " nothing to reload ..exiting. " )
return
already_up_ifacenames = [ ]
2015-10-20 08:45:20 -07:00
if not ifacenames : ifacenames = self . ifaceobjdict . keys ( )
filtered_ifacenames = [ i for i in ifacenames
if self . _iface_whitelisted ( auto , allow ,
excludepats , i ) ]
2014-11-11 21:58:12 -08:00
# generate dependency graph of interfaces
self . populate_dependency_info ( upops )
2015-11-22 16:26:14 -08:00
# 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 ( )
return
2016-02-25 17:10:33 -08:00
if ( not usecurrentconfig and self . flags . STATEMANAGER_ENABLE
2014-11-11 21:58:12 -08:00
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 = Set ( already_up_ifacenames_still_present ) . union (
filtered_ifacenames )
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 ( { } )
2015-10-20 08:45:20 -07:00
falready_up_ifacenames_not_present = [ i for i in
already_up_ifacenames_not_present
if self . _iface_whitelisted ( auto , allow ,
excludepats , i ) ]
2014-11-11 21:58:12 -08:00
self . populate_dependency_info ( downops ,
2015-10-20 08:45:20 -07:00
falready_up_ifacenames_not_present )
self . _sched_ifaces ( falready_up_ifacenames_not_present , downops ,
2015-04-25 15:33:28 -07:00
followdependents = False , sort = True )
2014-11-11 21:58:12 -08:00
else :
self . logger . debug ( ' no interfaces to down .. ' )
# Now, run 'up' with new config dict
# reset statemanager update flag to default
2015-04-25 15:33:28 -07:00
if auto :
2016-05-13 22:44:50 -07:00
ifupdownflags . flags . ALL = True
ifupdownflags . flags . WITH_DEPENDS = True
2014-11-11 21:58:12 -08:00
if new_ifaceobjdict :
2015-05-10 15:42:47 -04:00
# and now, ifaceobjdict is back to current config
2014-11-11 21:58:12 -08:00
self . ifaceobjdict = new_ifaceobjdict
self . dependency_graph = new_dependency_graph
if not self . ifaceobjdict :
return
self . logger . info ( ' reload: scheduling up on interfaces: %s '
% str ( interfaces_to_up ) )
2016-03-18 11:27:42 -07:00
ret = self . _sched_ifaces ( interfaces_to_up , upops ,
followdependents = True
2016-05-13 22:44:50 -07:00
if ifupdownflags . flags . WITH_DEPENDS else False )
2016-04-14 14:45:47 -07:00
if ifupdownflags . flags . DRYRUN :
2014-11-11 21:58:12 -08:00
return
self . _save_state ( )
2016-03-18 11:27:42 -07:00
if not iface_read_ret or not ret :
raise Exception ( )
2014-11-11 21:58:12 -08:00
def _reload_default ( self , upops , downops , auto = False , allow = None ,
ifacenames = None , excludepats = None , usecurrentconfig = False ,
2015-11-22 16:26:14 -08:00
syntaxcheck = False , * * extra_args ) :
2014-11-11 21:58:12 -08:00
""" reload interface config """
new_ifaceobjdict = { }
2014-01-16 06:46:17 -08:00
try :
2015-11-22 16:26:14 -08:00
iface_read_ret = self . read_iface_config ( )
2014-02-26 08:09:44 -08:00
except :
2014-01-16 06:46:17 -08:00
raise
2014-06-13 06:15:40 -07:00
if not self . ifaceobjdict :
self . logger . warn ( " nothing to reload ..exiting. " )
return
2015-10-20 08:45:20 -07:00
if not ifacenames : ifacenames = self . ifaceobjdict . keys ( )
new_filtered_ifacenames = [ i for i in ifacenames
if self . _iface_whitelisted ( auto , allow ,
excludepats , i ) ]
2014-01-30 22:36:41 -08:00
# generate dependency graph of interfaces
2014-03-18 16:38:00 -07:00
self . populate_dependency_info ( upops )
2015-10-20 08:45:20 -07:00
2015-11-22 16:26:14 -08:00
# 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 ( )
return
2016-02-25 17:10:33 -08:00
if ( not usecurrentconfig and self . flags . STATEMANAGER_ENABLE
2014-04-18 14:09:20 -07:00
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 )
2014-01-30 22:36:41 -08:00
2016-02-25 17:10:33 -08:00
self . ifaceobjdict = OrderedDict ( { } )
self . dependency_graph = OrderedDict ( { } )
2014-01-16 06:46:17 -08:00
# if old state is present, read old state and mark op for 'down'
# followed by 'up' aka: reload
2014-01-30 22:36:41 -08:00
# old interface config is read into self.ifaceobjdict
2014-01-16 06:46:17 -08:00
self . read_old_iface_config ( )
op = ' reload '
else :
# oldconfig not available, continue with 'up' with new config
op = ' up '
2016-03-31 16:09:37 -07:00
new_ifaceobjdict = self . ifaceobjdict
new_dependency_graph = self . dependency_graph
2014-01-16 06:46:17 -08:00
2014-02-19 21:30:55 -08:00
if op == ' reload ' and ifacenames :
2015-10-27 13:00:56 -07:00
ifacenames = self . ifaceobjdict . keys ( )
2015-10-20 08:45:20 -07:00
old_filtered_ifacenames = [ i for i in ifacenames
if self . _iface_whitelisted ( auto , allow ,
2014-02-08 09:05:32 -08:00
excludepats , i ) ]
2015-04-25 15:33:28 -07:00
2016-02-25 17:10:33 -08:00
# 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.
2016-03-08 08:12:33 -08:00
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
2016-02-25 17:10:33 -08:00
# make sure we pick up built-in interfaces
2015-04-25 15:33:28 -07:00
# 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 ' ) )
2014-01-30 22:36:41 -08:00
# 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 = [ ]
2016-02-25 17:10:33 -08:00
for ifname in self . ifaceobjdict . keys ( ) :
2014-11-11 21:58:12 -08:00
lastifaceobjlist = self . ifaceobjdict . get ( ifname )
2016-02-25 17:10:33 -08:00
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
2014-01-30 22:36:41 -08:00
objidx = 0
# If interface is not present in the new file
# append it to the down list
2014-03-25 15:21:19 -07:00
newifaceobjlist = new_ifaceobjdict . get ( ifname )
if not newifaceobjlist :
2014-01-30 22:36:41 -08:00
ifacedownlist . append ( ifname )
continue
2015-09-04 16:12:20 -07:00
# 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
2016-02-25 17:10:33 -08:00
not self . is_ifaceobj_builtin ( newifaceobjlist [ 0 ] ) and
2016-05-07 18:27:05 -07:00
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 ) ) )
2015-04-27 21:18:14 -07:00
if not down_changed :
continue
2014-03-25 15:21:19 -07:00
if len ( newifaceobjlist ) != len ( lastifaceobjlist ) :
2014-01-30 22:36:41 -08:00
ifacedownlist . append ( ifname )
continue
2015-04-25 15:33:28 -07:00
# If interface has changed between the current file
# and the last installed append it to the down list
2014-01-30 22:36:41 -08:00
# compare object list
2014-03-25 15:21:19 -07:00
for objidx in range ( 0 , len ( lastifaceobjlist ) ) :
oldobj = lastifaceobjlist [ objidx ]
newobj = newifaceobjlist [ objidx ]
2014-03-27 14:00:00 -07:00
if not newobj . compare ( oldobj ) :
2014-01-30 22:36:41 -08:00
ifacedownlist . append ( ifname )
continue
2014-02-19 21:30:55 -08:00
if ifacedownlist :
2014-11-11 21:58:12 -08:00
self . logger . info ( ' reload: scheduling down on interfaces: %s '
2014-01-16 06:46:17 -08:00
% str ( ifacedownlist ) )
2014-02-26 08:09:44 -08:00
# reinitialize dependency graph
self . dependency_graph = OrderedDict ( { } )
2016-02-25 17:10:33 -08:00
2014-01-30 22:36:41 -08:00
# Generate dependency info for old config
2016-03-08 08:12:33 -08:00
self . flags . CHECK_SHARED_DEPENDENTS = False
2014-04-18 14:09:20 -07:00
self . populate_dependency_info ( downops , ifacedownlist )
2016-03-08 08:12:33 -08:00
self . flags . CHECK_SHARED_DEPENDENTS = True
2014-12-17 12:39:38 -08:00
try :
2016-02-25 17:10:33 -08:00
# 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
2015-04-03 20:47:06 -07:00
self . _sched_ifaces ( ifacedownlist , downops ,
2015-04-25 15:33:28 -07:00
followdependents = False ,
sort = True )
2014-12-17 12:39:38 -08:00
except Exception , e :
self . logger . error ( str ( e ) )
pass
finally :
2016-02-25 17:10:33 -08:00
self . flags . SCHED_SKIP_CHECK_UPPERIFACES = False
2014-12-17 12:39:38 -08:00
self . _process_delay_admin_state_queue ( ' down ' )
2014-01-30 22:36:41 -08:00
else :
self . logger . debug ( ' no interfaces to down .. ' )
2014-01-16 06:46:17 -08:00
2014-02-26 08:09:44 -08:00
# Now, run 'up' with new config dict
# reset statemanager update flag to default
2014-06-13 06:15:40 -07:00
if not new_ifaceobjdict :
2016-03-17 16:23:40 -07:00
self . logger . debug ( ' no interfaces to up ' )
2014-06-13 06:15:40 -07:00
return
2015-04-25 15:33:28 -07:00
if auto :
2016-05-13 22:44:50 -07:00
ifupdownflags . flags . ALL = True
ifupdownflags . flags . WITH_DEPENDS = True
2015-05-10 15:42:47 -04:00
# and now, we are back to the current config in ifaceobjdict
2014-03-25 15:21:19 -07:00
self . ifaceobjdict = new_ifaceobjdict
self . dependency_graph = new_dependency_graph
2014-03-18 16:38:00 -07:00
2014-11-11 21:58:12 -08:00
self . logger . info ( ' reload: scheduling up on interfaces: %s '
2015-10-20 08:45:20 -07:00
% str ( new_filtered_ifacenames ) )
2016-04-25 22:27:31 -07:00
ifupdownflags . flags . CACHE = True
2014-12-17 12:39:38 -08:00
try :
2016-03-18 11:27:42 -07:00
ret = self . _sched_ifaces ( new_filtered_ifacenames , upops ,
followdependents = True
2016-05-13 22:44:50 -07:00
if ifupdownflags . flags . WITH_DEPENDS
else False )
2014-12-17 12:39:38 -08:00
except Exception , e :
2016-04-29 21:22:52 +02:00
ret = None
2014-12-17 12:39:38 -08:00
self . logger . error ( str ( e ) )
finally :
self . _process_delay_admin_state_queue ( ' up ' )
2016-04-14 14:45:47 -07:00
if ifupdownflags . flags . DRYRUN :
2014-02-14 09:55:19 -08:00
return
2014-03-25 15:21:19 -07:00
self . _save_state ( )
2013-11-04 06:06:11 -08:00
2016-03-18 11:27:42 -07:00
if not iface_read_ret or not ret :
raise Exception ( )
2014-11-11 21:58:12 -08:00
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 )
2014-04-01 15:21:51 -07:00
def _pretty_print_ordered_dict ( self , prefix , argdict ) :
2014-04-04 15:00:59 -07:00
outbuf = prefix + ' { \n '
2014-03-25 15:21:19 -07:00
for k , vlist in argdict . items ( ) :
2014-04-04 15:00:59 -07:00
outbuf + = ' \t %s : %s \n ' % ( k , str ( vlist ) )
2014-04-01 15:21:51 -07:00
self . logger . debug ( outbuf + ' } ' )
2013-11-04 06:06:11 -08:00
2014-03-25 15:21:19 -07:00
def print_dependency ( self , ifacenames , format ) :
""" prints iface dependency information """
2013-11-04 06:06:11 -08:00
2014-03-25 15:21:19 -07:00
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 )
2013-11-04 06:06:11 -08:00
2016-04-21 12:45:22 -07:00
def print_ifaceobjs_list ( self , ifacenames ) :
for i in ifacenames :
print i
2014-01-16 06:46:17 -08:00
def print_ifaceobjs_raw ( self , ifacenames ) :
2014-03-25 15:21:19 -07:00
""" prints raw lines for ifaces from config file """
2014-01-16 06:46:17 -08:00
for i in ifacenames :
2014-02-24 11:07:59 -08:00
for ifaceobj in self . get_ifaceobjs ( i ) :
2014-02-11 06:00:07 -08:00
if ( self . is_ifaceobj_builtin ( ifaceobj ) or
not ifaceobj . is_config_present ( ) ) :
continue
ifaceobj . dump_raw ( self . logger )
2014-01-16 06:46:17 -08:00
print ' \n '
2016-05-13 22:44:50 -07:00
if ( ifupdownflags . flags . WITH_DEPENDS and
not ifupdownflags . flags . ALL ) :
2014-03-22 22:16:53 -07:00
dlist = ifaceobj . lowerifaces
2014-02-19 21:30:55 -08:00
if not dlist : continue
2014-03-25 15:21:19 -07:00
self . print_ifaceobjs_raw ( dlist )
2014-01-16 06:46:17 -08:00
2014-04-22 21:55:11 -07:00
def _get_ifaceobjs_pretty ( self , ifacenames , ifaceobjs , running = False ) :
""" returns iface obj list """
2014-03-25 15:21:19 -07:00
2013-11-04 06:06:11 -08:00
for i in ifacenames :
2014-02-24 11:07:59 -08:00
for ifaceobj in self . get_ifaceobjs ( i ) :
2014-04-22 21:55:11 -07:00
if ( ( not running and self . is_ifaceobj_noconfig ( ifaceobj ) ) or
( running and not ifaceobj . is_config_present ( ) ) ) :
2014-02-11 06:00:07 -08:00
continue
2014-04-22 21:55:11 -07:00
ifaceobjs . append ( ifaceobj )
2016-05-13 22:44:50 -07:00
if ( ifupdownflags . flags . WITH_DEPENDS and
not ifupdownflags . flags . ALL ) :
2014-03-22 22:16:53 -07:00
dlist = ifaceobj . lowerifaces
2014-02-19 21:30:55 -08:00
if not dlist : continue
2014-04-22 21:55:11 -07:00
self . _get_ifaceobjs_pretty ( dlist , ifaceobjs , running )
2014-01-16 06:46:17 -08:00
2014-04-22 21:55:11 -07:00
def print_ifaceobjs_pretty ( self , ifacenames , format = ' native ' ) :
""" pretty prints iface in format given by keyword arg format """
2013-11-10 22:35:40 -08:00
2014-04-22 21:55:11 -07:00
ifaceobjs = [ ]
self . _get_ifaceobjs_pretty ( ifacenames , ifaceobjs )
if not ifaceobjs : return
if format == ' json ' :
2014-04-28 22:33:33 -07:00
print json . dumps ( ifaceobjs , cls = ifaceJsonEncoder ,
indent = 4 , separators = ( ' , ' , ' : ' ) )
2014-04-22 21:55:11 -07:00
else :
2014-11-11 21:58:12 -08:00
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 ( )
2014-03-25 15:21:19 -07:00
2014-04-22 21:55:11 -07:00
def _get_ifaceobjscurr_pretty ( self , ifacenames , ifaceobjs ) :
2013-11-10 22:35:40 -08:00
ret = 0
2013-11-04 06:06:11 -08:00
for i in ifacenames :
2014-05-26 09:03:29 -07:00
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 )
2016-05-13 22:44:50 -07:00
if ( ifupdownflags . flags . WITH_DEPENDS and
not ifupdownflags . flags . ALL ) :
2014-05-26 09:03:29 -07:00
dlist = ifaceobj . lowerifaces
if not dlist : continue
dret = self . _get_ifaceobjscurr_pretty ( dlist , ifaceobjs )
if dret : ret = 1
2014-04-22 21:55:11 -07:00
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
2015-11-17 09:48:21 -08:00
# 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 ' , ' ' )
2014-04-22 21:55:11 -07:00
if format == ' json ' :
2015-11-17 09:48:21 -08:00
print json . dumps ( ifaceobjs , cls = ifaceJsonEncoderWithStatus ,
indent = 2 , separators = ( ' , ' , ' : ' ) )
2014-04-22 21:55:11 -07:00
else :
Add support to display status (pass, fail) in ifquery --check json output
Ticket: CM-7464
Reviewed By: CCR-3507
Testing Done: Tested ifquery check sanity
ifquery --check non-json output displays 'pass' and 'fail' for
each attribute on the same line (see below). This output is not json
friendly. For json, include status in 'config_status' a dictionary
whose keys are similar to the 'config' dictionary but values are status
for the corresponding keys in the 'config' dictionary (see example below)
auto bond4
iface bond4 inet static
[pass]
bond-mode 802.3ad [pass]
bond-miimon 100 [pass]
bond-use-carrier 1 [pass]
bond-lacp-rate 1 [pass]
bond-min-links 1 [pass]
bond-xmit-hash-policy layer3+4 [pass]
bond-slaves swp3 swp4 [pass]
[
{
"name": "bond4",
"addr_method": "static",
"addr_family": "inet",
"auto": true,
"config": {
"bond-use-carrier": "1",
"bond-miimon": "100",
"bond-lacp-rate": "1",
"bond-min-links": "1",
"bond-slaves": "swp3 swp4",
"bond-mode": "802.3ad",
"bond-xmit-hash-policy": "layer3+4"
},
"config_status": {
"bond-use-carrier": "pass",
"bond-miimon": "pass",
"bond-lacp-rate": "pass",
"bond-min-links": "pass",
"bond-slaves": "pass",
"bond-mode": "pass",
"bond-xmit-hash-policy": "pass"
},
"status": "pass"
}
]
2015-09-17 21:57:06 -07:00
map ( lambda i : i . dump_pretty ( with_status = True ) , ifaceobjs )
2013-11-10 22:35:40 -08:00
return ret
2013-11-04 06:06:11 -08:00
2014-02-08 09:05:32 -08:00
def print_ifaceobjsrunning_pretty ( self , ifacenames , format = ' native ' ) :
2014-03-25 15:21:19 -07:00
""" pretty prints iface running state """
2014-04-22 21:55:11 -07:00
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 )
2014-03-25 15:21:19 -07:00
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 '