]> git.proxmox.com Git - mirror_ifupdown2.git/blame - ifupdown/ifupdownmain.py
addons: bridge: warn/err if bridge-access is missing under vxlan bridge VA port
[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 *
b54179d2 27from exceptions import *
3e8ee54f 28from sets import Set
a6f80f0e 29
482b2fab
JF
30from ipaddr import IPNetwork, IPv4Network, IPv6Network, IPAddress, IPv4Address, IPv6Address
31
2c0ad8b3
RP
32"""
33.. module:: ifupdownmain
34:synopsis: main module for ifupdown package
35
36.. moduleauthor:: Roopa Prabhu <roopa@cumulusnetworks.com>
37
38"""
39
86fc62e2 40_tickmark = u'\u2713'
41_crossmark = u'\u2717'
e74d01e1
RP
42_success_sym = '(%s)' %_tickmark
43_error_sym = '(%s)' %_crossmark
86fc62e2 44
dbc018d3 45class ifupdownMainFlags():
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
d2b35716
RP
115 if ((ifaceobj.link_kind & ifaceLinkKind.VRF) or
116 (ifaceobj.link_privflags & ifaceLinkPrivFlags.VRF_SLAVE)):
c8a3b44e 117 return
9858b0a6
RP
118 # if not a logical interface and addr method is manual,
119 # ignore link admin state changes
120 if (ifaceobj.addr_method == 'manual' and
121 not ifaceobj.link_kind):
a070c90e
RP
122 return
123 if self._delay_admin_state:
124 self._delay_admin_state_iface_queue.append(ifaceobj.name)
125 return
7f045fd8
RP
126 # If this object is a link slave, ie its link is controlled
127 # by its link master interface, then dont set the link state.
128 # But do allow user to change state of the link if the interface
129 # is already with its link master (hence the master check).
7e2e64fb 130 if ifaceobj.link_type == ifaceLinkType.LINK_SLAVE:
7f045fd8 131 return
a070c90e 132 if not self.link_exists(ifaceobj.name):
7e2e64fb 133 return
9858b0a6
RP
134 if ifaceobj.link_privflags & ifaceLinkPrivFlags.KEEP_LINK_DOWN:
135 # user has asked to explicitly keep the link down,
136 # so, force link down
137 self.logger.info('%s: keeping link down due to user config' %ifaceobj.name)
138 self.link_down(ifaceobj.name)
139 return
1a6bda12 140 self.link_up(ifaceobj.name)
be0b20f2 141
142 def run_down(self, ifaceobj):
d2b35716
RP
143 if ((ifaceobj.link_kind & ifaceLinkKind.VRF) or
144 (ifaceobj.link_privflags & ifaceLinkPrivFlags.VRF_SLAVE)):
9219cef3 145 return
0ba04b38
RP
146 # Skip link sets on ifaceobjs of type 'vlan' (used for l2 attrs)
147 # there is no real interface behind it
496745cd
RP
148 if ifaceobj.type == ifaceType.BRIDGE_VLAN:
149 return
9858b0a6
RP
150 # if not a logical interface and addr method is manual,
151 # ignore link admin state changes
152 if (ifaceobj.addr_method == 'manual' and
153 not ifaceobj.link_kind):
a070c90e
RP
154 return
155 if self._delay_admin_state:
156 self._delay_admin_state_iface_queue.append(ifaceobj.name)
157 return
7f045fd8
RP
158 # If this object is a link slave, ie its link is controlled
159 # by its link master interface, then dont set the link state.
160 # But do allow user to change state of the link if the interface
161 # is already with its link master (hence the master check).
7e2e64fb
RP
162 if ifaceobj.link_type == ifaceLinkType.LINK_SLAVE:
163 return
a070c90e 164 if not self.link_exists(ifaceobj.name):
7e2e64fb 165 return
1a6bda12 166 self.link_down(ifaceobj.name)
be0b20f2 167
31a5f4c3 168 # ifupdown object interface operation handlers
be0b20f2 169 ops_handlers = OrderedDict([('up', run_up),
170 ('down', run_down)])
a6f80f0e 171
cb7cc592 172 def run_sched_ifaceobj_posthook(self, ifaceobj, op):
dbc018d3
RP
173 if (ifaceobj.priv_flags and (ifaceobj.priv_flags.BUILTIN or
174 ifaceobj.priv_flags.NOCONFIG)):
5c721925 175 return
dbc018d3 176 if self.flags.STATEMANAGER_UPDATE:
cb7cc592 177 self.statemanager.ifaceobj_sync(ifaceobj, op)
31a5f4c3 178
179 # ifupdown object interface scheduler pre and posthooks
180 sched_hooks = {'posthook' : run_sched_ifaceobj_posthook}
181
14dc390d 182 def __init__(self, config={},
183 force=False, dryrun=False, nowait=False,
cca03c30 184 perfmode=False, withdepends=False, njobs=1,
14dc390d 185 cache=False, addons_enable=True, statemanager_enable=True,
3dcc1d0e 186 interfacesfile='/etc/network/interfaces',
187 interfacesfileiobuf=None,
6e16e5ae
N
188 interfacesfileformat='native',
189 withdefaults=False):
2c0ad8b3
RP
190 """This member function initializes the ifupdownmain object.
191
192 Kwargs:
193 config (dict): config dict from /etc/network/ifupdown2/ifupdown2.conf
194 force (bool): force interface configuration
195 dryrun (bool): dryrun interface configuration
196 withdepends (bool): apply interface configuration on all depends
197 interfacesfile (str): interfaces file. default is /etc/network/interfaces
198 interfacesfileformat (str): default is 'native'. Other choices are 'json'
199
200 Raises:
201 AttributeError, KeyError """
202
a6f80f0e 203 self.logger = logging.getLogger('ifupdown')
fc5e1735
RP
204 ifupdownflags.flags.FORCE = force
205 ifupdownflags.flags.DRYRUN = dryrun
6e16e5ae 206 ifupdownflags.flags.WITHDEFAULTS = withdefaults
fc5e1735
RP
207 ifupdownflags.flags.NOWAIT = nowait
208 ifupdownflags.flags.PERFMODE = perfmode
209 ifupdownflags.flags.CACHE = cache
d2b35716 210 ifupdownflags.flags.WITH_DEPENDS = withdepends
fc5e1735 211
dbc018d3 212 # Can be used to provide hints for caching
fc5e1735 213 ifupdownflags.flags.CACHE_FLAGS = 0x0
dbc018d3
RP
214
215 self.flags = ifupdownMainFlags()
216
dbc018d3 217 self.flags.STATEMANAGER_ENABLE = statemanager_enable
14dc390d 218 self.interfacesfile = interfacesfile
3dcc1d0e 219 self.interfacesfileiobuf = interfacesfileiobuf
220 self.interfacesfileformat = interfacesfileformat
14dc390d 221 self.config = config
222 self.logger.debug(self.config)
67cfaeb1 223 self.blacklisted_ifaces_present = False
a690dfae 224
2da58137
RP
225 self.type = ifaceType.UNKNOWN
226
dbc018d3
RP
227 self.flags.DELETE_DEPENDENT_IFACES_WITH_NOCONFIG = False
228 self.flags.ADDONS_ENABLE = addons_enable
eab25b7c 229
a6f80f0e 230 self.ifaces = OrderedDict()
eab25b7c 231 self.njobs = njobs
a6f80f0e 232 self.pp = pprint.PrettyPrinter(indent=4)
37c0543d 233 self.modules = OrderedDict({})
d08d5f54 234 self.module_attrs = {}
b6b8bd2b
JF
235 self.overridden_ifupdown_scripts = []
236
60dfcbdf
RP
237 if self.config.get('addon_python_modules_support', '1') == '1':
238 self.load_addon_modules(self.addon_modules_dir)
239 if self.config.get('addon_scripts_support', '0') == '1':
e938bfec 240 self.load_scripts(self.scripts_dir)
d08d5f54 241 self.dependency_graph = OrderedDict({})
a6f80f0e 242
8e113d63
RP
243 self._cache_no_repeats = {}
244
dbc018d3 245 if self.flags.STATEMANAGER_ENABLE:
20dd6242 246 try:
55072bd1 247 self.statemanager = statemanager.statemanager_api
20dd6242 248 self.statemanager.read_saved_state()
249 except Exception, e:
250 # XXX Maybe we should continue by ignoring old state
251 self.logger.warning('error reading state (%s)' %str(e))
252 raise
253 else:
dbc018d3 254 self.flags.STATEMANAGER_UPDATE = False
a070c90e
RP
255 self._delay_admin_state = True if self.config.get(
256 'delay_admin_state_change', '0') == '1' else False
257 self._delay_admin_state_iface_queue = []
cebe79c9
RP
258 if self._delay_admin_state:
259 self.logger.info('\'delay_admin_state_change\' is set. admin ' +
260 'state changes will be delayed till the end.')
261
262 self._link_master_slave = True if self.config.get(
a070c90e 263 'link_master_slave', '0') == '1' else False
cebe79c9
RP
264 if self._link_master_slave:
265 self.logger.info('\'link_master_slave\' is set. slave admin ' +
266 'state changes will be delayed till the ' +
267 'masters admin state change.')
a6f80f0e 268
2ddd65c5
RP
269 # squash iface objects for same interface both internal and
270 # external representation. It is off by default.
99ce6894
RP
271 self._ifaceobj_squash = True if self.config.get(
272 'ifaceobj_squash', '0') == '1' else False
273
2ddd65c5
RP
274 # squash iface objects for same interface internal
275 # representation only. External representation as seen by ifquery
276 # will continue to see multiple iface stanzas if it was specified
277 # that way by the user. It is on by default.
278 self._ifaceobj_squash_internal = True if self.config.get(
279 'ifaceobj_squash_internal', '1') == '1' else False
280
0582f185
RP
281 # initialize global config object with config passed by the user
282 # This makes config available to addon modules
283 ifupdownConfig.config = self.config
284
482b2fab
JF
285 self.validate_keywords = {
286 '<mac>': self._keyword_mac,
287 '<text>': self._keyword_text,
288 '<ipv4>': self._keyword_ipv4,
289 '<ipv6>': self._keyword_ipv6,
2c592263 290 '<ip>': self._keyword_ip,
482b2fab
JF
291 '<number>': self._keyword_number,
292 '<interface>': self._keyword_interface,
293 '<ipv4-vrf-text>': self._keyword_ipv4_vrf_text,
294 '<number-ipv4-list>': self._keyword_number_ipv4_list,
295 '<interface-list>': self._keyword_interface_list,
296 '<ipv4/prefixlen>': self._keyword_ipv4_prefixlen,
297 '<ipv6/prefixlen>': self._keyword_ipv6_prefixlen,
2c592263 298 '<ip/prefixlen>': self._keyword_ip_prefixlen,
482b2fab
JF
299 '<number-range-list>': self._keyword_number_range_list,
300 '<interface-range-list>': self._keyword_interface_range_list,
2c592263 301 '<mac-ip/prefixlen-list>': self._keyword_mac_ip_prefixlen_list,
482b2fab
JF
302 '<number-interface-list>': self._keyword_number_interface_list,
303 '<interface-yes-no-list>': self._keyword_interface_yes_no_list,
304 '<interface-yes-no-0-1-list>': self._keyword_interface_yes_no_0_1_list,
305 '<interface-yes-no-auto-list>': self._keyword_interface_yes_no_auto_list,
306 }
307
61c4d724
RP
308 def link_master_slave_ignore_error(self, errorstr):
309 # If link master slave flag is set,
310 # there may be cases where the lowerdev may not be
311 # up resulting in 'Network is down' error
312 # This can happen if the lowerdev is a LINK_SLAVE
313 # of another interface which is not up yet
314 # example of such a case:
315 # bringing up a vlan on a bond interface and the bond
316 # is a LINK_SLAVE of a bridge (in other words the bond is
317 # part of a bridge) which is not up yet
318 if self._link_master_slave:
a5bd56f2 319 if 'Network is down' in errorstr:
61c4d724
RP
320 return True
321 return False
322
31a5f4c3 323 def get_ifaceobjs(self, ifacename):
a6f80f0e 324 return self.ifaceobjdict.get(ifacename)
325
a9ab1b4f
RP
326 def get_ifaceobjs_saved(self, ifacename):
327 """ Return ifaceobjects from statemanager """
dbc018d3 328 if self.flags.STATEMANAGER_ENABLE:
a9ab1b4f
RP
329 return self.statemanager.get_ifaceobjs(ifacename)
330 else:
a5bd56f2 331 return None
a9ab1b4f 332
31a5f4c3 333 def get_ifaceobj_first(self, ifacename):
334 ifaceobjs = self.get_ifaceobjs(ifacename)
335 if ifaceobjs:
a6f80f0e 336 return ifaceobjs[0]
337 return None
338
c798b0f4 339 def get_ifacenames(self):
340 return self.ifaceobjdict.keys()
341
a6f80f0e 342 def get_iface_obj_last(self, ifacename):
343 return self.ifaceobjdict.get(ifacename)[-1]
344
a9ab1b4f 345
8c13865c
RP
346 def must_follow_upperifaces(self, ifacename):
347 #
348 # XXX: This bleeds the knowledge of iface
349 # types in the infrastructure module.
350 # Cant think of a better fix at the moment.
351 # In future maybe the module can set a flag
352 # to indicate if we should follow upperifaces
353 #
354 ifaceobj = self.get_ifaceobj_first(ifacename)
cb46a208 355 if ifaceobj.type == ifaceType.BRIDGE_VLAN:
8c13865c
RP
356 return False
357 return True
358
53b00224 359 def create_n_save_ifaceobj(self, ifacename, priv_flags=None,
360 increfcnt=False):
361 """ creates a iface object and adds it to the iface dictionary """
362 ifaceobj = iface()
363 ifaceobj.name = ifacename
364 ifaceobj.priv_flags = priv_flags
365 ifaceobj.auto = True
f3b69969
RP
366 if not self._link_master_slave:
367 ifaceobj.link_type = ifaceLinkType.LINK_NA
53b00224 368 if increfcnt:
369 ifaceobj.inc_refcnt()
370 self.ifaceobjdict[ifacename] = [ifaceobj]
371 return ifaceobj
372
d08d5f54 373 def create_n_save_ifaceobjcurr(self, ifaceobj):
923290bd 374 """ creates a copy of iface object and adds it to the iface
375 dict containing current iface objects
53b00224 376 """
739f665b 377 ifaceobjcurr = iface()
53b00224 378 ifaceobjcurr.name = ifaceobj.name
cb46a208 379 ifaceobjcurr.type = ifaceobj.type
62ddec8b 380 ifaceobjcurr.lowerifaces = ifaceobj.lowerifaces
dbc018d3 381 ifaceobjcurr.priv_flags = copy.deepcopy(ifaceobj.priv_flags)
2cd06f78 382 ifaceobjcurr.auto = ifaceobj.auto
923290bd 383 self.ifaceobjcurrdict.setdefault(ifaceobj.name,
384 []).append(ifaceobjcurr)
d08d5f54 385 return ifaceobjcurr
a6f80f0e 386
923290bd 387 def get_ifaceobjcurr(self, ifacename, idx=0):
388 ifaceobjlist = self.ifaceobjcurrdict.get(ifacename)
389 if not ifaceobjlist:
390 return None
391 if not idx:
392 return ifaceobjlist
393 else:
394 return ifaceobjlist[idx]
a6f80f0e 395
739f665b 396 def get_ifaceobjrunning(self, ifacename):
397 return self.ifaceobjrunningdict.get(ifacename)
398
a6f80f0e 399 def get_iface_refcnt(self, ifacename):
53b00224 400 """ Return iface ref count """
a6f80f0e 401 max = 0
31a5f4c3 402 ifaceobjs = self.get_ifaceobjs(ifacename)
20dd6242 403 if not ifaceobjs:
404 return 0
a6f80f0e 405 for i in ifaceobjs:
62ddec8b 406 if i.refcnt > max:
407 max = i.refcnt
a6f80f0e 408 return max
409
d08d5f54 410 def is_iface_builtin_byname(self, ifacename):
cca03c30 411 """ Returns true if iface name is a builtin interface.
a6f80f0e 412
cca03c30 413 A builtin interface is an interface which ifupdown understands.
414 The following are currently considered builtin ifaces:
415 - vlan interfaces in the format <ifacename>.<vlanid>
a6f80f0e 416 """
d08d5f54 417 return '.' in ifacename
a6f80f0e 418
37c0543d 419 def is_ifaceobj_builtin(self, ifaceobj):
420 """ Returns true if iface name is a builtin interface.
421
422 A builtin interface is an interface which ifupdown understands.
423 The following are currently considered builtin ifaces:
424 - vlan interfaces in the format <ifacename>.<vlanid>
425 """
7ef04d1b
RP
426 if (ifaceobj.priv_flags and ifaceobj.priv_flags.BUILTIN):
427 return True
428 return False
37c0543d 429
430 def is_ifaceobj_noconfig(self, ifaceobj):
53b00224 431 """ Returns true if iface object did not have a user defined config.
37c0543d 432
433 These interfaces appear only when they are dependents of interfaces
434 which have user defined config
435 """
dbc018d3 436 return (ifaceobj.priv_flags and ifaceobj.priv_flags.NOCONFIG)
37c0543d 437
d08d5f54 438 def is_iface_noconfig(self, ifacename):
439 """ Returns true if iface has no config """
37c0543d 440
31a5f4c3 441 ifaceobj = self.get_ifaceobj_first(ifacename)
d08d5f54 442 if not ifaceobj: return True
d08d5f54 443 return self.is_ifaceobj_noconfig(ifaceobj)
444
45ca0b6d 445 def check_shared_dependents(self, ifaceobj, dlist):
858a230f 446 """ ABSOLETE: Check if dlist intersects with any other
45ca0b6d
RP
447 interface with slave dependents.
448 example: bond and bridges.
449 This function logs such errors """
450 setdlist = Set(dlist)
451 for ifacename, ifacedlist in self.dependency_graph.items():
452 if not ifacedlist:
453 continue
454 check_depends = False
455 iobjs = self.get_ifaceobjs(ifacename)
dbc018d3
RP
456 if not iobjs:
457 continue
45ca0b6d
RP
458 for i in iobjs:
459 if (i.dependency_type == ifaceDependencyType.MASTER_SLAVE):
460 check_depends = True
461 if check_depends:
462 common = Set(ifacedlist).intersection(setdlist)
463 if common:
1cda1e43 464 self.logger.error('misconfig..?. iface %s and %s '
45ca0b6d 465 %(ifaceobj.name, ifacename) +
1cda1e43 466 'seem to share dependents/ports %s' %str(list(common)))
45ca0b6d 467
f7551dcb 468 def _set_iface_role(self, ifaceobj, role, upperifaceobj):
858a230f 469 if (self.flags.CHECK_SHARED_DEPENDENTS and
f7551dcb
RP
470 (ifaceobj.role & ifaceRole.SLAVE) and
471 (role == ifaceRole.SLAVE) and (upperifaceobj.role == ifaceRole.MASTER)):
858a230f
RP
472 self.logger.error("misconfig..? %s %s is enslaved to multiple interfaces %s"
473 %(ifaceobj.name,
474 ifaceLinkPrivFlags.get_all_str(ifaceobj.link_privflags), str(ifaceobj.upperifaces)))
475 ifaceobj.set_status(ifaceStatus.ERROR)
476 return
477 ifaceobj.role = role
478
65e0c276 479 def _set_iface_role_n_kind(self, ifaceobj, upperifaceobj):
858a230f 480
9858b0a6
RP
481 # If addr_method is set and link is not a logical interface,
482 # set flag KEEP_LINK_DOWN. addr_method == 'manual' only applies to
483 # logical interfaces.
484 if (ifaceobj.addr_method == 'manual' and not ifaceobj.link_kind):
485 ifaceobj.link_privflags |= ifaceLinkPrivFlags.KEEP_LINK_DOWN
486
65e0c276 487 if (upperifaceobj.link_kind & ifaceLinkKind.BOND):
f7551dcb 488 self._set_iface_role(ifaceobj, ifaceRole.SLAVE, upperifaceobj)
858a230f
RP
489 ifaceobj.link_privflags |= ifaceLinkPrivFlags.BOND_SLAVE
490
65e0c276 491 if (upperifaceobj.link_kind & ifaceLinkKind.BRIDGE):
f7551dcb 492 self._set_iface_role(ifaceobj, ifaceRole.SLAVE, upperifaceobj)
858a230f
RP
493 ifaceobj.link_privflags |= ifaceLinkPrivFlags.BRIDGE_PORT
494
ea9e3c0f
JF
495 if (ifaceobj.link_kind & ifaceLinkKind.VXLAN) \
496 and (upperifaceobj.link_kind & ifaceLinkKind.BRIDGE):
497 upperifaceobj.link_privflags |= ifaceLinkPrivFlags.BRIDGE_VXLAN
498
858a230f
RP
499 # vrf masters get processed after slaves, which means
500 # check both link_kind vrf and vrf slave
501 if ((upperifaceobj.link_kind & ifaceLinkKind.VRF) or
502 (ifaceobj.link_privflags & ifaceLinkPrivFlags.VRF_SLAVE)):
f7551dcb 503 self._set_iface_role(ifaceobj, ifaceRole.SLAVE, upperifaceobj)
858a230f 504 ifaceobj.link_privflags |= ifaceLinkPrivFlags.VRF_SLAVE
768b4ec5
RP
505 if self._link_master_slave:
506 if upperifaceobj.link_type == ifaceLinkType.LINK_MASTER:
507 ifaceobj.link_type = ifaceLinkType.LINK_SLAVE
508 else:
509 upperifaceobj.link_type = ifaceLinkType.LINK_NA
510 ifaceobj.link_type = ifaceLinkType.LINK_NA
65e0c276 511
ccbeedcd
RP
512 def dump_iface_dependency_info(self):
513 """ debug funtion to print raw dependency
514 info - lower and upper devices"""
515
516 for ifacename, ifaceobjs in self.ifaceobjdict.iteritems():
517 iobj = ifaceobjs[0]
518 self.logger.info("%s: refcnt: %d, lower: %s, upper: %s" %(ifacename,
519 self.get_iface_refcnt(ifacename),
520 str(iobj.lowerifaces) if iobj.lowerifaces else [],
521 str(iobj.upperifaces) if iobj.upperifaces else []))
522
523
7f045fd8 524 def preprocess_dependency_list(self, upperifaceobj, dlist, ops):
739f665b 525 """ We go through the dependency list and
526 delete or add interfaces from the interfaces dict by
527 applying the following rules:
dbc018d3 528 if flag DELETE_DEPENDENT_IFACES_WITH_NOCONFIG is True:
739f665b 529 we only consider devices whose configuration was
530 specified in the network interfaces file. We delete
531 any interface whose config was not specified except
532 for vlan devices. vlan devices get special treatment.
533 Even if they are not present they are created and added
534 to the ifacesdict
dbc018d3 535 elif flag DELETE_DEPENDENT_IFACES_WITH_NOCONFIG is False:
739f665b 536 we create objects for all dependent devices that are not
537 present in the ifacesdict
538 """
a6f80f0e 539 del_list = []
540
a6f80f0e 541 for d in dlist:
31a5f4c3 542 dilist = self.get_ifaceobjs(d)
d08d5f54 543 if not dilist:
7f045fd8 544 ni = None
d08d5f54 545 if self.is_iface_builtin_byname(d):
a070c90e 546 ni = self.create_n_save_ifaceobj(d,
dbc018d3
RP
547 ifacePrivFlags(True, True), True)
548 elif not self.flags.DELETE_DEPENDENT_IFACES_WITH_NOCONFIG:
549 ni = self.create_n_save_ifaceobj(d,
550 ifacePrivFlags(False, True), True)
a6f80f0e 551 else:
a6f80f0e 552 del_list.append(d)
7f045fd8
RP
553 if ni:
554 ni.add_to_upperifaces(upperifaceobj.name)
21289e4a 555 self._set_iface_role_n_kind(ni, upperifaceobj)
a6f80f0e 556 else:
557 for di in dilist:
558 di.inc_refcnt()
7f045fd8 559 di.add_to_upperifaces(upperifaceobj.name)
21289e4a 560 self._set_iface_role_n_kind(di, upperifaceobj)
a6f80f0e 561 for d in del_list:
562 dlist.remove(d)
563
4cc2df04 564 def preprocess_upperiface(self, lowerifaceobj, ulist, ops):
ccbeedcd
RP
565 for u in ulist:
566 if (lowerifaceobj.upperifaces and
567 u in lowerifaceobj.upperifaces):
568 continue
569 lowerifaceobj.add_to_upperifaces(u)
570 uifacelist = self.get_ifaceobjs(u)
571 if uifacelist:
572 for ui in uifacelist:
573 lowerifaceobj.inc_refcnt()
574 self._set_iface_role_n_kind(lowerifaceobj, ui)
575 ui.add_to_lowerifaces(lowerifaceobj.name)
4cc2df04
RP
576
577 def query_lowerifaces(self, ifaceobj, ops, ifacenames, type=None):
a6f80f0e 578 """ Gets iface dependents by calling into respective modules """
41febf89 579 ret_dlist = []
a6f80f0e 580
20dd6242 581 # Get dependents for interface by querying respective modules
ee3fcf44 582 for module in self.modules.values():
7949b8a5 583 try:
584 if ops[0] == 'query-running':
585 if (not hasattr(module,
586 'get_dependent_ifacenames_running')):
587 continue
588 dlist = module.get_dependent_ifacenames_running(ifaceobj)
589 else:
590 if (not hasattr(module, 'get_dependent_ifacenames')):
591 continue
592 dlist = module.get_dependent_ifacenames(ifaceobj,
ee3fcf44 593 ifacenames)
7949b8a5 594 except Exception, e:
595 self.logger.warn('%s: error getting dependent interfaces (%s)'
596 %(ifaceobj.name, str(e)))
597 dlist = None
598 pass
41febf89 599 if dlist: ret_dlist.extend(dlist)
84ca006f 600 return list(set(ret_dlist))
20dd6242 601
4cc2df04
RP
602 def query_upperifaces(self, ifaceobj, ops, ifacenames, type=None):
603 """ Gets iface upperifaces by calling into respective modules """
604 ret_ulist = []
605
606 # Get upperifaces for interface by querying respective modules
607 for module in self.modules.values():
608 try:
609 if ops[0] == 'query-running':
610 if (not hasattr(module,
611 'get_upper_ifacenames_running')):
612 continue
613 ulist = module.get_upper_ifacenames_running(ifaceobj)
614 else:
615 if (not hasattr(module, 'get_upper_ifacenames')):
616 continue
617 ulist = module.get_upper_ifacenames(ifaceobj, ifacenames)
618 except Exception, e:
619 self.logger.warn('%s: error getting upper interfaces (%s)'
620 %(ifaceobj.name, str(e)))
621 ulist = None
622 pass
623 if ulist: ret_ulist.extend(ulist)
624 return list(set(ret_ulist))
45ca0b6d 625
e1601369
RP
626 def populate_dependency_info(self, ops, ifacenames=None):
627 """ recursive function to generate iface dependency info """
628
629 if not ifacenames:
630 ifacenames = self.ifaceobjdict.keys()
631
632 iqueue = deque(ifacenames)
633 while iqueue:
634 i = iqueue.popleft()
635 # Go through all modules and find dependent ifaces
636 dlist = None
4cc2df04 637 ulist = None
2d8b307b
RP
638 ifaceobjs = self.get_ifaceobjs(i)
639 if not ifaceobjs:
e1601369 640 continue
4cc2df04 641 dependents_processed = False
2d8b307b
RP
642
643 # Store all dependency info in the first ifaceobj
644 # but get dependency info from all ifaceobjs
645 ifaceobj = ifaceobjs[0]
646 for iobj in ifaceobjs:
4cc2df04 647 ulist = self.query_upperifaces(iobj, ops, ifacenames)
2d8b307b 648 if iobj.lowerifaces:
4cc2df04 649 dependents_processed = True
2d8b307b 650 break
4cc2df04 651 dlist = self.query_lowerifaces(iobj, ops, ifacenames)
2d8b307b
RP
652 if dlist:
653 break
4cc2df04
RP
654 if ulist:
655 self.preprocess_upperiface(ifaceobj, ulist, ops)
4cc2df04 656 if dependents_processed:
e1601369
RP
657 continue
658 if dlist:
7f045fd8 659 self.preprocess_dependency_list(ifaceobj,
e1601369
RP
660 dlist, ops)
661 ifaceobj.lowerifaces = dlist
662 [iqueue.append(d) for d in dlist]
4cc2df04
RP
663 #if not self.dependency_graph.get(i):
664 # self.dependency_graph[i] = dlist
665
666 for i in self.ifaceobjdict.keys():
667 iobj = self.get_ifaceobj_first(i)
736e4b0d
RP
668 if (not iobj.link_kind and
669 not (iobj.link_privflags & ifaceLinkPrivFlags.LOOPBACK) and
670 iobj.name == 'lo'):
671 iobj.link_privflags |= ifaceLinkPrivFlags.LOOPBACK
4cc2df04
RP
672 if iobj.lowerifaces:
673 self.dependency_graph[i] = iobj.lowerifaces
674 else:
675 self.dependency_graph[i] = []
e1601369 676
67cfaeb1
RP
677 if not self.blacklisted_ifaces_present:
678 return
679
680 # Walk through the dependency graph and remove blacklisted
681 # interfaces that were picked up as dependents
682 for i in self.dependency_graph.keys():
683 ifaceobj = self.get_ifaceobj_first(i)
684 if not ifaceobj:
685 continue
858a230f 686
67cfaeb1
RP
687 if ifaceobj.blacklisted and not ifaceobj.upperifaces:
688 # if blacklisted and was not picked up as a
689 # dependent of a upper interface, delete the
690 # interface from the dependency graph
691 dlist = ifaceobj.lowerifaces
692 if dlist:
693 for d in dlist:
397214a5
RP
694 difaceobjs = self.get_ifaceobjs(d)
695 if not difaceobjs:
67cfaeb1 696 continue
67cfaeb1 697 try:
397214a5
RP
698 for d in difaceobjs:
699 d.dec_refcnt()
700 d.upperifaces.remove(i)
67cfaeb1
RP
701 except:
702 self.logger.debug('error removing %s from %s upperifaces' %(i, d))
703 pass
704 self.logger.debug("populate_dependency_info: deleting blacklisted interface %s" %i)
705 del self.dependency_graph[i]
858a230f 706 continue
67cfaeb1 707
8e113d63
RP
708 def _check_config_no_repeats(self, ifaceobj):
709 """ check if object has an attribute that is
710 restricted to a single object in the system.
711 if yes, warn and return """
712 for k,v in self._cache_no_repeats.items():
713 iv = ifaceobj.config.get(k)
714 if iv and iv[0] == v:
715 self.logger.error('ignoring interface %s. ' %ifaceobj.name +
716 'Only one object with attribute ' +
717 '\'%s %s\' allowed.' %(k, v))
718 return True
719 for k, v in self.config.get('no_repeats', {}).items():
720 iv = ifaceobj.config.get(k)
721 if iv and iv[0] == v:
722 self._cache_no_repeats[k] = v
723 return False
a6f80f0e 724
2ddd65c5
RP
725 def _save_iface_squash(self, ifaceobj):
726 """ squash ifaceobjects belonging to same iface
727 into a single object """
728 if self._check_config_no_repeats(ifaceobj):
729 return
730 ifaceobj.priv_flags = ifacePrivFlags()
731 if not self._link_master_slave:
732 ifaceobj.link_type = ifaceLinkType.LINK_NA
733 currentifaceobjlist = self.ifaceobjdict.get(ifaceobj.name)
734 if not currentifaceobjlist:
735 self.ifaceobjdict[ifaceobj.name] = [ifaceobj]
736 return
737 if ifaceobj.compare(currentifaceobjlist[0]):
738 self.logger.warn('duplicate interface %s found' %ifaceobj.name)
739 return
7b98c26f
JF
740 for obj in self.ifaceobjdict[ifaceobj.name]:
741 if obj.type == ifaceobj.type:
742 obj.squash(ifaceobj)
743 return
744 self.ifaceobjdict[ifaceobj.name].append(ifaceobj)
2ddd65c5 745
41febf89 746 def _save_iface(self, ifaceobj):
8e113d63
RP
747 if self._check_config_no_repeats(ifaceobj):
748 return
dbc018d3 749 ifaceobj.priv_flags = ifacePrivFlags()
7e2e64fb
RP
750 if not self._link_master_slave:
751 ifaceobj.link_type = ifaceLinkType.LINK_NA
679e6567
RP
752 currentifaceobjlist = self.ifaceobjdict.get(ifaceobj.name)
753 if not currentifaceobjlist:
99ce6894
RP
754 self.ifaceobjdict[ifaceobj.name]= [ifaceobj]
755 if not self._ifaceobj_squash:
756 ifaceobj.flags |= ifaceobj.YOUNGEST_SIBLING
757 return
679e6567
RP
758 if ifaceobj.compare(currentifaceobjlist[0]):
759 self.logger.warn('duplicate interface %s found' %ifaceobj.name)
760 return
8e113d63 761 if currentifaceobjlist[0].type == ifaceobj.type:
7444feea
ST
762 currentifaceobjlist[0].flags |= ifaceobj.HAS_SIBLINGS
763 ifaceobj.flags |= ifaceobj.HAS_SIBLINGS
764 # clear the OLDEST_SIBLING from all the siblings
765 for iface in self.ifaceobjdict[ifaceobj.name]:
766 iface.flags &= ~ifaceobj.OLDEST_SIBLING
767 # current sibling is the oldest
768 ifaceobj.flags |= ifaceobj.OLDEST_SIBLING
679e6567 769 self.ifaceobjdict[ifaceobj.name].append(ifaceobj)
41febf89 770
482b2fab
JF
771 def _keyword_text(self, value, validrange=None):
772 return isinstance(value, str) and len(value) > 0
773
774 def _keyword_mac(self, value, validrange=None):
775 if value.strip().startswith('ether'):
776 value = value.strip()[6:]
777 return re.match('[0-9a-f]{1,2}([-:])[0-9a-f]{1,2}(\\1[0-9a-f]{1,2}){4}$',
778 value.lower())
779
780 def _keyword_check_list(self, _list, obj, limit=None):
781 try:
782 if limit and limit > 0:
783 for i in xrange(0, limit):
784 obj(_list[i])
785 return len(_list) == limit
786 else:
787 for elem in _list:
788 obj(elem)
789 return True
790 except Exception as e:
791 self.logger.debug('keyword: check list: %s' % str(e))
792 return False
793
794 def _keyword_ipv4(self, value, validrange=None):
795 return self._keyword_check_list(value.split(), IPv4Address, limit=1)
796
797 def _keyword_ipv4_prefixlen(self, value, validrange=None):
798 return self._keyword_check_list(value.split(), IPv4Network, limit=1)
799
800 def _keyword_ipv6(self, value, validrange=None):
801 return self._keyword_check_list(value.split(), IPv6Address, limit=1)
802
803 def _keyword_ipv6_prefixlen(self, value, validrange=None):
804 return self._keyword_check_list(value.split(), IPv6Network, limit=1)
805
2c592263 806 def _keyword_ip(self, value, validrange=None):
482b2fab
JF
807 return self._keyword_check_list(value.split(), IPAddress, limit=1)
808
2c592263 809 def _keyword_ip_prefixlen(self, value, validrange=None):
482b2fab
JF
810 return self._keyword_check_list(value.split(), IPNetwork, limit=1)
811
2c592263 812 def _keyword_mac_ip_prefixlen_list(self, value, validrange=None):
482b2fab 813 """
2c592263 814 <mac> <ip> [<ip> ...]
482b2fab
JF
815 ex: address-virtual 00:11:22:33:44:01 11.0.1.1/24 11.0.1.2/24
816 """
817 try:
818 res = value.split()
819 if len(res) < 2:
820 return False
821 if not self._keyword_mac(res[0]):
822 return False
823 for ip in res[1:]:
2c592263 824 if not self._keyword_ip_prefixlen(ip):
482b2fab
JF
825 return False
826 return True
827 except Exception as e:
828 self.logger.debug('keyword: mac ipaddr prefixlen: %s' % str(e))
829 return False
830
831 def _keyword_number_ipv4_list(self, value, validrange=None):
832 """
833 <number>=<ipv4> [<number>=<ipv4> ...]
834 ex: bridge-mcqv4src 100=172.16.100.1 101=172.16.101.1
835 """
836 try:
837 elements = value.split(' ')
838 if not elements:
839 return False
840 for elem in elements:
841 v = elem.split('=')
842 int(v[0])
843 IPv4Address(v[1])
844 return True
845 except Exception as e:
846 self.logger.debug('keyword: number ipv4: %s' % str(e))
847 return False
848
849 def _keyword_interface(self, ifacename, validrange=None):
850 return self.get_ifaceobjs(ifacename)
851
852 def _keyword_ipv4_vrf_text(self, value, validrange=None):
853 """
854 <ipv4> "vrf" <text>
855 ex: clagd-backup-ip 10.10.10.42 vrf blue
856 """
857 values = value.split()
858 size = len(values)
859
860 if size > 3 or size < 1:
861 return False
862 try:
863 IPv4Address(values[0])
864 if size > 1:
865 if values[1] != 'vrf':
866 return False
867 if size > 2:
868 if not self._keyword_text(values[2]):
869 return False
870 return True
871 except Exception as e:
872 self.logger.debug('keyword: ipv4 vrf text: %s' % str(e))
873 return False
874
875 def _keyword_interface_list_with_value(self, value, validvals):
876 values = value.split()
877 try:
878 if len(values) == 1:
879 if values[0] in validvals:
880 return True
881 for v in values:
882 iface_value = v.split('=')
883 size = len(iface_value)
884 if size != 2:
885 if iface_value[0] == 'glob' or iface_value[0] == 'regex':
886 continue
887 return False
888 if not iface_value[1] in validvals:
889 return False
890 return True
891 except Exception as e:
892 self.logger.debug('keyword: interface list with value: %s' % str(e))
893 return False
894
895 def _keyword_interface_yes_no_list(self, value, validrange=None):
896 """
897 <yes|no> | ( <interface>=<yes|no> [<interface>=<yes|no> ...] )
898 ex: mstpctl-portrestrrole swp1=yes swp2=no
899 """
900 return self._keyword_interface_list_with_value(value, ['yes', 'no'])
901
902 def _keyword_interface_yes_no_auto_list(self, value, validrange=None):
903 """
904 <yes|no|auto> |
905 ( <interface>=<yes|no|auto> [<interface>=<yes|no|auto> ...] )
906 ex: mstpctl-portp2p swp1=yes swp2=no swp3=auto
907 """
908 return self._keyword_interface_list_with_value(value,
909 ['yes', 'no', 'auto'])
910
911 def _keyword_interface_yes_no_0_1_list(self, value, validrange=None):
912 """
913 <yes|no|0|1> |
914 ( <interface>=<yes|no|0|1> [<interface>=<yes|no|0|1> ...] )
915 ex: bridge-portmcrouter swp1=yes swp2=yes swp3=1
916 """
917 return self._keyword_interface_list_with_value(value,
918 ['yes', 'no', '1', '0'])
919
920 def _keyword_interface_range_list(self, value, validrange):
921 """
922 <number> | ( <interface>=<number> [ <interface>=number> ...] )
923 ex: mstpctl-portpathcost swp1=0 swp2=1
924 """
925 values = value.split()
926 try:
927 if len(values) == 1:
928 try:
929 n = int(values[0])
930 if n < int(validrange[0]) or n > int(
931 validrange[1]):
932 raise invalidValueError('value of out range "%s":'
933 ' valid attribute range: %s'
934 % (values[0],
935 '-'.join(validrange)))
936 return True
937 except invalidValueError as e:
938 raise e
939 except Exception as e:
940 self.logger.debug('keyword: interface range list: %s'
941 % str(e))
942 return False
943 for v in values:
944 iface_value = v.split('=')
945 size = len(iface_value)
946 if size != 2:
947 return False
948 number = int(iface_value[1])
949 if number < int(validrange[0]) or number > int(
950 validrange[1]):
951 raise invalidValueError(
952 'value of out range "%s" for iface "%s":'
953 ' valid attribute range: %s'
954 % (iface_value[1],
955 iface_value[0],
956 '-'.join(validrange)))
957 return True
958 except invalidValueError as e:
959 raise e
960 except Exception as e:
961 self.logger.debug('keyword: interface range list: %s' % str(e))
962 return False
963
964 def _keyword_interface_list(self, value, validrange=None):
965 """
966 [glob|regex] <interface> [ [glob|regex] <interface> ...]
967 ex: bridge-ports swp1 swp2 glob swp3-5.100 regex (swp[6|7|8].100)
968 """
969 interface_list = value.split()
970 size = len(interface_list)
971 i = 0
972 while i < size:
973 if interface_list[i] == 'glob' or interface_list[i] == 'regex':
974 i += 1
975 else:
976 if not self._keyword_interface(interface_list[i]):
977 return False
978 i += 1
979 return True
980
981 def _keyword_number_range_list(self, value, validrange=None):
982 """
983 <number> [<number>-<number>]
984 ex: bridge-vids 42 100-200
985 """
986 number_list = value.split()
987 try:
988 i = 0
989 while i < len(number_list):
990 if '-' in number_list[i]:
991 range = number_list[i].split('-')
992 a = int(range[0])
993 b = int(range[1])
994 if a > b:
995 return False
996 else:
997 int(number_list[i])
998 i += 1
999 return True
1000 except Exception as e:
1001 self.logger.debug('keyword: number range list: %s' % str(e))
1002 return False
1003
1004 def _keyword_number_interface_list(self, value, validrange=None):
1005 """
1006 <number> <interface> [<interface>... [<number> <interface> ... ]]
1007 bridge-waitport 42 swp1 swp2 swp3 9 swp4
1008 """
1009 interface_list = value.split()
1010 if not interface_list:
1011 return False
1012 try:
1013 int(interface_list[0])
1014 prev = True
1015 for elem in interface_list[1:]:
1016 try:
1017 int(elem)
1018 if prev:
1019 return False
1020 prev = True
1021 except:
1022 prev = False
1023 return not prev
1024 except Exception as e:
1025 self.logger.debug('keyword: number interface list: %s' % str(e))
1026 return False
1027
482b2fab
JF
1028 def _keyword_number(self, value, validrange=None):
1029 try:
1030 int(value)
1031 return True
1032 except Exception as e:
1033 self.logger.debug('keyword: number: %s' % str(e))
1034 return False
1035
1036 def _is_keyword(self, value):
1037 if isinstance(value, tuple):
1038 return True
1039 keyword_found = value in self.validate_keywords
1040 if value.startswith('<') and value.endswith('>') and not keyword_found:
1041 raise Exception('%s: invalid keyword, please make sure to use'
1042 ' a valid keyword see `ifquery -s`' % value)
1043 return keyword_found
1044
1045 def _check_validvals_value(self, attrname, value, validvals, validrange):
1046 if validvals and value not in validvals:
1047 is_valid = False
1048 for keyword in validvals:
1049 if self._is_keyword(keyword):
1050 if validrange:
1051 if self.validate_keywords[keyword](value, validrange):
1052 return {'result': True}
1053 else:
1054 if self.validate_keywords[keyword](value):
1055 return {'result': True}
1056 if not is_valid:
1057 return {
1058 'result': False,
1059 'message': 'invalid value "%s": valid attribute values: %s'
1060 % (value, validvals)
1061 }
1062 elif validrange:
1063 if len(validrange) != 2:
1064 raise Exception('%s: invalid range in addon configuration'
1065 % '-'.join(validrange))
1066 _value = int(value)
1067 if _value < int(validrange[0]) or _value > int(validrange[1]):
1068 return {
1069 'result': False,
1070 'message': 'value of out range "%s": '
1071 'valid attribute range: %s'
1072 % (value, '-'.join(validrange))
1073 }
1074 return {'result': True}
1075
1076 def _check_validvals(self, ifacename, module_name, attrs):
1077 ifaceobj = self.get_ifaceobjs(ifacename)
1078 if not ifaceobj:
1079 return
1080 success = True
1081 for attrname, attrvalue in ifaceobj[0].config.items():
1082 try:
1083 attrname_dict = attrs.get(attrname, {})
1084 validvals = attrname_dict.get('validvals', [])
1085 validrange = attrname_dict.get('validrange', [])
1086 for value in attrvalue:
1087 res = self._check_validvals_value(attrname,
1088 value,
1089 validvals,
1090 validrange)
1091 if not res['result']:
1092 self.logger.warn('%s: %s: %s' %
1093 (ifacename, attrname, res['message']))
1094 success = False
1095 except Exception as e:
1096 self.logger.warn('addon \'%s\': %s: %s' % (module_name,
1097 attrname,
1098 str(e)))
1099 success = False
1100 return success
1101
eb377c6c 1102 def _module_syntax_check(self, filtered_ifacenames):
482b2fab 1103 result = True
eb377c6c
JF
1104 for ifacename in filtered_ifacenames:
1105 for module in self.modules.values():
1106 try:
482b2fab
JF
1107 if hasattr(module, '_modinfo'):
1108 if not self._check_validvals(ifacename,
1109 module.__class__.__name__,
1110 module._modinfo.get('attrs', {})):
1111 result = False
1112 if hasattr(module, 'syntax_check') and callable(module.syntax_check):
8e9fc178
JF
1113 if not module.syntax_check(self.get_ifaceobjs(ifacename)[0],
1114 self.get_ifaceobjs):
482b2fab 1115 result = False
eb377c6c 1116 except Exception, e:
482b2fab
JF
1117 self.logger.warn('%s: %s' % (ifacename, str(e)))
1118 result = False
1119 return result
eb377c6c 1120
3dcc1d0e 1121 def _iface_configattr_syntax_checker(self, attrname, attrval):
d08d5f54 1122 for m, mdict in self.module_attrs.items():
7949b8a5 1123 if not mdict:
1124 continue
d08d5f54 1125 attrsdict = mdict.get('attrs')
7949b8a5 1126 try:
1553a881
RP
1127 a = attrsdict.get(attrname)
1128 if a:
1129 if a.get('deprecated'):
1130 newa = a.get('new-attribute')
1131 if newa:
f57b9804 1132 self.logger.warn('attribute %s is deprecated. use %s instead.' %(attrname, newa))
1553a881 1133 else:
f57b9804 1134 self.logger.warn('attribute %s is deprecated.'
1553a881 1135 %attrname)
7949b8a5 1136 return True
1137 except AttributeError:
1138 pass
d08d5f54 1139 return False
1140
3dcc1d0e 1141 def _ifaceobj_syntax_checker(self, ifaceobj):
cfa06db6 1142 ret = True
8e113d63 1143 for attrname, attrvalue in ifaceobj.config.items():
3dcc1d0e 1144 found = False
1145 for k, v in self.module_attrs.items():
1146 if v and v.get('attrs', {}).get(attrname):
1147 found = True
1148 break
1149 if not found:
cfa06db6 1150 ret = False
fa714fa2
ST
1151 self.logger.warn('%s: unsupported attribute \'%s\'' \
1152 % (ifaceobj.name, attrname))
3dcc1d0e 1153 continue
cfa06db6 1154 return ret
3dcc1d0e 1155
14dc390d 1156 def read_iface_config(self):
a6f80f0e 1157 """ Reads default network interface config /etc/network/interfaces. """
cfa06db6 1158 ret = True
14dc390d 1159 nifaces = networkInterfaces(self.interfacesfile,
3dcc1d0e 1160 self.interfacesfileiobuf,
1161 self.interfacesfileformat,
f27710fe 1162 template_enable=self.config.get('template_enable', 0),
14dc390d 1163 template_engine=self.config.get('template_engine'),
1164 template_lookuppath=self.config.get('template_lookuppath'))
2ddd65c5
RP
1165 if self._ifaceobj_squash or self._ifaceobj_squash_internal:
1166 nifaces.subscribe('iface_found', self._save_iface_squash)
1167 else:
1168 nifaces.subscribe('iface_found', self._save_iface)
60dfcbdf
RP
1169 if self.config.get('addon_syntax_check', '1') == '1':
1170 nifaces.subscribe('validateifaceattr',
1171 self._iface_configattr_syntax_checker)
1172 nifaces.subscribe('validateifaceobj', self._ifaceobj_syntax_checker)
a6f80f0e 1173 nifaces.load()
cfa06db6
RP
1174 if nifaces.errors or nifaces.warns:
1175 ret = False
1176 return ret
a6f80f0e 1177
a6f80f0e 1178 def read_old_iface_config(self):
14dc390d 1179 """ Reads the saved iface config instead of default iface config.
1180 And saved iface config is already read by the statemanager """
cb7cc592 1181 self.ifaceobjdict = copy.deepcopy(self.statemanager.ifaceobjdict)
a6f80f0e 1182
53b00224 1183 def _load_addon_modules_config(self):
1184 """ Load addon modules config file """
a6f80f0e 1185
37c0543d 1186 with open(self.addon_modules_configfile, 'r') as f:
1187 lines = f.readlines()
1188 for l in lines:
7bbc9340
RP
1189 try:
1190 litems = l.strip(' \n\t\r').split(',')
1191 if not litems or len(litems) < 2:
1192 continue
1193 operation = litems[0]
1194 mname = litems[1]
1195 self.module_ops[operation].append(mname)
1196 except Exception, e:
55d9fae1 1197 self.logger.warn('error reading line \'%s\' %s:' %(l, str(e)))
7bbc9340 1198 continue
37c0543d 1199
1200 def load_addon_modules(self, modules_dir):
a6f80f0e 1201 """ load python modules from modules_dir
1202
1203 Default modules_dir is /usr/share/ifupdownmodules
1204
1205 """
a6f80f0e 1206 self.logger.info('loading builtin modules from %s' %modules_dir)
53b00224 1207 self._load_addon_modules_config()
a6f80f0e 1208 if not modules_dir in sys.path:
37c0543d 1209 sys.path.append(modules_dir)
a6f80f0e 1210 try:
be0b20f2 1211 for op, mlist in self.module_ops.items():
d08d5f54 1212 for mname in mlist:
53b00224 1213 if self.modules.get(mname):
d08d5f54 1214 continue
1215 mpath = modules_dir + '/' + mname + '.py'
1216 if os.path.exists(mpath):
1217 try:
1218 m = __import__(mname)
1219 mclass = getattr(m, mname)
1220 except:
1221 raise
b54179d2
RP
1222 try:
1223 minstance = mclass()
b6b8bd2b
JF
1224 script_override = minstance.get_overrides_ifupdown_scripts()
1225 self.overridden_ifupdown_scripts.extend(script_override)
b54179d2
RP
1226 except moduleNotSupported, e:
1227 self.logger.info('module %s not loaded (%s)\n'
1228 %(mname, str(e)))
b54179d2
RP
1229 continue
1230 except:
1231 raise
d08d5f54 1232 self.modules[mname] = minstance
53b00224 1233 try:
d08d5f54 1234 self.module_attrs[mname] = minstance.get_modinfo()
53b00224 1235 except:
1236 pass
a6f80f0e 1237 except:
1238 raise
1239
37c0543d 1240 # Assign all modules to query operations
be0b20f2 1241 self.module_ops['query-checkcurr'] = self.modules.keys()
1242 self.module_ops['query-running'] = self.modules.keys()
1243 self.module_ops['query-dependency'] = self.modules.keys()
1244 self.module_ops['query'] = self.modules.keys()
1245 self.module_ops['query-raw'] = self.modules.keys()
d08d5f54 1246
14dc390d 1247
53b00224 1248 def _modules_help(self):
1249 """ Prints addon modules supported syntax """
1250
d08d5f54 1251 indent = ' '
1252 for m, mdict in self.module_attrs.items():
1253 if not mdict:
1254 continue
1255 print('%s: %s' %(m, mdict.get('mhelp')))
1256 attrdict = mdict.get('attrs')
1257 if not attrdict:
1258 continue
1259 try:
1260 for attrname, attrvaldict in attrdict.items():
1261 if attrvaldict.get('compat', False):
1262 continue
1263 print('%s%s' %(indent, attrname))
1264 print('%shelp: %s' %(indent + ' ',
1265 attrvaldict.get('help', '')))
1266 print ('%srequired: %s' %(indent + ' ',
1267 attrvaldict.get('required', False)))
1268 default = attrvaldict.get('default')
1269 if default:
1270 print('%sdefault: %s' %(indent + ' ', default))
1271
1272 validrange = attrvaldict.get('validrange')
1273 if validrange:
1b0b81a2 1274 print('%svalidrange: %s-%s'
7949b8a5 1275 %(indent + ' ', validrange[0], validrange[1]))
d08d5f54 1276
1277 validvals = attrvaldict.get('validvals')
1278 if validvals:
1279 print('%svalidvals: %s'
1280 %(indent + ' ', ','.join(validvals)))
1281
1282 examples = attrvaldict.get('example')
1283 if not examples:
1284 continue
a6f80f0e 1285
d08d5f54 1286 print '%sexample:' %(indent + ' ')
1287 for e in examples:
1288 print '%s%s' %(indent + ' ', e)
1289 except:
1290 pass
1291 print ''
1292
37c0543d 1293 def load_scripts(self, modules_dir):
a6f80f0e 1294 """ loading user modules from /etc/network/.
1295
1296 Note that previously loaded python modules override modules found
1297 under /etc/network if any
1298
1299 """
1300
37c0543d 1301 self.logger.info('looking for user scripts under %s' %modules_dir)
be0b20f2 1302 for op, mlist in self.script_ops.items():
d08d5f54 1303 msubdir = modules_dir + '/if-%s.d' %op
1304 self.logger.info('loading scripts under %s ...' %msubdir)
1305 try:
1306 module_list = os.listdir(msubdir)
1307 for module in module_list:
b6b8bd2b 1308 if self.modules.get(module) or module in self.overridden_ifupdown_scripts:
d08d5f54 1309 continue
b6b8bd2b 1310 self.script_ops[op].append(msubdir + '/' + module)
d08d5f54 1311 except:
f802fe3c 1312 # continue reading
1313 pass
a6f80f0e 1314
6e16e5ae
N
1315 def _sched_ifaces(self, ifacenames, ops, skipupperifaces=False,
1316 followdependents=True, sort=False):
c798b0f4 1317 self.logger.debug('scheduling \'%s\' for %s'
d08d5f54 1318 %(str(ops), str(ifacenames)))
7538dc77 1319 self._pretty_print_ordered_dict('dependency graph',
1320 self.dependency_graph)
6e16e5ae 1321 ifaceScheduler.sched_ifaces(self, ifacenames, ops,
c798b0f4 1322 dependency_graph=self.dependency_graph,
d08d5f54 1323 order=ifaceSchedulerFlags.INORDER
1324 if 'down' in ops[0]
c798b0f4 1325 else ifaceSchedulerFlags.POSTORDER,
a4912b99 1326 followdependents=followdependents,
e308cb82 1327 skipupperifaces=skipupperifaces,
2a8440a4 1328 sort=True if (sort or ifupdownflags.flags.CLASS) else False)
2009513f 1329 return ifaceScheduler.get_sched_status()
a6f80f0e 1330
41febf89
RP
1331 def _render_ifacename(self, ifacename):
1332 new_ifacenames = []
679e6567 1333 vlan_match = re.match("^([\d]+)-([\d]+)", ifacename)
41febf89
RP
1334 if vlan_match:
1335 vlan_groups = vlan_match.groups()
1336 if vlan_groups[0] and vlan_groups[1]:
679e6567 1337 [new_ifacenames.append('%d' %v)
41febf89
RP
1338 for v in range(int(vlan_groups[0]),
1339 int(vlan_groups[1])+1)]
1340 return new_ifacenames
1341
1342 def _preprocess_ifacenames(self, ifacenames):
a6f80f0e 1343 """ validates interface list for config existance.
1344
1345 returns -1 if one or more interface not found. else, returns 0
1346
1347 """
41febf89 1348 new_ifacenames = []
a6f80f0e 1349 err_iface = ''
1350 for i in ifacenames:
31a5f4c3 1351 ifaceobjs = self.get_ifaceobjs(i)
1352 if not ifaceobjs:
41febf89 1353 # if name not available, render interface name and check again
679e6567 1354 rendered_ifacenames = utils.expand_iface_range(i)
41febf89
RP
1355 if rendered_ifacenames:
1356 for ri in rendered_ifacenames:
1357 ifaceobjs = self.get_ifaceobjs(ri)
1358 if not ifaceobjs:
1359 err_iface += ' ' + ri
1360 else:
1361 new_ifacenames.append(ri)
1362 else:
1363 err_iface += ' ' + i
1364 else:
1365 new_ifacenames.append(i)
fe0a57d3 1366 if err_iface:
31c58787 1367 raise Exception('cannot find interfaces:%s' %err_iface)
41febf89 1368 return new_ifacenames
a6f80f0e 1369
53b00224 1370 def _iface_whitelisted(self, auto, allow_classes, excludepats, ifacename):
a6f80f0e 1371 """ Checks if interface is whitelisted depending on set of parameters.
1372
a6f80f0e 1373 interfaces are checked against the allow_classes and auto lists.
1374
1375 """
1042b709 1376
0532f0a3
RP
1377 ret = True
1378
19e2bf8c 1379 # Check if interface matches the exclude patter
fe0a57d3 1380 if excludepats:
3e8ee54f 1381 for e in excludepats:
d08d5f54 1382 if re.search(e, ifacename):
0532f0a3 1383 ret = False
31a5f4c3 1384 ifaceobjs = self.get_ifaceobjs(ifacename)
1385 if not ifaceobjs:
0532f0a3
RP
1386 if ret:
1387 self.logger.debug('iface %s' %ifacename + ' not found')
1388 return ret
67cfaeb1 1389 # If matched exclude pattern, return false
0532f0a3
RP
1390 if not ret:
1391 for i in ifaceobjs:
1392 i.blacklisted = True
67cfaeb1 1393 self.blacklisted_ifaces_present = True
0532f0a3
RP
1394 return ret
1395 # Check if interface belongs to the class
67cfaeb1 1396 # the user is interested in, if not return false
fe0a57d3 1397 if allow_classes:
19e2bf8c 1398 ret = False
a6f80f0e 1399 for i in ifaceobjs:
62ddec8b 1400 if i.classes:
3e8ee54f 1401 common = Set([allow_classes]).intersection(
62ddec8b 1402 Set(i.classes))
fe0a57d3 1403 if common:
0532f0a3 1404 ret = True
0532f0a3 1405 if not ret:
19e2bf8c
RP
1406 # If a class was requested and interface does not belong
1407 # to the class, only then mark the ifaceobjs as blacklisted
1408 self.blacklisted_ifaces_present = True
1409 for i in ifaceobjs:
1410 i.blacklisted = True
1411 return ret
67cfaeb1
RP
1412 # If the user has requested auto class, check if the interface
1413 # is marked auto
d08d5f54 1414 if auto:
19e2bf8c 1415 ret = False
a6f80f0e 1416 for i in ifaceobjs:
62ddec8b 1417 if i.auto:
0532f0a3 1418 ret = True
19e2bf8c
RP
1419 if not ret:
1420 # If auto was requested and interface was not marked auto,
1421 # only then mark all of them as blacklisted
1422 self.blacklisted_ifaces_present = True
1423 for i in ifaceobjs:
0532f0a3
RP
1424 i.blacklisted = True
1425 return ret
a6f80f0e 1426
53b00224 1427 def _compat_conv_op_to_mode(self, op):
1428 """ Returns old op name to work with existing scripts """
60dfcbdf 1429 if 'up' in op:
53b00224 1430 return 'start'
60dfcbdf 1431 elif 'down' in op:
53b00224 1432 return 'stop'
1433 else:
1434 return op
1435
a6f80f0e 1436 def generate_running_env(self, ifaceobj, op):
739f665b 1437 """ Generates a dictionary with env variables required for
1438 an interface. Used to support script execution for interfaces.
a6f80f0e 1439 """
1440
1441 cenv = None
60dfcbdf 1442 iface_env = ifaceobj.get_env()
62ddec8b 1443 if iface_env:
a6f80f0e 1444 cenv = os.environ
d08d5f54 1445 if cenv:
a6f80f0e 1446 cenv.update(iface_env)
1447 else:
1448 cenv = iface_env
60dfcbdf
RP
1449 else:
1450 cenv = {}
1451 cenv['MODE'] = self._compat_conv_op_to_mode(op)
1452 cenv['PHASE'] = op
1453
a6f80f0e 1454 return cenv
1455
53b00224 1456 def _save_state(self):
dbc018d3
RP
1457 if (not self.flags.STATEMANAGER_ENABLE or
1458 not self.flags.STATEMANAGER_UPDATE):
20dd6242 1459 return
1460 try:
1461 # Update persistant iface states
1462 self.statemanager.save_state()
1463 except Exception, e:
1464 if self.logger.isEnabledFor(logging.DEBUG):
1465 t = sys.exc_info()[2]
1466 traceback.print_tb(t)
1467 self.logger.warning('error saving state (%s)' %str(e))
1468
2da58137
RP
1469 def set_type(self, type):
1470 if type == 'iface':
1471 self.type = ifaceType.IFACE
1472 elif type == 'vlan':
1473 self.type = ifaceType.BRIDGE_VLAN
1474 else:
1475 self.type = ifaceType.UNKNOWN
1476
a070c90e
RP
1477 def _process_delay_admin_state_queue(self, op):
1478 if not self._delay_admin_state_iface_queue:
1479 return
1480 if op == 'up':
1481 func = self.link_up
1482 elif op == 'down':
1483 func = self.link_down
1484 else:
1485 return
1486 for i in self._delay_admin_state_iface_queue:
1487 try:
1488 if self.link_exists(i):
1489 func(i)
1490 except Exception, e:
1491 self.logger.warn(str(e))
1492 pass
1493
d08d5f54 1494 def up(self, ops, auto=False, allow_classes=None, ifacenames=None,
2da58137 1495 excludepats=None, printdependency=None, syntaxcheck=False,
ad25e7bb 1496 type=None, skipupperifaces=False):
2c0ad8b3
RP
1497 """This brings the interface(s) up
1498
1499 Args:
41febf89
RP
1500 ops (list): list of ops to perform on the interface(s).
1501 Eg: ['pre-up', 'up', 'post-up'
2c0ad8b3
RP
1502
1503 Kwargs:
1504 auto (bool): act on interfaces marked auto
1505 allow_classes (list): act on interfaces belonging to classes in the list
1506 ifacenames (list): act on interfaces specified in this list
1507 excludepats (list): list of patterns of interfaces to exclude
1508 syntaxcheck (bool): only perform syntax check
1509 """
53b00224 1510
2da58137
RP
1511 self.set_type(type)
1512
5ee3e1a8 1513 if allow_classes:
2a8440a4 1514 ifupdownflags.flags.CLASS = True
dbc018d3
RP
1515 if not self.flags.ADDONS_ENABLE:
1516 self.flags.STATEMANAGER_UPDATE = False
d08d5f54 1517 if auto:
d2b35716
RP
1518 ifupdownflags.flags.ALL = True
1519 ifupdownflags.flags.WITH_DEPENDS = True
d08d5f54 1520 try:
cfa06db6 1521 iface_read_ret = self.read_iface_config()
62ddec8b 1522 except Exception:
d08d5f54 1523 raise
a6f80f0e 1524
31a5f4c3 1525 if ifacenames:
41febf89 1526 ifacenames = self._preprocess_ifacenames(ifacenames)
a6f80f0e 1527
1528 # if iface list not given by user, assume all from config file
31a5f4c3 1529 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
a6f80f0e 1530
1531 # filter interfaces based on auto and allow classes
cca03c30 1532 filtered_ifacenames = [i for i in ifacenames
53b00224 1533 if self._iface_whitelisted(auto, allow_classes,
d08d5f54 1534 excludepats, i)]
fe0a57d3 1535 if not filtered_ifacenames:
d08d5f54 1536 raise Exception('no ifaces found matching given allow lists')
a6f80f0e 1537
20dd6242 1538 if printdependency:
c798b0f4 1539 self.populate_dependency_info(ops, filtered_ifacenames)
d08d5f54 1540 self.print_dependency(filtered_ifacenames, printdependency)
739f665b 1541 return
cca03c30 1542 else:
c798b0f4 1543 self.populate_dependency_info(ops)
1544
cfa06db6
RP
1545 # If only syntax check was requested, return here.
1546 # return here because we want to make sure most
1547 # errors above are caught and reported.
21289e4a 1548 if syntaxcheck:
482b2fab
JF
1549 if not self._module_syntax_check(filtered_ifacenames):
1550 raise Exception()
cfa06db6
RP
1551 if not iface_read_ret:
1552 raise Exception()
666c6141
RP
1553 elif self._any_iface_errors(filtered_ifacenames):
1554 raise Exception()
21289e4a
RP
1555 return
1556
24aa45e5 1557 ret = None
525f0a30 1558 try:
2009513f
RP
1559 ret = self._sched_ifaces(filtered_ifacenames, ops,
1560 skipupperifaces=skipupperifaces,
1561 followdependents=True
d2b35716
RP
1562 if ifupdownflags.flags.WITH_DEPENDS
1563 else False)
525f0a30 1564 finally:
a070c90e 1565 self._process_delay_admin_state_queue('up')
fc5e1735 1566 if not ifupdownflags.flags.DRYRUN and self.flags.ADDONS_ENABLE:
525f0a30 1567 self._save_state()
a6f80f0e 1568
2009513f
RP
1569 if not iface_read_ret or not ret:
1570 raise Exception()
1571
d08d5f54 1572 def down(self, ops, auto=False, allow_classes=None, ifacenames=None,
2da58137
RP
1573 excludepats=None, printdependency=None, usecurrentconfig=False,
1574 type=None):
53b00224 1575 """ down an interface """
1576
2da58137
RP
1577 self.set_type(type)
1578
5ee3e1a8 1579 if allow_classes:
2a8440a4 1580 ifupdownflags.flags.CLASS = True
dbc018d3
RP
1581 if not self.flags.ADDONS_ENABLE:
1582 self.flags.STATEMANAGER_UPDATE = False
d08d5f54 1583 if auto:
d2b35716
RP
1584 ifupdownflags.flags.ALL = True
1585 ifupdownflags.flags.WITH_DEPENDS = True
5c721925 1586 # For down we need to look at old state, unless usecurrentconfig
1587 # is set
dbc018d3 1588 if (not usecurrentconfig and self.flags.STATEMANAGER_ENABLE and
53b00224 1589 self.statemanager.ifaceobjdict):
31a5f4c3 1590 # Since we are using state manager objects,
1591 # skip the updating of state manager objects
5c721925 1592 self.logger.debug('Looking at old state ..')
d08d5f54 1593 self.read_old_iface_config()
fe0a57d3 1594 else:
d08d5f54 1595 # If no old state available
d08d5f54 1596 try:
1597 self.read_iface_config()
1598 except Exception, e:
1599 raise Exception('error reading iface config (%s)' %str(e))
d08d5f54 1600 if ifacenames:
1601 # If iface list is given by the caller, always check if iface
1602 # is present
31c58787 1603 try:
41febf89 1604 ifacenames = self._preprocess_ifacenames(ifacenames)
31c58787 1605 except Exception, e:
1606 raise Exception('%s' %str(e) +
1607 ' (interface was probably never up ?)')
1608
d08d5f54 1609 # if iface list not given by user, assume all from config file
fe0a57d3 1610 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
53b00224 1611
d08d5f54 1612 # filter interfaces based on auto and allow classes
1613 filtered_ifacenames = [i for i in ifacenames
53b00224 1614 if self._iface_whitelisted(auto, allow_classes,
d08d5f54 1615 excludepats, i)]
fe0a57d3 1616 if not filtered_ifacenames:
c0071225 1617 raise Exception('no ifaces found matching given allow lists ' +
41febf89 1618 '(or interfaces were probably never up ?)')
14dc390d 1619
d08d5f54 1620 if printdependency:
99b212b0 1621 self.populate_dependency_info(ops, filtered_ifacenames)
d08d5f54 1622 self.print_dependency(filtered_ifacenames, printdependency)
1623 return
99b212b0 1624 else:
1625 self.populate_dependency_info(ops)
525f0a30 1626
1627 try:
a4912b99 1628 self._sched_ifaces(filtered_ifacenames, ops,
dbc018d3 1629 followdependents=True
d2b35716 1630 if ifupdownflags.flags.WITH_DEPENDS else False)
525f0a30 1631 finally:
a070c90e 1632 self._process_delay_admin_state_queue('down')
fc5e1735 1633 if not ifupdownflags.flags.DRYRUN and self.flags.ADDONS_ENABLE:
525f0a30 1634 self._save_state()
d08d5f54 1635
4c56a7c1
RP
1636 def query(self, ops, auto=False, format_list=False, allow_classes=None,
1637 ifacenames=None,
739f665b 1638 excludepats=None, printdependency=None,
6e16e5ae 1639 format='native', type=None):
53b00224 1640 """ query an interface """
1641
2da58137
RP
1642 self.set_type(type)
1643
2ddd65c5
RP
1644 # Let us forget internal squashing when it comes to
1645 # ifquery. It can surprise people relying of ifquery
1646 # output
1647 self._ifaceobj_squash_internal = False
1648
5ee3e1a8 1649 if allow_classes:
2a8440a4 1650 ifupdownflags.flags.CLASS = True
dbc018d3 1651 if self.flags.STATEMANAGER_ENABLE and ops[0] == 'query-savedstate':
5c721925 1652 return self.statemanager.dump_pretty(ifacenames)
dbc018d3 1653 self.flags.STATEMANAGER_UPDATE = False
d08d5f54 1654 if auto:
739f665b 1655 self.logger.debug('setting flag ALL')
d2b35716
RP
1656 ifupdownflags.flags.ALL = True
1657 ifupdownflags.flags.WITH_DEPENDS = True
739f665b 1658
d08d5f54 1659 if ops[0] == 'query-syntax':
53b00224 1660 self._modules_help()
d08d5f54 1661 return
1662 elif ops[0] == 'query-running':
739f665b 1663 # create fake devices to all dependents that dont have config
dbc018d3
RP
1664 map(lambda i: self.create_n_save_ifaceobj(i,
1665 ifacePrivFlags(False, True)), ifacenames)
739f665b 1666 else:
1667 try:
1668 self.read_iface_config()
1669 except Exception:
1670 raise
1671
53b00224 1672 if ifacenames and ops[0] != 'query-running':
41febf89
RP
1673 # If iface list is given, always check if iface is present
1674 ifacenames = self._preprocess_ifacenames(ifacenames)
739f665b 1675
1676 # if iface list not given by user, assume all from config file
31a5f4c3 1677 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
739f665b 1678
1679 # filter interfaces based on auto and allow classes
d08d5f54 1680 if ops[0] == 'query-running':
739f665b 1681 filtered_ifacenames = ifacenames
1682 else:
1683 filtered_ifacenames = [i for i in ifacenames
53b00224 1684 if self._iface_whitelisted(auto, allow_classes,
d08d5f54 1685 excludepats, i)]
fe0a57d3 1686 if not filtered_ifacenames:
739f665b 1687 raise Exception('no ifaces found matching ' +
1688 'given allow lists')
37c0543d 1689
e1601369 1690 self.populate_dependency_info(ops)
d08d5f54 1691 if ops[0] == 'query-dependency' and printdependency:
1692 self.print_dependency(filtered_ifacenames, printdependency)
1693 return
739f665b 1694
4c56a7c1
RP
1695 if format_list and (ops[0] == 'query' or ops[0] == 'query-raw'):
1696 return self.print_ifaceobjs_list(filtered_ifacenames)
1697
634764bd 1698 if ops[0] == 'query' and not ifupdownflags.flags.WITHDEFAULTS:
75730152 1699 return self.print_ifaceobjs_pretty(filtered_ifacenames, format)
1700 elif ops[0] == 'query-raw':
1701 return self.print_ifaceobjs_raw(filtered_ifacenames)
1702
6e16e5ae 1703 ret = self._sched_ifaces(filtered_ifacenames, ops,
dbc018d3 1704 followdependents=True
d2b35716 1705 if ifupdownflags.flags.WITH_DEPENDS else False)
739f665b 1706
634764bd
RP
1707 if ops[0] == 'query' and ifupdownflags.flags.WITHDEFAULTS:
1708 return self.print_ifaceobjs_pretty(filtered_ifacenames, format)
1709 elif ops[0] == 'query-checkcurr':
d08d5f54 1710 ret = self.print_ifaceobjscurr_pretty(filtered_ifacenames, format)
739f665b 1711 if ret != 0:
1712 # if any of the object has an error, signal that silently
1713 raise Exception('')
d08d5f54 1714 elif ops[0] == 'query-running':
1715 self.print_ifaceobjsrunning_pretty(filtered_ifacenames, format)
739f665b 1716 return
1717
4e07a2d5 1718 def _reload_currentlyup(self, upops, downops, auto=False, allow=None,
2da58137 1719 ifacenames=None, excludepats=None, usecurrentconfig=False,
cfa06db6 1720 syntaxcheck=False, **extra_args):
2da58137 1721 """ reload currently up interfaces """
c0071225 1722 new_ifaceobjdict = {}
739f665b 1723
4e07a2d5
RP
1724 self.logger.info('reloading interfaces that are currently up ..')
1725
2da58137 1726 try:
cfa06db6 1727 iface_read_ret = self.read_iface_config()
2da58137
RP
1728 except:
1729 raise
2da58137
RP
1730 if not self.ifaceobjdict:
1731 self.logger.warn("nothing to reload ..exiting.")
1732 return
2da58137 1733 already_up_ifacenames = []
1042b709 1734 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
cfa06db6 1735
dbc018d3 1736 if (not usecurrentconfig and self.flags.STATEMANAGER_ENABLE
2da58137
RP
1737 and self.statemanager.ifaceobjdict):
1738 already_up_ifacenames = self.statemanager.ifaceobjdict.keys()
1739
2da58137
RP
1740 # Get already up interfaces that still exist in the interfaces file
1741 already_up_ifacenames_not_present = Set(
1742 already_up_ifacenames).difference(ifacenames)
1743 already_up_ifacenames_still_present = Set(
1744 already_up_ifacenames).difference(
1745 already_up_ifacenames_not_present)
4e07a2d5
RP
1746
1747 interfaces_to_up = already_up_ifacenames_still_present
1748
1749 # generate dependency graph of interfaces
1750 self.populate_dependency_info(upops, interfaces_to_up)
1751
1752 # If only syntax check was requested, return here.
1753 # return here because we want to make sure most
1754 # errors above are caught and reported.
1755 if syntaxcheck:
482b2fab
JF
1756 if not self._module_syntax_check(interfaces_to_up):
1757 raise Exception()
4e07a2d5
RP
1758 if not iface_read_ret:
1759 raise Exception()
1760 elif self._any_iface_errors(interfaces_to_up):
1761 raise Exception()
1762 return
2da58137
RP
1763
1764 if (already_up_ifacenames_not_present and
1765 self.config.get('ifreload_currentlyup_down_notpresent') == '1'):
1766 self.logger.info('reload: schedule down on interfaces: %s'
1767 %str(already_up_ifacenames_not_present))
1768
1769 # Save a copy of new iface objects and dependency_graph
1770 new_ifaceobjdict = dict(self.ifaceobjdict)
1771 new_dependency_graph = dict(self.dependency_graph)
1772
1773 # old interface config is read into self.ifaceobjdict
1774 self.read_old_iface_config()
1775
1776 # reinitialize dependency graph
1777 self.dependency_graph = OrderedDict({})
1042b709
RP
1778 falready_up_ifacenames_not_present = [i for i in
1779 already_up_ifacenames_not_present
1780 if self._iface_whitelisted(auto, allow,
1781 excludepats, i)]
2da58137 1782 self.populate_dependency_info(downops,
1042b709
RP
1783 falready_up_ifacenames_not_present)
1784 self._sched_ifaces(falready_up_ifacenames_not_present, downops,
e308cb82 1785 followdependents=False, sort=True)
2da58137 1786 else:
4e07a2d5 1787 self.logger.info('no interfaces to down ..')
2da58137
RP
1788
1789 # Now, run 'up' with new config dict
1790 # reset statemanager update flag to default
e308cb82 1791 if auto:
d2b35716
RP
1792 ifupdownflags.flags.ALL = True
1793 ifupdownflags.flags.WITH_DEPENDS = True
2da58137 1794 if new_ifaceobjdict:
3d44fbd0 1795 # and now, ifaceobjdict is back to current config
2da58137
RP
1796 self.ifaceobjdict = new_ifaceobjdict
1797 self.dependency_graph = new_dependency_graph
1798
1799 if not self.ifaceobjdict:
4e07a2d5
RP
1800 self.logger.info('no interfaces to up')
1801 return
2da58137
RP
1802 self.logger.info('reload: scheduling up on interfaces: %s'
1803 %str(interfaces_to_up))
2009513f
RP
1804 ret = self._sched_ifaces(interfaces_to_up, upops,
1805 followdependents=True
d2b35716 1806 if ifupdownflags.flags.WITH_DEPENDS else False)
fc5e1735 1807 if ifupdownflags.flags.DRYRUN:
2da58137
RP
1808 return
1809 self._save_state()
1810
2009513f
RP
1811 if not iface_read_ret or not ret:
1812 raise Exception()
1813
2da58137
RP
1814 def _reload_default(self, upops, downops, auto=False, allow=None,
1815 ifacenames=None, excludepats=None, usecurrentconfig=False,
cfa06db6 1816 syntaxcheck=False, **extra_args):
2da58137 1817 """ reload interface config """
2da58137 1818 new_ifaceobjdict = {}
739f665b 1819
1820 try:
cfa06db6 1821 iface_read_ret = self.read_iface_config()
20dd6242 1822 except:
739f665b 1823 raise
1824
c0071225
RP
1825 if not self.ifaceobjdict:
1826 self.logger.warn("nothing to reload ..exiting.")
1827 return
1042b709
RP
1828
1829 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
1830 new_filtered_ifacenames = [i for i in ifacenames
1831 if self._iface_whitelisted(auto, allow,
1832 excludepats, i)]
37c0543d 1833 # generate dependency graph of interfaces
c798b0f4 1834 self.populate_dependency_info(upops)
1042b709 1835
cfa06db6
RP
1836 # If only syntax check was requested, return here.
1837 # return here because we want to make sure most
1838 # errors above are caught and reported.
1839 if syntaxcheck:
482b2fab
JF
1840 if not self._module_syntax_check(new_filtered_ifacenames):
1841 raise Exception()
cfa06db6
RP
1842 if not iface_read_ret:
1843 raise Exception()
4e07a2d5
RP
1844 elif self._any_iface_errors(new_filtered_ifacenames):
1845 raise Exception()
cfa06db6
RP
1846 return
1847
dbc018d3 1848 if (not usecurrentconfig and self.flags.STATEMANAGER_ENABLE
14dc390d 1849 and self.statemanager.ifaceobjdict):
1850 # Save a copy of new iface objects and dependency_graph
1851 new_ifaceobjdict = dict(self.ifaceobjdict)
1852 new_dependency_graph = dict(self.dependency_graph)
37c0543d 1853
dbc018d3
RP
1854 self.ifaceobjdict = OrderedDict({})
1855 self.dependency_graph = OrderedDict({})
1856
739f665b 1857 # if old state is present, read old state and mark op for 'down'
1858 # followed by 'up' aka: reload
37c0543d 1859 # old interface config is read into self.ifaceobjdict
739f665b 1860 self.read_old_iface_config()
1861 op = 'reload'
1862 else:
1863 # oldconfig not available, continue with 'up' with new config
1864 op = 'up'
05ac52f0
RP
1865 new_ifaceobjdict = self.ifaceobjdict
1866 new_dependency_graph = self.dependency_graph
739f665b 1867
fe0a57d3 1868 if op == 'reload' and ifacenames:
93b399fb 1869 ifacenames = self.ifaceobjdict.keys()
1042b709
RP
1870 old_filtered_ifacenames = [i for i in ifacenames
1871 if self._iface_whitelisted(auto, allow,
d08d5f54 1872 excludepats, i)]
e308cb82 1873
dbc018d3
RP
1874 # generate dependency graph of old interfaces,
1875 # This should make sure built in interfaces are
1876 # populated. disable check shared dependents as an optimization.
1877 # these are saved interfaces and dependency for these
1878 # have been checked before they became part of saved state.
62f2caa4
RP
1879 try:
1880 self.flags.CHECK_SHARED_DEPENDENTS = False
1881 self.populate_dependency_info(upops)
1882 self.flags.CHECK_SHARED_DEPENDENTS = True
1883 except Exception, e:
1884 self.logger.info("error generating dependency graph for "
1885 "saved interfaces (%s)" %str(e))
1886 pass
1887
dbc018d3 1888 # make sure we pick up built-in interfaces
e308cb82
RP
1889 # if config file had 'ifreload_down_changed' variable
1890 # set, also look for interfaces that changed to down them
1891 down_changed = int(self.config.get('ifreload_down_changed', '1'))
1892
37c0543d 1893 # Generate the interface down list
1894 # Interfaces that go into the down list:
1895 # - interfaces that were present in last config and are not
1896 # present in the new config
1897 # - interfaces that were changed between the last and current
1898 # config
37c0543d 1899 ifacedownlist = []
dbc018d3 1900 for ifname in self.ifaceobjdict.keys():
2da58137 1901 lastifaceobjlist = self.ifaceobjdict.get(ifname)
dbc018d3
RP
1902 if not self.is_ifaceobj_builtin(lastifaceobjlist[0]):
1903 # if interface is not built-in and is not in
1904 # old filtered ifacenames
1905 if ifname not in old_filtered_ifacenames:
1906 continue
37c0543d 1907 objidx = 0
37c0543d 1908 # If interface is not present in the new file
1909 # append it to the down list
53b00224 1910 newifaceobjlist = new_ifaceobjdict.get(ifname)
1911 if not newifaceobjlist:
37c0543d 1912 ifacedownlist.append(ifname)
1913 continue
21289e4a
RP
1914 # If ifaceobj was present in the old interfaces file,
1915 # and does not have a config in the new interfaces file
1916 # but has been picked up as a dependent of another
1917 # interface, catch it here. This catches a common error
1918 # for example: remove a bond section from the interfaces
1919 # file, but leave it around as a bridge port
1920 # XXX: Ideally its better to just add it to the
1921 # ifacedownlist. But we will be cautious here
1922 # and just print a warning
1923 if (self.is_ifaceobj_noconfig(newifaceobjlist[0]) and
dbc018d3 1924 not self.is_ifaceobj_builtin(newifaceobjlist[0]) and
7ef04d1b
RP
1925 lastifaceobjlist[0].is_config_present() and
1926 lastifaceobjlist[0].link_kind):
50625cb0
JF
1927 self.logger.warn('%s: misconfig ? removed but still exists '
1928 'as a dependency of %s.\nPlease remove '
1929 'the dependency manually `ifdown %s` if '
1930 'it is being picked up as part of a regex'
1931 % (newifaceobjlist[objidx].name,
1932 str(newifaceobjlist[objidx].upperifaces),
1933 newifaceobjlist[objidx].name))
26434da6
RP
1934 if not down_changed:
1935 continue
53b00224 1936 if len(newifaceobjlist) != len(lastifaceobjlist):
37c0543d 1937 ifacedownlist.append(ifname)
1938 continue
e308cb82
RP
1939
1940 # If interface has changed between the current file
1941 # and the last installed append it to the down list
37c0543d 1942 # compare object list
53b00224 1943 for objidx in range(0, len(lastifaceobjlist)):
1944 oldobj = lastifaceobjlist[objidx]
1945 newobj = newifaceobjlist[objidx]
ca3f4fc7 1946 if not newobj.compare(oldobj):
37c0543d 1947 ifacedownlist.append(ifname)
1948 continue
1949
fe0a57d3 1950 if ifacedownlist:
2da58137 1951 self.logger.info('reload: scheduling down on interfaces: %s'
739f665b 1952 %str(ifacedownlist))
20dd6242 1953 # reinitialize dependency graph
1954 self.dependency_graph = OrderedDict({})
dbc018d3 1955
37c0543d 1956 # Generate dependency info for old config
62f2caa4 1957 self.flags.CHECK_SHARED_DEPENDENTS = False
14dc390d 1958 self.populate_dependency_info(downops, ifacedownlist)
62f2caa4
RP
1959 self.flags.CHECK_SHARED_DEPENDENTS = True
1960
a070c90e 1961 try:
dbc018d3
RP
1962 # XXX: Hack to skip checking upperifaces during down.
1963 # the dependency list is not complete here
1964 # and we dont want to down the upperiface.
1965 # Hence during reload, set this to true.
1966 # This is being added to avoid a failure in
1967 # scheduler._check_upperifaces when we are dowing
1968 # a builtin bridge port
1969 self.flags.SCHED_SKIP_CHECK_UPPERIFACES = True
a4912b99 1970 self._sched_ifaces(ifacedownlist, downops,
e308cb82
RP
1971 followdependents=False,
1972 sort=True)
a070c90e
RP
1973 except Exception, e:
1974 self.logger.error(str(e))
1975 pass
1976 finally:
dbc018d3 1977 self.flags.SCHED_SKIP_CHECK_UPPERIFACES = False
a070c90e 1978 self._process_delay_admin_state_queue('down')
37c0543d 1979 else:
4e07a2d5 1980 self.logger.info('no interfaces to down ..')
739f665b 1981
20dd6242 1982 # Now, run 'up' with new config dict
1983 # reset statemanager update flag to default
c0071225 1984 if not new_ifaceobjdict:
aa4e3022 1985 self.logger.debug('no interfaces to up')
c0071225 1986 return
e308cb82
RP
1987
1988 if auto:
d2b35716
RP
1989 ifupdownflags.flags.ALL = True
1990 ifupdownflags.flags.WITH_DEPENDS = True
3d44fbd0 1991 # and now, we are back to the current config in ifaceobjdict
53b00224 1992 self.ifaceobjdict = new_ifaceobjdict
1993 self.dependency_graph = new_dependency_graph
c798b0f4 1994
2da58137 1995 self.logger.info('reload: scheduling up on interfaces: %s'
1042b709 1996 %str(new_filtered_ifacenames))
8a360f1b 1997 ifupdownflags.flags.CACHE = True
a070c90e 1998 try:
2009513f
RP
1999 ret = self._sched_ifaces(new_filtered_ifacenames, upops,
2000 followdependents=True
d2b35716
RP
2001 if ifupdownflags.flags.WITH_DEPENDS
2002 else False)
a070c90e 2003 except Exception, e:
24aa45e5 2004 ret = None
a070c90e 2005 self.logger.error(str(e))
a070c90e
RP
2006 finally:
2007 self._process_delay_admin_state_queue('up')
fc5e1735 2008 if ifupdownflags.flags.DRYRUN:
e37ad4a6 2009 return
53b00224 2010 self._save_state()
a6f80f0e 2011
2009513f
RP
2012 if not iface_read_ret or not ret:
2013 raise Exception()
2014
2da58137
RP
2015 def reload(self, *args, **kargs):
2016 """ reload interface config """
2da58137
RP
2017 self.logger.debug('reloading interface config ..')
2018 if kargs.get('currentlyup', False):
2019 self._reload_currentlyup(*args, **kargs)
2020 else:
2021 self._reload_default(*args, **kargs)
2022
666c6141
RP
2023 def _any_iface_errors(self, ifacenames):
2024 for i in ifacenames:
2025 ifaceobjs = self.get_ifaceobjs(i)
2026 if not ifaceobjs: continue
2027 for ifaceobj in ifaceobjs:
2028 if (ifaceobj.status == ifaceStatus.NOTFOUND or
2029 ifaceobj.status == ifaceStatus.ERROR):
2030 return True
2031 return False
2032
7538dc77 2033 def _pretty_print_ordered_dict(self, prefix, argdict):
525f0a30 2034 outbuf = prefix + ' {\n'
53b00224 2035 for k, vlist in argdict.items():
525f0a30 2036 outbuf += '\t%s : %s\n' %(k, str(vlist))
7538dc77 2037 self.logger.debug(outbuf + '}')
a6f80f0e 2038
53b00224 2039 def print_dependency(self, ifacenames, format):
2040 """ prints iface dependency information """
a6f80f0e 2041
53b00224 2042 if not ifacenames:
2043 ifacenames = self.ifaceobjdict.keys()
2044 if format == 'list':
2045 for k,v in self.dependency_graph.items():
2046 print '%s : %s' %(k, str(v))
2047 elif format == 'dot':
2048 indegrees = {}
2049 map(lambda i: indegrees.update({i :
2050 self.get_iface_refcnt(i)}),
2051 self.dependency_graph.keys())
2052 graph.generate_dots(self.dependency_graph, indegrees)
a6f80f0e 2053
4c56a7c1
RP
2054 def print_ifaceobjs_list(self, ifacenames):
2055 for i in ifacenames:
2056 print i
2057
739f665b 2058 def print_ifaceobjs_raw(self, ifacenames):
53b00224 2059 """ prints raw lines for ifaces from config file """
2060
739f665b 2061 for i in ifacenames:
31a5f4c3 2062 for ifaceobj in self.get_ifaceobjs(i):
75730152 2063 if (self.is_ifaceobj_builtin(ifaceobj) or
2064 not ifaceobj.is_config_present()):
2065 continue
2066 ifaceobj.dump_raw(self.logger)
739f665b 2067 print '\n'
d2b35716
RP
2068 if (ifupdownflags.flags.WITH_DEPENDS and
2069 not ifupdownflags.flags.ALL):
62ddec8b 2070 dlist = ifaceobj.lowerifaces
fe0a57d3 2071 if not dlist: continue
53b00224 2072 self.print_ifaceobjs_raw(dlist)
739f665b 2073
2cd06f78 2074 def _get_ifaceobjs_pretty(self, ifacenames, ifaceobjs, running=False):
2075 """ returns iface obj list """
53b00224 2076
a6f80f0e 2077 for i in ifacenames:
31a5f4c3 2078 for ifaceobj in self.get_ifaceobjs(i):
2cd06f78 2079 if ((not running and self.is_ifaceobj_noconfig(ifaceobj)) or
f78ba1de
RP
2080 (running and not ifaceobj.is_config_present() and
2081 not self.is_iface_builtin_byname(i) and
2082 not ifaceobj.upperifaces)):
75730152 2083 continue
2cd06f78 2084 ifaceobjs.append(ifaceobj)
d2b35716
RP
2085 if (ifupdownflags.flags.WITH_DEPENDS and
2086 not ifupdownflags.flags.ALL):
62ddec8b 2087 dlist = ifaceobj.lowerifaces
fe0a57d3 2088 if not dlist: continue
2cd06f78 2089 self._get_ifaceobjs_pretty(dlist, ifaceobjs, running)
739f665b 2090
2cd06f78 2091 def print_ifaceobjs_pretty(self, ifacenames, format='native'):
2092 """ pretty prints iface in format given by keyword arg format """
eab25b7c 2093
2cd06f78 2094 ifaceobjs = []
2095 self._get_ifaceobjs_pretty(ifacenames, ifaceobjs)
2096 if not ifaceobjs: return
2097 if format == 'json':
3dcc1d0e 2098 print json.dumps(ifaceobjs, cls=ifaceJsonEncoder,
2099 indent=4, separators=(',', ': '))
2cd06f78 2100 else:
2da58137
RP
2101 expand = int(self.config.get('ifquery_ifacename_expand_range', '0'))
2102 for i in ifaceobjs:
2103 if not expand and (i.flags & iface.IFACERANGE_ENTRY):
2104 # print only the first one
2105 if i.flags & iface.IFACERANGE_START:
2106 i.dump_pretty(use_realname=True)
2107 else:
2108 i.dump_pretty()
53b00224 2109
2cd06f78 2110 def _get_ifaceobjscurr_pretty(self, ifacenames, ifaceobjs):
eab25b7c 2111 ret = 0
a6f80f0e 2112 for i in ifacenames:
923290bd 2113 ifaceobjscurr = self.get_ifaceobjcurr(i)
2114 if not ifaceobjscurr: continue
2115 for ifaceobj in ifaceobjscurr:
2116 if (ifaceobj.status == ifaceStatus.NOTFOUND or
2117 ifaceobj.status == ifaceStatus.ERROR):
2118 ret = 1
2119 if self.is_ifaceobj_noconfig(ifaceobj):
2120 continue
2121 ifaceobjs.append(ifaceobj)
d2b35716
RP
2122 if (ifupdownflags.flags.WITH_DEPENDS and
2123 not ifupdownflags.flags.ALL):
923290bd 2124 dlist = ifaceobj.lowerifaces
2125 if not dlist: continue
2126 dret = self._get_ifaceobjscurr_pretty(dlist, ifaceobjs)
2127 if dret: ret = 1
2cd06f78 2128 return ret
2129
2130 def print_ifaceobjscurr_pretty(self, ifacenames, format='native'):
2131 """ pretty prints current running state of interfaces with status.
2132
2133 returns 1 if any of the interface has an error,
2134 else returns 0
2135 """
2136
2137 ifaceobjs = []
2138 ret = self._get_ifaceobjscurr_pretty(ifacenames, ifaceobjs)
2139 if not ifaceobjs: return
307e06bb
RP
2140
2141 # override ifaceStatusUserStrs
2142 ifaceStatusUserStrs.SUCCESS = self.config.get('ifquery_check_success_str', _success_sym)
2143 ifaceStatusUserStrs.ERROR = self.config.get('ifquery_check_error_str', _error_sym)
2144 ifaceStatusUserStrs.UNKNOWN = self.config.get('ifquery_check_unknown_str', '')
2cd06f78 2145 if format == 'json':
307e06bb
RP
2146 print json.dumps(ifaceobjs, cls=ifaceJsonEncoderWithStatus,
2147 indent=2, separators=(',', ': '))
2cd06f78 2148 else:
fb10449e 2149 map(lambda i: i.dump_pretty(with_status=True), ifaceobjs)
eab25b7c 2150 return ret
a6f80f0e 2151
d08d5f54 2152 def print_ifaceobjsrunning_pretty(self, ifacenames, format='native'):
53b00224 2153 """ pretty prints iface running state """
2154
2cd06f78 2155 ifaceobjs = []
2156 self._get_ifaceobjs_pretty(ifacenames, ifaceobjs, running=True)
2157 if not ifaceobjs: return
2158 if format == 'json':
2159 print json.dumps(ifaceobjs, cls=ifaceJsonEncoder, indent=2,
2160 separators=(',', ': '))
2161 else:
2162 map(lambda i: i.dump_pretty(), ifaceobjs)
53b00224 2163
2164 def _dump(self):
2165 print 'ifupdown main object dump'
2166 print self.pp.pprint(self.modules)
2167 print self.pp.pprint(self.ifaceobjdict)
2168
2169 def _dump_ifaceobjs(self, ifacenames):
2170 for i in ifacenames:
2171 ifaceobjs = self.get_ifaceobjs(i)
2172 for i in ifaceobjs:
2173 i.dump(self.logger)
2174 print '\n'