]> git.proxmox.com Git - mirror_ifupdown2.git/blame - ifupdown/ifupdownmain.py
mstp: performances: now globaly caching "mstpctl showportdetail <bridgename> json...
[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
ea9e3c0f
JF
451 if (ifaceobj.link_kind & ifaceLinkKind.VXLAN) \
452 and (upperifaceobj.link_kind & ifaceLinkKind.BRIDGE):
453 upperifaceobj.link_privflags |= ifaceLinkPrivFlags.BRIDGE_VXLAN
454
858a230f
RP
455 # vrf masters get processed after slaves, which means
456 # check both link_kind vrf and vrf slave
457 if ((upperifaceobj.link_kind & ifaceLinkKind.VRF) or
458 (ifaceobj.link_privflags & ifaceLinkPrivFlags.VRF_SLAVE)):
f7551dcb 459 self._set_iface_role(ifaceobj, ifaceRole.SLAVE, upperifaceobj)
858a230f 460 ifaceobj.link_privflags |= ifaceLinkPrivFlags.VRF_SLAVE
768b4ec5
RP
461 if self._link_master_slave:
462 if upperifaceobj.link_type == ifaceLinkType.LINK_MASTER:
463 ifaceobj.link_type = ifaceLinkType.LINK_SLAVE
464 else:
465 upperifaceobj.link_type = ifaceLinkType.LINK_NA
466 ifaceobj.link_type = ifaceLinkType.LINK_NA
65e0c276 467
ccbeedcd
RP
468 def dump_iface_dependency_info(self):
469 """ debug funtion to print raw dependency
470 info - lower and upper devices"""
471
472 for ifacename, ifaceobjs in self.ifaceobjdict.iteritems():
473 iobj = ifaceobjs[0]
474 self.logger.info("%s: refcnt: %d, lower: %s, upper: %s" %(ifacename,
475 self.get_iface_refcnt(ifacename),
476 str(iobj.lowerifaces) if iobj.lowerifaces else [],
477 str(iobj.upperifaces) if iobj.upperifaces else []))
478
479
7f045fd8 480 def preprocess_dependency_list(self, upperifaceobj, dlist, ops):
739f665b 481 """ We go through the dependency list and
482 delete or add interfaces from the interfaces dict by
483 applying the following rules:
dbc018d3 484 if flag DELETE_DEPENDENT_IFACES_WITH_NOCONFIG is True:
739f665b 485 we only consider devices whose configuration was
486 specified in the network interfaces file. We delete
487 any interface whose config was not specified except
488 for vlan devices. vlan devices get special treatment.
489 Even if they are not present they are created and added
490 to the ifacesdict
dbc018d3 491 elif flag DELETE_DEPENDENT_IFACES_WITH_NOCONFIG is False:
739f665b 492 we create objects for all dependent devices that are not
493 present in the ifacesdict
494 """
a6f80f0e 495 del_list = []
496
a6f80f0e 497 for d in dlist:
31a5f4c3 498 dilist = self.get_ifaceobjs(d)
d08d5f54 499 if not dilist:
7f045fd8 500 ni = None
d08d5f54 501 if self.is_iface_builtin_byname(d):
a070c90e 502 ni = self.create_n_save_ifaceobj(d,
dbc018d3
RP
503 ifacePrivFlags(True, True), True)
504 elif not self.flags.DELETE_DEPENDENT_IFACES_WITH_NOCONFIG:
505 ni = self.create_n_save_ifaceobj(d,
506 ifacePrivFlags(False, True), True)
a6f80f0e 507 else:
a6f80f0e 508 del_list.append(d)
7f045fd8
RP
509 if ni:
510 ni.add_to_upperifaces(upperifaceobj.name)
21289e4a 511 self._set_iface_role_n_kind(ni, upperifaceobj)
a6f80f0e 512 else:
513 for di in dilist:
514 di.inc_refcnt()
7f045fd8 515 di.add_to_upperifaces(upperifaceobj.name)
21289e4a 516 self._set_iface_role_n_kind(di, upperifaceobj)
a6f80f0e 517 for d in del_list:
518 dlist.remove(d)
519
4cc2df04 520 def preprocess_upperiface(self, lowerifaceobj, ulist, ops):
ccbeedcd
RP
521 for u in ulist:
522 if (lowerifaceobj.upperifaces and
523 u in lowerifaceobj.upperifaces):
524 continue
525 lowerifaceobj.add_to_upperifaces(u)
526 uifacelist = self.get_ifaceobjs(u)
527 if uifacelist:
528 for ui in uifacelist:
529 lowerifaceobj.inc_refcnt()
530 self._set_iface_role_n_kind(lowerifaceobj, ui)
531 ui.add_to_lowerifaces(lowerifaceobj.name)
4cc2df04
RP
532
533 def query_lowerifaces(self, ifaceobj, ops, ifacenames, type=None):
a6f80f0e 534 """ Gets iface dependents by calling into respective modules """
41febf89 535 ret_dlist = []
a6f80f0e 536
20dd6242 537 # Get dependents for interface by querying respective modules
ee3fcf44 538 for module in self.modules.values():
7949b8a5 539 try:
540 if ops[0] == 'query-running':
541 if (not hasattr(module,
542 'get_dependent_ifacenames_running')):
543 continue
544 dlist = module.get_dependent_ifacenames_running(ifaceobj)
545 else:
546 if (not hasattr(module, 'get_dependent_ifacenames')):
547 continue
548 dlist = module.get_dependent_ifacenames(ifaceobj,
ee3fcf44 549 ifacenames)
7949b8a5 550 except Exception, e:
551 self.logger.warn('%s: error getting dependent interfaces (%s)'
552 %(ifaceobj.name, str(e)))
553 dlist = None
554 pass
41febf89 555 if dlist: ret_dlist.extend(dlist)
84ca006f 556 return list(set(ret_dlist))
20dd6242 557
4cc2df04
RP
558 def query_upperifaces(self, ifaceobj, ops, ifacenames, type=None):
559 """ Gets iface upperifaces by calling into respective modules """
560 ret_ulist = []
561
562 # Get upperifaces for interface by querying respective modules
563 for module in self.modules.values():
564 try:
565 if ops[0] == 'query-running':
566 if (not hasattr(module,
567 'get_upper_ifacenames_running')):
568 continue
569 ulist = module.get_upper_ifacenames_running(ifaceobj)
570 else:
571 if (not hasattr(module, 'get_upper_ifacenames')):
572 continue
573 ulist = module.get_upper_ifacenames(ifaceobj, ifacenames)
574 except Exception, e:
575 self.logger.warn('%s: error getting upper interfaces (%s)'
576 %(ifaceobj.name, str(e)))
577 ulist = None
578 pass
579 if ulist: ret_ulist.extend(ulist)
580 return list(set(ret_ulist))
45ca0b6d 581
e1601369
RP
582 def populate_dependency_info(self, ops, ifacenames=None):
583 """ recursive function to generate iface dependency info """
584
585 if not ifacenames:
586 ifacenames = self.ifaceobjdict.keys()
587
588 iqueue = deque(ifacenames)
589 while iqueue:
590 i = iqueue.popleft()
591 # Go through all modules and find dependent ifaces
592 dlist = None
4cc2df04 593 ulist = None
2d8b307b
RP
594 ifaceobjs = self.get_ifaceobjs(i)
595 if not ifaceobjs:
e1601369 596 continue
4cc2df04 597 dependents_processed = False
2d8b307b
RP
598
599 # Store all dependency info in the first ifaceobj
600 # but get dependency info from all ifaceobjs
601 ifaceobj = ifaceobjs[0]
602 for iobj in ifaceobjs:
4cc2df04 603 ulist = self.query_upperifaces(iobj, ops, ifacenames)
2d8b307b 604 if iobj.lowerifaces:
4cc2df04 605 dependents_processed = True
2d8b307b 606 break
4cc2df04 607 dlist = self.query_lowerifaces(iobj, ops, ifacenames)
2d8b307b
RP
608 if dlist:
609 break
4cc2df04
RP
610 if ulist:
611 self.preprocess_upperiface(ifaceobj, ulist, ops)
4cc2df04 612 if dependents_processed:
e1601369
RP
613 continue
614 if dlist:
7f045fd8 615 self.preprocess_dependency_list(ifaceobj,
e1601369
RP
616 dlist, ops)
617 ifaceobj.lowerifaces = dlist
618 [iqueue.append(d) for d in dlist]
4cc2df04
RP
619 #if not self.dependency_graph.get(i):
620 # self.dependency_graph[i] = dlist
621
622 for i in self.ifaceobjdict.keys():
623 iobj = self.get_ifaceobj_first(i)
624 if iobj.lowerifaces:
625 self.dependency_graph[i] = iobj.lowerifaces
626 else:
627 self.dependency_graph[i] = []
e1601369 628
67cfaeb1
RP
629 if not self.blacklisted_ifaces_present:
630 return
631
632 # Walk through the dependency graph and remove blacklisted
633 # interfaces that were picked up as dependents
634 for i in self.dependency_graph.keys():
635 ifaceobj = self.get_ifaceobj_first(i)
636 if not ifaceobj:
637 continue
858a230f 638
67cfaeb1
RP
639 if ifaceobj.blacklisted and not ifaceobj.upperifaces:
640 # if blacklisted and was not picked up as a
641 # dependent of a upper interface, delete the
642 # interface from the dependency graph
643 dlist = ifaceobj.lowerifaces
644 if dlist:
645 for d in dlist:
397214a5
RP
646 difaceobjs = self.get_ifaceobjs(d)
647 if not difaceobjs:
67cfaeb1 648 continue
67cfaeb1 649 try:
397214a5
RP
650 for d in difaceobjs:
651 d.dec_refcnt()
652 d.upperifaces.remove(i)
67cfaeb1
RP
653 except:
654 self.logger.debug('error removing %s from %s upperifaces' %(i, d))
655 pass
656 self.logger.debug("populate_dependency_info: deleting blacklisted interface %s" %i)
657 del self.dependency_graph[i]
858a230f 658 continue
67cfaeb1 659
8e113d63
RP
660 def _check_config_no_repeats(self, ifaceobj):
661 """ check if object has an attribute that is
662 restricted to a single object in the system.
663 if yes, warn and return """
664 for k,v in self._cache_no_repeats.items():
665 iv = ifaceobj.config.get(k)
666 if iv and iv[0] == v:
667 self.logger.error('ignoring interface %s. ' %ifaceobj.name +
668 'Only one object with attribute ' +
669 '\'%s %s\' allowed.' %(k, v))
670 return True
671 for k, v in self.config.get('no_repeats', {}).items():
672 iv = ifaceobj.config.get(k)
673 if iv and iv[0] == v:
674 self._cache_no_repeats[k] = v
675 return False
a6f80f0e 676
2ddd65c5
RP
677 def _save_iface_squash(self, ifaceobj):
678 """ squash ifaceobjects belonging to same iface
679 into a single object """
680 if self._check_config_no_repeats(ifaceobj):
681 return
682 ifaceobj.priv_flags = ifacePrivFlags()
683 if not self._link_master_slave:
684 ifaceobj.link_type = ifaceLinkType.LINK_NA
685 currentifaceobjlist = self.ifaceobjdict.get(ifaceobj.name)
686 if not currentifaceobjlist:
687 self.ifaceobjdict[ifaceobj.name] = [ifaceobj]
688 return
689 if ifaceobj.compare(currentifaceobjlist[0]):
690 self.logger.warn('duplicate interface %s found' %ifaceobj.name)
691 return
afb367d9
RP
692 if ifaceobj.type == ifaceType.BRIDGE_VLAN:
693 self.ifaceobjdict[ifaceobj.name].append(ifaceobj)
694 else:
695 currentifaceobjlist[0].squash(ifaceobj)
2ddd65c5 696
41febf89 697 def _save_iface(self, ifaceobj):
8e113d63
RP
698 if self._check_config_no_repeats(ifaceobj):
699 return
dbc018d3 700 ifaceobj.priv_flags = ifacePrivFlags()
7e2e64fb
RP
701 if not self._link_master_slave:
702 ifaceobj.link_type = ifaceLinkType.LINK_NA
679e6567
RP
703 currentifaceobjlist = self.ifaceobjdict.get(ifaceobj.name)
704 if not currentifaceobjlist:
99ce6894
RP
705 self.ifaceobjdict[ifaceobj.name]= [ifaceobj]
706 if not self._ifaceobj_squash:
707 ifaceobj.flags |= ifaceobj.YOUNGEST_SIBLING
708 return
679e6567
RP
709 if ifaceobj.compare(currentifaceobjlist[0]):
710 self.logger.warn('duplicate interface %s found' %ifaceobj.name)
711 return
8e113d63 712 if currentifaceobjlist[0].type == ifaceobj.type:
7444feea
ST
713 currentifaceobjlist[0].flags |= ifaceobj.HAS_SIBLINGS
714 ifaceobj.flags |= ifaceobj.HAS_SIBLINGS
715 # clear the OLDEST_SIBLING from all the siblings
716 for iface in self.ifaceobjdict[ifaceobj.name]:
717 iface.flags &= ~ifaceobj.OLDEST_SIBLING
718 # current sibling is the oldest
719 ifaceobj.flags |= ifaceobj.OLDEST_SIBLING
679e6567 720 self.ifaceobjdict[ifaceobj.name].append(ifaceobj)
41febf89 721
3dcc1d0e 722 def _iface_configattr_syntax_checker(self, attrname, attrval):
d08d5f54 723 for m, mdict in self.module_attrs.items():
7949b8a5 724 if not mdict:
725 continue
d08d5f54 726 attrsdict = mdict.get('attrs')
7949b8a5 727 try:
1553a881
RP
728 a = attrsdict.get(attrname)
729 if a:
730 if a.get('deprecated'):
731 newa = a.get('new-attribute')
732 if newa:
733 self.logger.warn('attribute %s is deprecated. Use %s instead' %(attrname, newa))
734 else:
735 self.logger.warn('attribute %s is deprecated'
736 %attrname)
7949b8a5 737 return True
738 except AttributeError:
739 pass
d08d5f54 740 return False
741
3dcc1d0e 742 def _ifaceobj_syntax_checker(self, ifaceobj):
cfa06db6 743 ret = True
8e113d63 744 for attrname, attrvalue in ifaceobj.config.items():
3dcc1d0e 745 found = False
746 for k, v in self.module_attrs.items():
747 if v and v.get('attrs', {}).get(attrname):
748 found = True
749 break
750 if not found:
cfa06db6 751 ret = False
fa714fa2
ST
752 self.logger.warn('%s: unsupported attribute \'%s\'' \
753 % (ifaceobj.name, attrname))
3dcc1d0e 754 continue
cfa06db6 755 return ret
3dcc1d0e 756
14dc390d 757 def read_iface_config(self):
a6f80f0e 758 """ Reads default network interface config /etc/network/interfaces. """
cfa06db6 759 ret = True
14dc390d 760 nifaces = networkInterfaces(self.interfacesfile,
3dcc1d0e 761 self.interfacesfileiobuf,
762 self.interfacesfileformat,
14dc390d 763 template_engine=self.config.get('template_engine'),
764 template_lookuppath=self.config.get('template_lookuppath'))
2ddd65c5
RP
765 if self._ifaceobj_squash or self._ifaceobj_squash_internal:
766 nifaces.subscribe('iface_found', self._save_iface_squash)
767 else:
768 nifaces.subscribe('iface_found', self._save_iface)
3dcc1d0e 769 nifaces.subscribe('validateifaceattr',
770 self._iface_configattr_syntax_checker)
771 nifaces.subscribe('validateifaceobj', self._ifaceobj_syntax_checker)
a6f80f0e 772 nifaces.load()
cfa06db6
RP
773 if nifaces.errors or nifaces.warns:
774 ret = False
775 return ret
a6f80f0e 776
a6f80f0e 777 def read_old_iface_config(self):
14dc390d 778 """ Reads the saved iface config instead of default iface config.
779 And saved iface config is already read by the statemanager """
cb7cc592 780 self.ifaceobjdict = copy.deepcopy(self.statemanager.ifaceobjdict)
a6f80f0e 781
53b00224 782 def _load_addon_modules_config(self):
783 """ Load addon modules config file """
a6f80f0e 784
37c0543d 785 with open(self.addon_modules_configfile, 'r') as f:
786 lines = f.readlines()
787 for l in lines:
7bbc9340
RP
788 try:
789 litems = l.strip(' \n\t\r').split(',')
790 if not litems or len(litems) < 2:
791 continue
792 operation = litems[0]
793 mname = litems[1]
794 self.module_ops[operation].append(mname)
795 except Exception, e:
796 self.logger.warn('error reading line \'%s\'' %(l, str(e)))
797 continue
37c0543d 798
799 def load_addon_modules(self, modules_dir):
a6f80f0e 800 """ load python modules from modules_dir
801
802 Default modules_dir is /usr/share/ifupdownmodules
803
804 """
a6f80f0e 805 self.logger.info('loading builtin modules from %s' %modules_dir)
53b00224 806 self._load_addon_modules_config()
a6f80f0e 807 if not modules_dir in sys.path:
37c0543d 808 sys.path.append(modules_dir)
a6f80f0e 809 try:
be0b20f2 810 for op, mlist in self.module_ops.items():
d08d5f54 811 for mname in mlist:
53b00224 812 if self.modules.get(mname):
d08d5f54 813 continue
814 mpath = modules_dir + '/' + mname + '.py'
815 if os.path.exists(mpath):
816 try:
817 m = __import__(mname)
818 mclass = getattr(m, mname)
819 except:
820 raise
fc5e1735 821 minstance = mclass()
d08d5f54 822 self.modules[mname] = minstance
53b00224 823 try:
d08d5f54 824 self.module_attrs[mname] = minstance.get_modinfo()
53b00224 825 except:
826 pass
a6f80f0e 827 except:
828 raise
829
37c0543d 830 # Assign all modules to query operations
be0b20f2 831 self.module_ops['query-checkcurr'] = self.modules.keys()
832 self.module_ops['query-running'] = self.modules.keys()
833 self.module_ops['query-dependency'] = self.modules.keys()
834 self.module_ops['query'] = self.modules.keys()
835 self.module_ops['query-raw'] = self.modules.keys()
d08d5f54 836
14dc390d 837
53b00224 838 def _modules_help(self):
839 """ Prints addon modules supported syntax """
840
d08d5f54 841 indent = ' '
842 for m, mdict in self.module_attrs.items():
843 if not mdict:
844 continue
845 print('%s: %s' %(m, mdict.get('mhelp')))
846 attrdict = mdict.get('attrs')
847 if not attrdict:
848 continue
849 try:
850 for attrname, attrvaldict in attrdict.items():
851 if attrvaldict.get('compat', False):
852 continue
853 print('%s%s' %(indent, attrname))
854 print('%shelp: %s' %(indent + ' ',
855 attrvaldict.get('help', '')))
856 print ('%srequired: %s' %(indent + ' ',
857 attrvaldict.get('required', False)))
858 default = attrvaldict.get('default')
859 if default:
860 print('%sdefault: %s' %(indent + ' ', default))
861
862 validrange = attrvaldict.get('validrange')
863 if validrange:
1b0b81a2 864 print('%svalidrange: %s-%s'
7949b8a5 865 %(indent + ' ', validrange[0], validrange[1]))
d08d5f54 866
867 validvals = attrvaldict.get('validvals')
868 if validvals:
869 print('%svalidvals: %s'
870 %(indent + ' ', ','.join(validvals)))
871
872 examples = attrvaldict.get('example')
873 if not examples:
874 continue
a6f80f0e 875
d08d5f54 876 print '%sexample:' %(indent + ' ')
877 for e in examples:
878 print '%s%s' %(indent + ' ', e)
879 except:
880 pass
881 print ''
882
37c0543d 883 def load_scripts(self, modules_dir):
a6f80f0e 884 """ loading user modules from /etc/network/.
885
886 Note that previously loaded python modules override modules found
887 under /etc/network if any
888
889 """
890
37c0543d 891 self.logger.info('looking for user scripts under %s' %modules_dir)
be0b20f2 892 for op, mlist in self.script_ops.items():
d08d5f54 893 msubdir = modules_dir + '/if-%s.d' %op
894 self.logger.info('loading scripts under %s ...' %msubdir)
895 try:
896 module_list = os.listdir(msubdir)
897 for module in module_list:
898 if self.modules.get(module) is not None:
899 continue
be0b20f2 900 self.script_ops[op].append(
a6f80f0e 901 msubdir + '/' + module)
d08d5f54 902 except:
f802fe3c 903 # continue reading
904 pass
a6f80f0e 905
6e16e5ae
N
906 def _sched_ifaces(self, ifacenames, ops, skipupperifaces=False,
907 followdependents=True, sort=False):
c798b0f4 908 self.logger.debug('scheduling \'%s\' for %s'
d08d5f54 909 %(str(ops), str(ifacenames)))
7538dc77 910 self._pretty_print_ordered_dict('dependency graph',
911 self.dependency_graph)
6e16e5ae 912 ifaceScheduler.sched_ifaces(self, ifacenames, ops,
c798b0f4 913 dependency_graph=self.dependency_graph,
d08d5f54 914 order=ifaceSchedulerFlags.INORDER
915 if 'down' in ops[0]
c798b0f4 916 else ifaceSchedulerFlags.POSTORDER,
a4912b99 917 followdependents=followdependents,
e308cb82 918 skipupperifaces=skipupperifaces,
dbc018d3 919 sort=True if (sort or self.flags.IFACE_CLASS) else False)
2009513f 920 return ifaceScheduler.get_sched_status()
a6f80f0e 921
41febf89
RP
922 def _render_ifacename(self, ifacename):
923 new_ifacenames = []
679e6567 924 vlan_match = re.match("^([\d]+)-([\d]+)", ifacename)
41febf89
RP
925 if vlan_match:
926 vlan_groups = vlan_match.groups()
927 if vlan_groups[0] and vlan_groups[1]:
679e6567 928 [new_ifacenames.append('%d' %v)
41febf89
RP
929 for v in range(int(vlan_groups[0]),
930 int(vlan_groups[1])+1)]
931 return new_ifacenames
932
933 def _preprocess_ifacenames(self, ifacenames):
a6f80f0e 934 """ validates interface list for config existance.
935
936 returns -1 if one or more interface not found. else, returns 0
937
938 """
41febf89 939 new_ifacenames = []
a6f80f0e 940 err_iface = ''
941 for i in ifacenames:
31a5f4c3 942 ifaceobjs = self.get_ifaceobjs(i)
943 if not ifaceobjs:
41febf89 944 # if name not available, render interface name and check again
679e6567 945 rendered_ifacenames = utils.expand_iface_range(i)
41febf89
RP
946 if rendered_ifacenames:
947 for ri in rendered_ifacenames:
948 ifaceobjs = self.get_ifaceobjs(ri)
949 if not ifaceobjs:
950 err_iface += ' ' + ri
951 else:
952 new_ifacenames.append(ri)
953 else:
954 err_iface += ' ' + i
955 else:
956 new_ifacenames.append(i)
fe0a57d3 957 if err_iface:
31c58787 958 raise Exception('cannot find interfaces:%s' %err_iface)
41febf89 959 return new_ifacenames
a6f80f0e 960
53b00224 961 def _iface_whitelisted(self, auto, allow_classes, excludepats, ifacename):
a6f80f0e 962 """ Checks if interface is whitelisted depending on set of parameters.
963
a6f80f0e 964 interfaces are checked against the allow_classes and auto lists.
965
966 """
1042b709 967
0532f0a3
RP
968 ret = True
969
19e2bf8c 970 # Check if interface matches the exclude patter
fe0a57d3 971 if excludepats:
3e8ee54f 972 for e in excludepats:
d08d5f54 973 if re.search(e, ifacename):
0532f0a3 974 ret = False
31a5f4c3 975 ifaceobjs = self.get_ifaceobjs(ifacename)
976 if not ifaceobjs:
0532f0a3
RP
977 if ret:
978 self.logger.debug('iface %s' %ifacename + ' not found')
979 return ret
67cfaeb1 980 # If matched exclude pattern, return false
0532f0a3
RP
981 if not ret:
982 for i in ifaceobjs:
983 i.blacklisted = True
67cfaeb1 984 self.blacklisted_ifaces_present = True
0532f0a3
RP
985 return ret
986 # Check if interface belongs to the class
67cfaeb1 987 # the user is interested in, if not return false
fe0a57d3 988 if allow_classes:
19e2bf8c 989 ret = False
a6f80f0e 990 for i in ifaceobjs:
62ddec8b 991 if i.classes:
3e8ee54f 992 common = Set([allow_classes]).intersection(
62ddec8b 993 Set(i.classes))
fe0a57d3 994 if common:
0532f0a3 995 ret = True
0532f0a3 996 if not ret:
19e2bf8c
RP
997 # If a class was requested and interface does not belong
998 # to the class, only then mark the ifaceobjs as blacklisted
999 self.blacklisted_ifaces_present = True
1000 for i in ifaceobjs:
1001 i.blacklisted = True
1002 return ret
67cfaeb1
RP
1003 # If the user has requested auto class, check if the interface
1004 # is marked auto
d08d5f54 1005 if auto:
19e2bf8c 1006 ret = False
a6f80f0e 1007 for i in ifaceobjs:
62ddec8b 1008 if i.auto:
0532f0a3 1009 ret = True
19e2bf8c
RP
1010 if not ret:
1011 # If auto was requested and interface was not marked auto,
1012 # only then mark all of them as blacklisted
1013 self.blacklisted_ifaces_present = True
1014 for i in ifaceobjs:
0532f0a3
RP
1015 i.blacklisted = True
1016 return ret
a6f80f0e 1017
53b00224 1018 def _compat_conv_op_to_mode(self, op):
1019 """ Returns old op name to work with existing scripts """
1020 if op == 'pre-up':
1021 return 'start'
1022 elif op == 'pre-down':
1023 return 'stop'
1024 else:
1025 return op
1026
a6f80f0e 1027 def generate_running_env(self, ifaceobj, op):
739f665b 1028 """ Generates a dictionary with env variables required for
1029 an interface. Used to support script execution for interfaces.
a6f80f0e 1030 """
1031
1032 cenv = None
62ddec8b 1033 iface_env = ifaceobj.env
1034 if iface_env:
a6f80f0e 1035 cenv = os.environ
d08d5f54 1036 if cenv:
a6f80f0e 1037 cenv.update(iface_env)
1038 else:
1039 cenv = iface_env
53b00224 1040 cenv['MODE'] = self._compat_conv_op_to_mode(op)
a6f80f0e 1041 return cenv
1042
53b00224 1043 def _save_state(self):
dbc018d3
RP
1044 if (not self.flags.STATEMANAGER_ENABLE or
1045 not self.flags.STATEMANAGER_UPDATE):
20dd6242 1046 return
1047 try:
1048 # Update persistant iface states
1049 self.statemanager.save_state()
1050 except Exception, e:
1051 if self.logger.isEnabledFor(logging.DEBUG):
1052 t = sys.exc_info()[2]
1053 traceback.print_tb(t)
1054 self.logger.warning('error saving state (%s)' %str(e))
1055
2da58137
RP
1056 def set_type(self, type):
1057 if type == 'iface':
1058 self.type = ifaceType.IFACE
1059 elif type == 'vlan':
1060 self.type = ifaceType.BRIDGE_VLAN
1061 else:
1062 self.type = ifaceType.UNKNOWN
1063
a070c90e
RP
1064 def _process_delay_admin_state_queue(self, op):
1065 if not self._delay_admin_state_iface_queue:
1066 return
1067 if op == 'up':
1068 func = self.link_up
1069 elif op == 'down':
1070 func = self.link_down
1071 else:
1072 return
1073 for i in self._delay_admin_state_iface_queue:
1074 try:
1075 if self.link_exists(i):
1076 func(i)
1077 except Exception, e:
1078 self.logger.warn(str(e))
1079 pass
1080
d08d5f54 1081 def up(self, ops, auto=False, allow_classes=None, ifacenames=None,
2da58137 1082 excludepats=None, printdependency=None, syntaxcheck=False,
ad25e7bb 1083 type=None, skipupperifaces=False):
2c0ad8b3
RP
1084 """This brings the interface(s) up
1085
1086 Args:
41febf89
RP
1087 ops (list): list of ops to perform on the interface(s).
1088 Eg: ['pre-up', 'up', 'post-up'
2c0ad8b3
RP
1089
1090 Kwargs:
1091 auto (bool): act on interfaces marked auto
1092 allow_classes (list): act on interfaces belonging to classes in the list
1093 ifacenames (list): act on interfaces specified in this list
1094 excludepats (list): list of patterns of interfaces to exclude
1095 syntaxcheck (bool): only perform syntax check
1096 """
53b00224 1097
2da58137
RP
1098 self.set_type(type)
1099
5ee3e1a8 1100 if allow_classes:
dbc018d3
RP
1101 self.flags.IFACE_CLASS = True
1102 if not self.flags.ADDONS_ENABLE:
1103 self.flags.STATEMANAGER_UPDATE = False
d08d5f54 1104 if auto:
dbc018d3
RP
1105 self.flags.ALL = True
1106 self.flags.WITH_DEPENDS = True
d08d5f54 1107 try:
cfa06db6 1108 iface_read_ret = self.read_iface_config()
62ddec8b 1109 except Exception:
d08d5f54 1110 raise
a6f80f0e 1111
31a5f4c3 1112 if ifacenames:
41febf89 1113 ifacenames = self._preprocess_ifacenames(ifacenames)
a6f80f0e 1114
1115 # if iface list not given by user, assume all from config file
31a5f4c3 1116 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
a6f80f0e 1117
1118 # filter interfaces based on auto and allow classes
cca03c30 1119 filtered_ifacenames = [i for i in ifacenames
53b00224 1120 if self._iface_whitelisted(auto, allow_classes,
d08d5f54 1121 excludepats, i)]
fe0a57d3 1122 if not filtered_ifacenames:
d08d5f54 1123 raise Exception('no ifaces found matching given allow lists')
a6f80f0e 1124
20dd6242 1125 if printdependency:
c798b0f4 1126 self.populate_dependency_info(ops, filtered_ifacenames)
d08d5f54 1127 self.print_dependency(filtered_ifacenames, printdependency)
739f665b 1128 return
cca03c30 1129 else:
c798b0f4 1130 self.populate_dependency_info(ops)
1131
cfa06db6
RP
1132 # If only syntax check was requested, return here.
1133 # return here because we want to make sure most
1134 # errors above are caught and reported.
21289e4a 1135 if syntaxcheck:
cfa06db6
RP
1136 if not iface_read_ret:
1137 raise Exception()
21289e4a
RP
1138 return
1139
525f0a30 1140 try:
2009513f
RP
1141 ret = self._sched_ifaces(filtered_ifacenames, ops,
1142 skipupperifaces=skipupperifaces,
1143 followdependents=True
1144 if self.flags.WITH_DEPENDS else False)
525f0a30 1145 finally:
a070c90e 1146 self._process_delay_admin_state_queue('up')
fc5e1735 1147 if not ifupdownflags.flags.DRYRUN and self.flags.ADDONS_ENABLE:
525f0a30 1148 self._save_state()
a6f80f0e 1149
2009513f
RP
1150 if not iface_read_ret or not ret:
1151 raise Exception()
1152
d08d5f54 1153 def down(self, ops, auto=False, allow_classes=None, ifacenames=None,
2da58137
RP
1154 excludepats=None, printdependency=None, usecurrentconfig=False,
1155 type=None):
53b00224 1156 """ down an interface """
1157
2da58137
RP
1158 self.set_type(type)
1159
5ee3e1a8 1160 if allow_classes:
dbc018d3
RP
1161 self.flags.IFACE_CLASS = True
1162 if not self.flags.ADDONS_ENABLE:
1163 self.flags.STATEMANAGER_UPDATE = False
d08d5f54 1164 if auto:
dbc018d3
RP
1165 self.flags.ALL = True
1166 self.flags.WITH_DEPENDS = True
5c721925 1167 # For down we need to look at old state, unless usecurrentconfig
1168 # is set
dbc018d3 1169 if (not usecurrentconfig and self.flags.STATEMANAGER_ENABLE and
53b00224 1170 self.statemanager.ifaceobjdict):
31a5f4c3 1171 # Since we are using state manager objects,
1172 # skip the updating of state manager objects
5c721925 1173 self.logger.debug('Looking at old state ..')
d08d5f54 1174 self.read_old_iface_config()
fe0a57d3 1175 else:
d08d5f54 1176 # If no old state available
d08d5f54 1177 try:
1178 self.read_iface_config()
1179 except Exception, e:
1180 raise Exception('error reading iface config (%s)' %str(e))
d08d5f54 1181 if ifacenames:
1182 # If iface list is given by the caller, always check if iface
1183 # is present
31c58787 1184 try:
41febf89 1185 ifacenames = self._preprocess_ifacenames(ifacenames)
31c58787 1186 except Exception, e:
1187 raise Exception('%s' %str(e) +
1188 ' (interface was probably never up ?)')
1189
d08d5f54 1190 # if iface list not given by user, assume all from config file
fe0a57d3 1191 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
53b00224 1192
d08d5f54 1193 # filter interfaces based on auto and allow classes
1194 filtered_ifacenames = [i for i in ifacenames
53b00224 1195 if self._iface_whitelisted(auto, allow_classes,
d08d5f54 1196 excludepats, i)]
fe0a57d3 1197 if not filtered_ifacenames:
c0071225 1198 raise Exception('no ifaces found matching given allow lists ' +
41febf89 1199 '(or interfaces were probably never up ?)')
14dc390d 1200
d08d5f54 1201 if printdependency:
99b212b0 1202 self.populate_dependency_info(ops, filtered_ifacenames)
d08d5f54 1203 self.print_dependency(filtered_ifacenames, printdependency)
1204 return
99b212b0 1205 else:
1206 self.populate_dependency_info(ops)
525f0a30 1207
1208 try:
a4912b99 1209 self._sched_ifaces(filtered_ifacenames, ops,
dbc018d3
RP
1210 followdependents=True
1211 if self.flags.WITH_DEPENDS else False)
525f0a30 1212 finally:
a070c90e 1213 self._process_delay_admin_state_queue('down')
fc5e1735 1214 if not ifupdownflags.flags.DRYRUN and self.flags.ADDONS_ENABLE:
525f0a30 1215 self._save_state()
d08d5f54 1216
4c56a7c1
RP
1217 def query(self, ops, auto=False, format_list=False, allow_classes=None,
1218 ifacenames=None,
739f665b 1219 excludepats=None, printdependency=None,
6e16e5ae 1220 format='native', type=None):
53b00224 1221 """ query an interface """
1222
2da58137
RP
1223 self.set_type(type)
1224
2ddd65c5
RP
1225 # Let us forget internal squashing when it comes to
1226 # ifquery. It can surprise people relying of ifquery
1227 # output
1228 self._ifaceobj_squash_internal = False
1229
5ee3e1a8 1230 if allow_classes:
dbc018d3
RP
1231 self.flags.IFACE_CLASS = True
1232 if self.flags.STATEMANAGER_ENABLE and ops[0] == 'query-savedstate':
5c721925 1233 return self.statemanager.dump_pretty(ifacenames)
dbc018d3 1234 self.flags.STATEMANAGER_UPDATE = False
d08d5f54 1235 if auto:
739f665b 1236 self.logger.debug('setting flag ALL')
dbc018d3
RP
1237 self.flags.ALL = True
1238 self.flags.WITH_DEPENDS = True
739f665b 1239
d08d5f54 1240 if ops[0] == 'query-syntax':
53b00224 1241 self._modules_help()
d08d5f54 1242 return
1243 elif ops[0] == 'query-running':
739f665b 1244 # create fake devices to all dependents that dont have config
dbc018d3
RP
1245 map(lambda i: self.create_n_save_ifaceobj(i,
1246 ifacePrivFlags(False, True)), ifacenames)
739f665b 1247 else:
1248 try:
1249 self.read_iface_config()
1250 except Exception:
1251 raise
1252
53b00224 1253 if ifacenames and ops[0] != 'query-running':
41febf89
RP
1254 # If iface list is given, always check if iface is present
1255 ifacenames = self._preprocess_ifacenames(ifacenames)
739f665b 1256
1257 # if iface list not given by user, assume all from config file
31a5f4c3 1258 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
739f665b 1259
1260 # filter interfaces based on auto and allow classes
d08d5f54 1261 if ops[0] == 'query-running':
739f665b 1262 filtered_ifacenames = ifacenames
1263 else:
1264 filtered_ifacenames = [i for i in ifacenames
53b00224 1265 if self._iface_whitelisted(auto, allow_classes,
d08d5f54 1266 excludepats, i)]
fe0a57d3 1267 if not filtered_ifacenames:
739f665b 1268 raise Exception('no ifaces found matching ' +
1269 'given allow lists')
37c0543d 1270
e1601369 1271 self.populate_dependency_info(ops)
d08d5f54 1272 if ops[0] == 'query-dependency' and printdependency:
1273 self.print_dependency(filtered_ifacenames, printdependency)
1274 return
739f665b 1275
4c56a7c1
RP
1276 if format_list and (ops[0] == 'query' or ops[0] == 'query-raw'):
1277 return self.print_ifaceobjs_list(filtered_ifacenames)
1278
634764bd 1279 if ops[0] == 'query' and not ifupdownflags.flags.WITHDEFAULTS:
75730152 1280 return self.print_ifaceobjs_pretty(filtered_ifacenames, format)
1281 elif ops[0] == 'query-raw':
1282 return self.print_ifaceobjs_raw(filtered_ifacenames)
1283
6e16e5ae 1284 ret = self._sched_ifaces(filtered_ifacenames, ops,
dbc018d3
RP
1285 followdependents=True
1286 if self.flags.WITH_DEPENDS else False)
739f665b 1287
634764bd
RP
1288 if ops[0] == 'query' and ifupdownflags.flags.WITHDEFAULTS:
1289 return self.print_ifaceobjs_pretty(filtered_ifacenames, format)
1290 elif ops[0] == 'query-checkcurr':
d08d5f54 1291 ret = self.print_ifaceobjscurr_pretty(filtered_ifacenames, format)
739f665b 1292 if ret != 0:
1293 # if any of the object has an error, signal that silently
1294 raise Exception('')
d08d5f54 1295 elif ops[0] == 'query-running':
1296 self.print_ifaceobjsrunning_pretty(filtered_ifacenames, format)
739f665b 1297 return
1298
2da58137
RP
1299 def _reload_currentlyup(self, upops, downops, auto=True, allow=None,
1300 ifacenames=None, excludepats=None, usecurrentconfig=False,
cfa06db6 1301 syntaxcheck=False, **extra_args):
2da58137 1302 """ reload currently up interfaces """
c0071225 1303 new_ifaceobjdict = {}
739f665b 1304
2da58137
RP
1305 # Override auto to true
1306 auto = True
2da58137 1307 try:
cfa06db6 1308 iface_read_ret = self.read_iface_config()
2da58137
RP
1309 except:
1310 raise
2da58137
RP
1311 if not self.ifaceobjdict:
1312 self.logger.warn("nothing to reload ..exiting.")
1313 return
2da58137 1314 already_up_ifacenames = []
1042b709
RP
1315 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
1316 filtered_ifacenames = [i for i in ifacenames
1317 if self._iface_whitelisted(auto, allow,
1318 excludepats, i)]
1319
2da58137
RP
1320 # generate dependency graph of interfaces
1321 self.populate_dependency_info(upops)
cfa06db6
RP
1322
1323 # If only syntax check was requested, return here.
1324 # return here because we want to make sure most
1325 # errors above are caught and reported.
1326 if syntaxcheck:
1327 if not iface_read_ret:
1328 raise Exception()
1329 return
1330
dbc018d3 1331 if (not usecurrentconfig and self.flags.STATEMANAGER_ENABLE
2da58137
RP
1332 and self.statemanager.ifaceobjdict):
1333 already_up_ifacenames = self.statemanager.ifaceobjdict.keys()
1334
2da58137
RP
1335 # Get already up interfaces that still exist in the interfaces file
1336 already_up_ifacenames_not_present = Set(
1337 already_up_ifacenames).difference(ifacenames)
1338 already_up_ifacenames_still_present = Set(
1339 already_up_ifacenames).difference(
1340 already_up_ifacenames_not_present)
1341 interfaces_to_up = Set(already_up_ifacenames_still_present).union(
1342 filtered_ifacenames)
1343
1344 if (already_up_ifacenames_not_present and
1345 self.config.get('ifreload_currentlyup_down_notpresent') == '1'):
1346 self.logger.info('reload: schedule down on interfaces: %s'
1347 %str(already_up_ifacenames_not_present))
1348
1349 # Save a copy of new iface objects and dependency_graph
1350 new_ifaceobjdict = dict(self.ifaceobjdict)
1351 new_dependency_graph = dict(self.dependency_graph)
1352
1353 # old interface config is read into self.ifaceobjdict
1354 self.read_old_iface_config()
1355
1356 # reinitialize dependency graph
1357 self.dependency_graph = OrderedDict({})
1042b709
RP
1358 falready_up_ifacenames_not_present = [i for i in
1359 already_up_ifacenames_not_present
1360 if self._iface_whitelisted(auto, allow,
1361 excludepats, i)]
2da58137 1362 self.populate_dependency_info(downops,
1042b709
RP
1363 falready_up_ifacenames_not_present)
1364 self._sched_ifaces(falready_up_ifacenames_not_present, downops,
e308cb82 1365 followdependents=False, sort=True)
2da58137
RP
1366 else:
1367 self.logger.debug('no interfaces to down ..')
1368
1369 # Now, run 'up' with new config dict
1370 # reset statemanager update flag to default
e308cb82 1371 if auto:
dbc018d3
RP
1372 self.flags.ALL = True
1373 self.flags.WITH_DEPENDS = True
2da58137 1374 if new_ifaceobjdict:
3d44fbd0 1375 # and now, ifaceobjdict is back to current config
2da58137
RP
1376 self.ifaceobjdict = new_ifaceobjdict
1377 self.dependency_graph = new_dependency_graph
1378
1379 if not self.ifaceobjdict:
1380 return
1381 self.logger.info('reload: scheduling up on interfaces: %s'
1382 %str(interfaces_to_up))
2009513f
RP
1383 ret = self._sched_ifaces(interfaces_to_up, upops,
1384 followdependents=True
1385 if self.flags.WITH_DEPENDS else False)
fc5e1735 1386 if ifupdownflags.flags.DRYRUN:
2da58137
RP
1387 return
1388 self._save_state()
1389
2009513f
RP
1390 if not iface_read_ret or not ret:
1391 raise Exception()
1392
2da58137
RP
1393 def _reload_default(self, upops, downops, auto=False, allow=None,
1394 ifacenames=None, excludepats=None, usecurrentconfig=False,
cfa06db6 1395 syntaxcheck=False, **extra_args):
2da58137 1396 """ reload interface config """
2da58137 1397 new_ifaceobjdict = {}
739f665b 1398
1399 try:
cfa06db6 1400 iface_read_ret = self.read_iface_config()
20dd6242 1401 except:
739f665b 1402 raise
1403
c0071225
RP
1404 if not self.ifaceobjdict:
1405 self.logger.warn("nothing to reload ..exiting.")
1406 return
1042b709
RP
1407
1408 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
1409 new_filtered_ifacenames = [i for i in ifacenames
1410 if self._iface_whitelisted(auto, allow,
1411 excludepats, i)]
37c0543d 1412 # generate dependency graph of interfaces
c798b0f4 1413 self.populate_dependency_info(upops)
1042b709 1414
cfa06db6
RP
1415 # If only syntax check was requested, return here.
1416 # return here because we want to make sure most
1417 # errors above are caught and reported.
1418 if syntaxcheck:
1419 if not iface_read_ret:
1420 raise Exception()
1421 return
1422
dbc018d3 1423 if (not usecurrentconfig and self.flags.STATEMANAGER_ENABLE
14dc390d 1424 and self.statemanager.ifaceobjdict):
1425 # Save a copy of new iface objects and dependency_graph
1426 new_ifaceobjdict = dict(self.ifaceobjdict)
1427 new_dependency_graph = dict(self.dependency_graph)
37c0543d 1428
dbc018d3
RP
1429 self.ifaceobjdict = OrderedDict({})
1430 self.dependency_graph = OrderedDict({})
1431
739f665b 1432 # if old state is present, read old state and mark op for 'down'
1433 # followed by 'up' aka: reload
37c0543d 1434 # old interface config is read into self.ifaceobjdict
739f665b 1435 self.read_old_iface_config()
1436 op = 'reload'
1437 else:
1438 # oldconfig not available, continue with 'up' with new config
1439 op = 'up'
05ac52f0
RP
1440 new_ifaceobjdict = self.ifaceobjdict
1441 new_dependency_graph = self.dependency_graph
739f665b 1442
fe0a57d3 1443 if op == 'reload' and ifacenames:
93b399fb 1444 ifacenames = self.ifaceobjdict.keys()
1042b709
RP
1445 old_filtered_ifacenames = [i for i in ifacenames
1446 if self._iface_whitelisted(auto, allow,
d08d5f54 1447 excludepats, i)]
e308cb82 1448
dbc018d3
RP
1449 # generate dependency graph of old interfaces,
1450 # This should make sure built in interfaces are
1451 # populated. disable check shared dependents as an optimization.
1452 # these are saved interfaces and dependency for these
1453 # have been checked before they became part of saved state.
62f2caa4
RP
1454 try:
1455 self.flags.CHECK_SHARED_DEPENDENTS = False
1456 self.populate_dependency_info(upops)
1457 self.flags.CHECK_SHARED_DEPENDENTS = True
1458 except Exception, e:
1459 self.logger.info("error generating dependency graph for "
1460 "saved interfaces (%s)" %str(e))
1461 pass
1462
dbc018d3 1463 # make sure we pick up built-in interfaces
e308cb82
RP
1464 # if config file had 'ifreload_down_changed' variable
1465 # set, also look for interfaces that changed to down them
1466 down_changed = int(self.config.get('ifreload_down_changed', '1'))
1467
37c0543d 1468 # Generate the interface down list
1469 # Interfaces that go into the down list:
1470 # - interfaces that were present in last config and are not
1471 # present in the new config
1472 # - interfaces that were changed between the last and current
1473 # config
37c0543d 1474 ifacedownlist = []
dbc018d3 1475 for ifname in self.ifaceobjdict.keys():
2da58137 1476 lastifaceobjlist = self.ifaceobjdict.get(ifname)
dbc018d3
RP
1477 if not self.is_ifaceobj_builtin(lastifaceobjlist[0]):
1478 # if interface is not built-in and is not in
1479 # old filtered ifacenames
1480 if ifname not in old_filtered_ifacenames:
1481 continue
37c0543d 1482 objidx = 0
37c0543d 1483 # If interface is not present in the new file
1484 # append it to the down list
53b00224 1485 newifaceobjlist = new_ifaceobjdict.get(ifname)
1486 if not newifaceobjlist:
37c0543d 1487 ifacedownlist.append(ifname)
1488 continue
21289e4a
RP
1489 # If ifaceobj was present in the old interfaces file,
1490 # and does not have a config in the new interfaces file
1491 # but has been picked up as a dependent of another
1492 # interface, catch it here. This catches a common error
1493 # for example: remove a bond section from the interfaces
1494 # file, but leave it around as a bridge port
1495 # XXX: Ideally its better to just add it to the
1496 # ifacedownlist. But we will be cautious here
1497 # and just print a warning
1498 if (self.is_ifaceobj_noconfig(newifaceobjlist[0]) and
dbc018d3 1499 not self.is_ifaceobj_builtin(newifaceobjlist[0]) and
21289e4a
RP
1500 lastifaceobjlist[0].is_config_present()):
1501 self.logger.warn('%s: misconfig ? removed but still exists as a dependency of %s' %(newifaceobjlist[objidx].name,
1502 str(newifaceobjlist[objidx].upperifaces)))
26434da6
RP
1503 if not down_changed:
1504 continue
53b00224 1505 if len(newifaceobjlist) != len(lastifaceobjlist):
37c0543d 1506 ifacedownlist.append(ifname)
1507 continue
e308cb82
RP
1508
1509 # If interface has changed between the current file
1510 # and the last installed append it to the down list
37c0543d 1511 # compare object list
53b00224 1512 for objidx in range(0, len(lastifaceobjlist)):
1513 oldobj = lastifaceobjlist[objidx]
1514 newobj = newifaceobjlist[objidx]
ca3f4fc7 1515 if not newobj.compare(oldobj):
37c0543d 1516 ifacedownlist.append(ifname)
1517 continue
1518
fe0a57d3 1519 if ifacedownlist:
2da58137 1520 self.logger.info('reload: scheduling down on interfaces: %s'
739f665b 1521 %str(ifacedownlist))
20dd6242 1522 # reinitialize dependency graph
1523 self.dependency_graph = OrderedDict({})
dbc018d3 1524
37c0543d 1525 # Generate dependency info for old config
62f2caa4 1526 self.flags.CHECK_SHARED_DEPENDENTS = False
14dc390d 1527 self.populate_dependency_info(downops, ifacedownlist)
62f2caa4
RP
1528 self.flags.CHECK_SHARED_DEPENDENTS = True
1529
a070c90e 1530 try:
dbc018d3
RP
1531 # XXX: Hack to skip checking upperifaces during down.
1532 # the dependency list is not complete here
1533 # and we dont want to down the upperiface.
1534 # Hence during reload, set this to true.
1535 # This is being added to avoid a failure in
1536 # scheduler._check_upperifaces when we are dowing
1537 # a builtin bridge port
1538 self.flags.SCHED_SKIP_CHECK_UPPERIFACES = True
a4912b99 1539 self._sched_ifaces(ifacedownlist, downops,
e308cb82
RP
1540 followdependents=False,
1541 sort=True)
a070c90e
RP
1542 except Exception, e:
1543 self.logger.error(str(e))
1544 pass
1545 finally:
dbc018d3 1546 self.flags.SCHED_SKIP_CHECK_UPPERIFACES = False
a070c90e 1547 self._process_delay_admin_state_queue('down')
37c0543d 1548 else:
1549 self.logger.debug('no interfaces to down ..')
739f665b 1550
20dd6242 1551 # Now, run 'up' with new config dict
1552 # reset statemanager update flag to default
c0071225 1553 if not new_ifaceobjdict:
aa4e3022 1554 self.logger.debug('no interfaces to up')
c0071225 1555 return
e308cb82
RP
1556
1557 if auto:
dbc018d3
RP
1558 self.flags.ALL = True
1559 self.flags.WITH_DEPENDS = True
3d44fbd0 1560 # and now, we are back to the current config in ifaceobjdict
53b00224 1561 self.ifaceobjdict = new_ifaceobjdict
1562 self.dependency_graph = new_dependency_graph
c798b0f4 1563
2da58137 1564 self.logger.info('reload: scheduling up on interfaces: %s'
1042b709 1565 %str(new_filtered_ifacenames))
8a360f1b 1566 ifupdownflags.flags.CACHE = True
a070c90e 1567 try:
2009513f
RP
1568 ret = self._sched_ifaces(new_filtered_ifacenames, upops,
1569 followdependents=True
1570 if self.flags.WITH_DEPENDS else False)
a070c90e
RP
1571 except Exception, e:
1572 self.logger.error(str(e))
1573 pass
1574 finally:
1575 self._process_delay_admin_state_queue('up')
fc5e1735 1576 if ifupdownflags.flags.DRYRUN:
e37ad4a6 1577 return
53b00224 1578 self._save_state()
a6f80f0e 1579
2009513f
RP
1580 if not iface_read_ret or not ret:
1581 raise Exception()
1582
2da58137
RP
1583 def reload(self, *args, **kargs):
1584 """ reload interface config """
2da58137
RP
1585 self.logger.debug('reloading interface config ..')
1586 if kargs.get('currentlyup', False):
1587 self._reload_currentlyup(*args, **kargs)
1588 else:
1589 self._reload_default(*args, **kargs)
1590
7538dc77 1591 def _pretty_print_ordered_dict(self, prefix, argdict):
525f0a30 1592 outbuf = prefix + ' {\n'
53b00224 1593 for k, vlist in argdict.items():
525f0a30 1594 outbuf += '\t%s : %s\n' %(k, str(vlist))
7538dc77 1595 self.logger.debug(outbuf + '}')
a6f80f0e 1596
53b00224 1597 def print_dependency(self, ifacenames, format):
1598 """ prints iface dependency information """
a6f80f0e 1599
53b00224 1600 if not ifacenames:
1601 ifacenames = self.ifaceobjdict.keys()
1602 if format == 'list':
1603 for k,v in self.dependency_graph.items():
1604 print '%s : %s' %(k, str(v))
1605 elif format == 'dot':
1606 indegrees = {}
1607 map(lambda i: indegrees.update({i :
1608 self.get_iface_refcnt(i)}),
1609 self.dependency_graph.keys())
1610 graph.generate_dots(self.dependency_graph, indegrees)
a6f80f0e 1611
4c56a7c1
RP
1612 def print_ifaceobjs_list(self, ifacenames):
1613 for i in ifacenames:
1614 print i
1615
739f665b 1616 def print_ifaceobjs_raw(self, ifacenames):
53b00224 1617 """ prints raw lines for ifaces from config file """
1618
739f665b 1619 for i in ifacenames:
31a5f4c3 1620 for ifaceobj in self.get_ifaceobjs(i):
75730152 1621 if (self.is_ifaceobj_builtin(ifaceobj) or
1622 not ifaceobj.is_config_present()):
1623 continue
1624 ifaceobj.dump_raw(self.logger)
739f665b 1625 print '\n'
dbc018d3 1626 if self.flags.WITH_DEPENDS and not self.flags.ALL:
62ddec8b 1627 dlist = ifaceobj.lowerifaces
fe0a57d3 1628 if not dlist: continue
53b00224 1629 self.print_ifaceobjs_raw(dlist)
739f665b 1630
2cd06f78 1631 def _get_ifaceobjs_pretty(self, ifacenames, ifaceobjs, running=False):
1632 """ returns iface obj list """
53b00224 1633
a6f80f0e 1634 for i in ifacenames:
31a5f4c3 1635 for ifaceobj in self.get_ifaceobjs(i):
2cd06f78 1636 if ((not running and self.is_ifaceobj_noconfig(ifaceobj)) or
1637 (running and not ifaceobj.is_config_present())):
75730152 1638 continue
2cd06f78 1639 ifaceobjs.append(ifaceobj)
dbc018d3 1640 if self.flags.WITH_DEPENDS and not self.flags.ALL:
62ddec8b 1641 dlist = ifaceobj.lowerifaces
fe0a57d3 1642 if not dlist: continue
2cd06f78 1643 self._get_ifaceobjs_pretty(dlist, ifaceobjs, running)
739f665b 1644
2cd06f78 1645 def print_ifaceobjs_pretty(self, ifacenames, format='native'):
1646 """ pretty prints iface in format given by keyword arg format """
eab25b7c 1647
2cd06f78 1648 ifaceobjs = []
1649 self._get_ifaceobjs_pretty(ifacenames, ifaceobjs)
1650 if not ifaceobjs: return
1651 if format == 'json':
3dcc1d0e 1652 print json.dumps(ifaceobjs, cls=ifaceJsonEncoder,
1653 indent=4, separators=(',', ': '))
2cd06f78 1654 else:
2da58137
RP
1655 expand = int(self.config.get('ifquery_ifacename_expand_range', '0'))
1656 for i in ifaceobjs:
1657 if not expand and (i.flags & iface.IFACERANGE_ENTRY):
1658 # print only the first one
1659 if i.flags & iface.IFACERANGE_START:
1660 i.dump_pretty(use_realname=True)
1661 else:
1662 i.dump_pretty()
53b00224 1663
2cd06f78 1664 def _get_ifaceobjscurr_pretty(self, ifacenames, ifaceobjs):
eab25b7c 1665 ret = 0
a6f80f0e 1666 for i in ifacenames:
923290bd 1667 ifaceobjscurr = self.get_ifaceobjcurr(i)
1668 if not ifaceobjscurr: continue
1669 for ifaceobj in ifaceobjscurr:
1670 if (ifaceobj.status == ifaceStatus.NOTFOUND or
1671 ifaceobj.status == ifaceStatus.ERROR):
1672 ret = 1
1673 if self.is_ifaceobj_noconfig(ifaceobj):
1674 continue
1675 ifaceobjs.append(ifaceobj)
dbc018d3 1676 if self.flags.WITH_DEPENDS and not self.flags.ALL:
923290bd 1677 dlist = ifaceobj.lowerifaces
1678 if not dlist: continue
1679 dret = self._get_ifaceobjscurr_pretty(dlist, ifaceobjs)
1680 if dret: ret = 1
2cd06f78 1681 return ret
1682
1683 def print_ifaceobjscurr_pretty(self, ifacenames, format='native'):
1684 """ pretty prints current running state of interfaces with status.
1685
1686 returns 1 if any of the interface has an error,
1687 else returns 0
1688 """
1689
1690 ifaceobjs = []
1691 ret = self._get_ifaceobjscurr_pretty(ifacenames, ifaceobjs)
1692 if not ifaceobjs: return
307e06bb
RP
1693
1694 # override ifaceStatusUserStrs
1695 ifaceStatusUserStrs.SUCCESS = self.config.get('ifquery_check_success_str', _success_sym)
1696 ifaceStatusUserStrs.ERROR = self.config.get('ifquery_check_error_str', _error_sym)
1697 ifaceStatusUserStrs.UNKNOWN = self.config.get('ifquery_check_unknown_str', '')
2cd06f78 1698 if format == 'json':
307e06bb
RP
1699 print json.dumps(ifaceobjs, cls=ifaceJsonEncoderWithStatus,
1700 indent=2, separators=(',', ': '))
2cd06f78 1701 else:
fb10449e 1702 map(lambda i: i.dump_pretty(with_status=True), ifaceobjs)
eab25b7c 1703 return ret
a6f80f0e 1704
d08d5f54 1705 def print_ifaceobjsrunning_pretty(self, ifacenames, format='native'):
53b00224 1706 """ pretty prints iface running state """
1707
2cd06f78 1708 ifaceobjs = []
1709 self._get_ifaceobjs_pretty(ifacenames, ifaceobjs, running=True)
1710 if not ifaceobjs: return
1711 if format == 'json':
1712 print json.dumps(ifaceobjs, cls=ifaceJsonEncoder, indent=2,
1713 separators=(',', ': '))
1714 else:
1715 map(lambda i: i.dump_pretty(), ifaceobjs)
53b00224 1716
1717 def _dump(self):
1718 print 'ifupdown main object dump'
1719 print self.pp.pprint(self.modules)
1720 print self.pp.pprint(self.ifaceobjdict)
1721
1722 def _dump_ifaceobjs(self, ifacenames):
1723 for i in ifacenames:
1724 ifaceobjs = self.get_ifaceobjs(i)
1725 for i in ifaceobjs:
1726 i.dump(self.logger)
1727 print '\n'