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