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