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