3 # Copyright 2014 Cumulus Networks, Inc. All rights reserved.
4 # Author: Roopa Prabhu, roopa@cumulusnetworks.com
18 import ifupdown
.statemanager
as statemanager
19 import ifupdown
.ifupdownconfig
as ifupdownConfig
20 from networkinterfaces
import *
22 from scheduler
import *
23 from collections
import deque
24 from collections
import OrderedDict
29 .. module:: ifupdownmain
30 :synopsis: main module for ifupdown package
32 .. moduleauthor:: Roopa Prabhu <roopa@cumulusnetworks.com>
37 _crossmark
= u
'\u2717'
38 _success_sym
= '(%s)' %_tickmark
39 _error_sym
= '(%s)' %_crossmark
41 class ifupdownFlags():
51 class ifupdownMainFlags():
55 COMPAT_EXEC_SCRIPTS
= False
56 STATEMANAGER_ENABLE
= True
57 STATEMANAGER_UPDATE
= True
59 DELETE_DEPENDENT_IFACES_WITH_NOCONFIG
= False
60 SCHED_SKIP_CHECK_UPPERIFACES
= False
61 CHECK_SHARED_DEPENDENTS
= True
63 class ifacePrivFlags():
64 # priv flags to mark iface objects
68 def __init__(self
, builtin
=False, noconfig
=False):
69 self
.BUILTIN
= builtin
70 self
.NOCONFIG
= noconfig
72 class ifupdownMain(ifupdownBase
):
73 """ ifupdown2 main class """
75 scripts_dir
='/etc/network'
76 addon_modules_dir
='/usr/share/ifupdown2/addons'
77 addon_modules_configfile
='/etc/network/ifupdown2/addons.conf'
79 # iface dictionary in the below format:
80 # { '<ifacename>' : [<ifaceobject1>, <ifaceobject2> ..] }
82 # { 'swp1' : [<iface swp1>, <iface swp2> ..] }
84 # Each ifaceobject corresponds to a configuration block for
86 # The value in the dictionary is a list because the network
87 # interface configuration file supports more than one iface section
88 # in the interfaces file
89 ifaceobjdict
= OrderedDict()
91 # iface dictionary representing the curr running state of an iface
92 # in the below format:
93 # {'<ifacename>' : <ifaceobject>}
94 ifaceobjcurrdict
= OrderedDict()
96 # Dictionary representing operation and modules
98 module_ops
= OrderedDict([('pre-up', []),
101 ('query-checkcurr', []),
102 ('query-running', []),
103 ('query-dependency', []),
110 # For old style /etc/network/ bash scripts
111 script_ops
= OrderedDict([('pre-up', []),
118 # Handlers for ops that ifupdown2 owns
119 def run_up(self
, ifaceobj
):
120 # Skip link sets on ifaceobjs of type 'vlan' (used for l2 attrs).
121 # there is no real interface behind it
122 if ifaceobj
.type == ifaceType
.BRIDGE_VLAN
:
124 if (ifaceobj
.addr_method
and
125 ifaceobj
.addr_method
== 'manual'):
127 if self
._delay
_admin
_state
:
128 self
._delay
_admin
_state
_iface
_queue
.append(ifaceobj
.name
)
130 # If this object is a link slave, ie its link is controlled
131 # by its link master interface, then dont set the link state.
132 # But do allow user to change state of the link if the interface
133 # is already with its link master (hence the master check).
134 if ifaceobj
.link_type
== ifaceLinkType
.LINK_SLAVE
:
136 if not self
.link_exists(ifaceobj
.name
):
138 self
.link_up(ifaceobj
.name
)
140 def run_down(self
, ifaceobj
):
141 # Skip link sets on ifaceobjs of type 'vlan' (used for l2 attrs)
142 # there is no real interface behind it
143 if ifaceobj
.type == ifaceType
.BRIDGE_VLAN
:
145 if (ifaceobj
.addr_method
and
146 ifaceobj
.addr_method
== 'manual'):
148 if self
._delay
_admin
_state
:
149 self
._delay
_admin
_state
_iface
_queue
.append(ifaceobj
.name
)
151 # If this object is a link slave, ie its link is controlled
152 # by its link master interface, then dont set the link state.
153 # But do allow user to change state of the link if the interface
154 # is already with its link master (hence the master check).
155 if ifaceobj
.link_type
== ifaceLinkType
.LINK_SLAVE
:
157 if not self
.link_exists(ifaceobj
.name
):
159 self
.link_down(ifaceobj
.name
)
161 # ifupdown object interface operation handlers
162 ops_handlers
= OrderedDict([('up', run_up
),
165 def run_sched_ifaceobj_posthook(self
, ifaceobj
, op
):
166 if (ifaceobj
.priv_flags
and (ifaceobj
.priv_flags
.BUILTIN
or
167 ifaceobj
.priv_flags
.NOCONFIG
)):
169 if self
.flags
.STATEMANAGER_UPDATE
:
170 self
.statemanager
.ifaceobj_sync(ifaceobj
, op
)
172 # ifupdown object interface scheduler pre and posthooks
173 sched_hooks
= {'posthook' : run_sched_ifaceobj_posthook
}
175 def __init__(self
, config
={},
176 force
=False, dryrun
=False, nowait
=False,
177 perfmode
=False, withdepends
=False, njobs
=1,
178 cache
=False, addons_enable
=True, statemanager_enable
=True,
179 interfacesfile
='/etc/network/interfaces',
180 interfacesfileiobuf
=None,
181 interfacesfileformat
='native'):
182 """This member function initializes the ifupdownmain object.
185 config (dict): config dict from /etc/network/ifupdown2/ifupdown2.conf
186 force (bool): force interface configuration
187 dryrun (bool): dryrun interface configuration
188 withdepends (bool): apply interface configuration on all depends
189 interfacesfile (str): interfaces file. default is /etc/network/interfaces
190 interfacesfileformat (str): default is 'native'. Other choices are 'json'
193 AttributeError, KeyError """
195 self
.logger
= logging
.getLogger('ifupdown')
199 self
.PERFMODE
= perfmode
201 # Can be used to provide hints for caching
202 self
.CACHE_FLAGS
= 0x0
204 self
.flags
= ifupdownMainFlags()
206 self
.flags
.WITH_DEPENDS
= withdepends
207 self
.flags
.STATEMANAGER_ENABLE
= statemanager_enable
208 self
.interfacesfile
= interfacesfile
209 self
.interfacesfileiobuf
= interfacesfileiobuf
210 self
.interfacesfileformat
= interfacesfileformat
212 self
.logger
.debug(self
.config
)
213 self
.blacklisted_ifaces_present
= False
215 self
.type = ifaceType
.UNKNOWN
217 self
.flags
.DELETE_DEPENDENT_IFACES_WITH_NOCONFIG
= False
218 self
.flags
.ADDONS_ENABLE
= addons_enable
220 # Copy flags into ifupdownFlags
221 # XXX: before we transition fully to ifupdownFlags
222 ifupdownFlags
.FORCE
= force
223 ifupdownFlags
.DRYRUN
= dryrun
224 ifupdownFlags
.NOWAIT
= nowait
225 ifupdownFlags
.PERFMODE
= perfmode
226 ifupdownFlags
.CACHE
= cache
228 self
.ifaces
= OrderedDict()
230 self
.pp
= pprint
.PrettyPrinter(indent
=4)
231 self
.modules
= OrderedDict({})
232 self
.module_attrs
= {}
234 self
.load_addon_modules(self
.addon_modules_dir
)
235 if self
.flags
.COMPAT_EXEC_SCRIPTS
:
236 self
.load_scripts(self
.scripts_dir
)
237 self
.dependency_graph
= OrderedDict({})
239 self
._cache
_no
_repeats
= {}
241 if self
.flags
.STATEMANAGER_ENABLE
:
243 self
.statemanager
= statemanager
.statemanager_api
244 self
.statemanager
.read_saved_state()
246 # XXX Maybe we should continue by ignoring old state
247 self
.logger
.warning('error reading state (%s)' %str
(e
))
250 self
.flags
.STATEMANAGER_UPDATE
= False
251 self
._delay
_admin
_state
= True if self
.config
.get(
252 'delay_admin_state_change', '0') == '1' else False
253 self
._delay
_admin
_state
_iface
_queue
= []
254 if self
._delay
_admin
_state
:
255 self
.logger
.info('\'delay_admin_state_change\' is set. admin ' +
256 'state changes will be delayed till the end.')
258 self
._link
_master
_slave
= True if self
.config
.get(
259 'link_master_slave', '0') == '1' else False
260 if self
._link
_master
_slave
:
261 self
.logger
.info('\'link_master_slave\' is set. slave admin ' +
262 'state changes will be delayed till the ' +
263 'masters admin state change.')
265 self
._ifaceobj
_squash
= True if self
.config
.get(
266 'ifaceobj_squash', '0') == '1' else False
268 # initialize global config object with config passed by the user
269 # This makes config available to addon modules
270 ifupdownConfig
.config
= self
.config
272 def link_master_slave_ignore_error(self
, errorstr
):
273 # If link master slave flag is set,
274 # there may be cases where the lowerdev may not be
275 # up resulting in 'Network is down' error
276 # This can happen if the lowerdev is a LINK_SLAVE
277 # of another interface which is not up yet
278 # example of such a case:
279 # bringing up a vlan on a bond interface and the bond
280 # is a LINK_SLAVE of a bridge (in other words the bond is
281 # part of a bridge) which is not up yet
282 if self
._link
_master
_slave
:
283 if 'Network is down':
287 def get_ifaceobjs(self
, ifacename
):
288 return self
.ifaceobjdict
.get(ifacename
)
290 def get_ifaceobjs_saved(self
, ifacename
):
291 """ Return ifaceobjects from statemanager """
292 if self
.flags
.STATEMANAGER_ENABLE
:
293 return self
.statemanager
.get_ifaceobjs(ifacename
)
297 def get_ifaceobj_first(self
, ifacename
):
298 ifaceobjs
= self
.get_ifaceobjs(ifacename
)
303 def get_ifacenames(self
):
304 return self
.ifaceobjdict
.keys()
306 def get_iface_obj_last(self
, ifacename
):
307 return self
.ifaceobjdict
.get(ifacename
)[-1]
310 def must_follow_upperifaces(self
, ifacename
):
312 # XXX: This bleeds the knowledge of iface
313 # types in the infrastructure module.
314 # Cant think of a better fix at the moment.
315 # In future maybe the module can set a flag
316 # to indicate if we should follow upperifaces
318 ifaceobj
= self
.get_ifaceobj_first(ifacename
)
319 if ifaceobj
.type == ifaceType
.BRIDGE_VLAN
:
323 def create_n_save_ifaceobj(self
, ifacename
, priv_flags
=None,
325 """ creates a iface object and adds it to the iface dictionary """
327 ifaceobj
.name
= ifacename
328 ifaceobj
.priv_flags
= priv_flags
330 if not self
._link
_master
_slave
:
331 ifaceobj
.link_type
= ifaceLinkType
.LINK_NA
333 ifaceobj
.inc_refcnt()
334 self
.ifaceobjdict
[ifacename
] = [ifaceobj
]
337 def create_n_save_ifaceobjcurr(self
, ifaceobj
):
338 """ creates a copy of iface object and adds it to the iface
339 dict containing current iface objects
341 ifaceobjcurr
= iface()
342 ifaceobjcurr
.name
= ifaceobj
.name
343 ifaceobjcurr
.type = ifaceobj
.type
344 ifaceobjcurr
.lowerifaces
= ifaceobj
.lowerifaces
345 ifaceobjcurr
.priv_flags
= copy
.deepcopy(ifaceobj
.priv_flags
)
346 ifaceobjcurr
.auto
= ifaceobj
.auto
347 self
.ifaceobjcurrdict
.setdefault(ifaceobj
.name
,
348 []).append(ifaceobjcurr
)
351 def get_ifaceobjcurr(self
, ifacename
, idx
=0):
352 ifaceobjlist
= self
.ifaceobjcurrdict
.get(ifacename
)
358 return ifaceobjlist
[idx
]
360 def get_ifaceobjrunning(self
, ifacename
):
361 return self
.ifaceobjrunningdict
.get(ifacename
)
363 def get_iface_refcnt(self
, ifacename
):
364 """ Return iface ref count """
366 ifaceobjs
= self
.get_ifaceobjs(ifacename
)
374 def is_iface_builtin_byname(self
, ifacename
):
375 """ Returns true if iface name is a builtin interface.
377 A builtin interface is an interface which ifupdown understands.
378 The following are currently considered builtin ifaces:
379 - vlan interfaces in the format <ifacename>.<vlanid>
381 return '.' in ifacename
383 def is_ifaceobj_builtin(self
, ifaceobj
):
384 """ Returns true if iface name is a builtin interface.
386 A builtin interface is an interface which ifupdown understands.
387 The following are currently considered builtin ifaces:
388 - vlan interfaces in the format <ifacename>.<vlanid>
391 return (ifaceobj
.priv_flags
and ifaceobj
.priv_flags
.BUILTIN
)
393 def is_ifaceobj_noconfig(self
, ifaceobj
):
394 """ Returns true if iface object did not have a user defined config.
396 These interfaces appear only when they are dependents of interfaces
397 which have user defined config
399 return (ifaceobj
.priv_flags
and ifaceobj
.priv_flags
.NOCONFIG
)
401 def is_iface_noconfig(self
, ifacename
):
402 """ Returns true if iface has no config """
404 ifaceobj
= self
.get_ifaceobj_first(ifacename
)
405 if not ifaceobj
: return True
406 return self
.is_ifaceobj_noconfig(ifaceobj
)
408 def check_shared_dependents(self
, ifaceobj
, dlist
):
409 """ Check if dlist intersects with any other
410 interface with slave dependents.
411 example: bond and bridges.
412 This function logs such errors """
413 setdlist
= Set(dlist
)
414 for ifacename
, ifacedlist
in self
.dependency_graph
.items():
417 check_depends
= False
418 iobjs
= self
.get_ifaceobjs(ifacename
)
422 if (i
.dependency_type
== ifaceDependencyType
.MASTER_SLAVE
):
425 common
= Set(ifacedlist
).intersection(setdlist
)
427 self
.logger
.error('misconfig..?. iface %s and %s '
428 %(ifaceobj
.name
, ifacename
) +
429 'seem to share dependents/ports %s' %str
(list(common
)))
431 def _set_iface_role_n_kind(self
, ifaceobj
, upperifaceobj
):
432 if (upperifaceobj
.link_kind
& ifaceLinkKind
.BOND
):
433 ifaceobj
.role |
= ifaceRole
.SLAVE
434 ifaceobj
.link_kind |
= ifaceLinkKind
.BOND_SLAVE
435 if (upperifaceobj
.link_kind
& ifaceLinkKind
.BRIDGE
):
436 ifaceobj
.role |
= ifaceRole
.SLAVE
437 ifaceobj
.link_kind |
= ifaceLinkKind
.BRIDGE_PORT
438 if self
._link
_master
_slave
:
439 if upperifaceobj
.link_type
== ifaceLinkType
.LINK_MASTER
:
440 ifaceobj
.link_type
= ifaceLinkType
.LINK_SLAVE
442 upperifaceobj
.link_type
= ifaceLinkType
.LINK_NA
443 ifaceobj
.link_type
= ifaceLinkType
.LINK_NA
444 if (ifaceobj
.link_kind
== ifaceLinkKind
.BOND_SLAVE
and
445 len(ifaceobj
.upperifaces
) > 1):
446 self
.logger
.warn("misconfig..? bond slave \'%s\' is enslaved to multiple interfaces %s" %(ifaceobj
.name
, str(ifaceobj
.upperifaces
)))
448 def dump_iface_dependency_info(self
):
449 """ debug funtion to print raw dependency
450 info - lower and upper devices"""
452 for ifacename
, ifaceobjs
in self
.ifaceobjdict
.iteritems():
454 self
.logger
.info("%s: refcnt: %d, lower: %s, upper: %s" %(ifacename
,
455 self
.get_iface_refcnt(ifacename
),
456 str(iobj
.lowerifaces
) if iobj
.lowerifaces
else [],
457 str(iobj
.upperifaces
) if iobj
.upperifaces
else []))
460 def preprocess_dependency_list(self
, upperifaceobj
, dlist
, ops
):
461 """ We go through the dependency list and
462 delete or add interfaces from the interfaces dict by
463 applying the following rules:
464 if flag DELETE_DEPENDENT_IFACES_WITH_NOCONFIG is True:
465 we only consider devices whose configuration was
466 specified in the network interfaces file. We delete
467 any interface whose config was not specified except
468 for vlan devices. vlan devices get special treatment.
469 Even if they are not present they are created and added
471 elif flag DELETE_DEPENDENT_IFACES_WITH_NOCONFIG is False:
472 we create objects for all dependent devices that are not
473 present in the ifacesdict
477 if (upperifaceobj
.dependency_type
== ifaceDependencyType
.MASTER_SLAVE
478 and self
.flags
.CHECK_SHARED_DEPENDENTS
):
479 self
.check_shared_dependents(upperifaceobj
, dlist
)
482 dilist
= self
.get_ifaceobjs(d
)
485 if self
.is_iface_builtin_byname(d
):
486 ni
= self
.create_n_save_ifaceobj(d
,
487 ifacePrivFlags(True, True), True)
488 elif not self
.flags
.DELETE_DEPENDENT_IFACES_WITH_NOCONFIG
:
489 ni
= self
.create_n_save_ifaceobj(d
,
490 ifacePrivFlags(False, True), True)
494 ni
.add_to_upperifaces(upperifaceobj
.name
)
495 self
._set
_iface
_role
_n
_kind
(ni
, upperifaceobj
)
499 di
.add_to_upperifaces(upperifaceobj
.name
)
500 self
._set
_iface
_role
_n
_kind
(di
, upperifaceobj
)
504 def preprocess_upperiface(self
, lowerifaceobj
, ulist
, ops
):
506 if (lowerifaceobj
.upperifaces
and
507 u
in lowerifaceobj
.upperifaces
):
509 lowerifaceobj
.add_to_upperifaces(u
)
510 uifacelist
= self
.get_ifaceobjs(u
)
512 for ui
in uifacelist
:
513 lowerifaceobj
.inc_refcnt()
514 self
._set
_iface
_role
_n
_kind
(lowerifaceobj
, ui
)
515 ui
.add_to_lowerifaces(lowerifaceobj
.name
)
517 def query_lowerifaces(self
, ifaceobj
, ops
, ifacenames
, type=None):
518 """ Gets iface dependents by calling into respective modules """
521 # Get dependents for interface by querying respective modules
522 for module
in self
.modules
.values():
524 if ops
[0] == 'query-running':
525 if (not hasattr(module
,
526 'get_dependent_ifacenames_running')):
528 dlist
= module
.get_dependent_ifacenames_running(ifaceobj
)
530 if (not hasattr(module
, 'get_dependent_ifacenames')):
532 dlist
= module
.get_dependent_ifacenames(ifaceobj
,
535 self
.logger
.warn('%s: error getting dependent interfaces (%s)'
536 %(ifaceobj
.name
, str(e
)))
539 if dlist
: ret_dlist
.extend(dlist
)
540 return list(set(ret_dlist
))
542 def query_upperifaces(self
, ifaceobj
, ops
, ifacenames
, type=None):
543 """ Gets iface upperifaces by calling into respective modules """
546 # Get upperifaces for interface by querying respective modules
547 for module
in self
.modules
.values():
549 if ops
[0] == 'query-running':
550 if (not hasattr(module
,
551 'get_upper_ifacenames_running')):
553 ulist
= module
.get_upper_ifacenames_running(ifaceobj
)
555 if (not hasattr(module
, 'get_upper_ifacenames')):
557 ulist
= module
.get_upper_ifacenames(ifaceobj
, ifacenames
)
559 self
.logger
.warn('%s: error getting upper interfaces (%s)'
560 %(ifaceobj
.name
, str(e
)))
563 if ulist
: ret_ulist
.extend(ulist
)
564 return list(set(ret_ulist
))
566 def populate_dependency_info(self
, ops
, ifacenames
=None):
567 """ recursive function to generate iface dependency info """
570 ifacenames
= self
.ifaceobjdict
.keys()
572 iqueue
= deque(ifacenames
)
575 # Go through all modules and find dependent ifaces
578 ifaceobjs
= self
.get_ifaceobjs(i
)
581 dependents_processed
= False
583 # Store all dependency info in the first ifaceobj
584 # but get dependency info from all ifaceobjs
585 ifaceobj
= ifaceobjs
[0]
586 for iobj
in ifaceobjs
:
587 ulist
= self
.query_upperifaces(iobj
, ops
, ifacenames
)
589 dependents_processed
= True
591 dlist
= self
.query_lowerifaces(iobj
, ops
, ifacenames
)
595 self
.preprocess_upperiface(ifaceobj
, ulist
, ops
)
596 if dependents_processed
:
599 self
.preprocess_dependency_list(ifaceobj
,
601 ifaceobj
.lowerifaces
= dlist
602 [iqueue
.append(d
) for d
in dlist
]
603 #if not self.dependency_graph.get(i):
604 # self.dependency_graph[i] = dlist
606 for i
in self
.ifaceobjdict
.keys():
607 iobj
= self
.get_ifaceobj_first(i
)
609 self
.dependency_graph
[i
] = iobj
.lowerifaces
611 self
.dependency_graph
[i
] = []
613 if not self
.blacklisted_ifaces_present
:
616 # Walk through the dependency graph and remove blacklisted
617 # interfaces that were picked up as dependents
618 for i
in self
.dependency_graph
.keys():
619 ifaceobj
= self
.get_ifaceobj_first(i
)
622 if ifaceobj
.blacklisted
and not ifaceobj
.upperifaces
:
623 # if blacklisted and was not picked up as a
624 # dependent of a upper interface, delete the
625 # interface from the dependency graph
626 dlist
= ifaceobj
.lowerifaces
629 difaceobjs
= self
.get_ifaceobjs(d
)
635 d
.upperifaces
.remove(i
)
637 self
.logger
.debug('error removing %s from %s upperifaces' %(i
, d
))
639 self
.logger
.debug("populate_dependency_info: deleting blacklisted interface %s" %i)
640 del self
.dependency_graph
[i
]
642 def _check_config_no_repeats(self
, ifaceobj
):
643 """ check if object has an attribute that is
644 restricted to a single object in the system.
645 if yes, warn and return """
646 for k
,v
in self
._cache
_no
_repeats
.items():
647 iv
= ifaceobj
.config
.get(k
)
648 if iv
and iv
[0] == v
:
649 self
.logger
.error('ignoring interface %s. ' %ifaceobj
.name
+
650 'Only one object with attribute ' +
651 '\'%s %s\' allowed.' %(k
, v
))
653 for k
, v
in self
.config
.get('no_repeats', {}).items():
654 iv
= ifaceobj
.config
.get(k
)
655 if iv
and iv
[0] == v
:
656 self
._cache
_no
_repeats
[k
] = v
659 def _save_iface(self
, ifaceobj
):
660 if self
._check
_config
_no
_repeats
(ifaceobj
):
662 ifaceobj
.priv_flags
= ifacePrivFlags()
663 if not self
._link
_master
_slave
:
664 ifaceobj
.link_type
= ifaceLinkType
.LINK_NA
665 currentifaceobjlist
= self
.ifaceobjdict
.get(ifaceobj
.name
)
666 if not currentifaceobjlist
:
667 self
.ifaceobjdict
[ifaceobj
.name
]= [ifaceobj
]
668 if not self
._ifaceobj
_squash
:
669 ifaceobj
.flags |
= ifaceobj
.YOUNGEST_SIBLING
671 if self
._ifaceobj
_squash
:
672 # squash with old iface object
673 currentifaceobjlist
[0].squash(ifaceobj
)
675 if ifaceobj
.compare(currentifaceobjlist
[0]):
676 self
.logger
.warn('duplicate interface %s found' %ifaceobj
.name
)
678 if currentifaceobjlist
[0].type == ifaceobj
.type:
679 currentifaceobjlist
[0].flags |
= ifaceobj
.HAS_SIBLINGS
680 ifaceobj
.flags |
= ifaceobj
.HAS_SIBLINGS
681 # clear the OLDEST_SIBLING from all the siblings
682 for iface
in self
.ifaceobjdict
[ifaceobj
.name
]:
683 iface
.flags
&= ~ifaceobj
.OLDEST_SIBLING
684 # current sibling is the oldest
685 ifaceobj
.flags |
= ifaceobj
.OLDEST_SIBLING
686 self
.ifaceobjdict
[ifaceobj
.name
].append(ifaceobj
)
688 def _iface_configattr_syntax_checker(self
, attrname
, attrval
):
689 for m
, mdict
in self
.module_attrs
.items():
692 attrsdict
= mdict
.get('attrs')
694 a
= attrsdict
.get(attrname
)
696 if a
.get('deprecated'):
697 newa
= a
.get('new-attribute')
699 self
.logger
.warn('attribute %s is deprecated. Use %s instead' %(attrname
, newa
))
701 self
.logger
.warn('attribute %s is deprecated'
704 except AttributeError:
708 def _ifaceobj_syntax_checker(self
, ifaceobj
):
710 for attrname
, attrvalue
in ifaceobj
.config
.items():
712 for k
, v
in self
.module_attrs
.items():
713 if v
and v
.get('attrs', {}).get(attrname
):
718 self
.logger
.warn('%s: unsupported attribute \'%s\'' \
719 % (ifaceobj
.name
, attrname
))
723 def read_iface_config(self
):
724 """ Reads default network interface config /etc/network/interfaces. """
726 nifaces
= networkInterfaces(self
.interfacesfile
,
727 self
.interfacesfileiobuf
,
728 self
.interfacesfileformat
,
729 template_engine
=self
.config
.get('template_engine'),
730 template_lookuppath
=self
.config
.get('template_lookuppath'))
731 nifaces
.subscribe('iface_found', self
._save
_iface
)
732 nifaces
.subscribe('validateifaceattr',
733 self
._iface
_configattr
_syntax
_checker
)
734 nifaces
.subscribe('validateifaceobj', self
._ifaceobj
_syntax
_checker
)
736 if nifaces
.errors
or nifaces
.warns
:
740 def read_old_iface_config(self
):
741 """ Reads the saved iface config instead of default iface config.
742 And saved iface config is already read by the statemanager """
743 self
.ifaceobjdict
= copy
.deepcopy(self
.statemanager
.ifaceobjdict
)
745 def _load_addon_modules_config(self
):
746 """ Load addon modules config file """
748 with
open(self
.addon_modules_configfile
, 'r') as f
:
749 lines
= f
.readlines()
752 litems
= l
.strip(' \n\t\r').split(',')
753 if not litems
or len(litems
) < 2:
755 operation
= litems
[0]
757 self
.module_ops
[operation
].append(mname
)
759 self
.logger
.warn('error reading line \'%s\'' %(l
, str(e
)))
762 def load_addon_modules(self
, modules_dir
):
763 """ load python modules from modules_dir
765 Default modules_dir is /usr/share/ifupdownmodules
768 self
.logger
.info('loading builtin modules from %s' %modules_dir
)
769 self
._load
_addon
_modules
_config
()
770 if not modules_dir
in sys
.path
:
771 sys
.path
.append(modules_dir
)
773 for op
, mlist
in self
.module_ops
.items():
775 if self
.modules
.get(mname
):
777 mpath
= modules_dir
+ '/' + mname
+ '.py'
778 if os
.path
.exists(mpath
):
780 m
= __import__(mname
)
781 mclass
= getattr(m
, mname
)
784 minstance
= mclass(force
=self
.FORCE
,
787 perfmode
=self
.PERFMODE
,
789 cacheflags
=self
.CACHE_FLAGS
)
790 self
.modules
[mname
] = minstance
792 self
.module_attrs
[mname
] = minstance
.get_modinfo()
798 # Assign all modules to query operations
799 self
.module_ops
['query-checkcurr'] = self
.modules
.keys()
800 self
.module_ops
['query-running'] = self
.modules
.keys()
801 self
.module_ops
['query-dependency'] = self
.modules
.keys()
802 self
.module_ops
['query'] = self
.modules
.keys()
803 self
.module_ops
['query-raw'] = self
.modules
.keys()
806 def _modules_help(self
):
807 """ Prints addon modules supported syntax """
810 for m
, mdict
in self
.module_attrs
.items():
813 print('%s: %s' %(m
, mdict
.get('mhelp')))
814 attrdict
= mdict
.get('attrs')
818 for attrname
, attrvaldict
in attrdict
.items():
819 if attrvaldict
.get('compat', False):
821 print('%s%s' %(indent
, attrname
))
822 print('%shelp: %s' %(indent
+ ' ',
823 attrvaldict
.get('help', '')))
824 print ('%srequired: %s' %(indent
+ ' ',
825 attrvaldict
.get('required', False)))
826 default
= attrvaldict
.get('default')
828 print('%sdefault: %s' %(indent
+ ' ', default
))
830 validrange
= attrvaldict
.get('validrange')
832 print('%svalidrange: %s-%s'
833 %(indent
+ ' ', validrange
[0], validrange
[1]))
835 validvals
= attrvaldict
.get('validvals')
837 print('%svalidvals: %s'
838 %(indent
+ ' ', ','.join(validvals
)))
840 examples
= attrvaldict
.get('example')
844 print '%sexample:' %(indent
+ ' ')
846 print '%s%s' %(indent
+ ' ', e
)
851 def load_scripts(self
, modules_dir
):
852 """ loading user modules from /etc/network/.
854 Note that previously loaded python modules override modules found
855 under /etc/network if any
859 self
.logger
.info('looking for user scripts under %s' %modules_dir
)
860 for op
, mlist
in self
.script_ops
.items():
861 msubdir
= modules_dir
+ '/if-%s.d' %op
862 self
.logger
.info('loading scripts under %s ...' %msubdir
)
864 module_list
= os
.listdir(msubdir
)
865 for module
in module_list
:
866 if self
.modules
.get(module
) is not None:
868 self
.script_ops
[op
].append(
869 msubdir
+ '/' + module
)
874 def _sched_ifaces(self
, ifacenames
, ops
, skipupperifaces
=False,
875 followdependents
=True, sort
=False):
876 self
.logger
.debug('scheduling \'%s\' for %s'
877 %(str(ops
), str(ifacenames
)))
878 self
._pretty
_print
_ordered
_dict
('dependency graph',
879 self
.dependency_graph
)
880 return ifaceScheduler
.sched_ifaces(self
, ifacenames
, ops
,
881 dependency_graph
=self
.dependency_graph
,
882 order
=ifaceSchedulerFlags
.INORDER
884 else ifaceSchedulerFlags
.POSTORDER
,
885 followdependents
=followdependents
,
886 skipupperifaces
=skipupperifaces
,
887 sort
=True if (sort
or self
.flags
.IFACE_CLASS
) else False)
889 def _render_ifacename(self
, ifacename
):
891 vlan_match
= re
.match("^([\d]+)-([\d]+)", ifacename
)
893 vlan_groups
= vlan_match
.groups()
894 if vlan_groups
[0] and vlan_groups
[1]:
895 [new_ifacenames
.append('%d' %v
)
896 for v
in range(int(vlan_groups
[0]),
897 int(vlan_groups
[1])+1)]
898 return new_ifacenames
900 def _preprocess_ifacenames(self
, ifacenames
):
901 """ validates interface list for config existance.
903 returns -1 if one or more interface not found. else, returns 0
909 ifaceobjs
= self
.get_ifaceobjs(i
)
911 # if name not available, render interface name and check again
912 rendered_ifacenames
= utils
.expand_iface_range(i
)
913 if rendered_ifacenames
:
914 for ri
in rendered_ifacenames
:
915 ifaceobjs
= self
.get_ifaceobjs(ri
)
917 err_iface
+= ' ' + ri
919 new_ifacenames
.append(ri
)
923 new_ifacenames
.append(i
)
925 raise Exception('cannot find interfaces:%s' %err_iface
)
926 return new_ifacenames
928 def _iface_whitelisted(self
, auto
, allow_classes
, excludepats
, ifacename
):
929 """ Checks if interface is whitelisted depending on set of parameters.
931 interfaces are checked against the allow_classes and auto lists.
937 # Check if interface matches the exclude patter
939 for e
in excludepats
:
940 if re
.search(e
, ifacename
):
942 ifaceobjs
= self
.get_ifaceobjs(ifacename
)
945 self
.logger
.debug('iface %s' %ifacename
+ ' not found')
947 # If matched exclude pattern, return false
951 self
.blacklisted_ifaces_present
= True
953 # Check if interface belongs to the class
954 # the user is interested in, if not return false
959 common
= Set([allow_classes
]).intersection(
964 # If a class was requested and interface does not belong
965 # to the class, only then mark the ifaceobjs as blacklisted
966 self
.blacklisted_ifaces_present
= True
970 # If the user has requested auto class, check if the interface
978 # If auto was requested and interface was not marked auto,
979 # only then mark all of them as blacklisted
980 self
.blacklisted_ifaces_present
= True
985 def _compat_conv_op_to_mode(self
, op
):
986 """ Returns old op name to work with existing scripts """
989 elif op
== 'pre-down':
994 def generate_running_env(self
, ifaceobj
, op
):
995 """ Generates a dictionary with env variables required for
996 an interface. Used to support script execution for interfaces.
1000 iface_env
= ifaceobj
.env
1004 cenv
.update(iface_env
)
1007 cenv
['MODE'] = self
._compat
_conv
_op
_to
_mode
(op
)
1010 def _save_state(self
):
1011 if (not self
.flags
.STATEMANAGER_ENABLE
or
1012 not self
.flags
.STATEMANAGER_UPDATE
):
1015 # Update persistant iface states
1016 self
.statemanager
.save_state()
1017 except Exception, e
:
1018 if self
.logger
.isEnabledFor(logging
.DEBUG
):
1019 t
= sys
.exc_info()[2]
1020 traceback
.print_tb(t
)
1021 self
.logger
.warning('error saving state (%s)' %str
(e
))
1023 def set_type(self
, type):
1025 self
.type = ifaceType
.IFACE
1026 elif type == 'vlan':
1027 self
.type = ifaceType
.BRIDGE_VLAN
1029 self
.type = ifaceType
.UNKNOWN
1031 def _process_delay_admin_state_queue(self
, op
):
1032 if not self
._delay
_admin
_state
_iface
_queue
:
1037 func
= self
.link_down
1040 for i
in self
._delay
_admin
_state
_iface
_queue
:
1042 if self
.link_exists(i
):
1044 except Exception, e
:
1045 self
.logger
.warn(str(e
))
1048 def up(self
, ops
, auto
=False, allow_classes
=None, ifacenames
=None,
1049 excludepats
=None, printdependency
=None, syntaxcheck
=False,
1050 type=None, skipupperifaces
=False):
1051 """This brings the interface(s) up
1054 ops (list): list of ops to perform on the interface(s).
1055 Eg: ['pre-up', 'up', 'post-up'
1058 auto (bool): act on interfaces marked auto
1059 allow_classes (list): act on interfaces belonging to classes in the list
1060 ifacenames (list): act on interfaces specified in this list
1061 excludepats (list): list of patterns of interfaces to exclude
1062 syntaxcheck (bool): only perform syntax check
1068 self
.flags
.IFACE_CLASS
= True
1069 if not self
.flags
.ADDONS_ENABLE
:
1070 self
.flags
.STATEMANAGER_UPDATE
= False
1072 self
.flags
.ALL
= True
1073 self
.flags
.WITH_DEPENDS
= True
1075 iface_read_ret
= self
.read_iface_config()
1080 ifacenames
= self
._preprocess
_ifacenames
(ifacenames
)
1082 # if iface list not given by user, assume all from config file
1083 if not ifacenames
: ifacenames
= self
.ifaceobjdict
.keys()
1085 # filter interfaces based on auto and allow classes
1086 filtered_ifacenames
= [i
for i
in ifacenames
1087 if self
._iface
_whitelisted
(auto
, allow_classes
,
1089 if not filtered_ifacenames
:
1090 raise Exception('no ifaces found matching given allow lists')
1093 self
.populate_dependency_info(ops
, filtered_ifacenames
)
1094 self
.print_dependency(filtered_ifacenames
, printdependency
)
1097 self
.populate_dependency_info(ops
)
1099 # If only syntax check was requested, return here.
1100 # return here because we want to make sure most
1101 # errors above are caught and reported.
1103 if not iface_read_ret
:
1108 self
._sched
_ifaces
(filtered_ifacenames
, ops
,
1109 skipupperifaces
=skipupperifaces
,
1110 followdependents
=True if self
.flags
.WITH_DEPENDS
else False)
1112 self
._process
_delay
_admin
_state
_queue
('up')
1113 if not self
.DRYRUN
and self
.flags
.ADDONS_ENABLE
:
1116 def down(self
, ops
, auto
=False, allow_classes
=None, ifacenames
=None,
1117 excludepats
=None, printdependency
=None, usecurrentconfig
=False,
1119 """ down an interface """
1124 self
.flags
.IFACE_CLASS
= True
1125 if not self
.flags
.ADDONS_ENABLE
:
1126 self
.flags
.STATEMANAGER_UPDATE
= False
1128 self
.flags
.ALL
= True
1129 self
.flags
.WITH_DEPENDS
= True
1130 # For down we need to look at old state, unless usecurrentconfig
1132 if (not usecurrentconfig
and self
.flags
.STATEMANAGER_ENABLE
and
1133 self
.statemanager
.ifaceobjdict
):
1134 # Since we are using state manager objects,
1135 # skip the updating of state manager objects
1136 self
.logger
.debug('Looking at old state ..')
1137 self
.read_old_iface_config()
1139 # If no old state available
1141 self
.read_iface_config()
1142 except Exception, e
:
1143 raise Exception('error reading iface config (%s)' %str
(e
))
1145 # If iface list is given by the caller, always check if iface
1148 ifacenames
= self
._preprocess
_ifacenames
(ifacenames
)
1149 except Exception, e
:
1150 raise Exception('%s' %str
(e
) +
1151 ' (interface was probably never up ?)')
1153 # if iface list not given by user, assume all from config file
1154 if not ifacenames
: ifacenames
= self
.ifaceobjdict
.keys()
1156 # filter interfaces based on auto and allow classes
1157 filtered_ifacenames
= [i
for i
in ifacenames
1158 if self
._iface
_whitelisted
(auto
, allow_classes
,
1160 if not filtered_ifacenames
:
1161 raise Exception('no ifaces found matching given allow lists ' +
1162 '(or interfaces were probably never up ?)')
1165 self
.populate_dependency_info(ops
, filtered_ifacenames
)
1166 self
.print_dependency(filtered_ifacenames
, printdependency
)
1169 self
.populate_dependency_info(ops
)
1172 self
._sched
_ifaces
(filtered_ifacenames
, ops
,
1173 followdependents
=True
1174 if self
.flags
.WITH_DEPENDS
else False)
1176 self
._process
_delay
_admin
_state
_queue
('down')
1177 if not self
.DRYRUN
and self
.flags
.ADDONS_ENABLE
:
1180 def query(self
, ops
, auto
=False, allow_classes
=None, ifacenames
=None,
1181 excludepats
=None, printdependency
=None,
1182 format
='native', type=None):
1183 """ query an interface """
1188 self
.flags
.IFACE_CLASS
= True
1189 if self
.flags
.STATEMANAGER_ENABLE
and ops
[0] == 'query-savedstate':
1190 return self
.statemanager
.dump_pretty(ifacenames
)
1191 self
.flags
.STATEMANAGER_UPDATE
= False
1193 self
.logger
.debug('setting flag ALL')
1194 self
.flags
.ALL
= True
1195 self
.flags
.WITH_DEPENDS
= True
1197 if ops
[0] == 'query-syntax':
1198 self
._modules
_help
()
1200 elif ops
[0] == 'query-running':
1201 # create fake devices to all dependents that dont have config
1202 map(lambda i
: self
.create_n_save_ifaceobj(i
,
1203 ifacePrivFlags(False, True)), ifacenames
)
1206 self
.read_iface_config()
1210 if ifacenames
and ops
[0] != 'query-running':
1211 # If iface list is given, always check if iface is present
1212 ifacenames
= self
._preprocess
_ifacenames
(ifacenames
)
1214 # if iface list not given by user, assume all from config file
1215 if not ifacenames
: ifacenames
= self
.ifaceobjdict
.keys()
1217 # filter interfaces based on auto and allow classes
1218 if ops
[0] == 'query-running':
1219 filtered_ifacenames
= ifacenames
1221 filtered_ifacenames
= [i
for i
in ifacenames
1222 if self
._iface
_whitelisted
(auto
, allow_classes
,
1224 if not filtered_ifacenames
:
1225 raise Exception('no ifaces found matching ' +
1226 'given allow lists')
1228 self
.populate_dependency_info(ops
)
1229 if ops
[0] == 'query-dependency' and printdependency
:
1230 self
.print_dependency(filtered_ifacenames
, printdependency
)
1233 if ops
[0] == 'query':
1234 return self
.print_ifaceobjs_pretty(filtered_ifacenames
, format
)
1235 elif ops
[0] == 'query-raw':
1236 return self
.print_ifaceobjs_raw(filtered_ifacenames
)
1238 self
._sched
_ifaces
(filtered_ifacenames
, ops
,
1239 followdependents
=True
1240 if self
.flags
.WITH_DEPENDS
else False)
1242 if ops
[0] == 'query-checkcurr':
1243 ret
= self
.print_ifaceobjscurr_pretty(filtered_ifacenames
, format
)
1245 # if any of the object has an error, signal that silently
1247 elif ops
[0] == 'query-running':
1248 self
.print_ifaceobjsrunning_pretty(filtered_ifacenames
, format
)
1251 def _reload_currentlyup(self
, upops
, downops
, auto
=True, allow
=None,
1252 ifacenames
=None, excludepats
=None, usecurrentconfig
=False,
1253 syntaxcheck
=False, **extra_args
):
1254 """ reload currently up interfaces """
1255 new_ifaceobjdict
= {}
1257 # Override auto to true
1260 iface_read_ret
= self
.read_iface_config()
1263 if not self
.ifaceobjdict
:
1264 self
.logger
.warn("nothing to reload ..exiting.")
1266 already_up_ifacenames
= []
1267 if not ifacenames
: ifacenames
= self
.ifaceobjdict
.keys()
1268 filtered_ifacenames
= [i
for i
in ifacenames
1269 if self
._iface
_whitelisted
(auto
, allow
,
1272 # generate dependency graph of interfaces
1273 self
.populate_dependency_info(upops
)
1275 # If only syntax check was requested, return here.
1276 # return here because we want to make sure most
1277 # errors above are caught and reported.
1279 if not iface_read_ret
:
1283 if (not usecurrentconfig
and self
.flags
.STATEMANAGER_ENABLE
1284 and self
.statemanager
.ifaceobjdict
):
1285 already_up_ifacenames
= self
.statemanager
.ifaceobjdict
.keys()
1287 # Get already up interfaces that still exist in the interfaces file
1288 already_up_ifacenames_not_present
= Set(
1289 already_up_ifacenames
).difference(ifacenames
)
1290 already_up_ifacenames_still_present
= Set(
1291 already_up_ifacenames
).difference(
1292 already_up_ifacenames_not_present
)
1293 interfaces_to_up
= Set(already_up_ifacenames_still_present
).union(
1294 filtered_ifacenames
)
1296 if (already_up_ifacenames_not_present
and
1297 self
.config
.get('ifreload_currentlyup_down_notpresent') == '1'):
1298 self
.logger
.info('reload: schedule down on interfaces: %s'
1299 %str
(already_up_ifacenames_not_present
))
1301 # Save a copy of new iface objects and dependency_graph
1302 new_ifaceobjdict
= dict(self
.ifaceobjdict
)
1303 new_dependency_graph
= dict(self
.dependency_graph
)
1305 # old interface config is read into self.ifaceobjdict
1306 self
.read_old_iface_config()
1308 # reinitialize dependency graph
1309 self
.dependency_graph
= OrderedDict({})
1310 falready_up_ifacenames_not_present
= [i
for i
in
1311 already_up_ifacenames_not_present
1312 if self
._iface
_whitelisted
(auto
, allow
,
1314 self
.populate_dependency_info(downops
,
1315 falready_up_ifacenames_not_present
)
1316 self
._sched
_ifaces
(falready_up_ifacenames_not_present
, downops
,
1317 followdependents
=False, sort
=True)
1319 self
.logger
.debug('no interfaces to down ..')
1321 # Now, run 'up' with new config dict
1322 # reset statemanager update flag to default
1324 self
.flags
.ALL
= True
1325 self
.flags
.WITH_DEPENDS
= True
1326 if new_ifaceobjdict
:
1327 # and now, ifaceobjdict is back to current config
1328 self
.ifaceobjdict
= new_ifaceobjdict
1329 self
.dependency_graph
= new_dependency_graph
1331 if not self
.ifaceobjdict
:
1333 self
.logger
.info('reload: scheduling up on interfaces: %s'
1334 %str
(interfaces_to_up
))
1335 self
._sched
_ifaces
(interfaces_to_up
, upops
,
1336 followdependents
=True
1337 if self
.flags
.WITH_DEPENDS
else False)
1342 def _reload_default(self
, upops
, downops
, auto
=False, allow
=None,
1343 ifacenames
=None, excludepats
=None, usecurrentconfig
=False,
1344 syntaxcheck
=False, **extra_args
):
1345 """ reload interface config """
1346 new_ifaceobjdict
= {}
1349 iface_read_ret
= self
.read_iface_config()
1353 if not self
.ifaceobjdict
:
1354 self
.logger
.warn("nothing to reload ..exiting.")
1357 if not ifacenames
: ifacenames
= self
.ifaceobjdict
.keys()
1358 new_filtered_ifacenames
= [i
for i
in ifacenames
1359 if self
._iface
_whitelisted
(auto
, allow
,
1361 # generate dependency graph of interfaces
1362 self
.populate_dependency_info(upops
)
1364 # If only syntax check was requested, return here.
1365 # return here because we want to make sure most
1366 # errors above are caught and reported.
1368 if not iface_read_ret
:
1372 if (not usecurrentconfig
and self
.flags
.STATEMANAGER_ENABLE
1373 and self
.statemanager
.ifaceobjdict
):
1374 # Save a copy of new iface objects and dependency_graph
1375 new_ifaceobjdict
= dict(self
.ifaceobjdict
)
1376 new_dependency_graph
= dict(self
.dependency_graph
)
1378 self
.ifaceobjdict
= OrderedDict({})
1379 self
.dependency_graph
= OrderedDict({})
1381 # if old state is present, read old state and mark op for 'down'
1382 # followed by 'up' aka: reload
1383 # old interface config is read into self.ifaceobjdict
1384 self
.read_old_iface_config()
1387 # oldconfig not available, continue with 'up' with new config
1390 if op
== 'reload' and ifacenames
:
1391 ifacenames
= self
.ifaceobjdict
.keys()
1392 old_filtered_ifacenames
= [i
for i
in ifacenames
1393 if self
._iface
_whitelisted
(auto
, allow
,
1396 # generate dependency graph of old interfaces,
1397 # This should make sure built in interfaces are
1398 # populated. disable check shared dependents as an optimization.
1399 # these are saved interfaces and dependency for these
1400 # have been checked before they became part of saved state.
1402 self
.flags
.CHECK_SHARED_DEPENDENTS
= False
1403 self
.populate_dependency_info(upops
)
1404 self
.flags
.CHECK_SHARED_DEPENDENTS
= True
1405 except Exception, e
:
1406 self
.logger
.info("error generating dependency graph for "
1407 "saved interfaces (%s)" %str
(e
))
1410 # make sure we pick up built-in interfaces
1411 # if config file had 'ifreload_down_changed' variable
1412 # set, also look for interfaces that changed to down them
1413 down_changed
= int(self
.config
.get('ifreload_down_changed', '1'))
1415 # Generate the interface down list
1416 # Interfaces that go into the down list:
1417 # - interfaces that were present in last config and are not
1418 # present in the new config
1419 # - interfaces that were changed between the last and current
1422 for ifname
in self
.ifaceobjdict
.keys():
1423 lastifaceobjlist
= self
.ifaceobjdict
.get(ifname
)
1424 if not self
.is_ifaceobj_builtin(lastifaceobjlist
[0]):
1425 # if interface is not built-in and is not in
1426 # old filtered ifacenames
1427 if ifname
not in old_filtered_ifacenames
:
1430 # If interface is not present in the new file
1431 # append it to the down list
1432 newifaceobjlist
= new_ifaceobjdict
.get(ifname
)
1433 if not newifaceobjlist
:
1434 ifacedownlist
.append(ifname
)
1436 # If ifaceobj was present in the old interfaces file,
1437 # and does not have a config in the new interfaces file
1438 # but has been picked up as a dependent of another
1439 # interface, catch it here. This catches a common error
1440 # for example: remove a bond section from the interfaces
1441 # file, but leave it around as a bridge port
1442 # XXX: Ideally its better to just add it to the
1443 # ifacedownlist. But we will be cautious here
1444 # and just print a warning
1445 if (self
.is_ifaceobj_noconfig(newifaceobjlist
[0]) and
1446 not self
.is_ifaceobj_builtin(newifaceobjlist
[0]) and
1447 lastifaceobjlist
[0].is_config_present()):
1448 self
.logger
.warn('%s: misconfig ? removed but still exists as a dependency of %s' %(newifaceobjlist
[objidx
].name
,
1449 str(newifaceobjlist
[objidx
].upperifaces
)))
1450 if not down_changed
:
1452 if len(newifaceobjlist
) != len(lastifaceobjlist
):
1453 ifacedownlist
.append(ifname
)
1456 # If interface has changed between the current file
1457 # and the last installed append it to the down list
1458 # compare object list
1459 for objidx
in range(0, len(lastifaceobjlist
)):
1460 oldobj
= lastifaceobjlist
[objidx
]
1461 newobj
= newifaceobjlist
[objidx
]
1462 if not newobj
.compare(oldobj
):
1463 ifacedownlist
.append(ifname
)
1467 self
.logger
.info('reload: scheduling down on interfaces: %s'
1468 %str
(ifacedownlist
))
1469 # reinitialize dependency graph
1470 self
.dependency_graph
= OrderedDict({})
1472 # Generate dependency info for old config
1473 self
.flags
.CHECK_SHARED_DEPENDENTS
= False
1474 self
.populate_dependency_info(downops
, ifacedownlist
)
1475 self
.flags
.CHECK_SHARED_DEPENDENTS
= True
1478 # XXX: Hack to skip checking upperifaces during down.
1479 # the dependency list is not complete here
1480 # and we dont want to down the upperiface.
1481 # Hence during reload, set this to true.
1482 # This is being added to avoid a failure in
1483 # scheduler._check_upperifaces when we are dowing
1484 # a builtin bridge port
1485 self
.flags
.SCHED_SKIP_CHECK_UPPERIFACES
= True
1486 self
._sched
_ifaces
(ifacedownlist
, downops
,
1487 followdependents
=False,
1489 except Exception, e
:
1490 self
.logger
.error(str(e
))
1493 self
.flags
.SCHED_SKIP_CHECK_UPPERIFACES
= False
1494 self
._process
_delay
_admin
_state
_queue
('down')
1496 self
.logger
.debug('no interfaces to down ..')
1498 # Now, run 'up' with new config dict
1499 # reset statemanager update flag to default
1500 if not new_ifaceobjdict
:
1504 self
.flags
.ALL
= True
1505 self
.flags
.WITH_DEPENDS
= True
1506 # and now, we are back to the current config in ifaceobjdict
1507 self
.ifaceobjdict
= new_ifaceobjdict
1508 self
.dependency_graph
= new_dependency_graph
1510 self
.logger
.info('reload: scheduling up on interfaces: %s'
1511 %str
(new_filtered_ifacenames
))
1513 self
._sched
_ifaces
(new_filtered_ifacenames
, upops
,
1514 followdependents
=True
1515 if self
.flags
.WITH_DEPENDS
else False)
1516 except Exception, e
:
1517 self
.logger
.error(str(e
))
1520 self
._process
_delay
_admin
_state
_queue
('up')
1525 def reload(self
, *args
, **kargs
):
1526 """ reload interface config """
1527 self
.logger
.debug('reloading interface config ..')
1528 if kargs
.get('currentlyup', False):
1529 self
._reload
_currentlyup
(*args
, **kargs
)
1531 self
._reload
_default
(*args
, **kargs
)
1533 def _pretty_print_ordered_dict(self
, prefix
, argdict
):
1534 outbuf
= prefix
+ ' {\n'
1535 for k
, vlist
in argdict
.items():
1536 outbuf
+= '\t%s : %s\n' %(k
, str(vlist
))
1537 self
.logger
.debug(outbuf
+ '}')
1539 def print_dependency(self
, ifacenames
, format
):
1540 """ prints iface dependency information """
1543 ifacenames
= self
.ifaceobjdict
.keys()
1544 if format
== 'list':
1545 for k
,v
in self
.dependency_graph
.items():
1546 print '%s : %s' %(k
, str(v
))
1547 elif format
== 'dot':
1549 map(lambda i
: indegrees
.update({i
:
1550 self
.get_iface_refcnt(i
)}),
1551 self
.dependency_graph
.keys())
1552 graph
.generate_dots(self
.dependency_graph
, indegrees
)
1554 def print_ifaceobjs_raw(self
, ifacenames
):
1555 """ prints raw lines for ifaces from config file """
1557 for i
in ifacenames
:
1558 for ifaceobj
in self
.get_ifaceobjs(i
):
1559 if (self
.is_ifaceobj_builtin(ifaceobj
) or
1560 not ifaceobj
.is_config_present()):
1562 ifaceobj
.dump_raw(self
.logger
)
1564 if self
.flags
.WITH_DEPENDS
and not self
.flags
.ALL
:
1565 dlist
= ifaceobj
.lowerifaces
1566 if not dlist
: continue
1567 self
.print_ifaceobjs_raw(dlist
)
1569 def _get_ifaceobjs_pretty(self
, ifacenames
, ifaceobjs
, running
=False):
1570 """ returns iface obj list """
1572 for i
in ifacenames
:
1573 for ifaceobj
in self
.get_ifaceobjs(i
):
1574 if ((not running
and self
.is_ifaceobj_noconfig(ifaceobj
)) or
1575 (running
and not ifaceobj
.is_config_present())):
1577 ifaceobjs
.append(ifaceobj
)
1578 if self
.flags
.WITH_DEPENDS
and not self
.flags
.ALL
:
1579 dlist
= ifaceobj
.lowerifaces
1580 if not dlist
: continue
1581 self
._get
_ifaceobjs
_pretty
(dlist
, ifaceobjs
, running
)
1583 def print_ifaceobjs_pretty(self
, ifacenames
, format
='native'):
1584 """ pretty prints iface in format given by keyword arg format """
1587 self
._get
_ifaceobjs
_pretty
(ifacenames
, ifaceobjs
)
1588 if not ifaceobjs
: return
1589 if format
== 'json':
1590 print json
.dumps(ifaceobjs
, cls
=ifaceJsonEncoder
,
1591 indent
=4, separators
=(',', ': '))
1593 expand
= int(self
.config
.get('ifquery_ifacename_expand_range', '0'))
1595 if not expand
and (i
.flags
& iface
.IFACERANGE_ENTRY
):
1596 # print only the first one
1597 if i
.flags
& iface
.IFACERANGE_START
:
1598 i
.dump_pretty(use_realname
=True)
1602 def _get_ifaceobjscurr_pretty(self
, ifacenames
, ifaceobjs
):
1604 for i
in ifacenames
:
1605 ifaceobjscurr
= self
.get_ifaceobjcurr(i
)
1606 if not ifaceobjscurr
: continue
1607 for ifaceobj
in ifaceobjscurr
:
1608 if (ifaceobj
.status
== ifaceStatus
.NOTFOUND
or
1609 ifaceobj
.status
== ifaceStatus
.ERROR
):
1611 if self
.is_ifaceobj_noconfig(ifaceobj
):
1613 ifaceobjs
.append(ifaceobj
)
1614 if self
.flags
.WITH_DEPENDS
and not self
.flags
.ALL
:
1615 dlist
= ifaceobj
.lowerifaces
1616 if not dlist
: continue
1617 dret
= self
._get
_ifaceobjscurr
_pretty
(dlist
, ifaceobjs
)
1621 def print_ifaceobjscurr_pretty(self
, ifacenames
, format
='native'):
1622 """ pretty prints current running state of interfaces with status.
1624 returns 1 if any of the interface has an error,
1629 ret
= self
._get
_ifaceobjscurr
_pretty
(ifacenames
, ifaceobjs
)
1630 if not ifaceobjs
: return
1632 # override ifaceStatusUserStrs
1633 ifaceStatusUserStrs
.SUCCESS
= self
.config
.get('ifquery_check_success_str', _success_sym
)
1634 ifaceStatusUserStrs
.ERROR
= self
.config
.get('ifquery_check_error_str', _error_sym
)
1635 ifaceStatusUserStrs
.UNKNOWN
= self
.config
.get('ifquery_check_unknown_str', '')
1636 if format
== 'json':
1637 print json
.dumps(ifaceobjs
, cls
=ifaceJsonEncoderWithStatus
,
1638 indent
=2, separators
=(',', ': '))
1640 map(lambda i
: i
.dump_pretty(with_status
=True), ifaceobjs
)
1643 def print_ifaceobjsrunning_pretty(self
, ifacenames
, format
='native'):
1644 """ pretty prints iface running state """
1647 self
._get
_ifaceobjs
_pretty
(ifacenames
, ifaceobjs
, running
=True)
1648 if not ifaceobjs
: return
1649 if format
== 'json':
1650 print json
.dumps(ifaceobjs
, cls
=ifaceJsonEncoder
, indent
=2,
1651 separators
=(',', ': '))
1653 map(lambda i
: i
.dump_pretty(), ifaceobjs
)
1656 print 'ifupdown main object dump'
1657 print self
.pp
.pprint(self
.modules
)
1658 print self
.pp
.pprint(self
.ifaceobjdict
)
1660 def _dump_ifaceobjs(self
, ifacenames
):
1661 for i
in ifacenames
:
1662 ifaceobjs
= self
.get_ifaceobjs(i
)