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