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 import ifupdown
.ifupdownflags
as ifupdownflags
21 from networkinterfaces
import *
23 from scheduler
import *
24 from collections
import deque
25 from collections
import OrderedDict
27 from exceptions
import *
30 from ipaddr
import IPNetwork
, IPv4Network
, IPv6Network
, IPAddress
, IPv4Address
, IPv6Address
33 .. module:: ifupdownmain
34 :synopsis: main module for ifupdown package
36 .. moduleauthor:: Roopa Prabhu <roopa@cumulusnetworks.com>
41 _crossmark
= u
'\u2717'
42 _success_sym
= '(%s)' %_tickmark
43 _error_sym
= '(%s)' %_crossmark
45 class ifupdownMainFlags():
46 COMPAT_EXEC_SCRIPTS
= False
47 STATEMANAGER_ENABLE
= True
48 STATEMANAGER_UPDATE
= True
50 DELETE_DEPENDENT_IFACES_WITH_NOCONFIG
= False
51 SCHED_SKIP_CHECK_UPPERIFACES
= False
52 CHECK_SHARED_DEPENDENTS
= True
54 class ifacePrivFlags():
55 # priv flags to mark iface objects
59 def __init__(self
, builtin
=False, noconfig
=False):
60 self
.BUILTIN
= builtin
61 self
.NOCONFIG
= noconfig
63 class ifupdownMain(ifupdownBase
):
64 """ ifupdown2 main class """
66 scripts_dir
='/etc/network'
67 addon_modules_dir
='/usr/share/ifupdown2/addons'
68 addon_modules_configfile
='/etc/network/ifupdown2/addons.conf'
70 # iface dictionary in the below format:
71 # { '<ifacename>' : [<ifaceobject1>, <ifaceobject2> ..] }
73 # { 'swp1' : [<iface swp1>, <iface swp2> ..] }
75 # Each ifaceobject corresponds to a configuration block for
77 # The value in the dictionary is a list because the network
78 # interface configuration file supports more than one iface section
79 # in the interfaces file
80 ifaceobjdict
= OrderedDict()
82 # iface dictionary representing the curr running state of an iface
83 # in the below format:
84 # {'<ifacename>' : <ifaceobject>}
85 ifaceobjcurrdict
= OrderedDict()
87 # Dictionary representing operation and modules
89 module_ops
= OrderedDict([('pre-up', []),
92 ('query-checkcurr', []),
93 ('query-running', []),
94 ('query-dependency', []),
101 # For old style /etc/network/ bash scripts
102 script_ops
= OrderedDict([('pre-up', []),
109 # Handlers for ops that ifupdown2 owns
110 def run_up(self
, ifaceobj
):
111 # Skip link sets on ifaceobjs of type 'vlan' (used for l2 attrs).
112 # there is no real interface behind it
113 if ifaceobj
.type == ifaceType
.BRIDGE_VLAN
:
115 if ((ifaceobj
.link_kind
& ifaceLinkKind
.VRF
) or
116 (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.VRF_SLAVE
)):
118 # if not a logical interface and addr method is manual,
119 # ignore link admin state changes
120 if (ifaceobj
.addr_method
== 'manual' and
121 not ifaceobj
.link_kind
):
123 if self
._delay
_admin
_state
:
124 self
._delay
_admin
_state
_iface
_queue
.append(ifaceobj
.name
)
126 # If this object is a link slave, ie its link is controlled
127 # by its link master interface, then dont set the link state.
128 # But do allow user to change state of the link if the interface
129 # is already with its link master (hence the master check).
130 if ifaceobj
.link_type
== ifaceLinkType
.LINK_SLAVE
:
132 if not self
.link_exists(ifaceobj
.name
):
134 if ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.KEEP_LINK_DOWN
:
135 # user has asked to explicitly keep the link down,
136 # so, force link down
137 self
.logger
.info('%s: keeping link down due to user config' %ifaceobj
.name
)
138 self
.link_down(ifaceobj
.name
)
140 self
.link_up(ifaceobj
.name
)
142 def run_down(self
, ifaceobj
):
143 if ((ifaceobj
.link_kind
& ifaceLinkKind
.VRF
) or
144 (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.VRF_SLAVE
)):
146 # Skip link sets on ifaceobjs of type 'vlan' (used for l2 attrs)
147 # there is no real interface behind it
148 if ifaceobj
.type == ifaceType
.BRIDGE_VLAN
:
150 # if not a logical interface and addr method is manual,
151 # ignore link admin state changes
152 if (ifaceobj
.addr_method
== 'manual' and
153 not ifaceobj
.link_kind
):
155 if self
._delay
_admin
_state
:
156 self
._delay
_admin
_state
_iface
_queue
.append(ifaceobj
.name
)
158 # If this object is a link slave, ie its link is controlled
159 # by its link master interface, then dont set the link state.
160 # But do allow user to change state of the link if the interface
161 # is already with its link master (hence the master check).
162 if ifaceobj
.link_type
== ifaceLinkType
.LINK_SLAVE
:
164 if not self
.link_exists(ifaceobj
.name
):
166 self
.link_down(ifaceobj
.name
)
168 # ifupdown object interface operation handlers
169 ops_handlers
= OrderedDict([('up', run_up
),
172 def run_sched_ifaceobj_posthook(self
, ifaceobj
, op
):
173 if (ifaceobj
.priv_flags
and (ifaceobj
.priv_flags
.BUILTIN
or
174 ifaceobj
.priv_flags
.NOCONFIG
)):
176 if self
.flags
.STATEMANAGER_UPDATE
:
177 self
.statemanager
.ifaceobj_sync(ifaceobj
, op
)
179 # ifupdown object interface scheduler pre and posthooks
180 sched_hooks
= {'posthook' : run_sched_ifaceobj_posthook
}
182 def __init__(self
, config
={},
183 force
=False, dryrun
=False, nowait
=False,
184 perfmode
=False, withdepends
=False, njobs
=1,
185 cache
=False, addons_enable
=True, statemanager_enable
=True,
186 interfacesfile
='/etc/network/interfaces',
187 interfacesfileiobuf
=None,
188 interfacesfileformat
='native',
190 """This member function initializes the ifupdownmain object.
193 config (dict): config dict from /etc/network/ifupdown2/ifupdown2.conf
194 force (bool): force interface configuration
195 dryrun (bool): dryrun interface configuration
196 withdepends (bool): apply interface configuration on all depends
197 interfacesfile (str): interfaces file. default is /etc/network/interfaces
198 interfacesfileformat (str): default is 'native'. Other choices are 'json'
201 AttributeError, KeyError """
203 self
.logger
= logging
.getLogger('ifupdown')
204 ifupdownflags
.flags
.FORCE
= force
205 ifupdownflags
.flags
.DRYRUN
= dryrun
206 ifupdownflags
.flags
.WITHDEFAULTS
= withdefaults
207 ifupdownflags
.flags
.NOWAIT
= nowait
208 ifupdownflags
.flags
.PERFMODE
= perfmode
209 ifupdownflags
.flags
.CACHE
= cache
210 ifupdownflags
.flags
.WITH_DEPENDS
= withdepends
212 # Can be used to provide hints for caching
213 ifupdownflags
.flags
.CACHE_FLAGS
= 0x0
215 self
.flags
= ifupdownMainFlags()
217 self
.flags
.STATEMANAGER_ENABLE
= statemanager_enable
218 self
.interfacesfile
= interfacesfile
219 self
.interfacesfileiobuf
= interfacesfileiobuf
220 self
.interfacesfileformat
= interfacesfileformat
222 self
.logger
.debug(self
.config
)
223 self
.blacklisted_ifaces_present
= False
225 self
.type = ifaceType
.UNKNOWN
227 self
.flags
.DELETE_DEPENDENT_IFACES_WITH_NOCONFIG
= False
228 self
.flags
.ADDONS_ENABLE
= addons_enable
230 self
.ifaces
= OrderedDict()
232 self
.pp
= pprint
.PrettyPrinter(indent
=4)
233 self
.modules
= OrderedDict({})
234 self
.module_attrs
= {}
235 self
.overridden_ifupdown_scripts
= []
237 if self
.config
.get('addon_python_modules_support', '1') == '1':
238 self
.load_addon_modules(self
.addon_modules_dir
)
239 if self
.config
.get('addon_scripts_support', '0') == '1':
240 self
.load_scripts(self
.scripts_dir
)
241 self
.dependency_graph
= OrderedDict({})
243 self
._cache
_no
_repeats
= {}
245 if self
.flags
.STATEMANAGER_ENABLE
:
247 self
.statemanager
= statemanager
.statemanager_api
248 self
.statemanager
.read_saved_state()
250 # XXX Maybe we should continue by ignoring old state
251 self
.logger
.warning('error reading state (%s)' %str
(e
))
254 self
.flags
.STATEMANAGER_UPDATE
= False
255 self
._delay
_admin
_state
= True if self
.config
.get(
256 'delay_admin_state_change', '0') == '1' else False
257 self
._delay
_admin
_state
_iface
_queue
= []
258 if self
._delay
_admin
_state
:
259 self
.logger
.info('\'delay_admin_state_change\' is set. admin ' +
260 'state changes will be delayed till the end.')
262 self
._link
_master
_slave
= True if self
.config
.get(
263 'link_master_slave', '0') == '1' else False
264 if self
._link
_master
_slave
:
265 self
.logger
.info('\'link_master_slave\' is set. slave admin ' +
266 'state changes will be delayed till the ' +
267 'masters admin state change.')
269 # squash iface objects for same interface both internal and
270 # external representation. It is off by default.
271 self
._ifaceobj
_squash
= True if self
.config
.get(
272 'ifaceobj_squash', '0') == '1' else False
274 # squash iface objects for same interface internal
275 # representation only. External representation as seen by ifquery
276 # will continue to see multiple iface stanzas if it was specified
277 # that way by the user. It is on by default.
278 self
._ifaceobj
_squash
_internal
= True if self
.config
.get(
279 'ifaceobj_squash_internal', '1') == '1' else False
281 # initialize global config object with config passed by the user
282 # This makes config available to addon modules
283 ifupdownConfig
.config
= self
.config
285 self
.validate_keywords
= {
286 '<mac>': self
._keyword
_mac
,
287 '<text>': self
._keyword
_text
,
288 '<ipv4>': self
._keyword
_ipv
4,
289 '<ipv6>': self
._keyword
_ipv
6,
290 '<ip>': self
._keyword
_ip
,
291 '<number>': self
._keyword
_number
,
292 '<interface>': self
._keyword
_interface
,
293 '<ipv4-vrf-text>': self
._keyword
_ipv
4_vrf
_text
,
294 '<number-ipv4-list>': self
._keyword
_number
_ipv
4_list
,
295 '<interface-list>': self
._keyword
_interface
_list
,
296 '<ipv4/prefixlen>': self
._keyword
_ipv
4_prefixlen
,
297 '<ipv6/prefixlen>': self
._keyword
_ipv
6_prefixlen
,
298 '<ip/prefixlen>': self
._keyword
_ip
_prefixlen
,
299 '<number-range-list>': self
._keyword
_number
_range
_list
,
300 '<interface-range-list>': self
._keyword
_interface
_range
_list
,
301 '<mac-ip/prefixlen-list>': self
._keyword
_mac
_ip
_prefixlen
_list
,
302 '<number-interface-list>': self
._keyword
_number
_interface
_list
,
303 '<interface-yes-no-list>': self
._keyword
_interface
_yes
_no
_list
,
304 '<interface-yes-no-0-1-list>': self
._keyword
_interface
_yes
_no
_0_1_list
,
305 '<interface-yes-no-auto-list>': self
._keyword
_interface
_yes
_no
_auto
_list
,
308 def link_master_slave_ignore_error(self
, errorstr
):
309 # If link master slave flag is set,
310 # there may be cases where the lowerdev may not be
311 # up resulting in 'Network is down' error
312 # This can happen if the lowerdev is a LINK_SLAVE
313 # of another interface which is not up yet
314 # example of such a case:
315 # bringing up a vlan on a bond interface and the bond
316 # is a LINK_SLAVE of a bridge (in other words the bond is
317 # part of a bridge) which is not up yet
318 if self
._link
_master
_slave
:
319 if 'Network is down' in errorstr
:
323 def get_ifaceobjs(self
, ifacename
):
324 return self
.ifaceobjdict
.get(ifacename
)
326 def get_ifaceobjs_saved(self
, ifacename
):
327 """ Return ifaceobjects from statemanager """
328 if self
.flags
.STATEMANAGER_ENABLE
:
329 return self
.statemanager
.get_ifaceobjs(ifacename
)
333 def get_ifaceobj_first(self
, ifacename
):
334 ifaceobjs
= self
.get_ifaceobjs(ifacename
)
339 def get_ifacenames(self
):
340 return self
.ifaceobjdict
.keys()
342 def get_iface_obj_last(self
, ifacename
):
343 return self
.ifaceobjdict
.get(ifacename
)[-1]
346 def must_follow_upperifaces(self
, ifacename
):
348 # XXX: This bleeds the knowledge of iface
349 # types in the infrastructure module.
350 # Cant think of a better fix at the moment.
351 # In future maybe the module can set a flag
352 # to indicate if we should follow upperifaces
354 ifaceobj
= self
.get_ifaceobj_first(ifacename
)
355 if ifaceobj
.type == ifaceType
.BRIDGE_VLAN
:
359 def create_n_save_ifaceobj(self
, ifacename
, priv_flags
=None,
361 """ creates a iface object and adds it to the iface dictionary """
363 ifaceobj
.name
= ifacename
364 ifaceobj
.priv_flags
= priv_flags
366 if not self
._link
_master
_slave
:
367 ifaceobj
.link_type
= ifaceLinkType
.LINK_NA
369 ifaceobj
.inc_refcnt()
370 self
.ifaceobjdict
[ifacename
] = [ifaceobj
]
373 def create_n_save_ifaceobjcurr(self
, ifaceobj
):
374 """ creates a copy of iface object and adds it to the iface
375 dict containing current iface objects
377 ifaceobjcurr
= iface()
378 ifaceobjcurr
.name
= ifaceobj
.name
379 ifaceobjcurr
.type = ifaceobj
.type
380 ifaceobjcurr
.lowerifaces
= ifaceobj
.lowerifaces
381 ifaceobjcurr
.priv_flags
= copy
.deepcopy(ifaceobj
.priv_flags
)
382 ifaceobjcurr
.auto
= ifaceobj
.auto
383 self
.ifaceobjcurrdict
.setdefault(ifaceobj
.name
,
384 []).append(ifaceobjcurr
)
387 def get_ifaceobjcurr(self
, ifacename
, idx
=0):
388 ifaceobjlist
= self
.ifaceobjcurrdict
.get(ifacename
)
394 return ifaceobjlist
[idx
]
396 def get_ifaceobjrunning(self
, ifacename
):
397 return self
.ifaceobjrunningdict
.get(ifacename
)
399 def get_iface_refcnt(self
, ifacename
):
400 """ Return iface ref count """
402 ifaceobjs
= self
.get_ifaceobjs(ifacename
)
410 def is_iface_builtin_byname(self
, ifacename
):
411 """ Returns true if iface name is a builtin interface.
413 A builtin interface is an interface which ifupdown understands.
414 The following are currently considered builtin ifaces:
415 - vlan interfaces in the format <ifacename>.<vlanid>
417 return '.' in ifacename
419 def is_ifaceobj_builtin(self
, ifaceobj
):
420 """ Returns true if iface name is a builtin interface.
422 A builtin interface is an interface which ifupdown understands.
423 The following are currently considered builtin ifaces:
424 - vlan interfaces in the format <ifacename>.<vlanid>
426 if (ifaceobj
.priv_flags
and ifaceobj
.priv_flags
.BUILTIN
):
430 def is_ifaceobj_noconfig(self
, ifaceobj
):
431 """ Returns true if iface object did not have a user defined config.
433 These interfaces appear only when they are dependents of interfaces
434 which have user defined config
436 return (ifaceobj
.priv_flags
and ifaceobj
.priv_flags
.NOCONFIG
)
438 def is_iface_noconfig(self
, ifacename
):
439 """ Returns true if iface has no config """
441 ifaceobj
= self
.get_ifaceobj_first(ifacename
)
442 if not ifaceobj
: return True
443 return self
.is_ifaceobj_noconfig(ifaceobj
)
445 def check_shared_dependents(self
, ifaceobj
, dlist
):
446 """ ABSOLETE: Check if dlist intersects with any other
447 interface with slave dependents.
448 example: bond and bridges.
449 This function logs such errors """
450 setdlist
= Set(dlist
)
451 for ifacename
, ifacedlist
in self
.dependency_graph
.items():
454 check_depends
= False
455 iobjs
= self
.get_ifaceobjs(ifacename
)
459 if (i
.dependency_type
== ifaceDependencyType
.MASTER_SLAVE
):
462 common
= Set(ifacedlist
).intersection(setdlist
)
464 self
.logger
.error('misconfig..?. iface %s and %s '
465 %(ifaceobj
.name
, ifacename
) +
466 'seem to share dependents/ports %s' %str
(list(common
)))
468 def _set_iface_role(self
, ifaceobj
, role
, upperifaceobj
):
469 if (self
.flags
.CHECK_SHARED_DEPENDENTS
and
470 (ifaceobj
.role
& ifaceRole
.SLAVE
) and
471 (role
== ifaceRole
.SLAVE
) and (upperifaceobj
.role
== ifaceRole
.MASTER
)):
472 self
.logger
.error("misconfig..? %s %s is enslaved to multiple interfaces %s"
474 ifaceLinkPrivFlags
.get_all_str(ifaceobj
.link_privflags
), str(ifaceobj
.upperifaces
)))
475 ifaceobj
.set_status(ifaceStatus
.ERROR
)
479 def _set_iface_role_n_kind(self
, ifaceobj
, upperifaceobj
):
481 # If addr_method is set and link is not a logical interface,
482 # set flag KEEP_LINK_DOWN. addr_method == 'manual' only applies to
483 # logical interfaces.
484 if (ifaceobj
.addr_method
== 'manual' and not ifaceobj
.link_kind
):
485 ifaceobj
.link_privflags |
= ifaceLinkPrivFlags
.KEEP_LINK_DOWN
487 if (upperifaceobj
.link_kind
& ifaceLinkKind
.BOND
):
488 self
._set
_iface
_role
(ifaceobj
, ifaceRole
.SLAVE
, upperifaceobj
)
489 ifaceobj
.link_privflags |
= ifaceLinkPrivFlags
.BOND_SLAVE
491 if (upperifaceobj
.link_kind
& ifaceLinkKind
.BRIDGE
):
492 self
._set
_iface
_role
(ifaceobj
, ifaceRole
.SLAVE
, upperifaceobj
)
493 ifaceobj
.link_privflags |
= ifaceLinkPrivFlags
.BRIDGE_PORT
495 if (ifaceobj
.link_kind
& ifaceLinkKind
.VXLAN
) \
496 and (upperifaceobj
.link_kind
& ifaceLinkKind
.BRIDGE
):
497 upperifaceobj
.link_privflags |
= ifaceLinkPrivFlags
.BRIDGE_VXLAN
499 # vrf masters get processed after slaves, which means
500 # check both link_kind vrf and vrf slave
501 if ((upperifaceobj
.link_kind
& ifaceLinkKind
.VRF
) or
502 (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.VRF_SLAVE
)):
503 self
._set
_iface
_role
(ifaceobj
, ifaceRole
.SLAVE
, upperifaceobj
)
504 ifaceobj
.link_privflags |
= ifaceLinkPrivFlags
.VRF_SLAVE
505 if self
._link
_master
_slave
:
506 if upperifaceobj
.link_type
== ifaceLinkType
.LINK_MASTER
:
507 ifaceobj
.link_type
= ifaceLinkType
.LINK_SLAVE
509 upperifaceobj
.link_type
= ifaceLinkType
.LINK_NA
510 ifaceobj
.link_type
= ifaceLinkType
.LINK_NA
512 def dump_iface_dependency_info(self
):
513 """ debug funtion to print raw dependency
514 info - lower and upper devices"""
516 for ifacename
, ifaceobjs
in self
.ifaceobjdict
.iteritems():
518 self
.logger
.info("%s: refcnt: %d, lower: %s, upper: %s" %(ifacename
,
519 self
.get_iface_refcnt(ifacename
),
520 str(iobj
.lowerifaces
) if iobj
.lowerifaces
else [],
521 str(iobj
.upperifaces
) if iobj
.upperifaces
else []))
524 def preprocess_dependency_list(self
, upperifaceobj
, dlist
, ops
):
525 """ We go through the dependency list and
526 delete or add interfaces from the interfaces dict by
527 applying the following rules:
528 if flag DELETE_DEPENDENT_IFACES_WITH_NOCONFIG is True:
529 we only consider devices whose configuration was
530 specified in the network interfaces file. We delete
531 any interface whose config was not specified except
532 for vlan devices. vlan devices get special treatment.
533 Even if they are not present they are created and added
535 elif flag DELETE_DEPENDENT_IFACES_WITH_NOCONFIG is False:
536 we create objects for all dependent devices that are not
537 present in the ifacesdict
542 dilist
= self
.get_ifaceobjs(d
)
545 if self
.is_iface_builtin_byname(d
):
546 ni
= self
.create_n_save_ifaceobj(d
,
547 ifacePrivFlags(True, True), True)
548 elif not self
.flags
.DELETE_DEPENDENT_IFACES_WITH_NOCONFIG
:
549 ni
= self
.create_n_save_ifaceobj(d
,
550 ifacePrivFlags(False, True), True)
554 ni
.add_to_upperifaces(upperifaceobj
.name
)
555 self
._set
_iface
_role
_n
_kind
(ni
, upperifaceobj
)
559 di
.add_to_upperifaces(upperifaceobj
.name
)
560 self
._set
_iface
_role
_n
_kind
(di
, upperifaceobj
)
564 def preprocess_upperiface(self
, lowerifaceobj
, ulist
, ops
):
566 if (lowerifaceobj
.upperifaces
and
567 u
in lowerifaceobj
.upperifaces
):
569 lowerifaceobj
.add_to_upperifaces(u
)
570 uifacelist
= self
.get_ifaceobjs(u
)
572 for ui
in uifacelist
:
573 lowerifaceobj
.inc_refcnt()
574 self
._set
_iface
_role
_n
_kind
(lowerifaceobj
, ui
)
575 ui
.add_to_lowerifaces(lowerifaceobj
.name
)
577 def query_lowerifaces(self
, ifaceobj
, ops
, ifacenames
, type=None):
578 """ Gets iface dependents by calling into respective modules """
581 # Get dependents for interface by querying respective modules
582 for module
in self
.modules
.values():
584 if ops
[0] == 'query-running':
585 if (not hasattr(module
,
586 'get_dependent_ifacenames_running')):
588 dlist
= module
.get_dependent_ifacenames_running(ifaceobj
)
590 if (not hasattr(module
, 'get_dependent_ifacenames')):
592 dlist
= module
.get_dependent_ifacenames(ifaceobj
,
595 self
.logger
.warn('%s: error getting dependent interfaces (%s)'
596 %(ifaceobj
.name
, str(e
)))
599 if dlist
: ret_dlist
.extend(dlist
)
600 return list(set(ret_dlist
))
602 def query_upperifaces(self
, ifaceobj
, ops
, ifacenames
, type=None):
603 """ Gets iface upperifaces by calling into respective modules """
606 # Get upperifaces for interface by querying respective modules
607 for module
in self
.modules
.values():
609 if ops
[0] == 'query-running':
610 if (not hasattr(module
,
611 'get_upper_ifacenames_running')):
613 ulist
= module
.get_upper_ifacenames_running(ifaceobj
)
615 if (not hasattr(module
, 'get_upper_ifacenames')):
617 ulist
= module
.get_upper_ifacenames(ifaceobj
, ifacenames
)
619 self
.logger
.warn('%s: error getting upper interfaces (%s)'
620 %(ifaceobj
.name
, str(e
)))
623 if ulist
: ret_ulist
.extend(ulist
)
624 return list(set(ret_ulist
))
626 def populate_dependency_info(self
, ops
, ifacenames
=None):
627 """ recursive function to generate iface dependency info """
630 ifacenames
= self
.ifaceobjdict
.keys()
632 iqueue
= deque(ifacenames
)
635 # Go through all modules and find dependent ifaces
638 ifaceobjs
= self
.get_ifaceobjs(i
)
641 dependents_processed
= False
643 # Store all dependency info in the first ifaceobj
644 # but get dependency info from all ifaceobjs
645 ifaceobj
= ifaceobjs
[0]
646 for iobj
in ifaceobjs
:
647 ulist
= self
.query_upperifaces(iobj
, ops
, ifacenames
)
649 dependents_processed
= True
651 dlist
= self
.query_lowerifaces(iobj
, ops
, ifacenames
)
655 self
.preprocess_upperiface(ifaceobj
, ulist
, ops
)
656 if dependents_processed
:
659 self
.preprocess_dependency_list(ifaceobj
,
661 ifaceobj
.lowerifaces
= dlist
662 [iqueue
.append(d
) for d
in dlist
]
663 #if not self.dependency_graph.get(i):
664 # self.dependency_graph[i] = dlist
666 for i
in self
.ifaceobjdict
.keys():
667 iobj
= self
.get_ifaceobj_first(i
)
668 if (not iobj
.link_kind
and
669 not (iobj
.link_privflags
& ifaceLinkPrivFlags
.LOOPBACK
) and
671 iobj
.link_privflags |
= ifaceLinkPrivFlags
.LOOPBACK
673 self
.dependency_graph
[i
] = iobj
.lowerifaces
675 self
.dependency_graph
[i
] = []
677 if not self
.blacklisted_ifaces_present
:
680 # Walk through the dependency graph and remove blacklisted
681 # interfaces that were picked up as dependents
682 for i
in self
.dependency_graph
.keys():
683 ifaceobj
= self
.get_ifaceobj_first(i
)
687 if ifaceobj
.blacklisted
and not ifaceobj
.upperifaces
:
688 # if blacklisted and was not picked up as a
689 # dependent of a upper interface, delete the
690 # interface from the dependency graph
691 dlist
= ifaceobj
.lowerifaces
694 difaceobjs
= self
.get_ifaceobjs(d
)
700 d
.upperifaces
.remove(i
)
702 self
.logger
.debug('error removing %s from %s upperifaces' %(i
, d
))
704 self
.logger
.debug("populate_dependency_info: deleting blacklisted interface %s" %i)
705 del self
.dependency_graph
[i
]
708 def _check_config_no_repeats(self
, ifaceobj
):
709 """ check if object has an attribute that is
710 restricted to a single object in the system.
711 if yes, warn and return """
712 for k
,v
in self
._cache
_no
_repeats
.items():
713 iv
= ifaceobj
.config
.get(k
)
714 if iv
and iv
[0] == v
:
715 self
.logger
.error('ignoring interface %s. ' %ifaceobj
.name
+
716 'Only one object with attribute ' +
717 '\'%s %s\' allowed.' %(k
, v
))
719 for k
, v
in self
.config
.get('no_repeats', {}).items():
720 iv
= ifaceobj
.config
.get(k
)
721 if iv
and iv
[0] == v
:
722 self
._cache
_no
_repeats
[k
] = v
725 def _save_iface_squash(self
, ifaceobj
):
726 """ squash ifaceobjects belonging to same iface
727 into a single object """
728 if self
._check
_config
_no
_repeats
(ifaceobj
):
730 ifaceobj
.priv_flags
= ifacePrivFlags()
731 if not self
._link
_master
_slave
:
732 ifaceobj
.link_type
= ifaceLinkType
.LINK_NA
733 currentifaceobjlist
= self
.ifaceobjdict
.get(ifaceobj
.name
)
734 if not currentifaceobjlist
:
735 self
.ifaceobjdict
[ifaceobj
.name
] = [ifaceobj
]
737 if ifaceobj
.compare(currentifaceobjlist
[0]):
738 self
.logger
.warn('duplicate interface %s found' %ifaceobj
.name
)
740 for obj
in self
.ifaceobjdict
[ifaceobj
.name
]:
741 if obj
.type == ifaceobj
.type:
744 self
.ifaceobjdict
[ifaceobj
.name
].append(ifaceobj
)
746 def _save_iface(self
, ifaceobj
):
747 if self
._check
_config
_no
_repeats
(ifaceobj
):
749 ifaceobj
.priv_flags
= ifacePrivFlags()
750 if not self
._link
_master
_slave
:
751 ifaceobj
.link_type
= ifaceLinkType
.LINK_NA
752 currentifaceobjlist
= self
.ifaceobjdict
.get(ifaceobj
.name
)
753 if not currentifaceobjlist
:
754 self
.ifaceobjdict
[ifaceobj
.name
]= [ifaceobj
]
755 if not self
._ifaceobj
_squash
:
756 ifaceobj
.flags |
= ifaceobj
.YOUNGEST_SIBLING
758 if ifaceobj
.compare(currentifaceobjlist
[0]):
759 self
.logger
.warn('duplicate interface %s found' %ifaceobj
.name
)
761 if currentifaceobjlist
[0].type == ifaceobj
.type:
762 currentifaceobjlist
[0].flags |
= ifaceobj
.HAS_SIBLINGS
763 ifaceobj
.flags |
= ifaceobj
.HAS_SIBLINGS
764 # clear the OLDEST_SIBLING from all the siblings
765 for iface
in self
.ifaceobjdict
[ifaceobj
.name
]:
766 iface
.flags
&= ~ifaceobj
.OLDEST_SIBLING
767 # current sibling is the oldest
768 ifaceobj
.flags |
= ifaceobj
.OLDEST_SIBLING
769 self
.ifaceobjdict
[ifaceobj
.name
].append(ifaceobj
)
771 def _keyword_text(self
, value
, validrange
=None):
772 return isinstance(value
, str) and len(value
) > 0
774 def _keyword_mac(self
, value
, validrange
=None):
775 if value
.strip().startswith('ether'):
776 value
= value
.strip()[6:]
777 return re
.match('[0-9a-f]{1,2}([-:])[0-9a-f]{1,2}(\\1[0-9a-f]{1,2}){4}$',
780 def _keyword_check_list(self
, _list
, obj
, limit
=None):
782 if limit
and limit
> 0:
783 for i
in xrange(0, limit
):
785 return len(_list
) == limit
790 except Exception as e
:
791 self
.logger
.debug('keyword: check list: %s' % str(e
))
794 def _keyword_ipv4(self
, value
, validrange
=None):
795 return self
._keyword
_check
_list
(value
.split(), IPv4Address
, limit
=1)
797 def _keyword_ipv4_prefixlen(self
, value
, validrange
=None):
798 return self
._keyword
_check
_list
(value
.split(), IPv4Network
, limit
=1)
800 def _keyword_ipv6(self
, value
, validrange
=None):
801 return self
._keyword
_check
_list
(value
.split(), IPv6Address
, limit
=1)
803 def _keyword_ipv6_prefixlen(self
, value
, validrange
=None):
804 return self
._keyword
_check
_list
(value
.split(), IPv6Network
, limit
=1)
806 def _keyword_ip(self
, value
, validrange
=None):
807 return self
._keyword
_check
_list
(value
.split(), IPAddress
, limit
=1)
809 def _keyword_ip_prefixlen(self
, value
, validrange
=None):
810 return self
._keyword
_check
_list
(value
.split(), IPNetwork
, limit
=1)
812 def _keyword_mac_ip_prefixlen_list(self
, value
, validrange
=None):
814 <mac> <ip> [<ip> ...]
815 ex: address-virtual 00:11:22:33:44:01 11.0.1.1/24 11.0.1.2/24
821 if not self
._keyword
_mac
(res
[0]):
824 if not self
._keyword
_ip
_prefixlen
(ip
):
827 except Exception as e
:
828 self
.logger
.debug('keyword: mac ipaddr prefixlen: %s' % str(e
))
831 def _keyword_number_ipv4_list(self
, value
, validrange
=None):
833 <number>=<ipv4> [<number>=<ipv4> ...]
834 ex: bridge-mcqv4src 100=172.16.100.1 101=172.16.101.1
837 elements
= value
.split(' ')
840 for elem
in elements
:
845 except Exception as e
:
846 self
.logger
.debug('keyword: number ipv4: %s' % str(e
))
849 def _keyword_interface(self
, ifacename
, validrange
=None):
850 return self
.get_ifaceobjs(ifacename
)
852 def _keyword_ipv4_vrf_text(self
, value
, validrange
=None):
855 ex: clagd-backup-ip 10.10.10.42 vrf blue
857 values
= value
.split()
860 if size
> 3 or size
< 1:
863 IPv4Address(values
[0])
865 if values
[1] != 'vrf':
868 if not self
._keyword
_text
(values
[2]):
871 except Exception as e
:
872 self
.logger
.debug('keyword: ipv4 vrf text: %s' % str(e
))
875 def _keyword_interface_list_with_value(self
, value
, validvals
):
876 values
= value
.split()
879 if values
[0] in validvals
:
882 iface_value
= v
.split('=')
883 size
= len(iface_value
)
885 if iface_value
[0] == 'glob' or iface_value
[0] == 'regex':
888 if not iface_value
[1] in validvals
:
891 except Exception as e
:
892 self
.logger
.debug('keyword: interface list with value: %s' % str(e
))
895 def _keyword_interface_yes_no_list(self
, value
, validrange
=None):
897 <yes|no> | ( <interface>=<yes|no> [<interface>=<yes|no> ...] )
898 ex: mstpctl-portrestrrole swp1=yes swp2=no
900 return self
._keyword
_interface
_list
_with
_value
(value
, ['yes', 'no'])
902 def _keyword_interface_yes_no_auto_list(self
, value
, validrange
=None):
905 ( <interface>=<yes|no|auto> [<interface>=<yes|no|auto> ...] )
906 ex: mstpctl-portp2p swp1=yes swp2=no swp3=auto
908 return self
._keyword
_interface
_list
_with
_value
(value
,
909 ['yes', 'no', 'auto'])
911 def _keyword_interface_yes_no_0_1_list(self
, value
, validrange
=None):
914 ( <interface>=<yes|no|0|1> [<interface>=<yes|no|0|1> ...] )
915 ex: bridge-portmcrouter swp1=yes swp2=yes swp3=1
917 return self
._keyword
_interface
_list
_with
_value
(value
,
918 ['yes', 'no', '1', '0'])
920 def _keyword_interface_range_list(self
, value
, validrange
):
922 <number> | ( <interface>=<number> [ <interface>=number> ...] )
923 ex: mstpctl-portpathcost swp1=0 swp2=1
925 values
= value
.split()
930 if n
< int(validrange
[0]) or n
> int(
932 raise invalidValueError('value of out range "%s":'
933 ' valid attribute range: %s'
935 '-'.join(validrange
)))
937 except invalidValueError
as e
:
939 except Exception as e
:
940 self
.logger
.debug('keyword: interface range list: %s'
944 iface_value
= v
.split('=')
945 size
= len(iface_value
)
948 number
= int(iface_value
[1])
949 if number
< int(validrange
[0]) or number
> int(
951 raise invalidValueError(
952 'value of out range "%s" for iface "%s":'
953 ' valid attribute range: %s'
956 '-'.join(validrange
)))
958 except invalidValueError
as e
:
960 except Exception as e
:
961 self
.logger
.debug('keyword: interface range list: %s' % str(e
))
964 def _keyword_interface_list(self
, value
, validrange
=None):
966 [glob|regex] <interface> [ [glob|regex] <interface> ...]
967 ex: bridge-ports swp1 swp2 glob swp3-5.100 regex (swp[6|7|8].100)
969 interface_list
= value
.split()
970 size
= len(interface_list
)
973 if interface_list
[i
] == 'glob' or interface_list
[i
] == 'regex':
976 if not self
._keyword
_interface
(interface_list
[i
]):
981 def _keyword_number_range_list(self
, value
, validrange
=None):
983 <number> [<number>-<number>]
984 ex: bridge-vids 42 100-200
986 number_list
= value
.split()
989 while i
< len(number_list
):
990 if '-' in number_list
[i
]:
991 range = number_list
[i
].split('-')
1000 except Exception as e
:
1001 self
.logger
.debug('keyword: number range list: %s' % str(e
))
1004 def _keyword_number_interface_list(self
, value
, validrange
=None):
1006 <number> <interface> [<interface>... [<number> <interface> ... ]]
1007 bridge-waitport 42 swp1 swp2 swp3 9 swp4
1009 interface_list
= value
.split()
1010 if not interface_list
:
1013 int(interface_list
[0])
1015 for elem
in interface_list
[1:]:
1024 except Exception as e
:
1025 self
.logger
.debug('keyword: number interface list: %s' % str(e
))
1028 def _keyword_number(self
, value
, validrange
=None):
1032 except Exception as e
:
1033 self
.logger
.debug('keyword: number: %s' % str(e
))
1036 def _is_keyword(self
, value
):
1037 if isinstance(value
, tuple):
1039 keyword_found
= value
in self
.validate_keywords
1040 if value
.startswith('<') and value
.endswith('>') and not keyword_found
:
1041 raise Exception('%s: invalid keyword, please make sure to use'
1042 ' a valid keyword see `ifquery -s`' % value
)
1043 return keyword_found
1045 def _check_validvals_value(self
, attrname
, value
, validvals
, validrange
):
1046 if validvals
and value
not in validvals
:
1048 for keyword
in validvals
:
1049 if self
._is
_keyword
(keyword
):
1051 if self
.validate_keywords
[keyword
](value
, validrange
):
1052 return {'result': True}
1054 if self
.validate_keywords
[keyword
](value
):
1055 return {'result': True}
1059 'message': 'invalid value "%s": valid attribute values: %s'
1060 % (value
, validvals
)
1063 if len(validrange
) != 2:
1064 raise Exception('%s: invalid range in addon configuration'
1065 % '-'.join(validrange
))
1067 if _value
< int(validrange
[0]) or _value
> int(validrange
[1]):
1070 'message': 'value of out range "%s": '
1071 'valid attribute range: %s'
1072 % (value
, '-'.join(validrange
))
1074 return {'result': True}
1076 def _check_validvals(self
, ifacename
, module_name
, attrs
):
1077 ifaceobj
= self
.get_ifaceobjs(ifacename
)
1081 for attrname
, attrvalue
in ifaceobj
[0].config
.items():
1083 attrname_dict
= attrs
.get(attrname
, {})
1084 validvals
= attrname_dict
.get('validvals', [])
1085 validrange
= attrname_dict
.get('validrange', [])
1086 for value
in attrvalue
:
1087 res
= self
._check
_validvals
_value
(attrname
,
1091 if not res
['result']:
1092 self
.logger
.warn('%s: %s: %s' %
1093 (ifacename
, attrname
, res
['message']))
1095 except Exception as e
:
1096 self
.logger
.warn('addon \'%s\': %s: %s' % (module_name
,
1102 def _module_syntax_check(self
, filtered_ifacenames
):
1104 for ifacename
in filtered_ifacenames
:
1105 for module
in self
.modules
.values():
1107 if hasattr(module
, '_modinfo'):
1108 if not self
._check
_validvals
(ifacename
,
1109 module
.__class
__.__name
__,
1110 module
._modinfo
.get('attrs', {})):
1112 if hasattr(module
, 'syntax_check') and callable(module
.syntax_check
):
1113 if not module
.syntax_check(self
.get_ifaceobjs(ifacename
)[0],
1114 self
.get_ifaceobjs
):
1116 except Exception, e
:
1117 self
.logger
.warn('%s: %s' % (ifacename
, str(e
)))
1121 def _iface_configattr_syntax_checker(self
, attrname
, attrval
):
1122 for m
, mdict
in self
.module_attrs
.items():
1125 attrsdict
= mdict
.get('attrs')
1127 a
= attrsdict
.get(attrname
)
1129 if a
.get('deprecated'):
1130 newa
= a
.get('new-attribute')
1132 self
.logger
.warn('attribute %s is deprecated. use %s instead.' %(attrname
, newa
))
1134 self
.logger
.warn('attribute %s is deprecated.'
1138 for key
in attrsdict
:
1139 if 'aliases' in attrsdict
[key
]:
1140 if attrname
in attrsdict
[key
]['aliases']:
1142 except AttributeError:
1146 def _ifaceobj_syntax_checker(self
, ifaceobj
):
1148 for attrname
, attrvalue
in ifaceobj
.config
.items():
1150 for k
, v
in self
.module_attrs
.items():
1151 if v
and v
.get('attrs', {}).get(attrname
):
1156 self
.logger
.warn('%s: unsupported attribute \'%s\'' \
1157 % (ifaceobj
.name
, attrname
))
1161 def read_iface_config(self
):
1162 """ Reads default network interface config /etc/network/interfaces. """
1164 nifaces
= networkInterfaces(self
.interfacesfile
,
1165 self
.interfacesfileiobuf
,
1166 self
.interfacesfileformat
,
1167 template_enable
=self
.config
.get('template_enable', 0),
1168 template_engine
=self
.config
.get('template_engine'),
1169 template_lookuppath
=self
.config
.get('template_lookuppath'))
1170 if self
._ifaceobj
_squash
or self
._ifaceobj
_squash
_internal
:
1171 nifaces
.subscribe('iface_found', self
._save
_iface
_squash
)
1173 nifaces
.subscribe('iface_found', self
._save
_iface
)
1174 if self
.config
.get('addon_syntax_check', '1') == '1':
1175 nifaces
.subscribe('validateifaceattr',
1176 self
._iface
_configattr
_syntax
_checker
)
1177 nifaces
.subscribe('validateifaceobj', self
._ifaceobj
_syntax
_checker
)
1179 if nifaces
.errors
or nifaces
.warns
:
1183 def read_old_iface_config(self
):
1184 """ Reads the saved iface config instead of default iface config.
1185 And saved iface config is already read by the statemanager """
1186 self
.ifaceobjdict
= copy
.deepcopy(self
.statemanager
.ifaceobjdict
)
1188 def _load_addon_modules_config(self
):
1189 """ Load addon modules config file """
1191 with
open(self
.addon_modules_configfile
, 'r') as f
:
1192 lines
= f
.readlines()
1195 litems
= l
.strip(' \n\t\r').split(',')
1196 if not litems
or len(litems
) < 2:
1198 operation
= litems
[0]
1200 self
.module_ops
[operation
].append(mname
)
1201 except Exception, e
:
1202 self
.logger
.warn('error reading line \'%s\' %s:' %(l
, str(e
)))
1205 def load_addon_modules(self
, modules_dir
):
1206 """ load python modules from modules_dir
1208 Default modules_dir is /usr/share/ifupdownmodules
1211 self
.logger
.info('loading builtin modules from %s' %modules_dir
)
1212 self
._load
_addon
_modules
_config
()
1213 if not modules_dir
in sys
.path
:
1214 sys
.path
.append(modules_dir
)
1216 for op
, mlist
in self
.module_ops
.items():
1218 if self
.modules
.get(mname
):
1220 mpath
= modules_dir
+ '/' + mname
+ '.py'
1221 if os
.path
.exists(mpath
):
1223 m
= __import__(mname
)
1224 mclass
= getattr(m
, mname
)
1228 minstance
= mclass()
1229 script_override
= minstance
.get_overrides_ifupdown_scripts()
1230 self
.overridden_ifupdown_scripts
.extend(script_override
)
1231 except moduleNotSupported
, e
:
1232 self
.logger
.info('module %s not loaded (%s)\n'
1237 self
.modules
[mname
] = minstance
1239 self
.module_attrs
[mname
] = minstance
.get_modinfo()
1245 # Assign all modules to query operations
1246 self
.module_ops
['query-checkcurr'] = self
.modules
.keys()
1247 self
.module_ops
['query-running'] = self
.modules
.keys()
1248 self
.module_ops
['query-dependency'] = self
.modules
.keys()
1249 self
.module_ops
['query'] = self
.modules
.keys()
1250 self
.module_ops
['query-raw'] = self
.modules
.keys()
1253 def _modules_help(self
):
1254 """ Prints addon modules supported syntax """
1257 for m
, mdict
in self
.module_attrs
.items():
1260 print('%s: %s' %(m
, mdict
.get('mhelp')))
1261 attrdict
= mdict
.get('attrs')
1265 for attrname
, attrvaldict
in attrdict
.items():
1266 if attrvaldict
.get('compat', False):
1268 print('%s%s' %(indent
, attrname
))
1269 print('%shelp: %s' %(indent
+ ' ',
1270 attrvaldict
.get('help', '')))
1271 print ('%srequired: %s' %(indent
+ ' ',
1272 attrvaldict
.get('required', False)))
1273 default
= attrvaldict
.get('default')
1275 print('%sdefault: %s' %(indent
+ ' ', default
))
1277 validrange
= attrvaldict
.get('validrange')
1279 print('%svalidrange: %s-%s'
1280 %(indent
+ ' ', validrange
[0], validrange
[1]))
1282 validvals
= attrvaldict
.get('validvals')
1284 print('%svalidvals: %s'
1285 %(indent
+ ' ', ','.join(validvals
)))
1287 examples
= attrvaldict
.get('example')
1291 print '%sexample:' %(indent
+ ' ')
1293 print '%s%s' %(indent
+ ' ', e
)
1298 def load_scripts(self
, modules_dir
):
1299 """ loading user modules from /etc/network/.
1301 Note that previously loaded python modules override modules found
1302 under /etc/network if any
1306 self
.logger
.info('looking for user scripts under %s' %modules_dir
)
1307 for op
, mlist
in self
.script_ops
.items():
1308 msubdir
= modules_dir
+ '/if-%s.d' %op
1309 self
.logger
.info('loading scripts under %s ...' %msubdir
)
1311 module_list
= os
.listdir(msubdir
)
1312 for module
in module_list
:
1313 if self
.modules
.get(module
) or module
in self
.overridden_ifupdown_scripts
:
1315 self
.script_ops
[op
].append(msubdir
+ '/' + module
)
1320 def _sched_ifaces(self
, ifacenames
, ops
, skipupperifaces
=False,
1321 followdependents
=True, sort
=False):
1322 self
.logger
.debug('scheduling \'%s\' for %s'
1323 %(str(ops
), str(ifacenames
)))
1324 self
._pretty
_print
_ordered
_dict
('dependency graph',
1325 self
.dependency_graph
)
1326 ifaceScheduler
.sched_ifaces(self
, ifacenames
, ops
,
1327 dependency_graph
=self
.dependency_graph
,
1328 order
=ifaceSchedulerFlags
.INORDER
1330 else ifaceSchedulerFlags
.POSTORDER
,
1331 followdependents
=followdependents
,
1332 skipupperifaces
=skipupperifaces
,
1333 sort
=True if (sort
or ifupdownflags
.flags
.CLASS
) else False)
1334 return ifaceScheduler
.get_sched_status()
1336 def _render_ifacename(self
, ifacename
):
1338 vlan_match
= re
.match("^([\d]+)-([\d]+)", ifacename
)
1340 vlan_groups
= vlan_match
.groups()
1341 if vlan_groups
[0] and vlan_groups
[1]:
1342 [new_ifacenames
.append('%d' %v
)
1343 for v
in range(int(vlan_groups
[0]),
1344 int(vlan_groups
[1])+1)]
1345 return new_ifacenames
1347 def _preprocess_ifacenames(self
, ifacenames
):
1348 """ validates interface list for config existance.
1350 returns -1 if one or more interface not found. else, returns 0
1355 for i
in ifacenames
:
1356 ifaceobjs
= self
.get_ifaceobjs(i
)
1358 # if name not available, render interface name and check again
1359 rendered_ifacenames
= utils
.expand_iface_range(i
)
1360 if rendered_ifacenames
:
1361 for ri
in rendered_ifacenames
:
1362 ifaceobjs
= self
.get_ifaceobjs(ri
)
1364 err_iface
+= ' ' + ri
1366 new_ifacenames
.append(ri
)
1368 err_iface
+= ' ' + i
1370 new_ifacenames
.append(i
)
1372 raise Exception('cannot find interfaces:%s' %err_iface
)
1373 return new_ifacenames
1375 def _iface_whitelisted(self
, auto
, allow_classes
, excludepats
, ifacename
):
1376 """ Checks if interface is whitelisted depending on set of parameters.
1378 interfaces are checked against the allow_classes and auto lists.
1384 # Check if interface matches the exclude patter
1386 for e
in excludepats
:
1387 if re
.search(e
, ifacename
):
1389 ifaceobjs
= self
.get_ifaceobjs(ifacename
)
1392 self
.logger
.debug('iface %s' %ifacename
+ ' not found')
1394 # If matched exclude pattern, return false
1397 i
.blacklisted
= True
1398 self
.blacklisted_ifaces_present
= True
1400 # Check if interface belongs to the class
1401 # the user is interested in, if not return false
1406 common
= Set([allow_classes
]).intersection(
1411 # If a class was requested and interface does not belong
1412 # to the class, only then mark the ifaceobjs as blacklisted
1413 self
.blacklisted_ifaces_present
= True
1415 i
.blacklisted
= True
1417 # If the user has requested auto class, check if the interface
1425 # If auto was requested and interface was not marked auto,
1426 # only then mark all of them as blacklisted
1427 self
.blacklisted_ifaces_present
= True
1429 i
.blacklisted
= True
1432 def _compat_conv_op_to_mode(self
, op
):
1433 """ Returns old op name to work with existing scripts """
1441 def generate_running_env(self
, ifaceobj
, op
):
1442 """ Generates a dictionary with env variables required for
1443 an interface. Used to support script execution for interfaces.
1447 iface_env
= ifaceobj
.get_env()
1451 cenv
.update(iface_env
)
1456 cenv
['MODE'] = self
._compat
_conv
_op
_to
_mode
(op
)
1461 def _save_state(self
):
1462 if (not self
.flags
.STATEMANAGER_ENABLE
or
1463 not self
.flags
.STATEMANAGER_UPDATE
):
1466 # Update persistant iface states
1467 self
.statemanager
.save_state()
1468 except Exception, e
:
1469 if self
.logger
.isEnabledFor(logging
.DEBUG
):
1470 t
= sys
.exc_info()[2]
1471 traceback
.print_tb(t
)
1472 self
.logger
.warning('error saving state (%s)' %str
(e
))
1474 def set_type(self
, type):
1476 self
.type = ifaceType
.IFACE
1477 elif type == 'vlan':
1478 self
.type = ifaceType
.BRIDGE_VLAN
1480 self
.type = ifaceType
.UNKNOWN
1482 def _process_delay_admin_state_queue(self
, op
):
1483 if not self
._delay
_admin
_state
_iface
_queue
:
1488 func
= self
.link_down
1491 for i
in self
._delay
_admin
_state
_iface
_queue
:
1493 if self
.link_exists(i
):
1495 except Exception, e
:
1496 self
.logger
.warn(str(e
))
1499 def up(self
, ops
, auto
=False, allow_classes
=None, ifacenames
=None,
1500 excludepats
=None, printdependency
=None, syntaxcheck
=False,
1501 type=None, skipupperifaces
=False):
1502 """This brings the interface(s) up
1505 ops (list): list of ops to perform on the interface(s).
1506 Eg: ['pre-up', 'up', 'post-up'
1509 auto (bool): act on interfaces marked auto
1510 allow_classes (list): act on interfaces belonging to classes in the list
1511 ifacenames (list): act on interfaces specified in this list
1512 excludepats (list): list of patterns of interfaces to exclude
1513 syntaxcheck (bool): only perform syntax check
1519 ifupdownflags
.flags
.CLASS
= True
1520 if not self
.flags
.ADDONS_ENABLE
:
1521 self
.flags
.STATEMANAGER_UPDATE
= False
1523 ifupdownflags
.flags
.ALL
= True
1524 ifupdownflags
.flags
.WITH_DEPENDS
= True
1526 iface_read_ret
= self
.read_iface_config()
1531 ifacenames
= self
._preprocess
_ifacenames
(ifacenames
)
1533 # if iface list not given by user, assume all from config file
1534 if not ifacenames
: ifacenames
= self
.ifaceobjdict
.keys()
1536 # filter interfaces based on auto and allow classes
1537 filtered_ifacenames
= [i
for i
in ifacenames
1538 if self
._iface
_whitelisted
(auto
, allow_classes
,
1540 if not filtered_ifacenames
:
1541 raise Exception('no ifaces found matching given allow lists')
1544 self
.populate_dependency_info(ops
, filtered_ifacenames
)
1545 self
.print_dependency(filtered_ifacenames
, printdependency
)
1548 self
.populate_dependency_info(ops
)
1550 # If only syntax check was requested, return here.
1551 # return here because we want to make sure most
1552 # errors above are caught and reported.
1554 if not self
._module
_syntax
_check
(filtered_ifacenames
):
1556 if not iface_read_ret
:
1558 elif self
._any
_iface
_errors
(filtered_ifacenames
):
1564 ret
= self
._sched
_ifaces
(filtered_ifacenames
, ops
,
1565 skipupperifaces
=skipupperifaces
,
1566 followdependents
=True
1567 if ifupdownflags
.flags
.WITH_DEPENDS
1570 self
._process
_delay
_admin
_state
_queue
('up')
1571 if not ifupdownflags
.flags
.DRYRUN
and self
.flags
.ADDONS_ENABLE
:
1574 if not iface_read_ret
or not ret
:
1577 def down(self
, ops
, auto
=False, allow_classes
=None, ifacenames
=None,
1578 excludepats
=None, printdependency
=None, usecurrentconfig
=False,
1580 """ down an interface """
1585 ifupdownflags
.flags
.CLASS
= True
1586 if not self
.flags
.ADDONS_ENABLE
:
1587 self
.flags
.STATEMANAGER_UPDATE
= False
1589 ifupdownflags
.flags
.ALL
= True
1590 ifupdownflags
.flags
.WITH_DEPENDS
= True
1591 # For down we need to look at old state, unless usecurrentconfig
1593 if (not usecurrentconfig
and self
.flags
.STATEMANAGER_ENABLE
and
1594 self
.statemanager
.ifaceobjdict
):
1595 # Since we are using state manager objects,
1596 # skip the updating of state manager objects
1597 self
.logger
.debug('Looking at old state ..')
1598 self
.read_old_iface_config()
1600 # If no old state available
1602 self
.read_iface_config()
1603 except Exception, e
:
1604 raise Exception('error reading iface config (%s)' %str
(e
))
1606 # If iface list is given by the caller, always check if iface
1609 ifacenames
= self
._preprocess
_ifacenames
(ifacenames
)
1610 except Exception, e
:
1611 raise Exception('%s' %str
(e
) +
1612 ' (interface was probably never up ?)')
1614 # if iface list not given by user, assume all from config file
1615 if not ifacenames
: ifacenames
= self
.ifaceobjdict
.keys()
1617 # filter interfaces based on auto and allow classes
1618 filtered_ifacenames
= [i
for i
in ifacenames
1619 if self
._iface
_whitelisted
(auto
, allow_classes
,
1621 if not filtered_ifacenames
:
1622 raise Exception('no ifaces found matching given allow lists ' +
1623 '(or interfaces were probably never up ?)')
1626 self
.populate_dependency_info(ops
, filtered_ifacenames
)
1627 self
.print_dependency(filtered_ifacenames
, printdependency
)
1630 self
.populate_dependency_info(ops
)
1633 self
._sched
_ifaces
(filtered_ifacenames
, ops
,
1634 followdependents
=True
1635 if ifupdownflags
.flags
.WITH_DEPENDS
else False)
1637 self
._process
_delay
_admin
_state
_queue
('down')
1638 if not ifupdownflags
.flags
.DRYRUN
and self
.flags
.ADDONS_ENABLE
:
1641 def query(self
, ops
, auto
=False, format_list
=False, allow_classes
=None,
1643 excludepats
=None, printdependency
=None,
1644 format
='native', type=None):
1645 """ query an interface """
1649 # Let us forget internal squashing when it comes to
1650 # ifquery. It can surprise people relying of ifquery
1652 self
._ifaceobj
_squash
_internal
= False
1655 ifupdownflags
.flags
.CLASS
= True
1656 if self
.flags
.STATEMANAGER_ENABLE
and ops
[0] == 'query-savedstate':
1657 return self
.statemanager
.dump_pretty(ifacenames
)
1658 self
.flags
.STATEMANAGER_UPDATE
= False
1660 self
.logger
.debug('setting flag ALL')
1661 ifupdownflags
.flags
.ALL
= True
1662 ifupdownflags
.flags
.WITH_DEPENDS
= True
1664 if ops
[0] == 'query-syntax':
1665 self
._modules
_help
()
1667 elif ops
[0] == 'query-running':
1668 # create fake devices to all dependents that dont have config
1669 map(lambda i
: self
.create_n_save_ifaceobj(i
,
1670 ifacePrivFlags(False, True)), ifacenames
)
1673 self
.read_iface_config()
1677 if ifacenames
and ops
[0] != 'query-running':
1678 # If iface list is given, always check if iface is present
1679 ifacenames
= self
._preprocess
_ifacenames
(ifacenames
)
1681 # if iface list not given by user, assume all from config file
1682 if not ifacenames
: ifacenames
= self
.ifaceobjdict
.keys()
1684 # filter interfaces based on auto and allow classes
1685 if ops
[0] == 'query-running':
1686 filtered_ifacenames
= ifacenames
1688 filtered_ifacenames
= [i
for i
in ifacenames
1689 if self
._iface
_whitelisted
(auto
, allow_classes
,
1691 if not filtered_ifacenames
:
1692 raise Exception('no ifaces found matching ' +
1693 'given allow lists')
1695 self
.populate_dependency_info(ops
)
1696 if ops
[0] == 'query-dependency' and printdependency
:
1697 self
.print_dependency(filtered_ifacenames
, printdependency
)
1700 if format_list
and (ops
[0] == 'query' or ops
[0] == 'query-raw'):
1701 return self
.print_ifaceobjs_list(filtered_ifacenames
)
1703 if ops
[0] == 'query' and not ifupdownflags
.flags
.WITHDEFAULTS
:
1704 return self
.print_ifaceobjs_pretty(filtered_ifacenames
, format
)
1705 elif ops
[0] == 'query-raw':
1706 return self
.print_ifaceobjs_raw(filtered_ifacenames
)
1708 ret
= self
._sched
_ifaces
(filtered_ifacenames
, ops
,
1709 followdependents
=True
1710 if ifupdownflags
.flags
.WITH_DEPENDS
else False)
1712 if ops
[0] == 'query' and ifupdownflags
.flags
.WITHDEFAULTS
:
1713 return self
.print_ifaceobjs_pretty(filtered_ifacenames
, format
)
1714 elif ops
[0] == 'query-checkcurr':
1715 ret
= self
.print_ifaceobjscurr_pretty(filtered_ifacenames
, format
)
1717 # if any of the object has an error, signal that silently
1719 elif ops
[0] == 'query-running':
1720 self
.print_ifaceobjsrunning_pretty(filtered_ifacenames
, format
)
1723 def _reload_currentlyup(self
, upops
, downops
, auto
=False, allow
=None,
1724 ifacenames
=None, excludepats
=None, usecurrentconfig
=False,
1725 syntaxcheck
=False, **extra_args
):
1726 """ reload currently up interfaces """
1727 new_ifaceobjdict
= {}
1729 self
.logger
.info('reloading interfaces that are currently up ..')
1732 iface_read_ret
= self
.read_iface_config()
1735 if not self
.ifaceobjdict
:
1736 self
.logger
.warn("nothing to reload ..exiting.")
1738 already_up_ifacenames
= []
1739 if not ifacenames
: ifacenames
= self
.ifaceobjdict
.keys()
1741 if (not usecurrentconfig
and self
.flags
.STATEMANAGER_ENABLE
1742 and self
.statemanager
.ifaceobjdict
):
1743 already_up_ifacenames
= self
.statemanager
.ifaceobjdict
.keys()
1745 # Get already up interfaces that still exist in the interfaces file
1746 already_up_ifacenames_not_present
= Set(
1747 already_up_ifacenames
).difference(ifacenames
)
1748 already_up_ifacenames_still_present
= Set(
1749 already_up_ifacenames
).difference(
1750 already_up_ifacenames_not_present
)
1752 interfaces_to_up
= already_up_ifacenames_still_present
1754 # generate dependency graph of interfaces
1755 self
.populate_dependency_info(upops
, interfaces_to_up
)
1757 # If only syntax check was requested, return here.
1758 # return here because we want to make sure most
1759 # errors above are caught and reported.
1761 if not self
._module
_syntax
_check
(interfaces_to_up
):
1763 if not iface_read_ret
:
1765 elif self
._any
_iface
_errors
(interfaces_to_up
):
1769 if (already_up_ifacenames_not_present
and
1770 self
.config
.get('ifreload_currentlyup_down_notpresent') == '1'):
1771 self
.logger
.info('reload: schedule down on interfaces: %s'
1772 %str
(already_up_ifacenames_not_present
))
1774 # Save a copy of new iface objects and dependency_graph
1775 new_ifaceobjdict
= dict(self
.ifaceobjdict
)
1776 new_dependency_graph
= dict(self
.dependency_graph
)
1778 # old interface config is read into self.ifaceobjdict
1779 self
.read_old_iface_config()
1781 # reinitialize dependency graph
1782 self
.dependency_graph
= OrderedDict({})
1783 falready_up_ifacenames_not_present
= [i
for i
in
1784 already_up_ifacenames_not_present
1785 if self
._iface
_whitelisted
(auto
, allow
,
1787 self
.populate_dependency_info(downops
,
1788 falready_up_ifacenames_not_present
)
1789 self
._sched
_ifaces
(falready_up_ifacenames_not_present
, downops
,
1790 followdependents
=False, sort
=True)
1792 self
.logger
.info('no interfaces to down ..')
1794 # Now, run 'up' with new config dict
1795 # reset statemanager update flag to default
1797 ifupdownflags
.flags
.ALL
= True
1798 ifupdownflags
.flags
.WITH_DEPENDS
= True
1799 if new_ifaceobjdict
:
1800 # and now, ifaceobjdict is back to current config
1801 self
.ifaceobjdict
= new_ifaceobjdict
1802 self
.dependency_graph
= new_dependency_graph
1804 if not self
.ifaceobjdict
:
1805 self
.logger
.info('no interfaces to up')
1807 self
.logger
.info('reload: scheduling up on interfaces: %s'
1808 %str
(interfaces_to_up
))
1809 ret
= self
._sched
_ifaces
(interfaces_to_up
, upops
,
1810 followdependents
=True
1811 if ifupdownflags
.flags
.WITH_DEPENDS
else False)
1812 if ifupdownflags
.flags
.DRYRUN
:
1816 if not iface_read_ret
or not ret
:
1819 def _reload_default(self
, upops
, downops
, auto
=False, allow
=None,
1820 ifacenames
=None, excludepats
=None, usecurrentconfig
=False,
1821 syntaxcheck
=False, **extra_args
):
1822 """ reload interface config """
1823 new_ifaceobjdict
= {}
1826 iface_read_ret
= self
.read_iface_config()
1830 if not self
.ifaceobjdict
:
1831 self
.logger
.warn("nothing to reload ..exiting.")
1834 if not ifacenames
: ifacenames
= self
.ifaceobjdict
.keys()
1835 new_filtered_ifacenames
= [i
for i
in ifacenames
1836 if self
._iface
_whitelisted
(auto
, allow
,
1838 # generate dependency graph of interfaces
1839 self
.populate_dependency_info(upops
)
1841 # If only syntax check was requested, return here.
1842 # return here because we want to make sure most
1843 # errors above are caught and reported.
1845 if not self
._module
_syntax
_check
(new_filtered_ifacenames
):
1847 if not iface_read_ret
:
1849 elif self
._any
_iface
_errors
(new_filtered_ifacenames
):
1853 if (not usecurrentconfig
and self
.flags
.STATEMANAGER_ENABLE
1854 and self
.statemanager
.ifaceobjdict
):
1855 # Save a copy of new iface objects and dependency_graph
1856 new_ifaceobjdict
= dict(self
.ifaceobjdict
)
1857 new_dependency_graph
= dict(self
.dependency_graph
)
1859 self
.ifaceobjdict
= OrderedDict({})
1860 self
.dependency_graph
= OrderedDict({})
1862 # if old state is present, read old state and mark op for 'down'
1863 # followed by 'up' aka: reload
1864 # old interface config is read into self.ifaceobjdict
1865 self
.read_old_iface_config()
1868 # oldconfig not available, continue with 'up' with new config
1870 new_ifaceobjdict
= self
.ifaceobjdict
1871 new_dependency_graph
= self
.dependency_graph
1873 if op
== 'reload' and ifacenames
:
1874 ifacenames
= self
.ifaceobjdict
.keys()
1875 old_filtered_ifacenames
= [i
for i
in ifacenames
1876 if self
._iface
_whitelisted
(auto
, allow
,
1879 # generate dependency graph of old interfaces,
1880 # This should make sure built in interfaces are
1881 # populated. disable check shared dependents as an optimization.
1882 # these are saved interfaces and dependency for these
1883 # have been checked before they became part of saved state.
1885 self
.flags
.CHECK_SHARED_DEPENDENTS
= False
1886 self
.populate_dependency_info(upops
)
1887 self
.flags
.CHECK_SHARED_DEPENDENTS
= True
1888 except Exception, e
:
1889 self
.logger
.info("error generating dependency graph for "
1890 "saved interfaces (%s)" %str
(e
))
1893 # make sure we pick up built-in interfaces
1894 # if config file had 'ifreload_down_changed' variable
1895 # set, also look for interfaces that changed to down them
1896 down_changed
= int(self
.config
.get('ifreload_down_changed', '1'))
1898 # Generate the interface down list
1899 # Interfaces that go into the down list:
1900 # - interfaces that were present in last config and are not
1901 # present in the new config
1902 # - interfaces that were changed between the last and current
1905 for ifname
in self
.ifaceobjdict
.keys():
1906 lastifaceobjlist
= self
.ifaceobjdict
.get(ifname
)
1907 if not self
.is_ifaceobj_builtin(lastifaceobjlist
[0]):
1908 # if interface is not built-in and is not in
1909 # old filtered ifacenames
1910 if ifname
not in old_filtered_ifacenames
:
1913 # If interface is not present in the new file
1914 # append it to the down list
1915 newifaceobjlist
= new_ifaceobjdict
.get(ifname
)
1916 if not newifaceobjlist
:
1917 ifacedownlist
.append(ifname
)
1919 # If ifaceobj was present in the old interfaces file,
1920 # and does not have a config in the new interfaces file
1921 # but has been picked up as a dependent of another
1922 # interface, catch it here. This catches a common error
1923 # for example: remove a bond section from the interfaces
1924 # file, but leave it around as a bridge port
1925 # XXX: Ideally its better to just add it to the
1926 # ifacedownlist. But we will be cautious here
1927 # and just print a warning
1928 if (self
.is_ifaceobj_noconfig(newifaceobjlist
[0]) and
1929 not self
.is_ifaceobj_builtin(newifaceobjlist
[0]) and
1930 lastifaceobjlist
[0].is_config_present() and
1931 lastifaceobjlist
[0].link_kind
):
1932 self
.logger
.warn('%s: misconfig ? removed but still exists '
1933 'as a dependency of %s.\nPlease remove '
1934 'the dependency manually `ifdown %s` if '
1935 'it is being picked up as part of a regex'
1936 % (newifaceobjlist
[objidx
].name
,
1937 str(newifaceobjlist
[objidx
].upperifaces
),
1938 newifaceobjlist
[objidx
].name
))
1939 if not down_changed
:
1941 if len(newifaceobjlist
) != len(lastifaceobjlist
):
1942 ifacedownlist
.append(ifname
)
1945 # If interface has changed between the current file
1946 # and the last installed append it to the down list
1947 # compare object list
1948 for objidx
in range(0, len(lastifaceobjlist
)):
1949 oldobj
= lastifaceobjlist
[objidx
]
1950 newobj
= newifaceobjlist
[objidx
]
1951 if not newobj
.compare(oldobj
):
1952 ifacedownlist
.append(ifname
)
1956 self
.logger
.info('reload: scheduling down on interfaces: %s'
1957 %str
(ifacedownlist
))
1958 # reinitialize dependency graph
1959 self
.dependency_graph
= OrderedDict({})
1961 # Generate dependency info for old config
1962 self
.flags
.CHECK_SHARED_DEPENDENTS
= False
1963 self
.populate_dependency_info(downops
, ifacedownlist
)
1964 self
.flags
.CHECK_SHARED_DEPENDENTS
= True
1967 # XXX: Hack to skip checking upperifaces during down.
1968 # the dependency list is not complete here
1969 # and we dont want to down the upperiface.
1970 # Hence during reload, set this to true.
1971 # This is being added to avoid a failure in
1972 # scheduler._check_upperifaces when we are dowing
1973 # a builtin bridge port
1974 self
.flags
.SCHED_SKIP_CHECK_UPPERIFACES
= True
1975 self
._sched
_ifaces
(ifacedownlist
, downops
,
1976 followdependents
=False,
1978 except Exception, e
:
1979 self
.logger
.error(str(e
))
1982 self
.flags
.SCHED_SKIP_CHECK_UPPERIFACES
= False
1983 self
._process
_delay
_admin
_state
_queue
('down')
1985 self
.logger
.info('no interfaces to down ..')
1987 # Now, run 'up' with new config dict
1988 # reset statemanager update flag to default
1989 if not new_ifaceobjdict
:
1990 self
.logger
.debug('no interfaces to up')
1994 ifupdownflags
.flags
.ALL
= True
1995 ifupdownflags
.flags
.WITH_DEPENDS
= True
1996 # and now, we are back to the current config in ifaceobjdict
1997 self
.ifaceobjdict
= new_ifaceobjdict
1998 self
.dependency_graph
= new_dependency_graph
2000 self
.logger
.info('reload: scheduling up on interfaces: %s'
2001 %str
(new_filtered_ifacenames
))
2002 ifupdownflags
.flags
.CACHE
= True
2004 ret
= self
._sched
_ifaces
(new_filtered_ifacenames
, upops
,
2005 followdependents
=True
2006 if ifupdownflags
.flags
.WITH_DEPENDS
2008 except Exception, e
:
2010 self
.logger
.error(str(e
))
2012 self
._process
_delay
_admin
_state
_queue
('up')
2013 if ifupdownflags
.flags
.DRYRUN
:
2017 if not iface_read_ret
or not ret
:
2020 def reload(self
, *args
, **kargs
):
2021 """ reload interface config """
2022 self
.logger
.debug('reloading interface config ..')
2023 if kargs
.get('currentlyup', False):
2024 self
._reload
_currentlyup
(*args
, **kargs
)
2026 self
._reload
_default
(*args
, **kargs
)
2028 def _any_iface_errors(self
, ifacenames
):
2029 for i
in ifacenames
:
2030 ifaceobjs
= self
.get_ifaceobjs(i
)
2031 if not ifaceobjs
: continue
2032 for ifaceobj
in ifaceobjs
:
2033 if (ifaceobj
.status
== ifaceStatus
.NOTFOUND
or
2034 ifaceobj
.status
== ifaceStatus
.ERROR
):
2038 def _pretty_print_ordered_dict(self
, prefix
, argdict
):
2039 outbuf
= prefix
+ ' {\n'
2040 for k
, vlist
in argdict
.items():
2041 outbuf
+= '\t%s : %s\n' %(k
, str(vlist
))
2042 self
.logger
.debug(outbuf
+ '}')
2044 def print_dependency(self
, ifacenames
, format
):
2045 """ prints iface dependency information """
2048 ifacenames
= self
.ifaceobjdict
.keys()
2049 if format
== 'list':
2050 for k
,v
in self
.dependency_graph
.items():
2051 print '%s : %s' %(k
, str(v
))
2052 elif format
== 'dot':
2054 map(lambda i
: indegrees
.update({i
:
2055 self
.get_iface_refcnt(i
)}),
2056 self
.dependency_graph
.keys())
2057 graph
.generate_dots(self
.dependency_graph
, indegrees
)
2059 def print_ifaceobjs_list(self
, ifacenames
):
2060 for i
in ifacenames
:
2063 def print_ifaceobjs_raw(self
, ifacenames
):
2064 """ prints raw lines for ifaces from config file """
2066 for i
in ifacenames
:
2067 for ifaceobj
in self
.get_ifaceobjs(i
):
2068 if (self
.is_ifaceobj_builtin(ifaceobj
) or
2069 not ifaceobj
.is_config_present()):
2071 ifaceobj
.dump_raw(self
.logger
)
2073 if (ifupdownflags
.flags
.WITH_DEPENDS
and
2074 not ifupdownflags
.flags
.ALL
):
2075 dlist
= ifaceobj
.lowerifaces
2076 if not dlist
: continue
2077 self
.print_ifaceobjs_raw(dlist
)
2079 def _get_ifaceobjs_pretty(self
, ifacenames
, ifaceobjs
, running
=False):
2080 """ returns iface obj list """
2082 for i
in ifacenames
:
2083 for ifaceobj
in self
.get_ifaceobjs(i
):
2084 if ((not running
and self
.is_ifaceobj_noconfig(ifaceobj
)) or
2085 (running
and not ifaceobj
.is_config_present() and
2086 not self
.is_iface_builtin_byname(i
) and
2087 not ifaceobj
.upperifaces
)):
2089 ifaceobjs
.append(ifaceobj
)
2090 if (ifupdownflags
.flags
.WITH_DEPENDS
and
2091 not ifupdownflags
.flags
.ALL
):
2092 dlist
= ifaceobj
.lowerifaces
2093 if not dlist
: continue
2094 self
._get
_ifaceobjs
_pretty
(dlist
, ifaceobjs
, running
)
2096 def print_ifaceobjs_pretty(self
, ifacenames
, format
='native'):
2097 """ pretty prints iface in format given by keyword arg format """
2100 self
._get
_ifaceobjs
_pretty
(ifacenames
, ifaceobjs
)
2101 if not ifaceobjs
: return
2102 if format
== 'json':
2103 print json
.dumps(ifaceobjs
, cls
=ifaceJsonEncoder
,
2104 indent
=4, separators
=(',', ': '))
2106 expand
= int(self
.config
.get('ifquery_ifacename_expand_range', '0'))
2108 if not expand
and (i
.flags
& iface
.IFACERANGE_ENTRY
):
2109 # print only the first one
2110 if i
.flags
& iface
.IFACERANGE_START
:
2111 i
.dump_pretty(use_realname
=True)
2115 def _get_ifaceobjscurr_pretty(self
, ifacenames
, ifaceobjs
):
2117 for i
in ifacenames
:
2118 ifaceobjscurr
= self
.get_ifaceobjcurr(i
)
2119 if not ifaceobjscurr
: continue
2120 for ifaceobj
in ifaceobjscurr
:
2121 if (ifaceobj
.status
== ifaceStatus
.NOTFOUND
or
2122 ifaceobj
.status
== ifaceStatus
.ERROR
):
2124 if self
.is_ifaceobj_noconfig(ifaceobj
):
2126 ifaceobjs
.append(ifaceobj
)
2127 if (ifupdownflags
.flags
.WITH_DEPENDS
and
2128 not ifupdownflags
.flags
.ALL
):
2129 dlist
= ifaceobj
.lowerifaces
2130 if not dlist
: continue
2131 dret
= self
._get
_ifaceobjscurr
_pretty
(dlist
, ifaceobjs
)
2135 def print_ifaceobjscurr_pretty(self
, ifacenames
, format
='native'):
2136 """ pretty prints current running state of interfaces with status.
2138 returns 1 if any of the interface has an error,
2143 ret
= self
._get
_ifaceobjscurr
_pretty
(ifacenames
, ifaceobjs
)
2144 if not ifaceobjs
: return
2146 # override ifaceStatusUserStrs
2147 ifaceStatusUserStrs
.SUCCESS
= self
.config
.get('ifquery_check_success_str', _success_sym
)
2148 ifaceStatusUserStrs
.ERROR
= self
.config
.get('ifquery_check_error_str', _error_sym
)
2149 ifaceStatusUserStrs
.UNKNOWN
= self
.config
.get('ifquery_check_unknown_str', '')
2150 if format
== 'json':
2151 print json
.dumps(ifaceobjs
, cls
=ifaceJsonEncoderWithStatus
,
2152 indent
=2, separators
=(',', ': '))
2154 map(lambda i
: i
.dump_pretty(with_status
=True), ifaceobjs
)
2157 def print_ifaceobjsrunning_pretty(self
, ifacenames
, format
='native'):
2158 """ pretty prints iface running state """
2161 self
._get
_ifaceobjs
_pretty
(ifacenames
, ifaceobjs
, running
=True)
2162 if not ifaceobjs
: return
2163 if format
== 'json':
2164 print json
.dumps(ifaceobjs
, cls
=ifaceJsonEncoder
, indent
=2,
2165 separators
=(',', ': '))
2167 map(lambda i
: i
.dump_pretty(), ifaceobjs
)
2170 print 'ifupdown main object dump'
2171 print self
.pp
.pprint(self
.modules
)
2172 print self
.pp
.pprint(self
.ifaceobjdict
)
2174 def _dump_ifaceobjs(self
, ifacenames
):
2175 for i
in ifacenames
:
2176 ifaceobjs
= self
.get_ifaceobjs(i
)