]> git.proxmox.com Git - mirror_ifupdown2.git/blame - ifupdown/ifupdownmain.py
Move link_master_slave flag overrides to /sbin/ifupdown + log a msg to
[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
302 if increfcnt:
303 ifaceobj.inc_refcnt()
304 self.ifaceobjdict[ifacename] = [ifaceobj]
305 return ifaceobj
306
d08d5f54 307 def create_n_save_ifaceobjcurr(self, ifaceobj):
923290bd 308 """ creates a copy of iface object and adds it to the iface
309 dict containing current iface objects
53b00224 310 """
739f665b 311 ifaceobjcurr = iface()
53b00224 312 ifaceobjcurr.name = ifaceobj.name
cb46a208 313 ifaceobjcurr.type = ifaceobj.type
62ddec8b 314 ifaceobjcurr.lowerifaces = ifaceobj.lowerifaces
315 ifaceobjcurr.priv_flags = ifaceobj.priv_flags
2cd06f78 316 ifaceobjcurr.auto = ifaceobj.auto
923290bd 317 self.ifaceobjcurrdict.setdefault(ifaceobj.name,
318 []).append(ifaceobjcurr)
d08d5f54 319 return ifaceobjcurr
a6f80f0e 320
923290bd 321 def get_ifaceobjcurr(self, ifacename, idx=0):
322 ifaceobjlist = self.ifaceobjcurrdict.get(ifacename)
323 if not ifaceobjlist:
324 return None
325 if not idx:
326 return ifaceobjlist
327 else:
328 return ifaceobjlist[idx]
a6f80f0e 329
739f665b 330 def get_ifaceobjrunning(self, ifacename):
331 return self.ifaceobjrunningdict.get(ifacename)
332
a6f80f0e 333 def get_iface_refcnt(self, ifacename):
53b00224 334 """ Return iface ref count """
a6f80f0e 335 max = 0
31a5f4c3 336 ifaceobjs = self.get_ifaceobjs(ifacename)
20dd6242 337 if not ifaceobjs:
338 return 0
a6f80f0e 339 for i in ifaceobjs:
62ddec8b 340 if i.refcnt > max:
341 max = i.refcnt
a6f80f0e 342 return max
343
d08d5f54 344 def is_iface_builtin_byname(self, ifacename):
cca03c30 345 """ Returns true if iface name is a builtin interface.
a6f80f0e 346
cca03c30 347 A builtin interface is an interface which ifupdown understands.
348 The following are currently considered builtin ifaces:
349 - vlan interfaces in the format <ifacename>.<vlanid>
a6f80f0e 350 """
d08d5f54 351 return '.' in ifacename
a6f80f0e 352
37c0543d 353 def is_ifaceobj_builtin(self, ifaceobj):
354 """ Returns true if iface name is a builtin interface.
355
356 A builtin interface is an interface which ifupdown understands.
357 The following are currently considered builtin ifaces:
358 - vlan interfaces in the format <ifacename>.<vlanid>
359 """
d08d5f54 360 return (ifaceobj.priv_flags & self.BUILTIN)
37c0543d 361
362 def is_ifaceobj_noconfig(self, ifaceobj):
53b00224 363 """ Returns true if iface object did not have a user defined config.
37c0543d 364
365 These interfaces appear only when they are dependents of interfaces
366 which have user defined config
367 """
d08d5f54 368 return (ifaceobj.priv_flags & self.NOCONFIG)
37c0543d 369
d08d5f54 370 def is_iface_noconfig(self, ifacename):
371 """ Returns true if iface has no config """
37c0543d 372
31a5f4c3 373 ifaceobj = self.get_ifaceobj_first(ifacename)
d08d5f54 374 if not ifaceobj: return True
d08d5f54 375 return self.is_ifaceobj_noconfig(ifaceobj)
376
7f045fd8 377 def preprocess_dependency_list(self, upperifaceobj, dlist, ops):
739f665b 378 """ We go through the dependency list and
379 delete or add interfaces from the interfaces dict by
380 applying the following rules:
381 if flag _DELETE_DEPENDENT_IFACES_WITH_NOCONFIG is True:
382 we only consider devices whose configuration was
383 specified in the network interfaces file. We delete
384 any interface whose config was not specified except
385 for vlan devices. vlan devices get special treatment.
386 Even if they are not present they are created and added
387 to the ifacesdict
388 elif flag _DELETE_DEPENDENT_IFACES_WITH_NOCONFIG is False:
389 we create objects for all dependent devices that are not
390 present in the ifacesdict
391 """
a6f80f0e 392 del_list = []
393
a6f80f0e 394 for d in dlist:
31a5f4c3 395 dilist = self.get_ifaceobjs(d)
d08d5f54 396 if not dilist:
7f045fd8 397 ni = None
d08d5f54 398 if self.is_iface_builtin_byname(d):
a070c90e
RP
399 ni = self.create_n_save_ifaceobj(d,
400 self.BUILTIN | self.NOCONFIG, True)
f3215127 401 elif not self._DELETE_DEPENDENT_IFACES_WITH_NOCONFIG:
7f045fd8
RP
402 ni = self.create_n_save_ifaceobj(d, self.NOCONFIG,
403 True)
a6f80f0e 404 else:
a6f80f0e 405 del_list.append(d)
7f045fd8
RP
406 if ni:
407 ni.add_to_upperifaces(upperifaceobj.name)
c9bba753
RP
408 if upperifaceobj.link_type == ifaceLinkType.LINK_MASTER:
409 ni.link_type = ifaceLinkType.LINK_SLAVE
a6f80f0e 410 else:
411 for di in dilist:
412 di.inc_refcnt()
7f045fd8 413 di.add_to_upperifaces(upperifaceobj.name)
33a2e9e9 414 if upperifaceobj.link_type == ifaceLinkType.LINK_MASTER:
c9bba753 415 di.link_type = ifaceLinkType.LINK_SLAVE
a6f80f0e 416 for d in del_list:
417 dlist.remove(d)
418
2da58137 419 def query_dependents(self, ifaceobj, ops, ifacenames, type=None):
a6f80f0e 420 """ Gets iface dependents by calling into respective modules """
41febf89 421 ret_dlist = []
a6f80f0e 422
20dd6242 423 # Get dependents for interface by querying respective modules
ee3fcf44 424 for module in self.modules.values():
7949b8a5 425 try:
426 if ops[0] == 'query-running':
427 if (not hasattr(module,
428 'get_dependent_ifacenames_running')):
429 continue
430 dlist = module.get_dependent_ifacenames_running(ifaceobj)
431 else:
432 if (not hasattr(module, 'get_dependent_ifacenames')):
433 continue
434 dlist = module.get_dependent_ifacenames(ifaceobj,
ee3fcf44 435 ifacenames)
7949b8a5 436 except Exception, e:
437 self.logger.warn('%s: error getting dependent interfaces (%s)'
438 %(ifaceobj.name, str(e)))
439 dlist = None
440 pass
41febf89 441 if dlist: ret_dlist.extend(dlist)
84ca006f 442 return list(set(ret_dlist))
20dd6242 443
e1601369
RP
444 def populate_dependency_info(self, ops, ifacenames=None):
445 """ recursive function to generate iface dependency info """
446
447 if not ifacenames:
448 ifacenames = self.ifaceobjdict.keys()
449
450 iqueue = deque(ifacenames)
451 while iqueue:
452 i = iqueue.popleft()
453 # Go through all modules and find dependent ifaces
454 dlist = None
455 ifaceobj = self.get_ifaceobj_first(i)
456 if not ifaceobj:
457 continue
458 dlist = ifaceobj.lowerifaces
459 if not dlist:
460 dlist = self.query_dependents(ifaceobj, ops, ifacenames)
461 else:
462 continue
463 if dlist:
7f045fd8 464 self.preprocess_dependency_list(ifaceobj,
e1601369
RP
465 dlist, ops)
466 ifaceobj.lowerifaces = dlist
467 [iqueue.append(d) for d in dlist]
468 if not self.dependency_graph.get(i):
469 self.dependency_graph[i] = dlist
470
8e113d63
RP
471 def _check_config_no_repeats(self, ifaceobj):
472 """ check if object has an attribute that is
473 restricted to a single object in the system.
474 if yes, warn and return """
475 for k,v in self._cache_no_repeats.items():
476 iv = ifaceobj.config.get(k)
477 if iv and iv[0] == v:
478 self.logger.error('ignoring interface %s. ' %ifaceobj.name +
479 'Only one object with attribute ' +
480 '\'%s %s\' allowed.' %(k, v))
481 return True
482 for k, v in self.config.get('no_repeats', {}).items():
483 iv = ifaceobj.config.get(k)
484 if iv and iv[0] == v:
485 self._cache_no_repeats[k] = v
486 return False
a6f80f0e 487
41febf89 488 def _save_iface(self, ifaceobj):
8e113d63
RP
489 if self._check_config_no_repeats(ifaceobj):
490 return
7e2e64fb
RP
491 if not self._link_master_slave:
492 ifaceobj.link_type = ifaceLinkType.LINK_NA
679e6567
RP
493 currentifaceobjlist = self.ifaceobjdict.get(ifaceobj.name)
494 if not currentifaceobjlist:
495 self.ifaceobjdict[ifaceobj.name]= [ifaceobj]
496 return
497 if ifaceobj.compare(currentifaceobjlist[0]):
498 self.logger.warn('duplicate interface %s found' %ifaceobj.name)
499 return
8e113d63
RP
500 if currentifaceobjlist[0].type == ifaceobj.type:
501 currentifaceobjlist[0].flags |= iface.HAS_SIBLINGS
502 ifaceobj.flags |= iface.HAS_SIBLINGS
679e6567 503 self.ifaceobjdict[ifaceobj.name].append(ifaceobj)
41febf89 504
3dcc1d0e 505 def _iface_configattr_syntax_checker(self, attrname, attrval):
d08d5f54 506 for m, mdict in self.module_attrs.items():
7949b8a5 507 if not mdict:
508 continue
d08d5f54 509 attrsdict = mdict.get('attrs')
7949b8a5 510 try:
511 if attrsdict.get(attrname):
512 return True
513 except AttributeError:
514 pass
d08d5f54 515 return False
516
3dcc1d0e 517 def _ifaceobj_syntax_checker(self, ifaceobj):
518 err = False
8e113d63 519 for attrname, attrvalue in ifaceobj.config.items():
3dcc1d0e 520 found = False
521 for k, v in self.module_attrs.items():
522 if v and v.get('attrs', {}).get(attrname):
523 found = True
524 break
525 if not found:
526 err = True
527 self.logger.warn('%s: unsupported attribute \'%s\'' %attrname)
528 continue
529 return err
530
14dc390d 531 def read_iface_config(self):
a6f80f0e 532 """ Reads default network interface config /etc/network/interfaces. """
14dc390d 533 nifaces = networkInterfaces(self.interfacesfile,
3dcc1d0e 534 self.interfacesfileiobuf,
535 self.interfacesfileformat,
14dc390d 536 template_engine=self.config.get('template_engine'),
537 template_lookuppath=self.config.get('template_lookuppath'))
d08d5f54 538 nifaces.subscribe('iface_found', self._save_iface)
3dcc1d0e 539 nifaces.subscribe('validateifaceattr',
540 self._iface_configattr_syntax_checker)
541 nifaces.subscribe('validateifaceobj', self._ifaceobj_syntax_checker)
a6f80f0e 542 nifaces.load()
543
a6f80f0e 544 def read_old_iface_config(self):
14dc390d 545 """ Reads the saved iface config instead of default iface config.
546 And saved iface config is already read by the statemanager """
cb7cc592 547 self.ifaceobjdict = copy.deepcopy(self.statemanager.ifaceobjdict)
a6f80f0e 548
53b00224 549 def _load_addon_modules_config(self):
550 """ Load addon modules config file """
a6f80f0e 551
37c0543d 552 with open(self.addon_modules_configfile, 'r') as f:
553 lines = f.readlines()
554 for l in lines:
c0071225 555 litems = l.rstrip(' \n\t\r').split(',')
37c0543d 556 operation = litems[0]
557 mname = litems[1]
be0b20f2 558 self.module_ops[operation].append(mname)
37c0543d 559
560 def load_addon_modules(self, modules_dir):
a6f80f0e 561 """ load python modules from modules_dir
562
563 Default modules_dir is /usr/share/ifupdownmodules
564
565 """
a6f80f0e 566 self.logger.info('loading builtin modules from %s' %modules_dir)
53b00224 567 self._load_addon_modules_config()
a6f80f0e 568 if not modules_dir in sys.path:
37c0543d 569 sys.path.append(modules_dir)
a6f80f0e 570 try:
be0b20f2 571 for op, mlist in self.module_ops.items():
d08d5f54 572 for mname in mlist:
53b00224 573 if self.modules.get(mname):
d08d5f54 574 continue
575 mpath = modules_dir + '/' + mname + '.py'
576 if os.path.exists(mpath):
577 try:
578 m = __import__(mname)
579 mclass = getattr(m, mname)
580 except:
581 raise
582 minstance = mclass(force=self.FORCE,
583 dryrun=self.DRYRUN,
584 nowait=self.NOWAIT,
585 perfmode=self.PERFMODE,
a690dfae 586 cache=self.CACHE,
587 cacheflags=self.CACHE_FLAGS)
d08d5f54 588 self.modules[mname] = minstance
53b00224 589 try:
d08d5f54 590 self.module_attrs[mname] = minstance.get_modinfo()
53b00224 591 except:
592 pass
a6f80f0e 593 except:
594 raise
595
37c0543d 596 # Assign all modules to query operations
be0b20f2 597 self.module_ops['query-checkcurr'] = self.modules.keys()
598 self.module_ops['query-running'] = self.modules.keys()
599 self.module_ops['query-dependency'] = self.modules.keys()
600 self.module_ops['query'] = self.modules.keys()
601 self.module_ops['query-raw'] = self.modules.keys()
d08d5f54 602
14dc390d 603
53b00224 604 def _modules_help(self):
605 """ Prints addon modules supported syntax """
606
d08d5f54 607 indent = ' '
608 for m, mdict in self.module_attrs.items():
609 if not mdict:
610 continue
611 print('%s: %s' %(m, mdict.get('mhelp')))
612 attrdict = mdict.get('attrs')
613 if not attrdict:
614 continue
615 try:
616 for attrname, attrvaldict in attrdict.items():
617 if attrvaldict.get('compat', False):
618 continue
619 print('%s%s' %(indent, attrname))
620 print('%shelp: %s' %(indent + ' ',
621 attrvaldict.get('help', '')))
622 print ('%srequired: %s' %(indent + ' ',
623 attrvaldict.get('required', False)))
624 default = attrvaldict.get('default')
625 if default:
626 print('%sdefault: %s' %(indent + ' ', default))
627
628 validrange = attrvaldict.get('validrange')
629 if validrange:
1b0b81a2 630 print('%svalidrange: %s-%s'
7949b8a5 631 %(indent + ' ', validrange[0], validrange[1]))
d08d5f54 632
633 validvals = attrvaldict.get('validvals')
634 if validvals:
635 print('%svalidvals: %s'
636 %(indent + ' ', ','.join(validvals)))
637
638 examples = attrvaldict.get('example')
639 if not examples:
640 continue
a6f80f0e 641
d08d5f54 642 print '%sexample:' %(indent + ' ')
643 for e in examples:
644 print '%s%s' %(indent + ' ', e)
645 except:
646 pass
647 print ''
648
37c0543d 649 def load_scripts(self, modules_dir):
a6f80f0e 650 """ loading user modules from /etc/network/.
651
652 Note that previously loaded python modules override modules found
653 under /etc/network if any
654
655 """
656
37c0543d 657 self.logger.info('looking for user scripts under %s' %modules_dir)
be0b20f2 658 for op, mlist in self.script_ops.items():
d08d5f54 659 msubdir = modules_dir + '/if-%s.d' %op
660 self.logger.info('loading scripts under %s ...' %msubdir)
661 try:
662 module_list = os.listdir(msubdir)
663 for module in module_list:
664 if self.modules.get(module) is not None:
665 continue
be0b20f2 666 self.script_ops[op].append(
a6f80f0e 667 msubdir + '/' + module)
d08d5f54 668 except:
f802fe3c 669 # continue reading
670 pass
a6f80f0e 671
ad25e7bb 672 def _sched_ifaces(self, ifacenames, ops, skipupperifaces=False):
c798b0f4 673 self.logger.debug('scheduling \'%s\' for %s'
d08d5f54 674 %(str(ops), str(ifacenames)))
7538dc77 675 self._pretty_print_ordered_dict('dependency graph',
676 self.dependency_graph)
c798b0f4 677 return ifaceScheduler.sched_ifaces(self, ifacenames, ops,
678 dependency_graph=self.dependency_graph,
d08d5f54 679 order=ifaceSchedulerFlags.INORDER
680 if 'down' in ops[0]
c798b0f4 681 else ifaceSchedulerFlags.POSTORDER,
ad25e7bb
RP
682 followdependents=True if self.WITH_DEPENDS else False,
683 skipupperifaces=skipupperifaces)
a6f80f0e 684
41febf89
RP
685 def _render_ifacename(self, ifacename):
686 new_ifacenames = []
679e6567 687 vlan_match = re.match("^([\d]+)-([\d]+)", ifacename)
41febf89
RP
688 if vlan_match:
689 vlan_groups = vlan_match.groups()
690 if vlan_groups[0] and vlan_groups[1]:
679e6567 691 [new_ifacenames.append('%d' %v)
41febf89
RP
692 for v in range(int(vlan_groups[0]),
693 int(vlan_groups[1])+1)]
694 return new_ifacenames
695
696 def _preprocess_ifacenames(self, ifacenames):
a6f80f0e 697 """ validates interface list for config existance.
698
699 returns -1 if one or more interface not found. else, returns 0
700
701 """
41febf89 702 new_ifacenames = []
a6f80f0e 703 err_iface = ''
704 for i in ifacenames:
31a5f4c3 705 ifaceobjs = self.get_ifaceobjs(i)
706 if not ifaceobjs:
41febf89 707 # if name not available, render interface name and check again
679e6567 708 rendered_ifacenames = utils.expand_iface_range(i)
41febf89
RP
709 if rendered_ifacenames:
710 for ri in rendered_ifacenames:
711 ifaceobjs = self.get_ifaceobjs(ri)
712 if not ifaceobjs:
713 err_iface += ' ' + ri
714 else:
715 new_ifacenames.append(ri)
716 else:
717 err_iface += ' ' + i
718 else:
719 new_ifacenames.append(i)
fe0a57d3 720 if err_iface:
31c58787 721 raise Exception('cannot find interfaces:%s' %err_iface)
41febf89 722 return new_ifacenames
a6f80f0e 723
53b00224 724 def _iface_whitelisted(self, auto, allow_classes, excludepats, ifacename):
a6f80f0e 725 """ Checks if interface is whitelisted depending on set of parameters.
726
a6f80f0e 727 interfaces are checked against the allow_classes and auto lists.
728
729 """
fe0a57d3 730 if excludepats:
3e8ee54f 731 for e in excludepats:
d08d5f54 732 if re.search(e, ifacename):
3e8ee54f 733 return False
31a5f4c3 734 ifaceobjs = self.get_ifaceobjs(ifacename)
735 if not ifaceobjs:
a6f80f0e 736 self.logger.debug('iface %s' %ifacename + ' not found')
737 return False
a6f80f0e 738 # We check classes first
fe0a57d3 739 if allow_classes:
a6f80f0e 740 for i in ifaceobjs:
62ddec8b 741 if i.classes:
3e8ee54f 742 common = Set([allow_classes]).intersection(
62ddec8b 743 Set(i.classes))
fe0a57d3 744 if common:
a6f80f0e 745 return True
746 return False
d08d5f54 747 if auto:
a6f80f0e 748 for i in ifaceobjs:
62ddec8b 749 if i.auto:
a6f80f0e 750 return True
751 return False
a6f80f0e 752 return True
753
53b00224 754 def _compat_conv_op_to_mode(self, op):
755 """ Returns old op name to work with existing scripts """
756 if op == 'pre-up':
757 return 'start'
758 elif op == 'pre-down':
759 return 'stop'
760 else:
761 return op
762
a6f80f0e 763 def generate_running_env(self, ifaceobj, op):
739f665b 764 """ Generates a dictionary with env variables required for
765 an interface. Used to support script execution for interfaces.
a6f80f0e 766 """
767
768 cenv = None
62ddec8b 769 iface_env = ifaceobj.env
770 if iface_env:
a6f80f0e 771 cenv = os.environ
d08d5f54 772 if cenv:
a6f80f0e 773 cenv.update(iface_env)
774 else:
775 cenv = iface_env
53b00224 776 cenv['MODE'] = self._compat_conv_op_to_mode(op)
a6f80f0e 777 return cenv
778
53b00224 779 def _save_state(self):
20dd6242 780 if not self.STATEMANAGER_ENABLE or not self.STATEMANAGER_UPDATE:
781 return
782 try:
783 # Update persistant iface states
784 self.statemanager.save_state()
785 except Exception, e:
786 if self.logger.isEnabledFor(logging.DEBUG):
787 t = sys.exc_info()[2]
788 traceback.print_tb(t)
789 self.logger.warning('error saving state (%s)' %str(e))
790
2da58137
RP
791 def set_type(self, type):
792 if type == 'iface':
793 self.type = ifaceType.IFACE
794 elif type == 'vlan':
795 self.type = ifaceType.BRIDGE_VLAN
796 else:
797 self.type = ifaceType.UNKNOWN
798
a070c90e
RP
799 def _process_delay_admin_state_queue(self, op):
800 if not self._delay_admin_state_iface_queue:
801 return
802 if op == 'up':
803 func = self.link_up
804 elif op == 'down':
805 func = self.link_down
806 else:
807 return
808 for i in self._delay_admin_state_iface_queue:
809 try:
810 if self.link_exists(i):
811 func(i)
812 except Exception, e:
813 self.logger.warn(str(e))
814 pass
815
d08d5f54 816 def up(self, ops, auto=False, allow_classes=None, ifacenames=None,
2da58137 817 excludepats=None, printdependency=None, syntaxcheck=False,
ad25e7bb 818 type=None, skipupperifaces=False):
2c0ad8b3
RP
819 """This brings the interface(s) up
820
821 Args:
41febf89
RP
822 ops (list): list of ops to perform on the interface(s).
823 Eg: ['pre-up', 'up', 'post-up'
2c0ad8b3
RP
824
825 Kwargs:
826 auto (bool): act on interfaces marked auto
827 allow_classes (list): act on interfaces belonging to classes in the list
828 ifacenames (list): act on interfaces specified in this list
829 excludepats (list): list of patterns of interfaces to exclude
830 syntaxcheck (bool): only perform syntax check
831 """
53b00224 832
2da58137
RP
833 self.set_type(type)
834
5ee3e1a8
RP
835 if allow_classes:
836 self.IFACE_CLASS = True
7538dc77 837 if not self.ADDONS_ENABLE: self.STATEMANAGER_UPDATE = False
d08d5f54 838 if auto:
a6f80f0e 839 self.ALL = True
cca03c30 840 self.WITH_DEPENDS = True
d08d5f54 841 try:
842 self.read_iface_config()
62ddec8b 843 except Exception:
d08d5f54 844 raise
a6f80f0e 845
9dce3561 846 # If only syntax check was requested, return here
847 if syntaxcheck:
848 return
849
31a5f4c3 850 if ifacenames:
41febf89 851 ifacenames = self._preprocess_ifacenames(ifacenames)
a6f80f0e 852
853 # if iface list not given by user, assume all from config file
31a5f4c3 854 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
a6f80f0e 855
856 # filter interfaces based on auto and allow classes
cca03c30 857 filtered_ifacenames = [i for i in ifacenames
53b00224 858 if self._iface_whitelisted(auto, allow_classes,
d08d5f54 859 excludepats, i)]
fe0a57d3 860 if not filtered_ifacenames:
d08d5f54 861 raise Exception('no ifaces found matching given allow lists')
a6f80f0e 862
20dd6242 863 if printdependency:
c798b0f4 864 self.populate_dependency_info(ops, filtered_ifacenames)
d08d5f54 865 self.print_dependency(filtered_ifacenames, printdependency)
739f665b 866 return
cca03c30 867 else:
c798b0f4 868 self.populate_dependency_info(ops)
869
525f0a30 870 try:
ad25e7bb
RP
871 self._sched_ifaces(filtered_ifacenames, ops,
872 skipupperifaces=skipupperifaces)
525f0a30 873 finally:
a070c90e 874 self._process_delay_admin_state_queue('up')
525f0a30 875 if not self.DRYRUN and self.ADDONS_ENABLE:
876 self._save_state()
a6f80f0e 877
d08d5f54 878 def down(self, ops, auto=False, allow_classes=None, ifacenames=None,
2da58137
RP
879 excludepats=None, printdependency=None, usecurrentconfig=False,
880 type=None):
53b00224 881 """ down an interface """
882
2da58137
RP
883 self.set_type(type)
884
5ee3e1a8
RP
885 if allow_classes:
886 self.IFACE_CLASS = True
7538dc77 887 if not self.ADDONS_ENABLE: self.STATEMANAGER_UPDATE = False
d08d5f54 888 if auto:
889 self.ALL = True
890 self.WITH_DEPENDS = True
5c721925 891 # For down we need to look at old state, unless usecurrentconfig
892 # is set
893 if (not usecurrentconfig and self.STATEMANAGER_ENABLE and
53b00224 894 self.statemanager.ifaceobjdict):
31a5f4c3 895 # Since we are using state manager objects,
896 # skip the updating of state manager objects
5c721925 897 self.logger.debug('Looking at old state ..')
d08d5f54 898 self.read_old_iface_config()
fe0a57d3 899 else:
d08d5f54 900 # If no old state available
d08d5f54 901 try:
902 self.read_iface_config()
903 except Exception, e:
904 raise Exception('error reading iface config (%s)' %str(e))
d08d5f54 905 if ifacenames:
906 # If iface list is given by the caller, always check if iface
907 # is present
31c58787 908 try:
41febf89 909 ifacenames = self._preprocess_ifacenames(ifacenames)
31c58787 910 except Exception, e:
911 raise Exception('%s' %str(e) +
912 ' (interface was probably never up ?)')
913
d08d5f54 914 # if iface list not given by user, assume all from config file
fe0a57d3 915 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
53b00224 916
d08d5f54 917 # filter interfaces based on auto and allow classes
918 filtered_ifacenames = [i for i in ifacenames
53b00224 919 if self._iface_whitelisted(auto, allow_classes,
d08d5f54 920 excludepats, i)]
fe0a57d3 921 if not filtered_ifacenames:
c0071225 922 raise Exception('no ifaces found matching given allow lists ' +
41febf89 923 '(or interfaces were probably never up ?)')
14dc390d 924
d08d5f54 925 if printdependency:
99b212b0 926 self.populate_dependency_info(ops, filtered_ifacenames)
d08d5f54 927 self.print_dependency(filtered_ifacenames, printdependency)
928 return
99b212b0 929 else:
930 self.populate_dependency_info(ops)
525f0a30 931
932 try:
933 self._sched_ifaces(filtered_ifacenames, ops)
934 finally:
a070c90e 935 self._process_delay_admin_state_queue('down')
525f0a30 936 if not self.DRYRUN and self.ADDONS_ENABLE:
937 self._save_state()
d08d5f54 938
939 def query(self, ops, auto=False, allow_classes=None, ifacenames=None,
739f665b 940 excludepats=None, printdependency=None,
2da58137 941 format='native', type=None):
53b00224 942 """ query an interface """
943
2da58137
RP
944 self.set_type(type)
945
5ee3e1a8
RP
946 if allow_classes:
947 self.IFACE_CLASS = True
5c721925 948 if self.STATEMANAGER_ENABLE and ops[0] == 'query-savedstate':
949 return self.statemanager.dump_pretty(ifacenames)
20dd6242 950 self.STATEMANAGER_UPDATE = False
d08d5f54 951 if auto:
739f665b 952 self.logger.debug('setting flag ALL')
953 self.ALL = True
37c0543d 954 self.WITH_DEPENDS = True
739f665b 955
d08d5f54 956 if ops[0] == 'query-syntax':
53b00224 957 self._modules_help()
d08d5f54 958 return
959 elif ops[0] == 'query-running':
739f665b 960 # create fake devices to all dependents that dont have config
37c0543d 961 map(lambda i: self.create_n_save_ifaceobj(i, self.NOCONFIG),
962 ifacenames)
739f665b 963 else:
964 try:
965 self.read_iface_config()
966 except Exception:
967 raise
968
53b00224 969 if ifacenames and ops[0] != 'query-running':
41febf89
RP
970 # If iface list is given, always check if iface is present
971 ifacenames = self._preprocess_ifacenames(ifacenames)
739f665b 972
973 # if iface list not given by user, assume all from config file
31a5f4c3 974 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
739f665b 975
976 # filter interfaces based on auto and allow classes
d08d5f54 977 if ops[0] == 'query-running':
739f665b 978 filtered_ifacenames = ifacenames
979 else:
980 filtered_ifacenames = [i for i in ifacenames
53b00224 981 if self._iface_whitelisted(auto, allow_classes,
d08d5f54 982 excludepats, i)]
fe0a57d3 983 if not filtered_ifacenames:
739f665b 984 raise Exception('no ifaces found matching ' +
985 'given allow lists')
37c0543d 986
e1601369 987 self.populate_dependency_info(ops)
d08d5f54 988 if ops[0] == 'query-dependency' and printdependency:
989 self.print_dependency(filtered_ifacenames, printdependency)
990 return
739f665b 991
75730152 992 if ops[0] == 'query':
993 return self.print_ifaceobjs_pretty(filtered_ifacenames, format)
994 elif ops[0] == 'query-raw':
995 return self.print_ifaceobjs_raw(filtered_ifacenames)
996
53b00224 997 self._sched_ifaces(filtered_ifacenames, ops)
739f665b 998
d08d5f54 999 if ops[0] == 'query-checkcurr':
1000 ret = self.print_ifaceobjscurr_pretty(filtered_ifacenames, format)
739f665b 1001 if ret != 0:
1002 # if any of the object has an error, signal that silently
1003 raise Exception('')
d08d5f54 1004 elif ops[0] == 'query-running':
1005 self.print_ifaceobjsrunning_pretty(filtered_ifacenames, format)
739f665b 1006 return
1007
2da58137
RP
1008 def _reload_currentlyup(self, upops, downops, auto=True, allow=None,
1009 ifacenames=None, excludepats=None, usecurrentconfig=False,
1010 **extra_args):
1011 """ reload currently up interfaces """
739f665b 1012 allow_classes = []
c0071225 1013 new_ifaceobjdict = {}
739f665b 1014
2da58137
RP
1015 # Override auto to true
1016 auto = True
97382e88
RP
1017 if auto:
1018 self.ALL = True
1019 self.WITH_DEPENDS = True
2da58137
RP
1020 try:
1021 self.read_iface_config()
1022 except:
1023 raise
2da58137
RP
1024 if not self.ifaceobjdict:
1025 self.logger.warn("nothing to reload ..exiting.")
1026 return
2da58137
RP
1027 already_up_ifacenames = []
1028 # generate dependency graph of interfaces
1029 self.populate_dependency_info(upops)
1030 if (not usecurrentconfig and self.STATEMANAGER_ENABLE
1031 and self.statemanager.ifaceobjdict):
1032 already_up_ifacenames = self.statemanager.ifaceobjdict.keys()
1033
1034 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
1035 filtered_ifacenames = [i for i in ifacenames
1036 if self._iface_whitelisted(auto, allow_classes,
1037 excludepats, i)]
1038
1039 # Get already up interfaces that still exist in the interfaces file
1040 already_up_ifacenames_not_present = Set(
1041 already_up_ifacenames).difference(ifacenames)
1042 already_up_ifacenames_still_present = Set(
1043 already_up_ifacenames).difference(
1044 already_up_ifacenames_not_present)
1045 interfaces_to_up = Set(already_up_ifacenames_still_present).union(
1046 filtered_ifacenames)
1047
1048 if (already_up_ifacenames_not_present and
1049 self.config.get('ifreload_currentlyup_down_notpresent') == '1'):
1050 self.logger.info('reload: schedule down on interfaces: %s'
1051 %str(already_up_ifacenames_not_present))
1052
1053 # Save a copy of new iface objects and dependency_graph
1054 new_ifaceobjdict = dict(self.ifaceobjdict)
1055 new_dependency_graph = dict(self.dependency_graph)
1056
1057 # old interface config is read into self.ifaceobjdict
1058 self.read_old_iface_config()
1059
1060 # reinitialize dependency graph
1061 self.dependency_graph = OrderedDict({})
1062 self.populate_dependency_info(downops,
1063 already_up_ifacenames_not_present)
1064 self._sched_ifaces(already_up_ifacenames_not_present, downops)
1065 else:
1066 self.logger.debug('no interfaces to down ..')
1067
1068 # Now, run 'up' with new config dict
1069 # reset statemanager update flag to default
1070 if new_ifaceobjdict:
1071 self.ifaceobjdict = new_ifaceobjdict
1072 self.dependency_graph = new_dependency_graph
1073
1074 if not self.ifaceobjdict:
1075 return
1076 self.logger.info('reload: scheduling up on interfaces: %s'
1077 %str(interfaces_to_up))
1078 self._sched_ifaces(interfaces_to_up, upops)
1079 if self.DRYRUN:
1080 return
1081 self._save_state()
1082
1083 def _reload_default(self, upops, downops, auto=False, allow=None,
1084 ifacenames=None, excludepats=None, usecurrentconfig=False,
1085 **extra_args):
1086 """ reload interface config """
1087 allow_classes = []
1088 new_ifaceobjdict = {}
739f665b 1089
97382e88
RP
1090 if auto:
1091 self.ALL = True
1092 self.WITH_DEPENDS = True
739f665b 1093 try:
1094 self.read_iface_config()
20dd6242 1095 except:
739f665b 1096 raise
1097
c0071225
RP
1098 if not self.ifaceobjdict:
1099 self.logger.warn("nothing to reload ..exiting.")
1100 return
37c0543d 1101 # generate dependency graph of interfaces
c798b0f4 1102 self.populate_dependency_info(upops)
14dc390d 1103 if (not usecurrentconfig and self.STATEMANAGER_ENABLE
1104 and self.statemanager.ifaceobjdict):
1105 # Save a copy of new iface objects and dependency_graph
1106 new_ifaceobjdict = dict(self.ifaceobjdict)
1107 new_dependency_graph = dict(self.dependency_graph)
37c0543d 1108
739f665b 1109 # if old state is present, read old state and mark op for 'down'
1110 # followed by 'up' aka: reload
37c0543d 1111 # old interface config is read into self.ifaceobjdict
739f665b 1112 self.read_old_iface_config()
1113 op = 'reload'
1114 else:
1115 # oldconfig not available, continue with 'up' with new config
1116 op = 'up'
1117
20dd6242 1118 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
fe0a57d3 1119 if op == 'reload' and ifacenames:
739f665b 1120 filtered_ifacenames = [i for i in ifacenames
53b00224 1121 if self._iface_whitelisted(auto, allow_classes,
d08d5f54 1122 excludepats, i)]
37c0543d 1123 # Generate the interface down list
1124 # Interfaces that go into the down list:
1125 # - interfaces that were present in last config and are not
1126 # present in the new config
1127 # - interfaces that were changed between the last and current
1128 # config
1129 #
37c0543d 1130 ifacedownlist = []
2da58137
RP
1131 for ifname in filtered_ifacenames:
1132 lastifaceobjlist = self.ifaceobjdict.get(ifname)
37c0543d 1133 objidx = 0
37c0543d 1134 # If interface is not present in the new file
1135 # append it to the down list
53b00224 1136 newifaceobjlist = new_ifaceobjdict.get(ifname)
1137 if not newifaceobjlist:
37c0543d 1138 ifacedownlist.append(ifname)
1139 continue
37c0543d 1140 # If interface has changed between the current file
1141 # and the last installed append it to the down list
53b00224 1142 if len(newifaceobjlist) != len(lastifaceobjlist):
37c0543d 1143 ifacedownlist.append(ifname)
1144 continue
37c0543d 1145 # compare object list
53b00224 1146 for objidx in range(0, len(lastifaceobjlist)):
1147 oldobj = lastifaceobjlist[objidx]
1148 newobj = newifaceobjlist[objidx]
ca3f4fc7 1149 if not newobj.compare(oldobj):
37c0543d 1150 ifacedownlist.append(ifname)
1151 continue
1152
fe0a57d3 1153 if ifacedownlist:
2da58137 1154 self.logger.info('reload: scheduling down on interfaces: %s'
739f665b 1155 %str(ifacedownlist))
20dd6242 1156 # reinitialize dependency graph
1157 self.dependency_graph = OrderedDict({})
37c0543d 1158 # Generate dependency info for old config
14dc390d 1159 self.populate_dependency_info(downops, ifacedownlist)
a070c90e
RP
1160 try:
1161 self._sched_ifaces(ifacedownlist, downops)
1162 except Exception, e:
1163 self.logger.error(str(e))
1164 pass
1165 finally:
1166 self._process_delay_admin_state_queue('down')
37c0543d 1167 else:
1168 self.logger.debug('no interfaces to down ..')
739f665b 1169
20dd6242 1170 # Now, run 'up' with new config dict
1171 # reset statemanager update flag to default
c0071225
RP
1172 if not new_ifaceobjdict:
1173 return
53b00224 1174 self.ifaceobjdict = new_ifaceobjdict
1175 self.dependency_graph = new_dependency_graph
739f665b 1176 ifacenames = self.ifaceobjdict.keys()
1177 filtered_ifacenames = [i for i in ifacenames
53b00224 1178 if self._iface_whitelisted(auto, allow_classes,
d08d5f54 1179 excludepats, i)]
c798b0f4 1180
2da58137
RP
1181 self.logger.info('reload: scheduling up on interfaces: %s'
1182 %str(filtered_ifacenames))
a070c90e
RP
1183 try:
1184 self._sched_ifaces(filtered_ifacenames, upops)
1185 except Exception, e:
1186 self.logger.error(str(e))
1187 pass
1188 finally:
1189 self._process_delay_admin_state_queue('up')
e37ad4a6 1190 if self.DRYRUN:
1191 return
53b00224 1192 self._save_state()
a6f80f0e 1193
2da58137
RP
1194 def reload(self, *args, **kargs):
1195 """ reload interface config """
2da58137
RP
1196 self.logger.debug('reloading interface config ..')
1197 if kargs.get('currentlyup', False):
1198 self._reload_currentlyup(*args, **kargs)
1199 else:
1200 self._reload_default(*args, **kargs)
1201
7538dc77 1202 def _pretty_print_ordered_dict(self, prefix, argdict):
525f0a30 1203 outbuf = prefix + ' {\n'
53b00224 1204 for k, vlist in argdict.items():
525f0a30 1205 outbuf += '\t%s : %s\n' %(k, str(vlist))
7538dc77 1206 self.logger.debug(outbuf + '}')
a6f80f0e 1207
53b00224 1208 def print_dependency(self, ifacenames, format):
1209 """ prints iface dependency information """
a6f80f0e 1210
53b00224 1211 if not ifacenames:
1212 ifacenames = self.ifaceobjdict.keys()
1213 if format == 'list':
1214 for k,v in self.dependency_graph.items():
1215 print '%s : %s' %(k, str(v))
1216 elif format == 'dot':
1217 indegrees = {}
1218 map(lambda i: indegrees.update({i :
1219 self.get_iface_refcnt(i)}),
1220 self.dependency_graph.keys())
1221 graph.generate_dots(self.dependency_graph, indegrees)
a6f80f0e 1222
739f665b 1223 def print_ifaceobjs_raw(self, ifacenames):
53b00224 1224 """ prints raw lines for ifaces from config file """
1225
739f665b 1226 for i in ifacenames:
31a5f4c3 1227 for ifaceobj in self.get_ifaceobjs(i):
75730152 1228 if (self.is_ifaceobj_builtin(ifaceobj) or
1229 not ifaceobj.is_config_present()):
1230 continue
1231 ifaceobj.dump_raw(self.logger)
739f665b 1232 print '\n'
339026c8 1233 if self.WITH_DEPENDS and not self.ALL:
62ddec8b 1234 dlist = ifaceobj.lowerifaces
fe0a57d3 1235 if not dlist: continue
53b00224 1236 self.print_ifaceobjs_raw(dlist)
739f665b 1237
2cd06f78 1238 def _get_ifaceobjs_pretty(self, ifacenames, ifaceobjs, running=False):
1239 """ returns iface obj list """
53b00224 1240
a6f80f0e 1241 for i in ifacenames:
31a5f4c3 1242 for ifaceobj in self.get_ifaceobjs(i):
2cd06f78 1243 if ((not running and self.is_ifaceobj_noconfig(ifaceobj)) or
1244 (running and not ifaceobj.is_config_present())):
75730152 1245 continue
2cd06f78 1246 ifaceobjs.append(ifaceobj)
339026c8 1247 if self.WITH_DEPENDS and not self.ALL:
62ddec8b 1248 dlist = ifaceobj.lowerifaces
fe0a57d3 1249 if not dlist: continue
2cd06f78 1250 self._get_ifaceobjs_pretty(dlist, ifaceobjs, running)
739f665b 1251
2cd06f78 1252 def print_ifaceobjs_pretty(self, ifacenames, format='native'):
1253 """ pretty prints iface in format given by keyword arg format """
eab25b7c 1254
2cd06f78 1255 ifaceobjs = []
1256 self._get_ifaceobjs_pretty(ifacenames, ifaceobjs)
1257 if not ifaceobjs: return
1258 if format == 'json':
3dcc1d0e 1259 print json.dumps(ifaceobjs, cls=ifaceJsonEncoder,
1260 indent=4, separators=(',', ': '))
2cd06f78 1261 else:
2da58137
RP
1262 expand = int(self.config.get('ifquery_ifacename_expand_range', '0'))
1263 for i in ifaceobjs:
1264 if not expand and (i.flags & iface.IFACERANGE_ENTRY):
1265 # print only the first one
1266 if i.flags & iface.IFACERANGE_START:
1267 i.dump_pretty(use_realname=True)
1268 else:
1269 i.dump_pretty()
53b00224 1270
2cd06f78 1271 def _get_ifaceobjscurr_pretty(self, ifacenames, ifaceobjs):
eab25b7c 1272 ret = 0
a6f80f0e 1273 for i in ifacenames:
923290bd 1274 ifaceobjscurr = self.get_ifaceobjcurr(i)
1275 if not ifaceobjscurr: continue
1276 for ifaceobj in ifaceobjscurr:
1277 if (ifaceobj.status == ifaceStatus.NOTFOUND or
1278 ifaceobj.status == ifaceStatus.ERROR):
1279 ret = 1
1280 if self.is_ifaceobj_noconfig(ifaceobj):
1281 continue
1282 ifaceobjs.append(ifaceobj)
1283 if self.WITH_DEPENDS and not self.ALL:
1284 dlist = ifaceobj.lowerifaces
1285 if not dlist: continue
1286 dret = self._get_ifaceobjscurr_pretty(dlist, ifaceobjs)
1287 if dret: ret = 1
2cd06f78 1288 return ret
1289
1290 def print_ifaceobjscurr_pretty(self, ifacenames, format='native'):
1291 """ pretty prints current running state of interfaces with status.
1292
1293 returns 1 if any of the interface has an error,
1294 else returns 0
1295 """
1296
1297 ifaceobjs = []
1298 ret = self._get_ifaceobjscurr_pretty(ifacenames, ifaceobjs)
1299 if not ifaceobjs: return
2cd06f78 1300 if format == 'json':
1301 print json.dumps(ifaceobjs, cls=ifaceJsonEncoder, indent=2,
1302 separators=(',', ': '))
1303 else:
86fc62e2 1304 map(lambda i: i.dump_pretty(with_status=True,
fac4138b
RP
1305 successstr=self.config.get('ifquery_check_success_str',
1306 _success_sym),
1307 errorstr=self.config.get('ifquery_check_error_str', _error_sym),
1308 unknownstr=self.config.get('ifquery_check_unknown_str', '')),
1309 ifaceobjs)
eab25b7c 1310 return ret
a6f80f0e 1311
d08d5f54 1312 def print_ifaceobjsrunning_pretty(self, ifacenames, format='native'):
53b00224 1313 """ pretty prints iface running state """
1314
2cd06f78 1315 ifaceobjs = []
1316 self._get_ifaceobjs_pretty(ifacenames, ifaceobjs, running=True)
1317 if not ifaceobjs: return
1318 if format == 'json':
1319 print json.dumps(ifaceobjs, cls=ifaceJsonEncoder, indent=2,
1320 separators=(',', ': '))
1321 else:
1322 map(lambda i: i.dump_pretty(), ifaceobjs)
53b00224 1323
1324 def _dump(self):
1325 print 'ifupdown main object dump'
1326 print self.pp.pprint(self.modules)
1327 print self.pp.pprint(self.ifaceobjdict)
1328
1329 def _dump_ifaceobjs(self, ifacenames):
1330 for i in ifacenames:
1331 ifaceobjs = self.get_ifaceobjs(i)
1332 for i in ifaceobjs:
1333 i.dump(self.logger)
1334 print '\n'