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