]> git.proxmox.com Git - mirror_ifupdown2.git/blame - ifupdown/ifupdownmain.py
Fix typo in comment in default config file
[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
a6f80f0e 18from statemanager import *
19from networkinterfaces import *
20from iface import *
21from scheduler import *
22from collections import deque
23from collections import OrderedDict
a6f80f0e 24from graph import *
3e8ee54f 25from sets import Set
a6f80f0e 26
2c0ad8b3
RP
27"""
28.. module:: ifupdownmain
29:synopsis: main module for ifupdown package
30
31.. moduleauthor:: Roopa Prabhu <roopa@cumulusnetworks.com>
32
33"""
34
86fc62e2 35_tickmark = u'\u2713'
36_crossmark = u'\u2717'
e74d01e1
RP
37_success_sym = '(%s)' %_tickmark
38_error_sym = '(%s)' %_crossmark
86fc62e2 39
84ca006f
RP
40class ifupdownFlags():
41 FORCE = False
42 DRYRUN = False
43 NOWAIT = False
44 PERFMODE = False
45 CACHE = False
46
47 # Flags
48 CACHE_FLAGS = 0x0
49
be0b20f2 50class ifupdownMain(ifupdownBase):
53b00224 51 """ ifupdown2 main class """
52
a6f80f0e 53 # Flags
cca03c30 54 WITH_DEPENDS = False
a6f80f0e 55 ALL = False
5ee3e1a8 56 IFACE_CLASS = False
6bd7fc74 57 COMPAT_EXEC_SCRIPTS = False
20dd6242 58 STATEMANAGER_ENABLE = True
59 STATEMANAGER_UPDATE = True
60 ADDONS_ENABLE = False
a6f80f0e 61
37c0543d 62 # priv flags to mark iface objects
a070c90e
RP
63 BUILTIN = 0x0001
64 NOCONFIG = 0x0010
37c0543d 65
66 scripts_dir='/etc/network'
67 addon_modules_dir='/usr/share/ifupdownaddons'
14dc390d 68 addon_modules_configfile='/var/lib/ifupdownaddons/addons.conf'
a6f80f0e 69
70 # iface dictionary in the below format:
71 # { '<ifacename>' : [<ifaceobject1>, <ifaceobject2> ..] }
72 # eg:
53b00224 73 # { 'swp1' : [<iface swp1>, <iface swp2> ..] }
a6f80f0e 74 #
75 # Each ifaceobject corresponds to a configuration block for
76 # that interface
53b00224 77 # The value in the dictionary is a list because the network
78 # interface configuration file supports more than one iface section
79 # in the interfaces file
a6f80f0e 80 ifaceobjdict = OrderedDict()
81
a6f80f0e 82 # iface dictionary representing the curr running state of an iface
83 # in the below format:
84 # {'<ifacename>' : <ifaceobject>}
85 ifaceobjcurrdict = OrderedDict()
86
be0b20f2 87 # Dictionary representing operation and modules
88 # for every operation
89 module_ops = OrderedDict([('pre-up', []),
d08d5f54 90 ('up' , []),
91 ('post-up' , []),
92 ('query-checkcurr', []),
93 ('query-running', []),
94 ('query-dependency', []),
75730152 95 ('query', []),
96 ('query-raw', []),
d08d5f54 97 ('pre-down', []),
98 ('down' , []),
99 ('post-down' , [])])
37c0543d 100
101 # For old style /etc/network/ bash scripts
be0b20f2 102 script_ops = OrderedDict([('pre-up', []),
d08d5f54 103 ('up' , []),
104 ('post-up' , []),
105 ('pre-down', []),
106 ('down' , []),
107 ('post-down' , [])])
a6f80f0e 108
be0b20f2 109 # Handlers for ops that ifupdown2 owns
110 def run_up(self, ifaceobj):
a070c90e
RP
111 if (ifaceobj.addr_method and
112 ifaceobj.addr_method == 'manual'):
113 return
114 if self._delay_admin_state:
115 self._delay_admin_state_iface_queue.append(ifaceobj.name)
116 return
7f045fd8
RP
117 # If this object is a link slave, ie its link is controlled
118 # by its link master interface, then dont set the link state.
119 # But do allow user to change state of the link if the interface
120 # is already with its link master (hence the master check).
7e2e64fb 121 if ifaceobj.link_type == ifaceLinkType.LINK_SLAVE:
7f045fd8 122 return
a070c90e 123 if not self.link_exists(ifaceobj.name):
7e2e64fb 124 return
a070c90e 125 self.link_up(ifaceobj.name)
be0b20f2 126
127 def run_down(self, ifaceobj):
a070c90e
RP
128 if (ifaceobj.addr_method and
129 ifaceobj.addr_method == 'manual'):
130 return
131 if self._delay_admin_state:
132 self._delay_admin_state_iface_queue.append(ifaceobj.name)
133 return
7f045fd8
RP
134 # If this object is a link slave, ie its link is controlled
135 # by its link master interface, then dont set the link state.
136 # But do allow user to change state of the link if the interface
137 # is already with its link master (hence the master check).
7e2e64fb
RP
138 if ifaceobj.link_type == ifaceLinkType.LINK_SLAVE:
139 return
a070c90e 140 if not self.link_exists(ifaceobj.name):
7e2e64fb 141 return
a070c90e 142 self.link_down(ifaceobj.name)
be0b20f2 143
31a5f4c3 144 # ifupdown object interface operation handlers
be0b20f2 145 ops_handlers = OrderedDict([('up', run_up),
146 ('down', run_down)])
a6f80f0e 147
cb7cc592 148 def run_sched_ifaceobj_posthook(self, ifaceobj, op):
5c721925 149 if ((ifaceobj.priv_flags & self.BUILTIN) or
150 (ifaceobj.priv_flags & self.NOCONFIG)):
151 return
20dd6242 152 if self.STATEMANAGER_UPDATE:
cb7cc592 153 self.statemanager.ifaceobj_sync(ifaceobj, op)
31a5f4c3 154
155 # ifupdown object interface scheduler pre and posthooks
156 sched_hooks = {'posthook' : run_sched_ifaceobj_posthook}
157
14dc390d 158 def __init__(self, config={},
159 force=False, dryrun=False, nowait=False,
cca03c30 160 perfmode=False, withdepends=False, njobs=1,
14dc390d 161 cache=False, addons_enable=True, statemanager_enable=True,
3dcc1d0e 162 interfacesfile='/etc/network/interfaces',
163 interfacesfileiobuf=None,
164 interfacesfileformat='native'):
2c0ad8b3
RP
165 """This member function initializes the ifupdownmain object.
166
167 Kwargs:
168 config (dict): config dict from /etc/network/ifupdown2/ifupdown2.conf
169 force (bool): force interface configuration
170 dryrun (bool): dryrun interface configuration
171 withdepends (bool): apply interface configuration on all depends
172 interfacesfile (str): interfaces file. default is /etc/network/interfaces
173 interfacesfileformat (str): default is 'native'. Other choices are 'json'
174
175 Raises:
176 AttributeError, KeyError """
177
a6f80f0e 178 self.logger = logging.getLogger('ifupdown')
eab25b7c 179 self.FORCE = force
180 self.DRYRUN = dryrun
181 self.NOWAIT = nowait
182 self.PERFMODE = perfmode
cca03c30 183 self.WITH_DEPENDS = withdepends
20dd6242 184 self.STATEMANAGER_ENABLE = statemanager_enable
739f665b 185 self.CACHE = cache
14dc390d 186 self.interfacesfile = interfacesfile
3dcc1d0e 187 self.interfacesfileiobuf = interfacesfileiobuf
188 self.interfacesfileformat = interfacesfileformat
14dc390d 189 self.config = config
190 self.logger.debug(self.config)
a690dfae 191
2da58137
RP
192 self.type = ifaceType.UNKNOWN
193
a690dfae 194 # Can be used to provide hints for caching
195 self.CACHE_FLAGS = 0x0
37c0543d 196 self._DELETE_DEPENDENT_IFACES_WITH_NOCONFIG = False
20dd6242 197 self.ADDONS_ENABLE = addons_enable
eab25b7c 198
84ca006f
RP
199 # Copy flags into ifupdownFlags
200 # XXX: before we transition fully to ifupdownFlags
201 ifupdownFlags.FORCE = force
202 ifupdownFlags.DRYRUN = dryrun
203 ifupdownFlags.NOWAIT = nowait
204 ifupdownFlags.PERFMODE = perfmode
205 ifupdownFlags.CACHE = cache
206
a6f80f0e 207 self.ifaces = OrderedDict()
eab25b7c 208 self.njobs = njobs
a6f80f0e 209 self.pp = pprint.PrettyPrinter(indent=4)
37c0543d 210 self.modules = OrderedDict({})
d08d5f54 211 self.module_attrs = {}
20dd6242 212
37c0543d 213 self.load_addon_modules(self.addon_modules_dir)
e938bfec 214 if self.COMPAT_EXEC_SCRIPTS:
215 self.load_scripts(self.scripts_dir)
d08d5f54 216 self.dependency_graph = OrderedDict({})
a6f80f0e 217
8e113d63
RP
218 self._cache_no_repeats = {}
219
20dd6242 220 if self.STATEMANAGER_ENABLE:
221 try:
222 self.statemanager = stateManager()
223 self.statemanager.read_saved_state()
224 except Exception, e:
225 # XXX Maybe we should continue by ignoring old state
226 self.logger.warning('error reading state (%s)' %str(e))
227 raise
228 else:
229 self.STATEMANAGER_UPDATE = False
a070c90e
RP
230 self._delay_admin_state = True if self.config.get(
231 'delay_admin_state_change', '0') == '1' else False
232 self._delay_admin_state_iface_queue = []
cebe79c9
RP
233 if self._delay_admin_state:
234 self.logger.info('\'delay_admin_state_change\' is set. admin ' +
235 'state changes will be delayed till the end.')
236
237 self._link_master_slave = True if self.config.get(
a070c90e 238 'link_master_slave', '0') == '1' else False
cebe79c9
RP
239 if self._link_master_slave:
240 self.logger.info('\'link_master_slave\' is set. slave admin ' +
241 'state changes will be delayed till the ' +
242 'masters admin state change.')
a6f80f0e 243
61c4d724
RP
244 def link_master_slave_ignore_error(self, errorstr):
245 # If link master slave flag is set,
246 # there may be cases where the lowerdev may not be
247 # up resulting in 'Network is down' error
248 # This can happen if the lowerdev is a LINK_SLAVE
249 # of another interface which is not up yet
250 # example of such a case:
251 # bringing up a vlan on a bond interface and the bond
252 # is a LINK_SLAVE of a bridge (in other words the bond is
253 # part of a bridge) which is not up yet
254 if self._link_master_slave:
255 if 'Network is down':
256 return True
257 return False
258
31a5f4c3 259 def get_ifaceobjs(self, ifacename):
a6f80f0e 260 return self.ifaceobjdict.get(ifacename)
261
a9ab1b4f
RP
262 def get_ifaceobjs_saved(self, ifacename):
263 """ Return ifaceobjects from statemanager """
264 if self.STATEMANAGER_ENABLE:
265 return self.statemanager.get_ifaceobjs(ifacename)
266 else:
267 None
268
31a5f4c3 269 def get_ifaceobj_first(self, ifacename):
270 ifaceobjs = self.get_ifaceobjs(ifacename)
271 if ifaceobjs:
a6f80f0e 272 return ifaceobjs[0]
273 return None
274
c798b0f4 275 def get_ifacenames(self):
276 return self.ifaceobjdict.keys()
277
a6f80f0e 278 def get_iface_obj_last(self, ifacename):
279 return self.ifaceobjdict.get(ifacename)[-1]
280
a9ab1b4f 281
8c13865c
RP
282 def must_follow_upperifaces(self, ifacename):
283 #
284 # XXX: This bleeds the knowledge of iface
285 # types in the infrastructure module.
286 # Cant think of a better fix at the moment.
287 # In future maybe the module can set a flag
288 # to indicate if we should follow upperifaces
289 #
290 ifaceobj = self.get_ifaceobj_first(ifacename)
cb46a208 291 if ifaceobj.type == ifaceType.BRIDGE_VLAN:
8c13865c
RP
292 return False
293 return True
294
53b00224 295 def create_n_save_ifaceobj(self, ifacename, priv_flags=None,
296 increfcnt=False):
297 """ creates a iface object and adds it to the iface dictionary """
298 ifaceobj = iface()
299 ifaceobj.name = ifacename
300 ifaceobj.priv_flags = priv_flags
301 ifaceobj.auto = True
f3b69969
RP
302 if not self._link_master_slave:
303 ifaceobj.link_type = ifaceLinkType.LINK_NA
53b00224 304 if increfcnt:
305 ifaceobj.inc_refcnt()
306 self.ifaceobjdict[ifacename] = [ifaceobj]
307 return ifaceobj
308
d08d5f54 309 def create_n_save_ifaceobjcurr(self, ifaceobj):
923290bd 310 """ creates a copy of iface object and adds it to the iface
311 dict containing current iface objects
53b00224 312 """
739f665b 313 ifaceobjcurr = iface()
53b00224 314 ifaceobjcurr.name = ifaceobj.name
cb46a208 315 ifaceobjcurr.type = ifaceobj.type
62ddec8b 316 ifaceobjcurr.lowerifaces = ifaceobj.lowerifaces
317 ifaceobjcurr.priv_flags = ifaceobj.priv_flags
2cd06f78 318 ifaceobjcurr.auto = ifaceobj.auto
923290bd 319 self.ifaceobjcurrdict.setdefault(ifaceobj.name,
320 []).append(ifaceobjcurr)
d08d5f54 321 return ifaceobjcurr
a6f80f0e 322
923290bd 323 def get_ifaceobjcurr(self, ifacename, idx=0):
324 ifaceobjlist = self.ifaceobjcurrdict.get(ifacename)
325 if not ifaceobjlist:
326 return None
327 if not idx:
328 return ifaceobjlist
329 else:
330 return ifaceobjlist[idx]
a6f80f0e 331
739f665b 332 def get_ifaceobjrunning(self, ifacename):
333 return self.ifaceobjrunningdict.get(ifacename)
334
a6f80f0e 335 def get_iface_refcnt(self, ifacename):
53b00224 336 """ Return iface ref count """
a6f80f0e 337 max = 0
31a5f4c3 338 ifaceobjs = self.get_ifaceobjs(ifacename)
20dd6242 339 if not ifaceobjs:
340 return 0
a6f80f0e 341 for i in ifaceobjs:
62ddec8b 342 if i.refcnt > max:
343 max = i.refcnt
a6f80f0e 344 return max
345
d08d5f54 346 def is_iface_builtin_byname(self, ifacename):
cca03c30 347 """ Returns true if iface name is a builtin interface.
a6f80f0e 348
cca03c30 349 A builtin interface is an interface which ifupdown understands.
350 The following are currently considered builtin ifaces:
351 - vlan interfaces in the format <ifacename>.<vlanid>
a6f80f0e 352 """
d08d5f54 353 return '.' in ifacename
a6f80f0e 354
37c0543d 355 def is_ifaceobj_builtin(self, ifaceobj):
356 """ Returns true if iface name is a builtin interface.
357
358 A builtin interface is an interface which ifupdown understands.
359 The following are currently considered builtin ifaces:
360 - vlan interfaces in the format <ifacename>.<vlanid>
361 """
d08d5f54 362 return (ifaceobj.priv_flags & self.BUILTIN)
37c0543d 363
364 def is_ifaceobj_noconfig(self, ifaceobj):
53b00224 365 """ Returns true if iface object did not have a user defined config.
37c0543d 366
367 These interfaces appear only when they are dependents of interfaces
368 which have user defined config
369 """
d08d5f54 370 return (ifaceobj.priv_flags & self.NOCONFIG)
37c0543d 371
d08d5f54 372 def is_iface_noconfig(self, ifacename):
373 """ Returns true if iface has no config """
37c0543d 374
31a5f4c3 375 ifaceobj = self.get_ifaceobj_first(ifacename)
d08d5f54 376 if not ifaceobj: return True
d08d5f54 377 return self.is_ifaceobj_noconfig(ifaceobj)
378
7f045fd8 379 def preprocess_dependency_list(self, upperifaceobj, dlist, ops):
739f665b 380 """ We go through the dependency list and
381 delete or add interfaces from the interfaces dict by
382 applying the following rules:
383 if flag _DELETE_DEPENDENT_IFACES_WITH_NOCONFIG is True:
384 we only consider devices whose configuration was
385 specified in the network interfaces file. We delete
386 any interface whose config was not specified except
387 for vlan devices. vlan devices get special treatment.
388 Even if they are not present they are created and added
389 to the ifacesdict
390 elif flag _DELETE_DEPENDENT_IFACES_WITH_NOCONFIG is False:
391 we create objects for all dependent devices that are not
392 present in the ifacesdict
393 """
a6f80f0e 394 del_list = []
395
a6f80f0e 396 for d in dlist:
31a5f4c3 397 dilist = self.get_ifaceobjs(d)
d08d5f54 398 if not dilist:
7f045fd8 399 ni = None
d08d5f54 400 if self.is_iface_builtin_byname(d):
a070c90e
RP
401 ni = self.create_n_save_ifaceobj(d,
402 self.BUILTIN | self.NOCONFIG, True)
f3215127 403 elif not self._DELETE_DEPENDENT_IFACES_WITH_NOCONFIG:
7f045fd8
RP
404 ni = self.create_n_save_ifaceobj(d, self.NOCONFIG,
405 True)
a6f80f0e 406 else:
a6f80f0e 407 del_list.append(d)
7f045fd8
RP
408 if ni:
409 ni.add_to_upperifaces(upperifaceobj.name)
c9bba753
RP
410 if upperifaceobj.link_type == ifaceLinkType.LINK_MASTER:
411 ni.link_type = ifaceLinkType.LINK_SLAVE
a6f80f0e 412 else:
413 for di in dilist:
414 di.inc_refcnt()
7f045fd8 415 di.add_to_upperifaces(upperifaceobj.name)
33a2e9e9 416 if upperifaceobj.link_type == ifaceLinkType.LINK_MASTER:
c9bba753 417 di.link_type = ifaceLinkType.LINK_SLAVE
a6f80f0e 418 for d in del_list:
419 dlist.remove(d)
420
2da58137 421 def query_dependents(self, ifaceobj, ops, ifacenames, type=None):
a6f80f0e 422 """ Gets iface dependents by calling into respective modules """
41febf89 423 ret_dlist = []
a6f80f0e 424
20dd6242 425 # Get dependents for interface by querying respective modules
ee3fcf44 426 for module in self.modules.values():
7949b8a5 427 try:
428 if ops[0] == 'query-running':
429 if (not hasattr(module,
430 'get_dependent_ifacenames_running')):
431 continue
432 dlist = module.get_dependent_ifacenames_running(ifaceobj)
433 else:
434 if (not hasattr(module, 'get_dependent_ifacenames')):
435 continue
436 dlist = module.get_dependent_ifacenames(ifaceobj,
ee3fcf44 437 ifacenames)
7949b8a5 438 except Exception, e:
439 self.logger.warn('%s: error getting dependent interfaces (%s)'
440 %(ifaceobj.name, str(e)))
441 dlist = None
442 pass
41febf89 443 if dlist: ret_dlist.extend(dlist)
84ca006f 444 return list(set(ret_dlist))
20dd6242 445
e1601369
RP
446 def populate_dependency_info(self, ops, ifacenames=None):
447 """ recursive function to generate iface dependency info """
448
449 if not ifacenames:
450 ifacenames = self.ifaceobjdict.keys()
451
452 iqueue = deque(ifacenames)
453 while iqueue:
454 i = iqueue.popleft()
455 # Go through all modules and find dependent ifaces
456 dlist = None
457 ifaceobj = self.get_ifaceobj_first(i)
458 if not ifaceobj:
459 continue
460 dlist = ifaceobj.lowerifaces
461 if not dlist:
462 dlist = self.query_dependents(ifaceobj, ops, ifacenames)
463 else:
464 continue
465 if dlist:
7f045fd8 466 self.preprocess_dependency_list(ifaceobj,
e1601369
RP
467 dlist, ops)
468 ifaceobj.lowerifaces = dlist
469 [iqueue.append(d) for d in dlist]
470 if not self.dependency_graph.get(i):
471 self.dependency_graph[i] = dlist
472
8e113d63
RP
473 def _check_config_no_repeats(self, ifaceobj):
474 """ check if object has an attribute that is
475 restricted to a single object in the system.
476 if yes, warn and return """
477 for k,v in self._cache_no_repeats.items():
478 iv = ifaceobj.config.get(k)
479 if iv and iv[0] == v:
480 self.logger.error('ignoring interface %s. ' %ifaceobj.name +
481 'Only one object with attribute ' +
482 '\'%s %s\' allowed.' %(k, v))
483 return True
484 for k, v in self.config.get('no_repeats', {}).items():
485 iv = ifaceobj.config.get(k)
486 if iv and iv[0] == v:
487 self._cache_no_repeats[k] = v
488 return False
a6f80f0e 489
41febf89 490 def _save_iface(self, ifaceobj):
8e113d63
RP
491 if self._check_config_no_repeats(ifaceobj):
492 return
7e2e64fb
RP
493 if not self._link_master_slave:
494 ifaceobj.link_type = ifaceLinkType.LINK_NA
679e6567
RP
495 currentifaceobjlist = self.ifaceobjdict.get(ifaceobj.name)
496 if not currentifaceobjlist:
497 self.ifaceobjdict[ifaceobj.name]= [ifaceobj]
498 return
499 if ifaceobj.compare(currentifaceobjlist[0]):
500 self.logger.warn('duplicate interface %s found' %ifaceobj.name)
501 return
8e113d63
RP
502 if currentifaceobjlist[0].type == ifaceobj.type:
503 currentifaceobjlist[0].flags |= iface.HAS_SIBLINGS
504 ifaceobj.flags |= iface.HAS_SIBLINGS
679e6567 505 self.ifaceobjdict[ifaceobj.name].append(ifaceobj)
41febf89 506
3dcc1d0e 507 def _iface_configattr_syntax_checker(self, attrname, attrval):
d08d5f54 508 for m, mdict in self.module_attrs.items():
7949b8a5 509 if not mdict:
510 continue
d08d5f54 511 attrsdict = mdict.get('attrs')
7949b8a5 512 try:
513 if attrsdict.get(attrname):
514 return True
515 except AttributeError:
516 pass
d08d5f54 517 return False
518
3dcc1d0e 519 def _ifaceobj_syntax_checker(self, ifaceobj):
520 err = False
8e113d63 521 for attrname, attrvalue in ifaceobj.config.items():
3dcc1d0e 522 found = False
523 for k, v in self.module_attrs.items():
524 if v and v.get('attrs', {}).get(attrname):
525 found = True
526 break
527 if not found:
528 err = True
529 self.logger.warn('%s: unsupported attribute \'%s\'' %attrname)
530 continue
531 return err
532
14dc390d 533 def read_iface_config(self):
a6f80f0e 534 """ Reads default network interface config /etc/network/interfaces. """
14dc390d 535 nifaces = networkInterfaces(self.interfacesfile,
3dcc1d0e 536 self.interfacesfileiobuf,
537 self.interfacesfileformat,
14dc390d 538 template_engine=self.config.get('template_engine'),
539 template_lookuppath=self.config.get('template_lookuppath'))
d08d5f54 540 nifaces.subscribe('iface_found', self._save_iface)
3dcc1d0e 541 nifaces.subscribe('validateifaceattr',
542 self._iface_configattr_syntax_checker)
543 nifaces.subscribe('validateifaceobj', self._ifaceobj_syntax_checker)
a6f80f0e 544 nifaces.load()
545
a6f80f0e 546 def read_old_iface_config(self):
14dc390d 547 """ Reads the saved iface config instead of default iface config.
548 And saved iface config is already read by the statemanager """
cb7cc592 549 self.ifaceobjdict = copy.deepcopy(self.statemanager.ifaceobjdict)
a6f80f0e 550
53b00224 551 def _load_addon_modules_config(self):
552 """ Load addon modules config file """
a6f80f0e 553
37c0543d 554 with open(self.addon_modules_configfile, 'r') as f:
555 lines = f.readlines()
556 for l in lines:
c0071225 557 litems = l.rstrip(' \n\t\r').split(',')
37c0543d 558 operation = litems[0]
559 mname = litems[1]
be0b20f2 560 self.module_ops[operation].append(mname)
37c0543d 561
562 def load_addon_modules(self, modules_dir):
a6f80f0e 563 """ load python modules from modules_dir
564
565 Default modules_dir is /usr/share/ifupdownmodules
566
567 """
a6f80f0e 568 self.logger.info('loading builtin modules from %s' %modules_dir)
53b00224 569 self._load_addon_modules_config()
a6f80f0e 570 if not modules_dir in sys.path:
37c0543d 571 sys.path.append(modules_dir)
a6f80f0e 572 try:
be0b20f2 573 for op, mlist in self.module_ops.items():
d08d5f54 574 for mname in mlist:
53b00224 575 if self.modules.get(mname):
d08d5f54 576 continue
577 mpath = modules_dir + '/' + mname + '.py'
578 if os.path.exists(mpath):
579 try:
580 m = __import__(mname)
581 mclass = getattr(m, mname)
582 except:
583 raise
584 minstance = mclass(force=self.FORCE,
585 dryrun=self.DRYRUN,
586 nowait=self.NOWAIT,
587 perfmode=self.PERFMODE,
a690dfae 588 cache=self.CACHE,
589 cacheflags=self.CACHE_FLAGS)
d08d5f54 590 self.modules[mname] = minstance
53b00224 591 try:
d08d5f54 592 self.module_attrs[mname] = minstance.get_modinfo()
53b00224 593 except:
594 pass
a6f80f0e 595 except:
596 raise
597
37c0543d 598 # Assign all modules to query operations
be0b20f2 599 self.module_ops['query-checkcurr'] = self.modules.keys()
600 self.module_ops['query-running'] = self.modules.keys()
601 self.module_ops['query-dependency'] = self.modules.keys()
602 self.module_ops['query'] = self.modules.keys()
603 self.module_ops['query-raw'] = self.modules.keys()
d08d5f54 604
14dc390d 605
53b00224 606 def _modules_help(self):
607 """ Prints addon modules supported syntax """
608
d08d5f54 609 indent = ' '
610 for m, mdict in self.module_attrs.items():
611 if not mdict:
612 continue
613 print('%s: %s' %(m, mdict.get('mhelp')))
614 attrdict = mdict.get('attrs')
615 if not attrdict:
616 continue
617 try:
618 for attrname, attrvaldict in attrdict.items():
619 if attrvaldict.get('compat', False):
620 continue
621 print('%s%s' %(indent, attrname))
622 print('%shelp: %s' %(indent + ' ',
623 attrvaldict.get('help', '')))
624 print ('%srequired: %s' %(indent + ' ',
625 attrvaldict.get('required', False)))
626 default = attrvaldict.get('default')
627 if default:
628 print('%sdefault: %s' %(indent + ' ', default))
629
630 validrange = attrvaldict.get('validrange')
631 if validrange:
1b0b81a2 632 print('%svalidrange: %s-%s'
7949b8a5 633 %(indent + ' ', validrange[0], validrange[1]))
d08d5f54 634
635 validvals = attrvaldict.get('validvals')
636 if validvals:
637 print('%svalidvals: %s'
638 %(indent + ' ', ','.join(validvals)))
639
640 examples = attrvaldict.get('example')
641 if not examples:
642 continue
a6f80f0e 643
d08d5f54 644 print '%sexample:' %(indent + ' ')
645 for e in examples:
646 print '%s%s' %(indent + ' ', e)
647 except:
648 pass
649 print ''
650
37c0543d 651 def load_scripts(self, modules_dir):
a6f80f0e 652 """ loading user modules from /etc/network/.
653
654 Note that previously loaded python modules override modules found
655 under /etc/network if any
656
657 """
658
37c0543d 659 self.logger.info('looking for user scripts under %s' %modules_dir)
be0b20f2 660 for op, mlist in self.script_ops.items():
d08d5f54 661 msubdir = modules_dir + '/if-%s.d' %op
662 self.logger.info('loading scripts under %s ...' %msubdir)
663 try:
664 module_list = os.listdir(msubdir)
665 for module in module_list:
666 if self.modules.get(module) is not None:
667 continue
be0b20f2 668 self.script_ops[op].append(
a6f80f0e 669 msubdir + '/' + module)
d08d5f54 670 except:
f802fe3c 671 # continue reading
672 pass
a6f80f0e 673
ad25e7bb 674 def _sched_ifaces(self, ifacenames, ops, skipupperifaces=False):
c798b0f4 675 self.logger.debug('scheduling \'%s\' for %s'
d08d5f54 676 %(str(ops), str(ifacenames)))
7538dc77 677 self._pretty_print_ordered_dict('dependency graph',
678 self.dependency_graph)
c798b0f4 679 return ifaceScheduler.sched_ifaces(self, ifacenames, ops,
680 dependency_graph=self.dependency_graph,
d08d5f54 681 order=ifaceSchedulerFlags.INORDER
682 if 'down' in ops[0]
c798b0f4 683 else ifaceSchedulerFlags.POSTORDER,
ad25e7bb
RP
684 followdependents=True if self.WITH_DEPENDS else False,
685 skipupperifaces=skipupperifaces)
a6f80f0e 686
41febf89
RP
687 def _render_ifacename(self, ifacename):
688 new_ifacenames = []
679e6567 689 vlan_match = re.match("^([\d]+)-([\d]+)", ifacename)
41febf89
RP
690 if vlan_match:
691 vlan_groups = vlan_match.groups()
692 if vlan_groups[0] and vlan_groups[1]:
679e6567 693 [new_ifacenames.append('%d' %v)
41febf89
RP
694 for v in range(int(vlan_groups[0]),
695 int(vlan_groups[1])+1)]
696 return new_ifacenames
697
698 def _preprocess_ifacenames(self, ifacenames):
a6f80f0e 699 """ validates interface list for config existance.
700
701 returns -1 if one or more interface not found. else, returns 0
702
703 """
41febf89 704 new_ifacenames = []
a6f80f0e 705 err_iface = ''
706 for i in ifacenames:
31a5f4c3 707 ifaceobjs = self.get_ifaceobjs(i)
708 if not ifaceobjs:
41febf89 709 # if name not available, render interface name and check again
679e6567 710 rendered_ifacenames = utils.expand_iface_range(i)
41febf89
RP
711 if rendered_ifacenames:
712 for ri in rendered_ifacenames:
713 ifaceobjs = self.get_ifaceobjs(ri)
714 if not ifaceobjs:
715 err_iface += ' ' + ri
716 else:
717 new_ifacenames.append(ri)
718 else:
719 err_iface += ' ' + i
720 else:
721 new_ifacenames.append(i)
fe0a57d3 722 if err_iface:
31c58787 723 raise Exception('cannot find interfaces:%s' %err_iface)
41febf89 724 return new_ifacenames
a6f80f0e 725
53b00224 726 def _iface_whitelisted(self, auto, allow_classes, excludepats, ifacename):
a6f80f0e 727 """ Checks if interface is whitelisted depending on set of parameters.
728
a6f80f0e 729 interfaces are checked against the allow_classes and auto lists.
730
731 """
fe0a57d3 732 if excludepats:
3e8ee54f 733 for e in excludepats:
d08d5f54 734 if re.search(e, ifacename):
3e8ee54f 735 return False
31a5f4c3 736 ifaceobjs = self.get_ifaceobjs(ifacename)
737 if not ifaceobjs:
a6f80f0e 738 self.logger.debug('iface %s' %ifacename + ' not found')
739 return False
a6f80f0e 740 # We check classes first
fe0a57d3 741 if allow_classes:
a6f80f0e 742 for i in ifaceobjs:
62ddec8b 743 if i.classes:
3e8ee54f 744 common = Set([allow_classes]).intersection(
62ddec8b 745 Set(i.classes))
fe0a57d3 746 if common:
a6f80f0e 747 return True
748 return False
d08d5f54 749 if auto:
a6f80f0e 750 for i in ifaceobjs:
62ddec8b 751 if i.auto:
a6f80f0e 752 return True
753 return False
a6f80f0e 754 return True
755
53b00224 756 def _compat_conv_op_to_mode(self, op):
757 """ Returns old op name to work with existing scripts """
758 if op == 'pre-up':
759 return 'start'
760 elif op == 'pre-down':
761 return 'stop'
762 else:
763 return op
764
a6f80f0e 765 def generate_running_env(self, ifaceobj, op):
739f665b 766 """ Generates a dictionary with env variables required for
767 an interface. Used to support script execution for interfaces.
a6f80f0e 768 """
769
770 cenv = None
62ddec8b 771 iface_env = ifaceobj.env
772 if iface_env:
a6f80f0e 773 cenv = os.environ
d08d5f54 774 if cenv:
a6f80f0e 775 cenv.update(iface_env)
776 else:
777 cenv = iface_env
53b00224 778 cenv['MODE'] = self._compat_conv_op_to_mode(op)
a6f80f0e 779 return cenv
780
53b00224 781 def _save_state(self):
20dd6242 782 if not self.STATEMANAGER_ENABLE or not self.STATEMANAGER_UPDATE:
783 return
784 try:
785 # Update persistant iface states
786 self.statemanager.save_state()
787 except Exception, e:
788 if self.logger.isEnabledFor(logging.DEBUG):
789 t = sys.exc_info()[2]
790 traceback.print_tb(t)
791 self.logger.warning('error saving state (%s)' %str(e))
792
2da58137
RP
793 def set_type(self, type):
794 if type == 'iface':
795 self.type = ifaceType.IFACE
796 elif type == 'vlan':
797 self.type = ifaceType.BRIDGE_VLAN
798 else:
799 self.type = ifaceType.UNKNOWN
800
a070c90e
RP
801 def _process_delay_admin_state_queue(self, op):
802 if not self._delay_admin_state_iface_queue:
803 return
804 if op == 'up':
805 func = self.link_up
806 elif op == 'down':
807 func = self.link_down
808 else:
809 return
810 for i in self._delay_admin_state_iface_queue:
811 try:
812 if self.link_exists(i):
813 func(i)
814 except Exception, e:
815 self.logger.warn(str(e))
816 pass
817
d08d5f54 818 def up(self, ops, auto=False, allow_classes=None, ifacenames=None,
2da58137 819 excludepats=None, printdependency=None, syntaxcheck=False,
ad25e7bb 820 type=None, skipupperifaces=False):
2c0ad8b3
RP
821 """This brings the interface(s) up
822
823 Args:
41febf89
RP
824 ops (list): list of ops to perform on the interface(s).
825 Eg: ['pre-up', 'up', 'post-up'
2c0ad8b3
RP
826
827 Kwargs:
828 auto (bool): act on interfaces marked auto
829 allow_classes (list): act on interfaces belonging to classes in the list
830 ifacenames (list): act on interfaces specified in this list
831 excludepats (list): list of patterns of interfaces to exclude
832 syntaxcheck (bool): only perform syntax check
833 """
53b00224 834
2da58137
RP
835 self.set_type(type)
836
5ee3e1a8
RP
837 if allow_classes:
838 self.IFACE_CLASS = True
7538dc77 839 if not self.ADDONS_ENABLE: self.STATEMANAGER_UPDATE = False
d08d5f54 840 if auto:
a6f80f0e 841 self.ALL = True
cca03c30 842 self.WITH_DEPENDS = True
d08d5f54 843 try:
844 self.read_iface_config()
62ddec8b 845 except Exception:
d08d5f54 846 raise
a6f80f0e 847
9dce3561 848 # If only syntax check was requested, return here
849 if syntaxcheck:
850 return
851
31a5f4c3 852 if ifacenames:
41febf89 853 ifacenames = self._preprocess_ifacenames(ifacenames)
a6f80f0e 854
855 # if iface list not given by user, assume all from config file
31a5f4c3 856 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
a6f80f0e 857
858 # filter interfaces based on auto and allow classes
cca03c30 859 filtered_ifacenames = [i for i in ifacenames
53b00224 860 if self._iface_whitelisted(auto, allow_classes,
d08d5f54 861 excludepats, i)]
fe0a57d3 862 if not filtered_ifacenames:
d08d5f54 863 raise Exception('no ifaces found matching given allow lists')
a6f80f0e 864
20dd6242 865 if printdependency:
c798b0f4 866 self.populate_dependency_info(ops, filtered_ifacenames)
d08d5f54 867 self.print_dependency(filtered_ifacenames, printdependency)
739f665b 868 return
cca03c30 869 else:
c798b0f4 870 self.populate_dependency_info(ops)
871
525f0a30 872 try:
ad25e7bb
RP
873 self._sched_ifaces(filtered_ifacenames, ops,
874 skipupperifaces=skipupperifaces)
525f0a30 875 finally:
a070c90e 876 self._process_delay_admin_state_queue('up')
525f0a30 877 if not self.DRYRUN and self.ADDONS_ENABLE:
878 self._save_state()
a6f80f0e 879
d08d5f54 880 def down(self, ops, auto=False, allow_classes=None, ifacenames=None,
2da58137
RP
881 excludepats=None, printdependency=None, usecurrentconfig=False,
882 type=None):
53b00224 883 """ down an interface """
884
2da58137
RP
885 self.set_type(type)
886
5ee3e1a8
RP
887 if allow_classes:
888 self.IFACE_CLASS = True
7538dc77 889 if not self.ADDONS_ENABLE: self.STATEMANAGER_UPDATE = False
d08d5f54 890 if auto:
891 self.ALL = True
892 self.WITH_DEPENDS = True
5c721925 893 # For down we need to look at old state, unless usecurrentconfig
894 # is set
895 if (not usecurrentconfig and self.STATEMANAGER_ENABLE and
53b00224 896 self.statemanager.ifaceobjdict):
31a5f4c3 897 # Since we are using state manager objects,
898 # skip the updating of state manager objects
5c721925 899 self.logger.debug('Looking at old state ..')
d08d5f54 900 self.read_old_iface_config()
fe0a57d3 901 else:
d08d5f54 902 # If no old state available
d08d5f54 903 try:
904 self.read_iface_config()
905 except Exception, e:
906 raise Exception('error reading iface config (%s)' %str(e))
d08d5f54 907 if ifacenames:
908 # If iface list is given by the caller, always check if iface
909 # is present
31c58787 910 try:
41febf89 911 ifacenames = self._preprocess_ifacenames(ifacenames)
31c58787 912 except Exception, e:
913 raise Exception('%s' %str(e) +
914 ' (interface was probably never up ?)')
915
d08d5f54 916 # if iface list not given by user, assume all from config file
fe0a57d3 917 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
53b00224 918
d08d5f54 919 # filter interfaces based on auto and allow classes
920 filtered_ifacenames = [i for i in ifacenames
53b00224 921 if self._iface_whitelisted(auto, allow_classes,
d08d5f54 922 excludepats, i)]
fe0a57d3 923 if not filtered_ifacenames:
c0071225 924 raise Exception('no ifaces found matching given allow lists ' +
41febf89 925 '(or interfaces were probably never up ?)')
14dc390d 926
d08d5f54 927 if printdependency:
99b212b0 928 self.populate_dependency_info(ops, filtered_ifacenames)
d08d5f54 929 self.print_dependency(filtered_ifacenames, printdependency)
930 return
99b212b0 931 else:
932 self.populate_dependency_info(ops)
525f0a30 933
934 try:
935 self._sched_ifaces(filtered_ifacenames, ops)
936 finally:
a070c90e 937 self._process_delay_admin_state_queue('down')
525f0a30 938 if not self.DRYRUN and self.ADDONS_ENABLE:
939 self._save_state()
d08d5f54 940
941 def query(self, ops, auto=False, allow_classes=None, ifacenames=None,
739f665b 942 excludepats=None, printdependency=None,
2da58137 943 format='native', type=None):
53b00224 944 """ query an interface """
945
2da58137
RP
946 self.set_type(type)
947
5ee3e1a8
RP
948 if allow_classes:
949 self.IFACE_CLASS = True
5c721925 950 if self.STATEMANAGER_ENABLE and ops[0] == 'query-savedstate':
951 return self.statemanager.dump_pretty(ifacenames)
20dd6242 952 self.STATEMANAGER_UPDATE = False
d08d5f54 953 if auto:
739f665b 954 self.logger.debug('setting flag ALL')
955 self.ALL = True
37c0543d 956 self.WITH_DEPENDS = True
739f665b 957
d08d5f54 958 if ops[0] == 'query-syntax':
53b00224 959 self._modules_help()
d08d5f54 960 return
961 elif ops[0] == 'query-running':
739f665b 962 # create fake devices to all dependents that dont have config
37c0543d 963 map(lambda i: self.create_n_save_ifaceobj(i, self.NOCONFIG),
964 ifacenames)
739f665b 965 else:
966 try:
967 self.read_iface_config()
968 except Exception:
969 raise
970
53b00224 971 if ifacenames and ops[0] != 'query-running':
41febf89
RP
972 # If iface list is given, always check if iface is present
973 ifacenames = self._preprocess_ifacenames(ifacenames)
739f665b 974
975 # if iface list not given by user, assume all from config file
31a5f4c3 976 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
739f665b 977
978 # filter interfaces based on auto and allow classes
d08d5f54 979 if ops[0] == 'query-running':
739f665b 980 filtered_ifacenames = ifacenames
981 else:
982 filtered_ifacenames = [i for i in ifacenames
53b00224 983 if self._iface_whitelisted(auto, allow_classes,
d08d5f54 984 excludepats, i)]
fe0a57d3 985 if not filtered_ifacenames:
739f665b 986 raise Exception('no ifaces found matching ' +
987 'given allow lists')
37c0543d 988
e1601369 989 self.populate_dependency_info(ops)
d08d5f54 990 if ops[0] == 'query-dependency' and printdependency:
991 self.print_dependency(filtered_ifacenames, printdependency)
992 return
739f665b 993
75730152 994 if ops[0] == 'query':
995 return self.print_ifaceobjs_pretty(filtered_ifacenames, format)
996 elif ops[0] == 'query-raw':
997 return self.print_ifaceobjs_raw(filtered_ifacenames)
998
53b00224 999 self._sched_ifaces(filtered_ifacenames, ops)
739f665b 1000
d08d5f54 1001 if ops[0] == 'query-checkcurr':
1002 ret = self.print_ifaceobjscurr_pretty(filtered_ifacenames, format)
739f665b 1003 if ret != 0:
1004 # if any of the object has an error, signal that silently
1005 raise Exception('')
d08d5f54 1006 elif ops[0] == 'query-running':
1007 self.print_ifaceobjsrunning_pretty(filtered_ifacenames, format)
739f665b 1008 return
1009
2da58137
RP
1010 def _reload_currentlyup(self, upops, downops, auto=True, allow=None,
1011 ifacenames=None, excludepats=None, usecurrentconfig=False,
1012 **extra_args):
1013 """ reload currently up interfaces """
739f665b 1014 allow_classes = []
c0071225 1015 new_ifaceobjdict = {}
739f665b 1016
2da58137
RP
1017 # Override auto to true
1018 auto = True
97382e88
RP
1019 if auto:
1020 self.ALL = True
1021 self.WITH_DEPENDS = True
2da58137
RP
1022 try:
1023 self.read_iface_config()
1024 except:
1025 raise
2da58137
RP
1026 if not self.ifaceobjdict:
1027 self.logger.warn("nothing to reload ..exiting.")
1028 return
2da58137
RP
1029 already_up_ifacenames = []
1030 # generate dependency graph of interfaces
1031 self.populate_dependency_info(upops)
1032 if (not usecurrentconfig and self.STATEMANAGER_ENABLE
1033 and self.statemanager.ifaceobjdict):
1034 already_up_ifacenames = self.statemanager.ifaceobjdict.keys()
1035
1036 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
1037 filtered_ifacenames = [i for i in ifacenames
1038 if self._iface_whitelisted(auto, allow_classes,
1039 excludepats, i)]
1040
1041 # Get already up interfaces that still exist in the interfaces file
1042 already_up_ifacenames_not_present = Set(
1043 already_up_ifacenames).difference(ifacenames)
1044 already_up_ifacenames_still_present = Set(
1045 already_up_ifacenames).difference(
1046 already_up_ifacenames_not_present)
1047 interfaces_to_up = Set(already_up_ifacenames_still_present).union(
1048 filtered_ifacenames)
1049
1050 if (already_up_ifacenames_not_present and
1051 self.config.get('ifreload_currentlyup_down_notpresent') == '1'):
1052 self.logger.info('reload: schedule down on interfaces: %s'
1053 %str(already_up_ifacenames_not_present))
1054
1055 # Save a copy of new iface objects and dependency_graph
1056 new_ifaceobjdict = dict(self.ifaceobjdict)
1057 new_dependency_graph = dict(self.dependency_graph)
1058
1059 # old interface config is read into self.ifaceobjdict
1060 self.read_old_iface_config()
1061
1062 # reinitialize dependency graph
1063 self.dependency_graph = OrderedDict({})
1064 self.populate_dependency_info(downops,
1065 already_up_ifacenames_not_present)
1066 self._sched_ifaces(already_up_ifacenames_not_present, downops)
1067 else:
1068 self.logger.debug('no interfaces to down ..')
1069
1070 # Now, run 'up' with new config dict
1071 # reset statemanager update flag to default
1072 if new_ifaceobjdict:
1073 self.ifaceobjdict = new_ifaceobjdict
1074 self.dependency_graph = new_dependency_graph
1075
1076 if not self.ifaceobjdict:
1077 return
1078 self.logger.info('reload: scheduling up on interfaces: %s'
1079 %str(interfaces_to_up))
1080 self._sched_ifaces(interfaces_to_up, upops)
1081 if self.DRYRUN:
1082 return
1083 self._save_state()
1084
1085 def _reload_default(self, upops, downops, auto=False, allow=None,
1086 ifacenames=None, excludepats=None, usecurrentconfig=False,
1087 **extra_args):
1088 """ reload interface config """
1089 allow_classes = []
1090 new_ifaceobjdict = {}
739f665b 1091
97382e88
RP
1092 if auto:
1093 self.ALL = True
1094 self.WITH_DEPENDS = True
739f665b 1095 try:
1096 self.read_iface_config()
20dd6242 1097 except:
739f665b 1098 raise
1099
c0071225
RP
1100 if not self.ifaceobjdict:
1101 self.logger.warn("nothing to reload ..exiting.")
1102 return
37c0543d 1103 # generate dependency graph of interfaces
c798b0f4 1104 self.populate_dependency_info(upops)
14dc390d 1105 if (not usecurrentconfig and self.STATEMANAGER_ENABLE
1106 and self.statemanager.ifaceobjdict):
1107 # Save a copy of new iface objects and dependency_graph
1108 new_ifaceobjdict = dict(self.ifaceobjdict)
1109 new_dependency_graph = dict(self.dependency_graph)
37c0543d 1110
739f665b 1111 # if old state is present, read old state and mark op for 'down'
1112 # followed by 'up' aka: reload
37c0543d 1113 # old interface config is read into self.ifaceobjdict
739f665b 1114 self.read_old_iface_config()
1115 op = 'reload'
1116 else:
1117 # oldconfig not available, continue with 'up' with new config
1118 op = 'up'
1119
20dd6242 1120 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
fe0a57d3 1121 if op == 'reload' and ifacenames:
739f665b 1122 filtered_ifacenames = [i for i in ifacenames
53b00224 1123 if self._iface_whitelisted(auto, allow_classes,
d08d5f54 1124 excludepats, i)]
37c0543d 1125 # Generate the interface down list
1126 # Interfaces that go into the down list:
1127 # - interfaces that were present in last config and are not
1128 # present in the new config
1129 # - interfaces that were changed between the last and current
1130 # config
1131 #
37c0543d 1132 ifacedownlist = []
2da58137
RP
1133 for ifname in filtered_ifacenames:
1134 lastifaceobjlist = self.ifaceobjdict.get(ifname)
37c0543d 1135 objidx = 0
37c0543d 1136 # If interface is not present in the new file
1137 # append it to the down list
53b00224 1138 newifaceobjlist = new_ifaceobjdict.get(ifname)
1139 if not newifaceobjlist:
37c0543d 1140 ifacedownlist.append(ifname)
1141 continue
37c0543d 1142 # If interface has changed between the current file
1143 # and the last installed append it to the down list
53b00224 1144 if len(newifaceobjlist) != len(lastifaceobjlist):
37c0543d 1145 ifacedownlist.append(ifname)
1146 continue
37c0543d 1147 # compare object list
53b00224 1148 for objidx in range(0, len(lastifaceobjlist)):
1149 oldobj = lastifaceobjlist[objidx]
1150 newobj = newifaceobjlist[objidx]
ca3f4fc7 1151 if not newobj.compare(oldobj):
37c0543d 1152 ifacedownlist.append(ifname)
1153 continue
1154
fe0a57d3 1155 if ifacedownlist:
2da58137 1156 self.logger.info('reload: scheduling down on interfaces: %s'
739f665b 1157 %str(ifacedownlist))
20dd6242 1158 # reinitialize dependency graph
1159 self.dependency_graph = OrderedDict({})
37c0543d 1160 # Generate dependency info for old config
14dc390d 1161 self.populate_dependency_info(downops, ifacedownlist)
a070c90e
RP
1162 try:
1163 self._sched_ifaces(ifacedownlist, downops)
1164 except Exception, e:
1165 self.logger.error(str(e))
1166 pass
1167 finally:
1168 self._process_delay_admin_state_queue('down')
37c0543d 1169 else:
1170 self.logger.debug('no interfaces to down ..')
739f665b 1171
20dd6242 1172 # Now, run 'up' with new config dict
1173 # reset statemanager update flag to default
c0071225
RP
1174 if not new_ifaceobjdict:
1175 return
53b00224 1176 self.ifaceobjdict = new_ifaceobjdict
1177 self.dependency_graph = new_dependency_graph
739f665b 1178 ifacenames = self.ifaceobjdict.keys()
1179 filtered_ifacenames = [i for i in ifacenames
53b00224 1180 if self._iface_whitelisted(auto, allow_classes,
d08d5f54 1181 excludepats, i)]
c798b0f4 1182
2da58137
RP
1183 self.logger.info('reload: scheduling up on interfaces: %s'
1184 %str(filtered_ifacenames))
a070c90e
RP
1185 try:
1186 self._sched_ifaces(filtered_ifacenames, upops)
1187 except Exception, e:
1188 self.logger.error(str(e))
1189 pass
1190 finally:
1191 self._process_delay_admin_state_queue('up')
e37ad4a6 1192 if self.DRYRUN:
1193 return
53b00224 1194 self._save_state()
a6f80f0e 1195
2da58137
RP
1196 def reload(self, *args, **kargs):
1197 """ reload interface config """
2da58137
RP
1198 self.logger.debug('reloading interface config ..')
1199 if kargs.get('currentlyup', False):
1200 self._reload_currentlyup(*args, **kargs)
1201 else:
1202 self._reload_default(*args, **kargs)
1203
7538dc77 1204 def _pretty_print_ordered_dict(self, prefix, argdict):
525f0a30 1205 outbuf = prefix + ' {\n'
53b00224 1206 for k, vlist in argdict.items():
525f0a30 1207 outbuf += '\t%s : %s\n' %(k, str(vlist))
7538dc77 1208 self.logger.debug(outbuf + '}')
a6f80f0e 1209
53b00224 1210 def print_dependency(self, ifacenames, format):
1211 """ prints iface dependency information """
a6f80f0e 1212
53b00224 1213 if not ifacenames:
1214 ifacenames = self.ifaceobjdict.keys()
1215 if format == 'list':
1216 for k,v in self.dependency_graph.items():
1217 print '%s : %s' %(k, str(v))
1218 elif format == 'dot':
1219 indegrees = {}
1220 map(lambda i: indegrees.update({i :
1221 self.get_iface_refcnt(i)}),
1222 self.dependency_graph.keys())
1223 graph.generate_dots(self.dependency_graph, indegrees)
a6f80f0e 1224
739f665b 1225 def print_ifaceobjs_raw(self, ifacenames):
53b00224 1226 """ prints raw lines for ifaces from config file """
1227
739f665b 1228 for i in ifacenames:
31a5f4c3 1229 for ifaceobj in self.get_ifaceobjs(i):
75730152 1230 if (self.is_ifaceobj_builtin(ifaceobj) or
1231 not ifaceobj.is_config_present()):
1232 continue
1233 ifaceobj.dump_raw(self.logger)
739f665b 1234 print '\n'
339026c8 1235 if self.WITH_DEPENDS and not self.ALL:
62ddec8b 1236 dlist = ifaceobj.lowerifaces
fe0a57d3 1237 if not dlist: continue
53b00224 1238 self.print_ifaceobjs_raw(dlist)
739f665b 1239
2cd06f78 1240 def _get_ifaceobjs_pretty(self, ifacenames, ifaceobjs, running=False):
1241 """ returns iface obj list """
53b00224 1242
a6f80f0e 1243 for i in ifacenames:
31a5f4c3 1244 for ifaceobj in self.get_ifaceobjs(i):
2cd06f78 1245 if ((not running and self.is_ifaceobj_noconfig(ifaceobj)) or
1246 (running and not ifaceobj.is_config_present())):
75730152 1247 continue
2cd06f78 1248 ifaceobjs.append(ifaceobj)
339026c8 1249 if self.WITH_DEPENDS and not self.ALL:
62ddec8b 1250 dlist = ifaceobj.lowerifaces
fe0a57d3 1251 if not dlist: continue
2cd06f78 1252 self._get_ifaceobjs_pretty(dlist, ifaceobjs, running)
739f665b 1253
2cd06f78 1254 def print_ifaceobjs_pretty(self, ifacenames, format='native'):
1255 """ pretty prints iface in format given by keyword arg format """
eab25b7c 1256
2cd06f78 1257 ifaceobjs = []
1258 self._get_ifaceobjs_pretty(ifacenames, ifaceobjs)
1259 if not ifaceobjs: return
1260 if format == 'json':
3dcc1d0e 1261 print json.dumps(ifaceobjs, cls=ifaceJsonEncoder,
1262 indent=4, separators=(',', ': '))
2cd06f78 1263 else:
2da58137
RP
1264 expand = int(self.config.get('ifquery_ifacename_expand_range', '0'))
1265 for i in ifaceobjs:
1266 if not expand and (i.flags & iface.IFACERANGE_ENTRY):
1267 # print only the first one
1268 if i.flags & iface.IFACERANGE_START:
1269 i.dump_pretty(use_realname=True)
1270 else:
1271 i.dump_pretty()
53b00224 1272
2cd06f78 1273 def _get_ifaceobjscurr_pretty(self, ifacenames, ifaceobjs):
eab25b7c 1274 ret = 0
a6f80f0e 1275 for i in ifacenames:
923290bd 1276 ifaceobjscurr = self.get_ifaceobjcurr(i)
1277 if not ifaceobjscurr: continue
1278 for ifaceobj in ifaceobjscurr:
1279 if (ifaceobj.status == ifaceStatus.NOTFOUND or
1280 ifaceobj.status == ifaceStatus.ERROR):
1281 ret = 1
1282 if self.is_ifaceobj_noconfig(ifaceobj):
1283 continue
1284 ifaceobjs.append(ifaceobj)
1285 if self.WITH_DEPENDS and not self.ALL:
1286 dlist = ifaceobj.lowerifaces
1287 if not dlist: continue
1288 dret = self._get_ifaceobjscurr_pretty(dlist, ifaceobjs)
1289 if dret: ret = 1
2cd06f78 1290 return ret
1291
1292 def print_ifaceobjscurr_pretty(self, ifacenames, format='native'):
1293 """ pretty prints current running state of interfaces with status.
1294
1295 returns 1 if any of the interface has an error,
1296 else returns 0
1297 """
1298
1299 ifaceobjs = []
1300 ret = self._get_ifaceobjscurr_pretty(ifacenames, ifaceobjs)
1301 if not ifaceobjs: return
2cd06f78 1302 if format == 'json':
1303 print json.dumps(ifaceobjs, cls=ifaceJsonEncoder, indent=2,
1304 separators=(',', ': '))
1305 else:
86fc62e2 1306 map(lambda i: i.dump_pretty(with_status=True,
fac4138b
RP
1307 successstr=self.config.get('ifquery_check_success_str',
1308 _success_sym),
1309 errorstr=self.config.get('ifquery_check_error_str', _error_sym),
1310 unknownstr=self.config.get('ifquery_check_unknown_str', '')),
1311 ifaceobjs)
eab25b7c 1312 return ret
a6f80f0e 1313
d08d5f54 1314 def print_ifaceobjsrunning_pretty(self, ifacenames, format='native'):
53b00224 1315 """ pretty prints iface running state """
1316
2cd06f78 1317 ifaceobjs = []
1318 self._get_ifaceobjs_pretty(ifacenames, ifaceobjs, running=True)
1319 if not ifaceobjs: return
1320 if format == 'json':
1321 print json.dumps(ifaceobjs, cls=ifaceJsonEncoder, indent=2,
1322 separators=(',', ': '))
1323 else:
1324 map(lambda i: i.dump_pretty(), ifaceobjs)
53b00224 1325
1326 def _dump(self):
1327 print 'ifupdown main object dump'
1328 print self.pp.pprint(self.modules)
1329 print self.pp.pprint(self.ifaceobjdict)
1330
1331 def _dump_ifaceobjs(self, ifacenames):
1332 for i in ifacenames:
1333 ifaceobjs = self.get_ifaceobjs(i)
1334 for i in ifaceobjs:
1335 i.dump(self.logger)
1336 print '\n'