]> git.proxmox.com Git - mirror_ifupdown2.git/blame - ifupdown/ifupdownmain.py
ifupdownmain: don't down vrf master in sched callback ops
[mirror_ifupdown2.git] / ifupdown / ifupdownmain.py
CommitLineData
a6f80f0e 1#!/usr/bin/python
3e8ee54f 2#
904908bc 3# Copyright 2014 Cumulus Networks, Inc. All rights reserved.
3e8ee54f 4# Author: Roopa Prabhu, roopa@cumulusnetworks.com
5#
6# ifupdownMain --
7# ifupdown main module
8#
a6f80f0e 9
10import os
11import re
3e8ee54f 12import imp
13import pprint
14import logging
15import sys, traceback
cb7cc592 16import copy
2cd06f78 17import json
55072bd1 18import ifupdown.statemanager as statemanager
0582f185 19import ifupdown.ifupdownconfig as ifupdownConfig
a6f80f0e 20from networkinterfaces import *
21from iface import *
22from scheduler import *
23from collections import deque
24from collections import OrderedDict
a6f80f0e 25from graph import *
3e8ee54f 26from sets import Set
a6f80f0e 27
2c0ad8b3
RP
28"""
29.. module:: ifupdownmain
30:synopsis: main module for ifupdown package
31
32.. moduleauthor:: Roopa Prabhu <roopa@cumulusnetworks.com>
33
34"""
35
86fc62e2 36_tickmark = u'\u2713'
37_crossmark = u'\u2717'
e74d01e1
RP
38_success_sym = '(%s)' %_tickmark
39_error_sym = '(%s)' %_crossmark
86fc62e2 40
84ca006f
RP
41class ifupdownFlags():
42 FORCE = False
43 DRYRUN = False
44 NOWAIT = False
45 PERFMODE = False
46 CACHE = False
47
48 # Flags
49 CACHE_FLAGS = 0x0
50
dbc018d3 51class ifupdownMainFlags():
cca03c30 52 WITH_DEPENDS = False
a6f80f0e 53 ALL = False
5ee3e1a8 54 IFACE_CLASS = False
6bd7fc74 55 COMPAT_EXEC_SCRIPTS = False
20dd6242 56 STATEMANAGER_ENABLE = True
57 STATEMANAGER_UPDATE = True
58 ADDONS_ENABLE = False
dbc018d3
RP
59 DELETE_DEPENDENT_IFACES_WITH_NOCONFIG = False
60 SCHED_SKIP_CHECK_UPPERIFACES = False
61 CHECK_SHARED_DEPENDENTS = True
a6f80f0e 62
dbc018d3 63class ifacePrivFlags():
37c0543d 64 # priv flags to mark iface objects
dbc018d3
RP
65 BUILTIN = False
66 NOCONFIG = False
67
68 def __init__(self, builtin=False, noconfig=False):
69 self.BUILTIN = builtin
70 self.NOCONFIG = noconfig
71
72class ifupdownMain(ifupdownBase):
73 """ ifupdown2 main class """
37c0543d 74
75 scripts_dir='/etc/network'
1642c64b
RP
76 addon_modules_dir='/usr/share/ifupdown2/addons'
77 addon_modules_configfile='/etc/network/ifupdown2/addons.conf'
a6f80f0e 78
79 # iface dictionary in the below format:
80 # { '<ifacename>' : [<ifaceobject1>, <ifaceobject2> ..] }
81 # eg:
53b00224 82 # { 'swp1' : [<iface swp1>, <iface swp2> ..] }
a6f80f0e 83 #
84 # Each ifaceobject corresponds to a configuration block for
85 # that interface
53b00224 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
a6f80f0e 89 ifaceobjdict = OrderedDict()
90
a6f80f0e 91 # iface dictionary representing the curr running state of an iface
92 # in the below format:
93 # {'<ifacename>' : <ifaceobject>}
94 ifaceobjcurrdict = OrderedDict()
95
be0b20f2 96 # Dictionary representing operation and modules
97 # for every operation
98 module_ops = OrderedDict([('pre-up', []),
d08d5f54 99 ('up' , []),
100 ('post-up' , []),
101 ('query-checkcurr', []),
102 ('query-running', []),
103 ('query-dependency', []),
75730152 104 ('query', []),
105 ('query-raw', []),
d08d5f54 106 ('pre-down', []),
107 ('down' , []),
108 ('post-down' , [])])
37c0543d 109
110 # For old style /etc/network/ bash scripts
be0b20f2 111 script_ops = OrderedDict([('pre-up', []),
d08d5f54 112 ('up' , []),
113 ('post-up' , []),
114 ('pre-down', []),
115 ('down' , []),
116 ('post-down' , [])])
a6f80f0e 117
be0b20f2 118 # Handlers for ops that ifupdown2 owns
119 def run_up(self, ifaceobj):
496745cd
RP
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:
123 return
a070c90e
RP
124 if (ifaceobj.addr_method and
125 ifaceobj.addr_method == 'manual'):
126 return
127 if self._delay_admin_state:
128 self._delay_admin_state_iface_queue.append(ifaceobj.name)
129 return
7f045fd8
RP
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).
7e2e64fb 134 if ifaceobj.link_type == ifaceLinkType.LINK_SLAVE:
7f045fd8 135 return
a070c90e 136 if not self.link_exists(ifaceobj.name):
7e2e64fb 137 return
a070c90e 138 self.link_up(ifaceobj.name)
be0b20f2 139
140 def run_down(self, ifaceobj):
496745cd
RP
141 # Skip link sets on ifaceobjs of type 'vlan' (used for l2 attrs)
142 # there is no real interface behind it
9219cef3
RP
143 if ifaceobj.kind & ifaceLinkKind.VRF:
144 return
496745cd
RP
145 if ifaceobj.type == ifaceType.BRIDGE_VLAN:
146 return
a070c90e
RP
147 if (ifaceobj.addr_method and
148 ifaceobj.addr_method == 'manual'):
149 return
150 if self._delay_admin_state:
151 self._delay_admin_state_iface_queue.append(ifaceobj.name)
152 return
7f045fd8
RP
153 # If this object is a link slave, ie its link is controlled
154 # by its link master interface, then dont set the link state.
155 # But do allow user to change state of the link if the interface
156 # is already with its link master (hence the master check).
7e2e64fb
RP
157 if ifaceobj.link_type == ifaceLinkType.LINK_SLAVE:
158 return
a070c90e 159 if not self.link_exists(ifaceobj.name):
7e2e64fb 160 return
a070c90e 161 self.link_down(ifaceobj.name)
be0b20f2 162
31a5f4c3 163 # ifupdown object interface operation handlers
be0b20f2 164 ops_handlers = OrderedDict([('up', run_up),
165 ('down', run_down)])
a6f80f0e 166
cb7cc592 167 def run_sched_ifaceobj_posthook(self, ifaceobj, op):
dbc018d3
RP
168 if (ifaceobj.priv_flags and (ifaceobj.priv_flags.BUILTIN or
169 ifaceobj.priv_flags.NOCONFIG)):
5c721925 170 return
dbc018d3 171 if self.flags.STATEMANAGER_UPDATE:
cb7cc592 172 self.statemanager.ifaceobj_sync(ifaceobj, op)
31a5f4c3 173
174 # ifupdown object interface scheduler pre and posthooks
175 sched_hooks = {'posthook' : run_sched_ifaceobj_posthook}
176
14dc390d 177 def __init__(self, config={},
178 force=False, dryrun=False, nowait=False,
cca03c30 179 perfmode=False, withdepends=False, njobs=1,
14dc390d 180 cache=False, addons_enable=True, statemanager_enable=True,
3dcc1d0e 181 interfacesfile='/etc/network/interfaces',
182 interfacesfileiobuf=None,
183 interfacesfileformat='native'):
2c0ad8b3
RP
184 """This member function initializes the ifupdownmain object.
185
186 Kwargs:
187 config (dict): config dict from /etc/network/ifupdown2/ifupdown2.conf
188 force (bool): force interface configuration
189 dryrun (bool): dryrun interface configuration
190 withdepends (bool): apply interface configuration on all depends
191 interfacesfile (str): interfaces file. default is /etc/network/interfaces
192 interfacesfileformat (str): default is 'native'. Other choices are 'json'
193
194 Raises:
195 AttributeError, KeyError """
196
a6f80f0e 197 self.logger = logging.getLogger('ifupdown')
eab25b7c 198 self.FORCE = force
199 self.DRYRUN = dryrun
200 self.NOWAIT = nowait
201 self.PERFMODE = perfmode
739f665b 202 self.CACHE = cache
dbc018d3
RP
203 # Can be used to provide hints for caching
204 self.CACHE_FLAGS = 0x0
205
206 self.flags = ifupdownMainFlags()
207
208 self.flags.WITH_DEPENDS = withdepends
209 self.flags.STATEMANAGER_ENABLE = statemanager_enable
14dc390d 210 self.interfacesfile = interfacesfile
3dcc1d0e 211 self.interfacesfileiobuf = interfacesfileiobuf
212 self.interfacesfileformat = interfacesfileformat
14dc390d 213 self.config = config
214 self.logger.debug(self.config)
67cfaeb1 215 self.blacklisted_ifaces_present = False
a690dfae 216
2da58137
RP
217 self.type = ifaceType.UNKNOWN
218
dbc018d3
RP
219 self.flags.DELETE_DEPENDENT_IFACES_WITH_NOCONFIG = False
220 self.flags.ADDONS_ENABLE = addons_enable
eab25b7c 221
84ca006f
RP
222 # Copy flags into ifupdownFlags
223 # XXX: before we transition fully to ifupdownFlags
224 ifupdownFlags.FORCE = force
225 ifupdownFlags.DRYRUN = dryrun
226 ifupdownFlags.NOWAIT = nowait
227 ifupdownFlags.PERFMODE = perfmode
228 ifupdownFlags.CACHE = cache
229
a6f80f0e 230 self.ifaces = OrderedDict()
eab25b7c 231 self.njobs = njobs
a6f80f0e 232 self.pp = pprint.PrettyPrinter(indent=4)
37c0543d 233 self.modules = OrderedDict({})
d08d5f54 234 self.module_attrs = {}
20dd6242 235
37c0543d 236 self.load_addon_modules(self.addon_modules_dir)
dbc018d3 237 if self.flags.COMPAT_EXEC_SCRIPTS:
e938bfec 238 self.load_scripts(self.scripts_dir)
d08d5f54 239 self.dependency_graph = OrderedDict({})
a6f80f0e 240
8e113d63
RP
241 self._cache_no_repeats = {}
242
dbc018d3 243 if self.flags.STATEMANAGER_ENABLE:
20dd6242 244 try:
55072bd1 245 self.statemanager = statemanager.statemanager_api
20dd6242 246 self.statemanager.read_saved_state()
247 except Exception, e:
248 # XXX Maybe we should continue by ignoring old state
249 self.logger.warning('error reading state (%s)' %str(e))
250 raise
251 else:
dbc018d3 252 self.flags.STATEMANAGER_UPDATE = False
a070c90e
RP
253 self._delay_admin_state = True if self.config.get(
254 'delay_admin_state_change', '0') == '1' else False
255 self._delay_admin_state_iface_queue = []
cebe79c9
RP
256 if self._delay_admin_state:
257 self.logger.info('\'delay_admin_state_change\' is set. admin ' +
258 'state changes will be delayed till the end.')
259
260 self._link_master_slave = True if self.config.get(
a070c90e 261 'link_master_slave', '0') == '1' else False
cebe79c9
RP
262 if self._link_master_slave:
263 self.logger.info('\'link_master_slave\' is set. slave admin ' +
264 'state changes will be delayed till the ' +
265 'masters admin state change.')
a6f80f0e 266
2ddd65c5
RP
267 # squash iface objects for same interface both internal and
268 # external representation. It is off by default.
99ce6894
RP
269 self._ifaceobj_squash = True if self.config.get(
270 'ifaceobj_squash', '0') == '1' else False
271
2ddd65c5
RP
272 # squash iface objects for same interface internal
273 # representation only. External representation as seen by ifquery
274 # will continue to see multiple iface stanzas if it was specified
275 # that way by the user. It is on by default.
276 self._ifaceobj_squash_internal = True if self.config.get(
277 'ifaceobj_squash_internal', '1') == '1' else False
278
0582f185
RP
279 # initialize global config object with config passed by the user
280 # This makes config available to addon modules
281 ifupdownConfig.config = self.config
282
61c4d724
RP
283 def link_master_slave_ignore_error(self, errorstr):
284 # If link master slave flag is set,
285 # there may be cases where the lowerdev may not be
286 # up resulting in 'Network is down' error
287 # This can happen if the lowerdev is a LINK_SLAVE
288 # of another interface which is not up yet
289 # example of such a case:
290 # bringing up a vlan on a bond interface and the bond
291 # is a LINK_SLAVE of a bridge (in other words the bond is
292 # part of a bridge) which is not up yet
293 if self._link_master_slave:
294 if 'Network is down':
295 return True
296 return False
297
31a5f4c3 298 def get_ifaceobjs(self, ifacename):
a6f80f0e 299 return self.ifaceobjdict.get(ifacename)
300
a9ab1b4f
RP
301 def get_ifaceobjs_saved(self, ifacename):
302 """ Return ifaceobjects from statemanager """
dbc018d3 303 if self.flags.STATEMANAGER_ENABLE:
a9ab1b4f
RP
304 return self.statemanager.get_ifaceobjs(ifacename)
305 else:
306 None
307
31a5f4c3 308 def get_ifaceobj_first(self, ifacename):
309 ifaceobjs = self.get_ifaceobjs(ifacename)
310 if ifaceobjs:
a6f80f0e 311 return ifaceobjs[0]
312 return None
313
c798b0f4 314 def get_ifacenames(self):
315 return self.ifaceobjdict.keys()
316
a6f80f0e 317 def get_iface_obj_last(self, ifacename):
318 return self.ifaceobjdict.get(ifacename)[-1]
319
a9ab1b4f 320
8c13865c
RP
321 def must_follow_upperifaces(self, ifacename):
322 #
323 # XXX: This bleeds the knowledge of iface
324 # types in the infrastructure module.
325 # Cant think of a better fix at the moment.
326 # In future maybe the module can set a flag
327 # to indicate if we should follow upperifaces
328 #
329 ifaceobj = self.get_ifaceobj_first(ifacename)
cb46a208 330 if ifaceobj.type == ifaceType.BRIDGE_VLAN:
8c13865c
RP
331 return False
332 return True
333
53b00224 334 def create_n_save_ifaceobj(self, ifacename, priv_flags=None,
335 increfcnt=False):
336 """ creates a iface object and adds it to the iface dictionary """
337 ifaceobj = iface()
338 ifaceobj.name = ifacename
339 ifaceobj.priv_flags = priv_flags
340 ifaceobj.auto = True
f3b69969
RP
341 if not self._link_master_slave:
342 ifaceobj.link_type = ifaceLinkType.LINK_NA
53b00224 343 if increfcnt:
344 ifaceobj.inc_refcnt()
345 self.ifaceobjdict[ifacename] = [ifaceobj]
346 return ifaceobj
347
d08d5f54 348 def create_n_save_ifaceobjcurr(self, ifaceobj):
923290bd 349 """ creates a copy of iface object and adds it to the iface
350 dict containing current iface objects
53b00224 351 """
739f665b 352 ifaceobjcurr = iface()
53b00224 353 ifaceobjcurr.name = ifaceobj.name
cb46a208 354 ifaceobjcurr.type = ifaceobj.type
62ddec8b 355 ifaceobjcurr.lowerifaces = ifaceobj.lowerifaces
dbc018d3 356 ifaceobjcurr.priv_flags = copy.deepcopy(ifaceobj.priv_flags)
2cd06f78 357 ifaceobjcurr.auto = ifaceobj.auto
923290bd 358 self.ifaceobjcurrdict.setdefault(ifaceobj.name,
359 []).append(ifaceobjcurr)
d08d5f54 360 return ifaceobjcurr
a6f80f0e 361
923290bd 362 def get_ifaceobjcurr(self, ifacename, idx=0):
363 ifaceobjlist = self.ifaceobjcurrdict.get(ifacename)
364 if not ifaceobjlist:
365 return None
366 if not idx:
367 return ifaceobjlist
368 else:
369 return ifaceobjlist[idx]
a6f80f0e 370
739f665b 371 def get_ifaceobjrunning(self, ifacename):
372 return self.ifaceobjrunningdict.get(ifacename)
373
a6f80f0e 374 def get_iface_refcnt(self, ifacename):
53b00224 375 """ Return iface ref count """
a6f80f0e 376 max = 0
31a5f4c3 377 ifaceobjs = self.get_ifaceobjs(ifacename)
20dd6242 378 if not ifaceobjs:
379 return 0
a6f80f0e 380 for i in ifaceobjs:
62ddec8b 381 if i.refcnt > max:
382 max = i.refcnt
a6f80f0e 383 return max
384
d08d5f54 385 def is_iface_builtin_byname(self, ifacename):
cca03c30 386 """ Returns true if iface name is a builtin interface.
a6f80f0e 387
cca03c30 388 A builtin interface is an interface which ifupdown understands.
389 The following are currently considered builtin ifaces:
390 - vlan interfaces in the format <ifacename>.<vlanid>
a6f80f0e 391 """
d08d5f54 392 return '.' in ifacename
a6f80f0e 393
37c0543d 394 def is_ifaceobj_builtin(self, ifaceobj):
395 """ Returns true if iface name is a builtin interface.
396
397 A builtin interface is an interface which ifupdown understands.
398 The following are currently considered builtin ifaces:
399 - vlan interfaces in the format <ifacename>.<vlanid>
400 """
dbc018d3
RP
401
402 return (ifaceobj.priv_flags and ifaceobj.priv_flags.BUILTIN)
37c0543d 403
404 def is_ifaceobj_noconfig(self, ifaceobj):
53b00224 405 """ Returns true if iface object did not have a user defined config.
37c0543d 406
407 These interfaces appear only when they are dependents of interfaces
408 which have user defined config
409 """
dbc018d3 410 return (ifaceobj.priv_flags and ifaceobj.priv_flags.NOCONFIG)
37c0543d 411
d08d5f54 412 def is_iface_noconfig(self, ifacename):
413 """ Returns true if iface has no config """
37c0543d 414
31a5f4c3 415 ifaceobj = self.get_ifaceobj_first(ifacename)
d08d5f54 416 if not ifaceobj: return True
d08d5f54 417 return self.is_ifaceobj_noconfig(ifaceobj)
418
45ca0b6d
RP
419 def check_shared_dependents(self, ifaceobj, dlist):
420 """ Check if dlist intersects with any other
421 interface with slave dependents.
422 example: bond and bridges.
423 This function logs such errors """
424 setdlist = Set(dlist)
425 for ifacename, ifacedlist in self.dependency_graph.items():
426 if not ifacedlist:
427 continue
428 check_depends = False
429 iobjs = self.get_ifaceobjs(ifacename)
dbc018d3
RP
430 if not iobjs:
431 continue
45ca0b6d
RP
432 for i in iobjs:
433 if (i.dependency_type == ifaceDependencyType.MASTER_SLAVE):
434 check_depends = True
435 if check_depends:
436 common = Set(ifacedlist).intersection(setdlist)
437 if common:
1cda1e43 438 self.logger.error('misconfig..?. iface %s and %s '
45ca0b6d 439 %(ifaceobj.name, ifacename) +
1cda1e43 440 'seem to share dependents/ports %s' %str(list(common)))
45ca0b6d 441
65e0c276
RP
442 def _set_iface_role_n_kind(self, ifaceobj, upperifaceobj):
443 if (upperifaceobj.link_kind & ifaceLinkKind.BOND):
444 ifaceobj.role |= ifaceRole.SLAVE
445 ifaceobj.link_kind |= ifaceLinkKind.BOND_SLAVE
446 if (upperifaceobj.link_kind & ifaceLinkKind.BRIDGE):
447 ifaceobj.role |= ifaceRole.SLAVE
448 ifaceobj.link_kind |= ifaceLinkKind.BRIDGE_PORT
768b4ec5
RP
449 if self._link_master_slave:
450 if upperifaceobj.link_type == ifaceLinkType.LINK_MASTER:
451 ifaceobj.link_type = ifaceLinkType.LINK_SLAVE
452 else:
453 upperifaceobj.link_type = ifaceLinkType.LINK_NA
454 ifaceobj.link_type = ifaceLinkType.LINK_NA
21289e4a
RP
455 if (ifaceobj.link_kind == ifaceLinkKind.BOND_SLAVE and
456 len(ifaceobj.upperifaces) > 1):
457 self.logger.warn("misconfig..? bond slave \'%s\' is enslaved to multiple interfaces %s" %(ifaceobj.name, str(ifaceobj.upperifaces)))
65e0c276 458
ccbeedcd
RP
459 def dump_iface_dependency_info(self):
460 """ debug funtion to print raw dependency
461 info - lower and upper devices"""
462
463 for ifacename, ifaceobjs in self.ifaceobjdict.iteritems():
464 iobj = ifaceobjs[0]
465 self.logger.info("%s: refcnt: %d, lower: %s, upper: %s" %(ifacename,
466 self.get_iface_refcnt(ifacename),
467 str(iobj.lowerifaces) if iobj.lowerifaces else [],
468 str(iobj.upperifaces) if iobj.upperifaces else []))
469
470
7f045fd8 471 def preprocess_dependency_list(self, upperifaceobj, dlist, ops):
739f665b 472 """ We go through the dependency list and
473 delete or add interfaces from the interfaces dict by
474 applying the following rules:
dbc018d3 475 if flag DELETE_DEPENDENT_IFACES_WITH_NOCONFIG is True:
739f665b 476 we only consider devices whose configuration was
477 specified in the network interfaces file. We delete
478 any interface whose config was not specified except
479 for vlan devices. vlan devices get special treatment.
480 Even if they are not present they are created and added
481 to the ifacesdict
dbc018d3 482 elif flag DELETE_DEPENDENT_IFACES_WITH_NOCONFIG is False:
739f665b 483 we create objects for all dependent devices that are not
484 present in the ifacesdict
485 """
a6f80f0e 486 del_list = []
487
dbc018d3
RP
488 if (upperifaceobj.dependency_type == ifaceDependencyType.MASTER_SLAVE
489 and self.flags.CHECK_SHARED_DEPENDENTS):
45ca0b6d
RP
490 self.check_shared_dependents(upperifaceobj, dlist)
491
a6f80f0e 492 for d in dlist:
31a5f4c3 493 dilist = self.get_ifaceobjs(d)
d08d5f54 494 if not dilist:
7f045fd8 495 ni = None
d08d5f54 496 if self.is_iface_builtin_byname(d):
a070c90e 497 ni = self.create_n_save_ifaceobj(d,
dbc018d3
RP
498 ifacePrivFlags(True, True), True)
499 elif not self.flags.DELETE_DEPENDENT_IFACES_WITH_NOCONFIG:
500 ni = self.create_n_save_ifaceobj(d,
501 ifacePrivFlags(False, True), True)
a6f80f0e 502 else:
a6f80f0e 503 del_list.append(d)
7f045fd8
RP
504 if ni:
505 ni.add_to_upperifaces(upperifaceobj.name)
21289e4a 506 self._set_iface_role_n_kind(ni, upperifaceobj)
a6f80f0e 507 else:
508 for di in dilist:
509 di.inc_refcnt()
7f045fd8 510 di.add_to_upperifaces(upperifaceobj.name)
21289e4a 511 self._set_iface_role_n_kind(di, upperifaceobj)
a6f80f0e 512 for d in del_list:
513 dlist.remove(d)
514
4cc2df04 515 def preprocess_upperiface(self, lowerifaceobj, ulist, ops):
ccbeedcd
RP
516 for u in ulist:
517 if (lowerifaceobj.upperifaces and
518 u in lowerifaceobj.upperifaces):
519 continue
520 lowerifaceobj.add_to_upperifaces(u)
521 uifacelist = self.get_ifaceobjs(u)
522 if uifacelist:
523 for ui in uifacelist:
524 lowerifaceobj.inc_refcnt()
525 self._set_iface_role_n_kind(lowerifaceobj, ui)
526 ui.add_to_lowerifaces(lowerifaceobj.name)
4cc2df04
RP
527
528 def query_lowerifaces(self, ifaceobj, ops, ifacenames, type=None):
a6f80f0e 529 """ Gets iface dependents by calling into respective modules """
41febf89 530 ret_dlist = []
a6f80f0e 531
20dd6242 532 # Get dependents for interface by querying respective modules
ee3fcf44 533 for module in self.modules.values():
7949b8a5 534 try:
535 if ops[0] == 'query-running':
536 if (not hasattr(module,
537 'get_dependent_ifacenames_running')):
538 continue
539 dlist = module.get_dependent_ifacenames_running(ifaceobj)
540 else:
541 if (not hasattr(module, 'get_dependent_ifacenames')):
542 continue
543 dlist = module.get_dependent_ifacenames(ifaceobj,
ee3fcf44 544 ifacenames)
7949b8a5 545 except Exception, e:
546 self.logger.warn('%s: error getting dependent interfaces (%s)'
547 %(ifaceobj.name, str(e)))
548 dlist = None
549 pass
41febf89 550 if dlist: ret_dlist.extend(dlist)
84ca006f 551 return list(set(ret_dlist))
20dd6242 552
4cc2df04
RP
553 def query_upperifaces(self, ifaceobj, ops, ifacenames, type=None):
554 """ Gets iface upperifaces by calling into respective modules """
555 ret_ulist = []
556
557 # Get upperifaces for interface by querying respective modules
558 for module in self.modules.values():
559 try:
560 if ops[0] == 'query-running':
561 if (not hasattr(module,
562 'get_upper_ifacenames_running')):
563 continue
564 ulist = module.get_upper_ifacenames_running(ifaceobj)
565 else:
566 if (not hasattr(module, 'get_upper_ifacenames')):
567 continue
568 ulist = module.get_upper_ifacenames(ifaceobj, ifacenames)
569 except Exception, e:
570 self.logger.warn('%s: error getting upper interfaces (%s)'
571 %(ifaceobj.name, str(e)))
572 ulist = None
573 pass
574 if ulist: ret_ulist.extend(ulist)
575 return list(set(ret_ulist))
45ca0b6d 576
e1601369
RP
577 def populate_dependency_info(self, ops, ifacenames=None):
578 """ recursive function to generate iface dependency info """
579
580 if not ifacenames:
581 ifacenames = self.ifaceobjdict.keys()
582
583 iqueue = deque(ifacenames)
584 while iqueue:
585 i = iqueue.popleft()
586 # Go through all modules and find dependent ifaces
587 dlist = None
4cc2df04 588 ulist = None
2d8b307b
RP
589 ifaceobjs = self.get_ifaceobjs(i)
590 if not ifaceobjs:
e1601369 591 continue
4cc2df04 592 dependents_processed = False
2d8b307b
RP
593
594 # Store all dependency info in the first ifaceobj
595 # but get dependency info from all ifaceobjs
596 ifaceobj = ifaceobjs[0]
597 for iobj in ifaceobjs:
4cc2df04 598 ulist = self.query_upperifaces(iobj, ops, ifacenames)
2d8b307b 599 if iobj.lowerifaces:
4cc2df04 600 dependents_processed = True
2d8b307b 601 break
4cc2df04 602 dlist = self.query_lowerifaces(iobj, ops, ifacenames)
2d8b307b
RP
603 if dlist:
604 break
4cc2df04
RP
605 if ulist:
606 self.preprocess_upperiface(ifaceobj, ulist, ops)
4cc2df04 607 if dependents_processed:
e1601369
RP
608 continue
609 if dlist:
7f045fd8 610 self.preprocess_dependency_list(ifaceobj,
e1601369
RP
611 dlist, ops)
612 ifaceobj.lowerifaces = dlist
613 [iqueue.append(d) for d in dlist]
4cc2df04
RP
614 #if not self.dependency_graph.get(i):
615 # self.dependency_graph[i] = dlist
616
617 for i in self.ifaceobjdict.keys():
618 iobj = self.get_ifaceobj_first(i)
619 if iobj.lowerifaces:
620 self.dependency_graph[i] = iobj.lowerifaces
621 else:
622 self.dependency_graph[i] = []
e1601369 623
67cfaeb1
RP
624 if not self.blacklisted_ifaces_present:
625 return
626
627 # Walk through the dependency graph and remove blacklisted
628 # interfaces that were picked up as dependents
629 for i in self.dependency_graph.keys():
630 ifaceobj = self.get_ifaceobj_first(i)
631 if not ifaceobj:
632 continue
633 if ifaceobj.blacklisted and not ifaceobj.upperifaces:
634 # if blacklisted and was not picked up as a
635 # dependent of a upper interface, delete the
636 # interface from the dependency graph
637 dlist = ifaceobj.lowerifaces
638 if dlist:
639 for d in dlist:
397214a5
RP
640 difaceobjs = self.get_ifaceobjs(d)
641 if not difaceobjs:
67cfaeb1 642 continue
67cfaeb1 643 try:
397214a5
RP
644 for d in difaceobjs:
645 d.dec_refcnt()
646 d.upperifaces.remove(i)
67cfaeb1
RP
647 except:
648 self.logger.debug('error removing %s from %s upperifaces' %(i, d))
649 pass
650 self.logger.debug("populate_dependency_info: deleting blacklisted interface %s" %i)
651 del self.dependency_graph[i]
652
8e113d63
RP
653 def _check_config_no_repeats(self, ifaceobj):
654 """ check if object has an attribute that is
655 restricted to a single object in the system.
656 if yes, warn and return """
657 for k,v in self._cache_no_repeats.items():
658 iv = ifaceobj.config.get(k)
659 if iv and iv[0] == v:
660 self.logger.error('ignoring interface %s. ' %ifaceobj.name +
661 'Only one object with attribute ' +
662 '\'%s %s\' allowed.' %(k, v))
663 return True
664 for k, v in self.config.get('no_repeats', {}).items():
665 iv = ifaceobj.config.get(k)
666 if iv and iv[0] == v:
667 self._cache_no_repeats[k] = v
668 return False
a6f80f0e 669
2ddd65c5
RP
670 def _save_iface_squash(self, ifaceobj):
671 """ squash ifaceobjects belonging to same iface
672 into a single object """
673 if self._check_config_no_repeats(ifaceobj):
674 return
675 ifaceobj.priv_flags = ifacePrivFlags()
676 if not self._link_master_slave:
677 ifaceobj.link_type = ifaceLinkType.LINK_NA
678 currentifaceobjlist = self.ifaceobjdict.get(ifaceobj.name)
679 if not currentifaceobjlist:
680 self.ifaceobjdict[ifaceobj.name] = [ifaceobj]
681 return
682 if ifaceobj.compare(currentifaceobjlist[0]):
683 self.logger.warn('duplicate interface %s found' %ifaceobj.name)
684 return
685 currentifaceobjlist[0].squash(ifaceobj)
686
41febf89 687 def _save_iface(self, ifaceobj):
8e113d63
RP
688 if self._check_config_no_repeats(ifaceobj):
689 return
dbc018d3 690 ifaceobj.priv_flags = ifacePrivFlags()
7e2e64fb
RP
691 if not self._link_master_slave:
692 ifaceobj.link_type = ifaceLinkType.LINK_NA
679e6567
RP
693 currentifaceobjlist = self.ifaceobjdict.get(ifaceobj.name)
694 if not currentifaceobjlist:
99ce6894
RP
695 self.ifaceobjdict[ifaceobj.name]= [ifaceobj]
696 if not self._ifaceobj_squash:
697 ifaceobj.flags |= ifaceobj.YOUNGEST_SIBLING
698 return
679e6567
RP
699 if ifaceobj.compare(currentifaceobjlist[0]):
700 self.logger.warn('duplicate interface %s found' %ifaceobj.name)
701 return
8e113d63 702 if currentifaceobjlist[0].type == ifaceobj.type:
7444feea
ST
703 currentifaceobjlist[0].flags |= ifaceobj.HAS_SIBLINGS
704 ifaceobj.flags |= ifaceobj.HAS_SIBLINGS
705 # clear the OLDEST_SIBLING from all the siblings
706 for iface in self.ifaceobjdict[ifaceobj.name]:
707 iface.flags &= ~ifaceobj.OLDEST_SIBLING
708 # current sibling is the oldest
709 ifaceobj.flags |= ifaceobj.OLDEST_SIBLING
679e6567 710 self.ifaceobjdict[ifaceobj.name].append(ifaceobj)
41febf89 711
3dcc1d0e 712 def _iface_configattr_syntax_checker(self, attrname, attrval):
d08d5f54 713 for m, mdict in self.module_attrs.items():
7949b8a5 714 if not mdict:
715 continue
d08d5f54 716 attrsdict = mdict.get('attrs')
7949b8a5 717 try:
1553a881
RP
718 a = attrsdict.get(attrname)
719 if a:
720 if a.get('deprecated'):
721 newa = a.get('new-attribute')
722 if newa:
723 self.logger.warn('attribute %s is deprecated. Use %s instead' %(attrname, newa))
724 else:
725 self.logger.warn('attribute %s is deprecated'
726 %attrname)
7949b8a5 727 return True
728 except AttributeError:
729 pass
d08d5f54 730 return False
731
3dcc1d0e 732 def _ifaceobj_syntax_checker(self, ifaceobj):
cfa06db6 733 ret = True
8e113d63 734 for attrname, attrvalue in ifaceobj.config.items():
3dcc1d0e 735 found = False
736 for k, v in self.module_attrs.items():
737 if v and v.get('attrs', {}).get(attrname):
738 found = True
739 break
740 if not found:
cfa06db6 741 ret = False
fa714fa2
ST
742 self.logger.warn('%s: unsupported attribute \'%s\'' \
743 % (ifaceobj.name, attrname))
3dcc1d0e 744 continue
cfa06db6 745 return ret
3dcc1d0e 746
14dc390d 747 def read_iface_config(self):
a6f80f0e 748 """ Reads default network interface config /etc/network/interfaces. """
cfa06db6 749 ret = True
14dc390d 750 nifaces = networkInterfaces(self.interfacesfile,
3dcc1d0e 751 self.interfacesfileiobuf,
752 self.interfacesfileformat,
14dc390d 753 template_engine=self.config.get('template_engine'),
754 template_lookuppath=self.config.get('template_lookuppath'))
2ddd65c5
RP
755 if self._ifaceobj_squash or self._ifaceobj_squash_internal:
756 nifaces.subscribe('iface_found', self._save_iface_squash)
757 else:
758 nifaces.subscribe('iface_found', self._save_iface)
3dcc1d0e 759 nifaces.subscribe('validateifaceattr',
760 self._iface_configattr_syntax_checker)
761 nifaces.subscribe('validateifaceobj', self._ifaceobj_syntax_checker)
a6f80f0e 762 nifaces.load()
cfa06db6
RP
763 if nifaces.errors or nifaces.warns:
764 ret = False
765 return ret
a6f80f0e 766
a6f80f0e 767 def read_old_iface_config(self):
14dc390d 768 """ Reads the saved iface config instead of default iface config.
769 And saved iface config is already read by the statemanager """
cb7cc592 770 self.ifaceobjdict = copy.deepcopy(self.statemanager.ifaceobjdict)
a6f80f0e 771
53b00224 772 def _load_addon_modules_config(self):
773 """ Load addon modules config file """
a6f80f0e 774
37c0543d 775 with open(self.addon_modules_configfile, 'r') as f:
776 lines = f.readlines()
777 for l in lines:
7bbc9340
RP
778 try:
779 litems = l.strip(' \n\t\r').split(',')
780 if not litems or len(litems) < 2:
781 continue
782 operation = litems[0]
783 mname = litems[1]
784 self.module_ops[operation].append(mname)
785 except Exception, e:
786 self.logger.warn('error reading line \'%s\'' %(l, str(e)))
787 continue
37c0543d 788
789 def load_addon_modules(self, modules_dir):
a6f80f0e 790 """ load python modules from modules_dir
791
792 Default modules_dir is /usr/share/ifupdownmodules
793
794 """
a6f80f0e 795 self.logger.info('loading builtin modules from %s' %modules_dir)
53b00224 796 self._load_addon_modules_config()
a6f80f0e 797 if not modules_dir in sys.path:
37c0543d 798 sys.path.append(modules_dir)
a6f80f0e 799 try:
be0b20f2 800 for op, mlist in self.module_ops.items():
d08d5f54 801 for mname in mlist:
53b00224 802 if self.modules.get(mname):
d08d5f54 803 continue
804 mpath = modules_dir + '/' + mname + '.py'
805 if os.path.exists(mpath):
806 try:
807 m = __import__(mname)
808 mclass = getattr(m, mname)
809 except:
810 raise
811 minstance = mclass(force=self.FORCE,
812 dryrun=self.DRYRUN,
813 nowait=self.NOWAIT,
814 perfmode=self.PERFMODE,
a690dfae 815 cache=self.CACHE,
816 cacheflags=self.CACHE_FLAGS)
d08d5f54 817 self.modules[mname] = minstance
53b00224 818 try:
d08d5f54 819 self.module_attrs[mname] = minstance.get_modinfo()
53b00224 820 except:
821 pass
a6f80f0e 822 except:
823 raise
824
37c0543d 825 # Assign all modules to query operations
be0b20f2 826 self.module_ops['query-checkcurr'] = self.modules.keys()
827 self.module_ops['query-running'] = self.modules.keys()
828 self.module_ops['query-dependency'] = self.modules.keys()
829 self.module_ops['query'] = self.modules.keys()
830 self.module_ops['query-raw'] = self.modules.keys()
d08d5f54 831
14dc390d 832
53b00224 833 def _modules_help(self):
834 """ Prints addon modules supported syntax """
835
d08d5f54 836 indent = ' '
837 for m, mdict in self.module_attrs.items():
838 if not mdict:
839 continue
840 print('%s: %s' %(m, mdict.get('mhelp')))
841 attrdict = mdict.get('attrs')
842 if not attrdict:
843 continue
844 try:
845 for attrname, attrvaldict in attrdict.items():
846 if attrvaldict.get('compat', False):
847 continue
848 print('%s%s' %(indent, attrname))
849 print('%shelp: %s' %(indent + ' ',
850 attrvaldict.get('help', '')))
851 print ('%srequired: %s' %(indent + ' ',
852 attrvaldict.get('required', False)))
853 default = attrvaldict.get('default')
854 if default:
855 print('%sdefault: %s' %(indent + ' ', default))
856
857 validrange = attrvaldict.get('validrange')
858 if validrange:
1b0b81a2 859 print('%svalidrange: %s-%s'
7949b8a5 860 %(indent + ' ', validrange[0], validrange[1]))
d08d5f54 861
862 validvals = attrvaldict.get('validvals')
863 if validvals:
864 print('%svalidvals: %s'
865 %(indent + ' ', ','.join(validvals)))
866
867 examples = attrvaldict.get('example')
868 if not examples:
869 continue
a6f80f0e 870
d08d5f54 871 print '%sexample:' %(indent + ' ')
872 for e in examples:
873 print '%s%s' %(indent + ' ', e)
874 except:
875 pass
876 print ''
877
37c0543d 878 def load_scripts(self, modules_dir):
a6f80f0e 879 """ loading user modules from /etc/network/.
880
881 Note that previously loaded python modules override modules found
882 under /etc/network if any
883
884 """
885
37c0543d 886 self.logger.info('looking for user scripts under %s' %modules_dir)
be0b20f2 887 for op, mlist in self.script_ops.items():
d08d5f54 888 msubdir = modules_dir + '/if-%s.d' %op
889 self.logger.info('loading scripts under %s ...' %msubdir)
890 try:
891 module_list = os.listdir(msubdir)
892 for module in module_list:
893 if self.modules.get(module) is not None:
894 continue
be0b20f2 895 self.script_ops[op].append(
a6f80f0e 896 msubdir + '/' + module)
d08d5f54 897 except:
f802fe3c 898 # continue reading
899 pass
a6f80f0e 900
a4912b99 901 def _sched_ifaces(self, ifacenames, ops, skipupperifaces=False,
e308cb82 902 followdependents=True, sort=False):
c798b0f4 903 self.logger.debug('scheduling \'%s\' for %s'
d08d5f54 904 %(str(ops), str(ifacenames)))
7538dc77 905 self._pretty_print_ordered_dict('dependency graph',
906 self.dependency_graph)
2009513f 907 ifaceScheduler.sched_ifaces(self, ifacenames, ops,
c798b0f4 908 dependency_graph=self.dependency_graph,
d08d5f54 909 order=ifaceSchedulerFlags.INORDER
910 if 'down' in ops[0]
c798b0f4 911 else ifaceSchedulerFlags.POSTORDER,
a4912b99 912 followdependents=followdependents,
e308cb82 913 skipupperifaces=skipupperifaces,
dbc018d3 914 sort=True if (sort or self.flags.IFACE_CLASS) else False)
2009513f 915 return ifaceScheduler.get_sched_status()
a6f80f0e 916
41febf89
RP
917 def _render_ifacename(self, ifacename):
918 new_ifacenames = []
679e6567 919 vlan_match = re.match("^([\d]+)-([\d]+)", ifacename)
41febf89
RP
920 if vlan_match:
921 vlan_groups = vlan_match.groups()
922 if vlan_groups[0] and vlan_groups[1]:
679e6567 923 [new_ifacenames.append('%d' %v)
41febf89
RP
924 for v in range(int(vlan_groups[0]),
925 int(vlan_groups[1])+1)]
926 return new_ifacenames
927
928 def _preprocess_ifacenames(self, ifacenames):
a6f80f0e 929 """ validates interface list for config existance.
930
931 returns -1 if one or more interface not found. else, returns 0
932
933 """
41febf89 934 new_ifacenames = []
a6f80f0e 935 err_iface = ''
936 for i in ifacenames:
31a5f4c3 937 ifaceobjs = self.get_ifaceobjs(i)
938 if not ifaceobjs:
41febf89 939 # if name not available, render interface name and check again
679e6567 940 rendered_ifacenames = utils.expand_iface_range(i)
41febf89
RP
941 if rendered_ifacenames:
942 for ri in rendered_ifacenames:
943 ifaceobjs = self.get_ifaceobjs(ri)
944 if not ifaceobjs:
945 err_iface += ' ' + ri
946 else:
947 new_ifacenames.append(ri)
948 else:
949 err_iface += ' ' + i
950 else:
951 new_ifacenames.append(i)
fe0a57d3 952 if err_iface:
31c58787 953 raise Exception('cannot find interfaces:%s' %err_iface)
41febf89 954 return new_ifacenames
a6f80f0e 955
53b00224 956 def _iface_whitelisted(self, auto, allow_classes, excludepats, ifacename):
a6f80f0e 957 """ Checks if interface is whitelisted depending on set of parameters.
958
a6f80f0e 959 interfaces are checked against the allow_classes and auto lists.
960
961 """
1042b709 962
0532f0a3
RP
963 ret = True
964
19e2bf8c 965 # Check if interface matches the exclude patter
fe0a57d3 966 if excludepats:
3e8ee54f 967 for e in excludepats:
d08d5f54 968 if re.search(e, ifacename):
0532f0a3 969 ret = False
31a5f4c3 970 ifaceobjs = self.get_ifaceobjs(ifacename)
971 if not ifaceobjs:
0532f0a3
RP
972 if ret:
973 self.logger.debug('iface %s' %ifacename + ' not found')
974 return ret
67cfaeb1 975 # If matched exclude pattern, return false
0532f0a3
RP
976 if not ret:
977 for i in ifaceobjs:
978 i.blacklisted = True
67cfaeb1 979 self.blacklisted_ifaces_present = True
0532f0a3
RP
980 return ret
981 # Check if interface belongs to the class
67cfaeb1 982 # the user is interested in, if not return false
fe0a57d3 983 if allow_classes:
19e2bf8c 984 ret = False
a6f80f0e 985 for i in ifaceobjs:
62ddec8b 986 if i.classes:
3e8ee54f 987 common = Set([allow_classes]).intersection(
62ddec8b 988 Set(i.classes))
fe0a57d3 989 if common:
0532f0a3 990 ret = True
0532f0a3 991 if not ret:
19e2bf8c
RP
992 # If a class was requested and interface does not belong
993 # to the class, only then mark the ifaceobjs as blacklisted
994 self.blacklisted_ifaces_present = True
995 for i in ifaceobjs:
996 i.blacklisted = True
997 return ret
67cfaeb1
RP
998 # If the user has requested auto class, check if the interface
999 # is marked auto
d08d5f54 1000 if auto:
19e2bf8c 1001 ret = False
a6f80f0e 1002 for i in ifaceobjs:
62ddec8b 1003 if i.auto:
0532f0a3 1004 ret = True
19e2bf8c
RP
1005 if not ret:
1006 # If auto was requested and interface was not marked auto,
1007 # only then mark all of them as blacklisted
1008 self.blacklisted_ifaces_present = True
1009 for i in ifaceobjs:
0532f0a3
RP
1010 i.blacklisted = True
1011 return ret
a6f80f0e 1012
53b00224 1013 def _compat_conv_op_to_mode(self, op):
1014 """ Returns old op name to work with existing scripts """
1015 if op == 'pre-up':
1016 return 'start'
1017 elif op == 'pre-down':
1018 return 'stop'
1019 else:
1020 return op
1021
a6f80f0e 1022 def generate_running_env(self, ifaceobj, op):
739f665b 1023 """ Generates a dictionary with env variables required for
1024 an interface. Used to support script execution for interfaces.
a6f80f0e 1025 """
1026
1027 cenv = None
62ddec8b 1028 iface_env = ifaceobj.env
1029 if iface_env:
a6f80f0e 1030 cenv = os.environ
d08d5f54 1031 if cenv:
a6f80f0e 1032 cenv.update(iface_env)
1033 else:
1034 cenv = iface_env
53b00224 1035 cenv['MODE'] = self._compat_conv_op_to_mode(op)
a6f80f0e 1036 return cenv
1037
53b00224 1038 def _save_state(self):
dbc018d3
RP
1039 if (not self.flags.STATEMANAGER_ENABLE or
1040 not self.flags.STATEMANAGER_UPDATE):
20dd6242 1041 return
1042 try:
1043 # Update persistant iface states
1044 self.statemanager.save_state()
1045 except Exception, e:
1046 if self.logger.isEnabledFor(logging.DEBUG):
1047 t = sys.exc_info()[2]
1048 traceback.print_tb(t)
1049 self.logger.warning('error saving state (%s)' %str(e))
1050
2da58137
RP
1051 def set_type(self, type):
1052 if type == 'iface':
1053 self.type = ifaceType.IFACE
1054 elif type == 'vlan':
1055 self.type = ifaceType.BRIDGE_VLAN
1056 else:
1057 self.type = ifaceType.UNKNOWN
1058
a070c90e
RP
1059 def _process_delay_admin_state_queue(self, op):
1060 if not self._delay_admin_state_iface_queue:
1061 return
1062 if op == 'up':
1063 func = self.link_up
1064 elif op == 'down':
1065 func = self.link_down
1066 else:
1067 return
1068 for i in self._delay_admin_state_iface_queue:
1069 try:
1070 if self.link_exists(i):
1071 func(i)
1072 except Exception, e:
1073 self.logger.warn(str(e))
1074 pass
1075
d08d5f54 1076 def up(self, ops, auto=False, allow_classes=None, ifacenames=None,
2da58137 1077 excludepats=None, printdependency=None, syntaxcheck=False,
ad25e7bb 1078 type=None, skipupperifaces=False):
2c0ad8b3
RP
1079 """This brings the interface(s) up
1080
1081 Args:
41febf89
RP
1082 ops (list): list of ops to perform on the interface(s).
1083 Eg: ['pre-up', 'up', 'post-up'
2c0ad8b3
RP
1084
1085 Kwargs:
1086 auto (bool): act on interfaces marked auto
1087 allow_classes (list): act on interfaces belonging to classes in the list
1088 ifacenames (list): act on interfaces specified in this list
1089 excludepats (list): list of patterns of interfaces to exclude
1090 syntaxcheck (bool): only perform syntax check
1091 """
53b00224 1092
2da58137
RP
1093 self.set_type(type)
1094
5ee3e1a8 1095 if allow_classes:
dbc018d3
RP
1096 self.flags.IFACE_CLASS = True
1097 if not self.flags.ADDONS_ENABLE:
1098 self.flags.STATEMANAGER_UPDATE = False
d08d5f54 1099 if auto:
dbc018d3
RP
1100 self.flags.ALL = True
1101 self.flags.WITH_DEPENDS = True
d08d5f54 1102 try:
cfa06db6 1103 iface_read_ret = self.read_iface_config()
62ddec8b 1104 except Exception:
d08d5f54 1105 raise
a6f80f0e 1106
31a5f4c3 1107 if ifacenames:
41febf89 1108 ifacenames = self._preprocess_ifacenames(ifacenames)
a6f80f0e 1109
1110 # if iface list not given by user, assume all from config file
31a5f4c3 1111 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
a6f80f0e 1112
1113 # filter interfaces based on auto and allow classes
cca03c30 1114 filtered_ifacenames = [i for i in ifacenames
53b00224 1115 if self._iface_whitelisted(auto, allow_classes,
d08d5f54 1116 excludepats, i)]
fe0a57d3 1117 if not filtered_ifacenames:
d08d5f54 1118 raise Exception('no ifaces found matching given allow lists')
a6f80f0e 1119
20dd6242 1120 if printdependency:
c798b0f4 1121 self.populate_dependency_info(ops, filtered_ifacenames)
d08d5f54 1122 self.print_dependency(filtered_ifacenames, printdependency)
739f665b 1123 return
cca03c30 1124 else:
c798b0f4 1125 self.populate_dependency_info(ops)
1126
cfa06db6
RP
1127 # If only syntax check was requested, return here.
1128 # return here because we want to make sure most
1129 # errors above are caught and reported.
21289e4a 1130 if syntaxcheck:
cfa06db6
RP
1131 if not iface_read_ret:
1132 raise Exception()
21289e4a
RP
1133 return
1134
525f0a30 1135 try:
2009513f
RP
1136 ret = self._sched_ifaces(filtered_ifacenames, ops,
1137 skipupperifaces=skipupperifaces,
1138 followdependents=True
1139 if self.flags.WITH_DEPENDS else False)
525f0a30 1140 finally:
a070c90e 1141 self._process_delay_admin_state_queue('up')
dbc018d3 1142 if not self.DRYRUN and self.flags.ADDONS_ENABLE:
525f0a30 1143 self._save_state()
a6f80f0e 1144
2009513f
RP
1145 if not iface_read_ret or not ret:
1146 raise Exception()
1147
d08d5f54 1148 def down(self, ops, auto=False, allow_classes=None, ifacenames=None,
2da58137
RP
1149 excludepats=None, printdependency=None, usecurrentconfig=False,
1150 type=None):
53b00224 1151 """ down an interface """
1152
2da58137
RP
1153 self.set_type(type)
1154
5ee3e1a8 1155 if allow_classes:
dbc018d3
RP
1156 self.flags.IFACE_CLASS = True
1157 if not self.flags.ADDONS_ENABLE:
1158 self.flags.STATEMANAGER_UPDATE = False
d08d5f54 1159 if auto:
dbc018d3
RP
1160 self.flags.ALL = True
1161 self.flags.WITH_DEPENDS = True
5c721925 1162 # For down we need to look at old state, unless usecurrentconfig
1163 # is set
dbc018d3 1164 if (not usecurrentconfig and self.flags.STATEMANAGER_ENABLE and
53b00224 1165 self.statemanager.ifaceobjdict):
31a5f4c3 1166 # Since we are using state manager objects,
1167 # skip the updating of state manager objects
5c721925 1168 self.logger.debug('Looking at old state ..')
d08d5f54 1169 self.read_old_iface_config()
fe0a57d3 1170 else:
d08d5f54 1171 # If no old state available
d08d5f54 1172 try:
1173 self.read_iface_config()
1174 except Exception, e:
1175 raise Exception('error reading iface config (%s)' %str(e))
d08d5f54 1176 if ifacenames:
1177 # If iface list is given by the caller, always check if iface
1178 # is present
31c58787 1179 try:
41febf89 1180 ifacenames = self._preprocess_ifacenames(ifacenames)
31c58787 1181 except Exception, e:
1182 raise Exception('%s' %str(e) +
1183 ' (interface was probably never up ?)')
1184
d08d5f54 1185 # if iface list not given by user, assume all from config file
fe0a57d3 1186 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
53b00224 1187
d08d5f54 1188 # filter interfaces based on auto and allow classes
1189 filtered_ifacenames = [i for i in ifacenames
53b00224 1190 if self._iface_whitelisted(auto, allow_classes,
d08d5f54 1191 excludepats, i)]
fe0a57d3 1192 if not filtered_ifacenames:
c0071225 1193 raise Exception('no ifaces found matching given allow lists ' +
41febf89 1194 '(or interfaces were probably never up ?)')
14dc390d 1195
d08d5f54 1196 if printdependency:
99b212b0 1197 self.populate_dependency_info(ops, filtered_ifacenames)
d08d5f54 1198 self.print_dependency(filtered_ifacenames, printdependency)
1199 return
99b212b0 1200 else:
1201 self.populate_dependency_info(ops)
525f0a30 1202
1203 try:
a4912b99 1204 self._sched_ifaces(filtered_ifacenames, ops,
dbc018d3
RP
1205 followdependents=True
1206 if self.flags.WITH_DEPENDS else False)
525f0a30 1207 finally:
a070c90e 1208 self._process_delay_admin_state_queue('down')
dbc018d3 1209 if not self.DRYRUN and self.flags.ADDONS_ENABLE:
525f0a30 1210 self._save_state()
d08d5f54 1211
1212 def query(self, ops, auto=False, allow_classes=None, ifacenames=None,
739f665b 1213 excludepats=None, printdependency=None,
2da58137 1214 format='native', type=None):
53b00224 1215 """ query an interface """
1216
2da58137
RP
1217 self.set_type(type)
1218
2ddd65c5
RP
1219 # Let us forget internal squashing when it comes to
1220 # ifquery. It can surprise people relying of ifquery
1221 # output
1222 self._ifaceobj_squash_internal = False
1223
5ee3e1a8 1224 if allow_classes:
dbc018d3
RP
1225 self.flags.IFACE_CLASS = True
1226 if self.flags.STATEMANAGER_ENABLE and ops[0] == 'query-savedstate':
5c721925 1227 return self.statemanager.dump_pretty(ifacenames)
dbc018d3 1228 self.flags.STATEMANAGER_UPDATE = False
d08d5f54 1229 if auto:
739f665b 1230 self.logger.debug('setting flag ALL')
dbc018d3
RP
1231 self.flags.ALL = True
1232 self.flags.WITH_DEPENDS = True
739f665b 1233
d08d5f54 1234 if ops[0] == 'query-syntax':
53b00224 1235 self._modules_help()
d08d5f54 1236 return
1237 elif ops[0] == 'query-running':
739f665b 1238 # create fake devices to all dependents that dont have config
dbc018d3
RP
1239 map(lambda i: self.create_n_save_ifaceobj(i,
1240 ifacePrivFlags(False, True)), ifacenames)
739f665b 1241 else:
1242 try:
1243 self.read_iface_config()
1244 except Exception:
1245 raise
1246
53b00224 1247 if ifacenames and ops[0] != 'query-running':
41febf89
RP
1248 # If iface list is given, always check if iface is present
1249 ifacenames = self._preprocess_ifacenames(ifacenames)
739f665b 1250
1251 # if iface list not given by user, assume all from config file
31a5f4c3 1252 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
739f665b 1253
1254 # filter interfaces based on auto and allow classes
d08d5f54 1255 if ops[0] == 'query-running':
739f665b 1256 filtered_ifacenames = ifacenames
1257 else:
1258 filtered_ifacenames = [i for i in ifacenames
53b00224 1259 if self._iface_whitelisted(auto, allow_classes,
d08d5f54 1260 excludepats, i)]
fe0a57d3 1261 if not filtered_ifacenames:
739f665b 1262 raise Exception('no ifaces found matching ' +
1263 'given allow lists')
37c0543d 1264
e1601369 1265 self.populate_dependency_info(ops)
d08d5f54 1266 if ops[0] == 'query-dependency' and printdependency:
1267 self.print_dependency(filtered_ifacenames, printdependency)
1268 return
739f665b 1269
75730152 1270 if ops[0] == 'query':
1271 return self.print_ifaceobjs_pretty(filtered_ifacenames, format)
1272 elif ops[0] == 'query-raw':
1273 return self.print_ifaceobjs_raw(filtered_ifacenames)
1274
2009513f 1275 ret = self._sched_ifaces(filtered_ifacenames, ops,
dbc018d3
RP
1276 followdependents=True
1277 if self.flags.WITH_DEPENDS else False)
739f665b 1278
d08d5f54 1279 if ops[0] == 'query-checkcurr':
1280 ret = self.print_ifaceobjscurr_pretty(filtered_ifacenames, format)
739f665b 1281 if ret != 0:
1282 # if any of the object has an error, signal that silently
1283 raise Exception('')
d08d5f54 1284 elif ops[0] == 'query-running':
1285 self.print_ifaceobjsrunning_pretty(filtered_ifacenames, format)
739f665b 1286 return
1287
2da58137
RP
1288 def _reload_currentlyup(self, upops, downops, auto=True, allow=None,
1289 ifacenames=None, excludepats=None, usecurrentconfig=False,
cfa06db6 1290 syntaxcheck=False, **extra_args):
2da58137 1291 """ reload currently up interfaces """
c0071225 1292 new_ifaceobjdict = {}
739f665b 1293
2da58137
RP
1294 # Override auto to true
1295 auto = True
2da58137 1296 try:
cfa06db6 1297 iface_read_ret = self.read_iface_config()
2da58137
RP
1298 except:
1299 raise
2da58137
RP
1300 if not self.ifaceobjdict:
1301 self.logger.warn("nothing to reload ..exiting.")
1302 return
2da58137 1303 already_up_ifacenames = []
1042b709
RP
1304 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
1305 filtered_ifacenames = [i for i in ifacenames
1306 if self._iface_whitelisted(auto, allow,
1307 excludepats, i)]
1308
2da58137
RP
1309 # generate dependency graph of interfaces
1310 self.populate_dependency_info(upops)
cfa06db6
RP
1311
1312 # If only syntax check was requested, return here.
1313 # return here because we want to make sure most
1314 # errors above are caught and reported.
1315 if syntaxcheck:
1316 if not iface_read_ret:
1317 raise Exception()
1318 return
1319
dbc018d3 1320 if (not usecurrentconfig and self.flags.STATEMANAGER_ENABLE
2da58137
RP
1321 and self.statemanager.ifaceobjdict):
1322 already_up_ifacenames = self.statemanager.ifaceobjdict.keys()
1323
2da58137
RP
1324 # Get already up interfaces that still exist in the interfaces file
1325 already_up_ifacenames_not_present = Set(
1326 already_up_ifacenames).difference(ifacenames)
1327 already_up_ifacenames_still_present = Set(
1328 already_up_ifacenames).difference(
1329 already_up_ifacenames_not_present)
1330 interfaces_to_up = Set(already_up_ifacenames_still_present).union(
1331 filtered_ifacenames)
1332
1333 if (already_up_ifacenames_not_present and
1334 self.config.get('ifreload_currentlyup_down_notpresent') == '1'):
1335 self.logger.info('reload: schedule down on interfaces: %s'
1336 %str(already_up_ifacenames_not_present))
1337
1338 # Save a copy of new iface objects and dependency_graph
1339 new_ifaceobjdict = dict(self.ifaceobjdict)
1340 new_dependency_graph = dict(self.dependency_graph)
1341
1342 # old interface config is read into self.ifaceobjdict
1343 self.read_old_iface_config()
1344
1345 # reinitialize dependency graph
1346 self.dependency_graph = OrderedDict({})
1042b709
RP
1347 falready_up_ifacenames_not_present = [i for i in
1348 already_up_ifacenames_not_present
1349 if self._iface_whitelisted(auto, allow,
1350 excludepats, i)]
2da58137 1351 self.populate_dependency_info(downops,
1042b709
RP
1352 falready_up_ifacenames_not_present)
1353 self._sched_ifaces(falready_up_ifacenames_not_present, downops,
e308cb82 1354 followdependents=False, sort=True)
2da58137
RP
1355 else:
1356 self.logger.debug('no interfaces to down ..')
1357
1358 # Now, run 'up' with new config dict
1359 # reset statemanager update flag to default
e308cb82 1360 if auto:
dbc018d3
RP
1361 self.flags.ALL = True
1362 self.flags.WITH_DEPENDS = True
2da58137 1363 if new_ifaceobjdict:
3d44fbd0 1364 # and now, ifaceobjdict is back to current config
2da58137
RP
1365 self.ifaceobjdict = new_ifaceobjdict
1366 self.dependency_graph = new_dependency_graph
1367
1368 if not self.ifaceobjdict:
1369 return
1370 self.logger.info('reload: scheduling up on interfaces: %s'
1371 %str(interfaces_to_up))
2009513f
RP
1372 ret = self._sched_ifaces(interfaces_to_up, upops,
1373 followdependents=True
1374 if self.flags.WITH_DEPENDS else False)
2da58137
RP
1375 if self.DRYRUN:
1376 return
1377 self._save_state()
1378
2009513f
RP
1379 if not iface_read_ret or not ret:
1380 raise Exception()
1381
2da58137
RP
1382 def _reload_default(self, upops, downops, auto=False, allow=None,
1383 ifacenames=None, excludepats=None, usecurrentconfig=False,
cfa06db6 1384 syntaxcheck=False, **extra_args):
2da58137 1385 """ reload interface config """
2da58137 1386 new_ifaceobjdict = {}
739f665b 1387
1388 try:
cfa06db6 1389 iface_read_ret = self.read_iface_config()
20dd6242 1390 except:
739f665b 1391 raise
1392
c0071225
RP
1393 if not self.ifaceobjdict:
1394 self.logger.warn("nothing to reload ..exiting.")
1395 return
1042b709
RP
1396
1397 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
1398 new_filtered_ifacenames = [i for i in ifacenames
1399 if self._iface_whitelisted(auto, allow,
1400 excludepats, i)]
37c0543d 1401 # generate dependency graph of interfaces
c798b0f4 1402 self.populate_dependency_info(upops)
1042b709 1403
cfa06db6
RP
1404 # If only syntax check was requested, return here.
1405 # return here because we want to make sure most
1406 # errors above are caught and reported.
1407 if syntaxcheck:
1408 if not iface_read_ret:
1409 raise Exception()
1410 return
1411
dbc018d3 1412 if (not usecurrentconfig and self.flags.STATEMANAGER_ENABLE
14dc390d 1413 and self.statemanager.ifaceobjdict):
1414 # Save a copy of new iface objects and dependency_graph
1415 new_ifaceobjdict = dict(self.ifaceobjdict)
1416 new_dependency_graph = dict(self.dependency_graph)
37c0543d 1417
dbc018d3
RP
1418 self.ifaceobjdict = OrderedDict({})
1419 self.dependency_graph = OrderedDict({})
1420
739f665b 1421 # if old state is present, read old state and mark op for 'down'
1422 # followed by 'up' aka: reload
37c0543d 1423 # old interface config is read into self.ifaceobjdict
739f665b 1424 self.read_old_iface_config()
1425 op = 'reload'
1426 else:
1427 # oldconfig not available, continue with 'up' with new config
1428 op = 'up'
1429
fe0a57d3 1430 if op == 'reload' and ifacenames:
93b399fb 1431 ifacenames = self.ifaceobjdict.keys()
1042b709
RP
1432 old_filtered_ifacenames = [i for i in ifacenames
1433 if self._iface_whitelisted(auto, allow,
d08d5f54 1434 excludepats, i)]
e308cb82 1435
dbc018d3
RP
1436 # generate dependency graph of old interfaces,
1437 # This should make sure built in interfaces are
1438 # populated. disable check shared dependents as an optimization.
1439 # these are saved interfaces and dependency for these
1440 # have been checked before they became part of saved state.
62f2caa4
RP
1441 try:
1442 self.flags.CHECK_SHARED_DEPENDENTS = False
1443 self.populate_dependency_info(upops)
1444 self.flags.CHECK_SHARED_DEPENDENTS = True
1445 except Exception, e:
1446 self.logger.info("error generating dependency graph for "
1447 "saved interfaces (%s)" %str(e))
1448 pass
1449
dbc018d3 1450 # make sure we pick up built-in interfaces
e308cb82
RP
1451 # if config file had 'ifreload_down_changed' variable
1452 # set, also look for interfaces that changed to down them
1453 down_changed = int(self.config.get('ifreload_down_changed', '1'))
1454
37c0543d 1455 # Generate the interface down list
1456 # Interfaces that go into the down list:
1457 # - interfaces that were present in last config and are not
1458 # present in the new config
1459 # - interfaces that were changed between the last and current
1460 # config
37c0543d 1461 ifacedownlist = []
dbc018d3 1462 for ifname in self.ifaceobjdict.keys():
2da58137 1463 lastifaceobjlist = self.ifaceobjdict.get(ifname)
dbc018d3
RP
1464 if not self.is_ifaceobj_builtin(lastifaceobjlist[0]):
1465 # if interface is not built-in and is not in
1466 # old filtered ifacenames
1467 if ifname not in old_filtered_ifacenames:
1468 continue
37c0543d 1469 objidx = 0
37c0543d 1470 # If interface is not present in the new file
1471 # append it to the down list
53b00224 1472 newifaceobjlist = new_ifaceobjdict.get(ifname)
1473 if not newifaceobjlist:
37c0543d 1474 ifacedownlist.append(ifname)
1475 continue
21289e4a
RP
1476 # If ifaceobj was present in the old interfaces file,
1477 # and does not have a config in the new interfaces file
1478 # but has been picked up as a dependent of another
1479 # interface, catch it here. This catches a common error
1480 # for example: remove a bond section from the interfaces
1481 # file, but leave it around as a bridge port
1482 # XXX: Ideally its better to just add it to the
1483 # ifacedownlist. But we will be cautious here
1484 # and just print a warning
1485 if (self.is_ifaceobj_noconfig(newifaceobjlist[0]) and
dbc018d3 1486 not self.is_ifaceobj_builtin(newifaceobjlist[0]) and
21289e4a
RP
1487 lastifaceobjlist[0].is_config_present()):
1488 self.logger.warn('%s: misconfig ? removed but still exists as a dependency of %s' %(newifaceobjlist[objidx].name,
1489 str(newifaceobjlist[objidx].upperifaces)))
26434da6
RP
1490 if not down_changed:
1491 continue
53b00224 1492 if len(newifaceobjlist) != len(lastifaceobjlist):
37c0543d 1493 ifacedownlist.append(ifname)
1494 continue
e308cb82
RP
1495
1496 # If interface has changed between the current file
1497 # and the last installed append it to the down list
37c0543d 1498 # compare object list
53b00224 1499 for objidx in range(0, len(lastifaceobjlist)):
1500 oldobj = lastifaceobjlist[objidx]
1501 newobj = newifaceobjlist[objidx]
ca3f4fc7 1502 if not newobj.compare(oldobj):
37c0543d 1503 ifacedownlist.append(ifname)
1504 continue
1505
fe0a57d3 1506 if ifacedownlist:
2da58137 1507 self.logger.info('reload: scheduling down on interfaces: %s'
739f665b 1508 %str(ifacedownlist))
20dd6242 1509 # reinitialize dependency graph
1510 self.dependency_graph = OrderedDict({})
dbc018d3 1511
37c0543d 1512 # Generate dependency info for old config
62f2caa4 1513 self.flags.CHECK_SHARED_DEPENDENTS = False
14dc390d 1514 self.populate_dependency_info(downops, ifacedownlist)
62f2caa4
RP
1515 self.flags.CHECK_SHARED_DEPENDENTS = True
1516
a070c90e 1517 try:
dbc018d3
RP
1518 # XXX: Hack to skip checking upperifaces during down.
1519 # the dependency list is not complete here
1520 # and we dont want to down the upperiface.
1521 # Hence during reload, set this to true.
1522 # This is being added to avoid a failure in
1523 # scheduler._check_upperifaces when we are dowing
1524 # a builtin bridge port
1525 self.flags.SCHED_SKIP_CHECK_UPPERIFACES = True
a4912b99 1526 self._sched_ifaces(ifacedownlist, downops,
e308cb82
RP
1527 followdependents=False,
1528 sort=True)
a070c90e
RP
1529 except Exception, e:
1530 self.logger.error(str(e))
1531 pass
1532 finally:
dbc018d3 1533 self.flags.SCHED_SKIP_CHECK_UPPERIFACES = False
a070c90e 1534 self._process_delay_admin_state_queue('down')
37c0543d 1535 else:
1536 self.logger.debug('no interfaces to down ..')
739f665b 1537
20dd6242 1538 # Now, run 'up' with new config dict
1539 # reset statemanager update flag to default
c0071225 1540 if not new_ifaceobjdict:
aa4e3022 1541 self.logger.debug('no interfaces to up')
c0071225 1542 return
e308cb82
RP
1543
1544 if auto:
dbc018d3
RP
1545 self.flags.ALL = True
1546 self.flags.WITH_DEPENDS = True
3d44fbd0 1547 # and now, we are back to the current config in ifaceobjdict
53b00224 1548 self.ifaceobjdict = new_ifaceobjdict
1549 self.dependency_graph = new_dependency_graph
c798b0f4 1550
2da58137 1551 self.logger.info('reload: scheduling up on interfaces: %s'
1042b709 1552 %str(new_filtered_ifacenames))
a070c90e 1553 try:
2009513f
RP
1554 ret = self._sched_ifaces(new_filtered_ifacenames, upops,
1555 followdependents=True
1556 if self.flags.WITH_DEPENDS else False)
a070c90e
RP
1557 except Exception, e:
1558 self.logger.error(str(e))
1559 pass
1560 finally:
1561 self._process_delay_admin_state_queue('up')
e37ad4a6 1562 if self.DRYRUN:
1563 return
53b00224 1564 self._save_state()
a6f80f0e 1565
2009513f
RP
1566 if not iface_read_ret or not ret:
1567 raise Exception()
1568
2da58137
RP
1569 def reload(self, *args, **kargs):
1570 """ reload interface config """
2da58137
RP
1571 self.logger.debug('reloading interface config ..')
1572 if kargs.get('currentlyup', False):
1573 self._reload_currentlyup(*args, **kargs)
1574 else:
1575 self._reload_default(*args, **kargs)
1576
7538dc77 1577 def _pretty_print_ordered_dict(self, prefix, argdict):
525f0a30 1578 outbuf = prefix + ' {\n'
53b00224 1579 for k, vlist in argdict.items():
525f0a30 1580 outbuf += '\t%s : %s\n' %(k, str(vlist))
7538dc77 1581 self.logger.debug(outbuf + '}')
a6f80f0e 1582
53b00224 1583 def print_dependency(self, ifacenames, format):
1584 """ prints iface dependency information """
a6f80f0e 1585
53b00224 1586 if not ifacenames:
1587 ifacenames = self.ifaceobjdict.keys()
1588 if format == 'list':
1589 for k,v in self.dependency_graph.items():
1590 print '%s : %s' %(k, str(v))
1591 elif format == 'dot':
1592 indegrees = {}
1593 map(lambda i: indegrees.update({i :
1594 self.get_iface_refcnt(i)}),
1595 self.dependency_graph.keys())
1596 graph.generate_dots(self.dependency_graph, indegrees)
a6f80f0e 1597
739f665b 1598 def print_ifaceobjs_raw(self, ifacenames):
53b00224 1599 """ prints raw lines for ifaces from config file """
1600
739f665b 1601 for i in ifacenames:
31a5f4c3 1602 for ifaceobj in self.get_ifaceobjs(i):
75730152 1603 if (self.is_ifaceobj_builtin(ifaceobj) or
1604 not ifaceobj.is_config_present()):
1605 continue
1606 ifaceobj.dump_raw(self.logger)
739f665b 1607 print '\n'
dbc018d3 1608 if self.flags.WITH_DEPENDS and not self.flags.ALL:
62ddec8b 1609 dlist = ifaceobj.lowerifaces
fe0a57d3 1610 if not dlist: continue
53b00224 1611 self.print_ifaceobjs_raw(dlist)
739f665b 1612
2cd06f78 1613 def _get_ifaceobjs_pretty(self, ifacenames, ifaceobjs, running=False):
1614 """ returns iface obj list """
53b00224 1615
a6f80f0e 1616 for i in ifacenames:
31a5f4c3 1617 for ifaceobj in self.get_ifaceobjs(i):
2cd06f78 1618 if ((not running and self.is_ifaceobj_noconfig(ifaceobj)) or
1619 (running and not ifaceobj.is_config_present())):
75730152 1620 continue
2cd06f78 1621 ifaceobjs.append(ifaceobj)
dbc018d3 1622 if self.flags.WITH_DEPENDS and not self.flags.ALL:
62ddec8b 1623 dlist = ifaceobj.lowerifaces
fe0a57d3 1624 if not dlist: continue
2cd06f78 1625 self._get_ifaceobjs_pretty(dlist, ifaceobjs, running)
739f665b 1626
2cd06f78 1627 def print_ifaceobjs_pretty(self, ifacenames, format='native'):
1628 """ pretty prints iface in format given by keyword arg format """
eab25b7c 1629
2cd06f78 1630 ifaceobjs = []
1631 self._get_ifaceobjs_pretty(ifacenames, ifaceobjs)
1632 if not ifaceobjs: return
1633 if format == 'json':
3dcc1d0e 1634 print json.dumps(ifaceobjs, cls=ifaceJsonEncoder,
1635 indent=4, separators=(',', ': '))
2cd06f78 1636 else:
2da58137
RP
1637 expand = int(self.config.get('ifquery_ifacename_expand_range', '0'))
1638 for i in ifaceobjs:
1639 if not expand and (i.flags & iface.IFACERANGE_ENTRY):
1640 # print only the first one
1641 if i.flags & iface.IFACERANGE_START:
1642 i.dump_pretty(use_realname=True)
1643 else:
1644 i.dump_pretty()
53b00224 1645
2cd06f78 1646 def _get_ifaceobjscurr_pretty(self, ifacenames, ifaceobjs):
eab25b7c 1647 ret = 0
a6f80f0e 1648 for i in ifacenames:
923290bd 1649 ifaceobjscurr = self.get_ifaceobjcurr(i)
1650 if not ifaceobjscurr: continue
1651 for ifaceobj in ifaceobjscurr:
1652 if (ifaceobj.status == ifaceStatus.NOTFOUND or
1653 ifaceobj.status == ifaceStatus.ERROR):
1654 ret = 1
1655 if self.is_ifaceobj_noconfig(ifaceobj):
1656 continue
1657 ifaceobjs.append(ifaceobj)
dbc018d3 1658 if self.flags.WITH_DEPENDS and not self.flags.ALL:
923290bd 1659 dlist = ifaceobj.lowerifaces
1660 if not dlist: continue
1661 dret = self._get_ifaceobjscurr_pretty(dlist, ifaceobjs)
1662 if dret: ret = 1
2cd06f78 1663 return ret
1664
1665 def print_ifaceobjscurr_pretty(self, ifacenames, format='native'):
1666 """ pretty prints current running state of interfaces with status.
1667
1668 returns 1 if any of the interface has an error,
1669 else returns 0
1670 """
1671
1672 ifaceobjs = []
1673 ret = self._get_ifaceobjscurr_pretty(ifacenames, ifaceobjs)
1674 if not ifaceobjs: return
307e06bb
RP
1675
1676 # override ifaceStatusUserStrs
1677 ifaceStatusUserStrs.SUCCESS = self.config.get('ifquery_check_success_str', _success_sym)
1678 ifaceStatusUserStrs.ERROR = self.config.get('ifquery_check_error_str', _error_sym)
1679 ifaceStatusUserStrs.UNKNOWN = self.config.get('ifquery_check_unknown_str', '')
2cd06f78 1680 if format == 'json':
307e06bb
RP
1681 print json.dumps(ifaceobjs, cls=ifaceJsonEncoderWithStatus,
1682 indent=2, separators=(',', ': '))
2cd06f78 1683 else:
fb10449e 1684 map(lambda i: i.dump_pretty(with_status=True), ifaceobjs)
eab25b7c 1685 return ret
a6f80f0e 1686
d08d5f54 1687 def print_ifaceobjsrunning_pretty(self, ifacenames, format='native'):
53b00224 1688 """ pretty prints iface running state """
1689
2cd06f78 1690 ifaceobjs = []
1691 self._get_ifaceobjs_pretty(ifacenames, ifaceobjs, running=True)
1692 if not ifaceobjs: return
1693 if format == 'json':
1694 print json.dumps(ifaceobjs, cls=ifaceJsonEncoder, indent=2,
1695 separators=(',', ': '))
1696 else:
1697 map(lambda i: i.dump_pretty(), ifaceobjs)
53b00224 1698
1699 def _dump(self):
1700 print 'ifupdown main object dump'
1701 print self.pp.pprint(self.modules)
1702 print self.pp.pprint(self.ifaceobjdict)
1703
1704 def _dump_ifaceobjs(self, ifacenames):
1705 for i in ifacenames:
1706 ifaceobjs = self.get_ifaceobjs(i)
1707 for i in ifaceobjs:
1708 i.dump(self.logger)
1709 print '\n'