]> git.proxmox.com Git - mirror_ifupdown2.git/blame - pkg/ifupdownmain.py
remove dhclient -nw option + cleanup
[mirror_ifupdown2.git] / pkg / ifupdownmain.py
CommitLineData
a6f80f0e 1#!/usr/bin/python
3e8ee54f 2#
3# Copyright 2013. Cumulus Networks, Inc.
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
a6f80f0e 16from statemanager import *
17from networkinterfaces import *
18from iface import *
19from scheduler import *
20from collections import deque
21from collections import OrderedDict
a6f80f0e 22from graph import *
3e8ee54f 23from sets import Set
a6f80f0e 24
be0b20f2 25class ifupdownMain(ifupdownBase):
a6f80f0e 26
27 # Flags
cca03c30 28 WITH_DEPENDS = False
a6f80f0e 29 ALL = False
eab25b7c 30 STATE_CHECK = False
a6f80f0e 31
37c0543d 32 # priv flags to mark iface objects
33 BUILTIN = 0x1
34 NOCONFIG = 0x2
35
36 scripts_dir='/etc/network'
37 addon_modules_dir='/usr/share/ifupdownaddons'
38 addon_modules_configfile='/etc/network/.addons.conf'
a6f80f0e 39
40 # iface dictionary in the below format:
41 # { '<ifacename>' : [<ifaceobject1>, <ifaceobject2> ..] }
42 # eg:
43 # { 'swp1' : [<ifaceobject1>, <ifaceobject2> ..] }
44 #
45 # Each ifaceobject corresponds to a configuration block for
46 # that interface
47 ifaceobjdict = OrderedDict()
48
49
50 # iface dictionary representing the curr running state of an iface
51 # in the below format:
52 # {'<ifacename>' : <ifaceobject>}
53 ifaceobjcurrdict = OrderedDict()
54
be0b20f2 55 # Dictionary representing operation and modules
56 # for every operation
57 module_ops = OrderedDict([('pre-up', []),
d08d5f54 58 ('up' , []),
59 ('post-up' , []),
60 ('query-checkcurr', []),
61 ('query-running', []),
62 ('query-dependency', []),
75730152 63 ('query', []),
64 ('query-raw', []),
d08d5f54 65 ('pre-down', []),
66 ('down' , []),
67 ('post-down' , [])])
37c0543d 68
69 # For old style /etc/network/ bash scripts
be0b20f2 70 script_ops = OrderedDict([('pre-up', []),
d08d5f54 71 ('up' , []),
72 ('post-up' , []),
73 ('pre-down', []),
74 ('down' , []),
75 ('post-down' , [])])
a6f80f0e 76
be0b20f2 77 # Handlers for ops that ifupdown2 owns
78 def run_up(self, ifaceobj):
79 ifacename = ifaceobj.get_name()
80 if self.link_exists(ifacename):
81 self.link_up(ifacename)
82
83 def run_down(self, ifaceobj):
84 ifacename = ifaceobj.get_name()
85 if self.link_exists(ifacename):
86 self.link_down(ifacename)
87
88 ops_handlers = OrderedDict([('up', run_up),
89 ('down', run_down)])
a6f80f0e 90
eab25b7c 91 def __init__(self, force=False, dryrun=False, nowait=False,
cca03c30 92 perfmode=False, withdepends=False, njobs=1,
d08d5f54 93 cache=False):
a6f80f0e 94 self.logger = logging.getLogger('ifupdown')
95
eab25b7c 96 self.FORCE = force
97 self.DRYRUN = dryrun
98 self.NOWAIT = nowait
99 self.PERFMODE = perfmode
cca03c30 100 self.WITH_DEPENDS = withdepends
739f665b 101 self.CACHE = cache
37c0543d 102 self._DELETE_DEPENDENT_IFACES_WITH_NOCONFIG = False
eab25b7c 103
a6f80f0e 104 self.ifaces = OrderedDict()
eab25b7c 105 self.njobs = njobs
a6f80f0e 106 self.pp = pprint.PrettyPrinter(indent=4)
37c0543d 107 self.modules = OrderedDict({})
d08d5f54 108 self.module_attrs = {}
37c0543d 109 self.load_addon_modules(self.addon_modules_dir)
110 self.load_scripts(self.scripts_dir)
d08d5f54 111 self.dependency_graph = OrderedDict({})
a6f80f0e 112
113 try:
114 self.statemanager = stateManager()
115 self.statemanager.read_saved_state()
116 except Exception, e:
117 # XXX Maybe we should continue by ignoring old state
118 self.logger.warning('error reading state (%s)' %str(e))
119 raise
120
121 def get_subops(self, op):
122 """ Returns sub-operation list """
be0b20f2 123 return self.module_ops.get(op).keys()
a6f80f0e 124
125 def compat_conv_op_to_mode(self, op):
126 """ Returns old op name to work with existing scripts """
d08d5f54 127 if op == 'pre-up':
a6f80f0e 128 return 'start'
d08d5f54 129 elif op == 'pre-down':
a6f80f0e 130 return 'stop'
131 else:
132 return op
133
134 def set_force(self, force):
135 """ Set force flag. """
a6f80f0e 136 self.FORCE = force
137
138 def get_force(self):
139 """ return force flag. """
140 return self.FORCE
141
142 def set_dryrun(self, dryrun):
a6f80f0e 143 self.DRYRUN = dryrun
144
145 def get_dryrun(self):
146 return self.DRYRUN
147
739f665b 148 def get_cache(self):
149 return self.CACHE
150
151 def get_ifaceobjdict(self):
152 return self.ifaceobjdict
153
154 def set_ifaceobjdict(self, ifaceobjdict):
739f665b 155 self.ifaceobjdict = ifaceobjdict
156
37c0543d 157 def set_dependency_graph(self, dependency_graph):
158 self.dependency_graph = dependency_graph
159
160 def get_dependency_graph(self):
161 return self.dependency_graph
162
eab25b7c 163 def set_perfmode(self, perfmode):
eab25b7c 164 self.PERFMODE = perfmode
165
166 def get_perfmode(self):
167 return self.PERFMODE
168
a6f80f0e 169 def set_nowait(self, nowait):
a6f80f0e 170 self.NOWAIT = nowait
171
172 def get_nowait(self):
173 return self.NOWAIT
174
175 def set_njobs(self, njobs):
176 self.logger.debug('setting njobs to %d' %njobs)
177 self.njobs = njobs
178
179 def get_njobs(self):
180 return self.njobs
181
cca03c30 182 def get_withdepends(self):
183 return self.WITH_DEPENDS
a6f80f0e 184
cca03c30 185 def set_withdepends(self, withdepends):
186 self.logger.debug('setting withdepends to true')
187 self.WITH_DEPENDS = withdepends
a6f80f0e 188
189 def set_iface_state(self, ifaceobj, state, status):
190 ifaceobj.set_state(state)
191 ifaceobj.set_status(status)
192 self.statemanager.update_iface_state(ifaceobj)
193
194 def get_iface_objs(self, ifacename):
195 return self.ifaceobjdict.get(ifacename)
196
197 def get_iface_obj_first(self, ifacename):
198 ifaceobjs = self.get_iface_objs(ifacename)
199 if ifaceobjs is not None:
200 return ifaceobjs[0]
201 return None
202
203 def get_iface_obj_last(self, ifacename):
204 return self.ifaceobjdict.get(ifacename)[-1]
205
d08d5f54 206 def create_n_save_ifaceobjcurr(self, ifaceobj):
739f665b 207 ifacename = ifaceobj.get_name()
208 ifaceobjcurr = self.get_ifaceobjcurr(ifacename)
69f58278 209 if ifaceobjcurr:
739f665b 210 return ifaceobjcurr
a6f80f0e 211
739f665b 212 ifaceobjcurr = iface()
213 ifaceobjcurr.set_name(ifacename)
f3215127 214 ifaceobjcurr.set_lowerifaces(ifaceobj.get_lowerifaces())
69f58278 215 ifaceobjcurr.set_priv_flags(ifaceobj.get_priv_flags())
739f665b 216 self.ifaceobjcurrdict[ifacename] = ifaceobjcurr
a6f80f0e 217
d08d5f54 218 return ifaceobjcurr
a6f80f0e 219
220 def get_ifaceobjcurr(self, ifacename):
221 return self.ifaceobjcurrdict.get(ifacename)
222
739f665b 223 def get_ifaceobjrunning(self, ifacename):
224 return self.ifaceobjrunningdict.get(ifacename)
225
a6f80f0e 226 def get_iface_status(self, ifacename):
227 ifaceobjs = self.get_iface_objs(ifacename)
228 for i in ifaceobjs:
229 if i.get_status() != ifaceStatus.SUCCESS:
230 return i.get_status()
231
232 return ifaceStatus.SUCCESS
233
234 def get_iface_refcnt(self, ifacename):
235 max = 0
236 ifaceobjs = self.get_iface_objs(ifacename)
237 for i in ifaceobjs:
238 if i.get_refcnt() > max:
239 max = i.get_refcnt()
240 return max
241
37c0543d 242 def create_n_save_ifaceobj(self, ifacename, priv_flags=None,
243 increfcnt=False):
a6f80f0e 244 """ creates and returns a fake vlan iface object.
739f665b 245 This was added to support creation of simple vlan
246 devices without any user specified configuration.
a6f80f0e 247 """
739f665b 248 ifaceobj = iface()
249 ifaceobj.set_name(ifacename)
37c0543d 250 ifaceobj.priv_flags = priv_flags
251 ifaceobj.set_auto()
d08d5f54 252 if increfcnt:
739f665b 253 ifaceobj.inc_refcnt()
254 self.ifaceobjdict[ifacename] = [ifaceobj]
a6f80f0e 255
f3215127 256 return ifaceobj
257
d08d5f54 258 def is_iface_builtin_byname(self, ifacename):
cca03c30 259 """ Returns true if iface name is a builtin interface.
a6f80f0e 260
cca03c30 261 A builtin interface is an interface which ifupdown understands.
262 The following are currently considered builtin ifaces:
263 - vlan interfaces in the format <ifacename>.<vlanid>
a6f80f0e 264 """
d08d5f54 265 return '.' in ifacename
a6f80f0e 266
37c0543d 267 def is_ifaceobj_builtin(self, ifaceobj):
268 """ Returns true if iface name is a builtin interface.
269
270 A builtin interface is an interface which ifupdown understands.
271 The following are currently considered builtin ifaces:
272 - vlan interfaces in the format <ifacename>.<vlanid>
273 """
d08d5f54 274 return (ifaceobj.priv_flags & self.BUILTIN)
37c0543d 275
276 def is_ifaceobj_noconfig(self, ifaceobj):
277 """ Returns true if iface name did not have a user defined config.
278
279 These interfaces appear only when they are dependents of interfaces
280 which have user defined config
281 """
d08d5f54 282 return (ifaceobj.priv_flags & self.NOCONFIG)
37c0543d 283
d08d5f54 284 def is_iface_noconfig(self, ifacename):
285 """ Returns true if iface has no config """
37c0543d 286
d08d5f54 287 ifaceobj = self.get_iface_obj_first(ifacename)
288 if not ifaceobj: return True
37c0543d 289
d08d5f54 290 return self.is_ifaceobj_noconfig(ifaceobj)
291
f3215127 292 def preprocess_dependency_list(self, upperifacename, dlist, ops):
739f665b 293 """ We go through the dependency list and
294 delete or add interfaces from the interfaces dict by
295 applying the following rules:
296 if flag _DELETE_DEPENDENT_IFACES_WITH_NOCONFIG is True:
297 we only consider devices whose configuration was
298 specified in the network interfaces file. We delete
299 any interface whose config was not specified except
300 for vlan devices. vlan devices get special treatment.
301 Even if they are not present they are created and added
302 to the ifacesdict
303 elif flag _DELETE_DEPENDENT_IFACES_WITH_NOCONFIG is False:
304 we create objects for all dependent devices that are not
305 present in the ifacesdict
306 """
a6f80f0e 307 del_list = []
308
a6f80f0e 309 for d in dlist:
310 dilist = self.get_iface_objs(d)
d08d5f54 311 if not dilist:
312 if self.is_iface_builtin_byname(d):
f3215127 313 self.create_n_save_ifaceobj(d, self.BUILTIN | self.NOCONFIG,
314 True).add_to_upperifaces(upperifacename)
315 elif not self._DELETE_DEPENDENT_IFACES_WITH_NOCONFIG:
316 self.create_n_save_ifaceobj(d, self.NOCONFIG,
317 True).add_to_upperifaces(upperifacename)
a6f80f0e 318 else:
a6f80f0e 319 del_list.append(d)
320 else:
321 for di in dilist:
322 di.inc_refcnt()
f3215127 323 di.add_to_upperifaces(upperifacename)
a6f80f0e 324
325 for d in del_list:
326 dlist.remove(d)
327
d08d5f54 328 def query_dependents(self, ifaceobj, ops):
a6f80f0e 329 """ Gets iface dependents by calling into respective modules """
330 dlist = None
331
a6f80f0e 332 # Get dependents for interface by querying respective modules
d08d5f54 333 for op in ops:
be0b20f2 334 for mname in self.module_ops.get(op):
37c0543d 335 module = self.modules.get(mname)
336 if op == 'query-running':
337 if (hasattr(module,
338 'get_dependent_ifacenames_running') == False):
339 continue
340 dlist = module.get_dependent_ifacenames_running(ifaceobj)
341 else:
342 if (hasattr(module, 'get_dependent_ifacenames') == False):
343 continue
344 dlist = module.get_dependent_ifacenames(ifaceobj,
739f665b 345 self.ifaceobjdict.keys())
fe0a57d3 346 if dlist:
37c0543d 347 self.logger.debug('%s: ' %ifaceobj.get_name() +
f3215127 348 'got lowerifaces/dependents: %s' %str(dlist))
37c0543d 349 break
a6f80f0e 350 return dlist
351
d08d5f54 352 def populate_dependency_info(self, ifacenames, ops):
a6f80f0e 353 """ recursive function to generate iface dependency info """
354
37c0543d 355 if ifacenames is None:
356 ifacenames = self.ifaceobjdict.keys()
357
358 self.logger.debug('populating dependency info for %s' %str(ifacenames))
a6f80f0e 359
551a3627 360 iqueue = deque(ifacenames)
361 while iqueue:
362 i = iqueue.popleft()
363
a6f80f0e 364 # Go through all modules and find dependent ifaces
365 dlist = None
366 ifaceobj = self.get_iface_obj_first(i)
367 if ifaceobj is None:
368 continue
369
f3215127 370 dlist = ifaceobj.get_lowerifaces()
a6f80f0e 371 if dlist is None:
d08d5f54 372 dlist = self.query_dependents(ifaceobj, ops)
3e8ee54f 373 else:
3e8ee54f 374 continue
a6f80f0e 375
10720a53 376 if dlist is not None:
f3215127 377 self.preprocess_dependency_list(ifaceobj.get_name(),
378 dlist, ops)
379 self.logger.debug('%s: lowerifaces/dependents after processing: %s'
37c0543d 380 %(i, str(dlist)))
f3215127 381 ifaceobj.set_lowerifaces(dlist)
739f665b 382 [iqueue.append(d) for d in dlist]
a6f80f0e 383
37c0543d 384 if self.dependency_graph.get(i) is None:
385 self.dependency_graph[i] = dlist
a6f80f0e 386
d08d5f54 387 def _save_iface(self, ifaceobj):
388 if not self.ifaceobjdict.get(ifaceobj.get_name()):
a6f80f0e 389 self.ifaceobjdict[ifaceobj.get_name()] = [ifaceobj]
390 else:
391 self.ifaceobjdict[ifaceobj.get_name()].append(ifaceobj)
392
d08d5f54 393 def _module_syntax_checker(self, attrname, attrval):
394 for m, mdict in self.module_attrs.items():
395 attrsdict = mdict.get('attrs')
396 if attrsdict and attrname in attrsdict.keys(): return True
397 return False
398
a6f80f0e 399 def read_default_iface_config(self):
400 """ Reads default network interface config /etc/network/interfaces. """
401 nifaces = networkInterfaces()
d08d5f54 402 nifaces.subscribe('iface_found', self._save_iface)
403 nifaces.subscribe('validate', self._module_syntax_checker)
a6f80f0e 404 nifaces.load()
405
406 def read_iface_config(self):
407 return self.read_default_iface_config()
408
409 def read_old_iface_config(self):
410 """ Reads the saved iface config instead of default iface config. """
411
412 # Read it from the statemanager
413 self.ifaceobjdict = self.statemanager.get_ifaceobjdict()
414
37c0543d 415 def load_addon_modules_config(self):
416 with open(self.addon_modules_configfile, 'r') as f:
417 lines = f.readlines()
418 for l in lines:
419 litems = l.rstrip(' \n').split(',')
420 operation = litems[0]
421 mname = litems[1]
be0b20f2 422 self.module_ops[operation].append(mname)
37c0543d 423
424 def load_addon_modules(self, modules_dir):
a6f80f0e 425 """ load python modules from modules_dir
426
427 Default modules_dir is /usr/share/ifupdownmodules
428
429 """
a6f80f0e 430 self.logger.info('loading builtin modules from %s' %modules_dir)
6ef5bfa2 431 self.load_addon_modules_config()
a6f80f0e 432 if not modules_dir in sys.path:
37c0543d 433 sys.path.append(modules_dir)
a6f80f0e 434 try:
be0b20f2 435 for op, mlist in self.module_ops.items():
d08d5f54 436 for mname in mlist:
437 if self.modules.get(mname) is not None:
438 continue
439 mpath = modules_dir + '/' + mname + '.py'
440 if os.path.exists(mpath):
441 try:
442 m = __import__(mname)
443 mclass = getattr(m, mname)
444 except:
445 raise
446 minstance = mclass(force=self.FORCE,
447 dryrun=self.DRYRUN,
448 nowait=self.NOWAIT,
449 perfmode=self.PERFMODE,
450 cache=self.CACHE)
451 self.modules[mname] = minstance
452 if hasattr(minstance, 'get_modinfo'):
453 self.module_attrs[mname] = minstance.get_modinfo()
a6f80f0e 454 except:
455 raise
456
37c0543d 457 # Assign all modules to query operations
be0b20f2 458 self.module_ops['query-checkcurr'] = self.modules.keys()
459 self.module_ops['query-running'] = self.modules.keys()
460 self.module_ops['query-dependency'] = self.modules.keys()
461 self.module_ops['query'] = self.modules.keys()
462 self.module_ops['query-raw'] = self.modules.keys()
d08d5f54 463
464 def modules_help(self):
465 indent = ' '
466 for m, mdict in self.module_attrs.items():
467 if not mdict:
468 continue
469 print('%s: %s' %(m, mdict.get('mhelp')))
470 attrdict = mdict.get('attrs')
471 if not attrdict:
472 continue
473 try:
474 for attrname, attrvaldict in attrdict.items():
475 if attrvaldict.get('compat', False):
476 continue
477 print('%s%s' %(indent, attrname))
478 print('%shelp: %s' %(indent + ' ',
479 attrvaldict.get('help', '')))
480 print ('%srequired: %s' %(indent + ' ',
481 attrvaldict.get('required', False)))
482 default = attrvaldict.get('default')
483 if default:
484 print('%sdefault: %s' %(indent + ' ', default))
485
486 validrange = attrvaldict.get('validrange')
487 if validrange:
488 print('%svalidrange: %s'
489 %(indent + ' ', '-'.join(validrange)))
490
491 validvals = attrvaldict.get('validvals')
492 if validvals:
493 print('%svalidvals: %s'
494 %(indent + ' ', ','.join(validvals)))
495
496 examples = attrvaldict.get('example')
497 if not examples:
498 continue
a6f80f0e 499
d08d5f54 500 print '%sexample:' %(indent + ' ')
501 for e in examples:
502 print '%s%s' %(indent + ' ', e)
503 except:
504 pass
505 print ''
506
37c0543d 507 def load_scripts(self, modules_dir):
a6f80f0e 508 """ loading user modules from /etc/network/.
509
510 Note that previously loaded python modules override modules found
511 under /etc/network if any
512
513 """
514
37c0543d 515 self.logger.info('looking for user scripts under %s' %modules_dir)
be0b20f2 516 for op, mlist in self.script_ops.items():
d08d5f54 517 msubdir = modules_dir + '/if-%s.d' %op
518 self.logger.info('loading scripts under %s ...' %msubdir)
519 try:
520 module_list = os.listdir(msubdir)
521 for module in module_list:
522 if self.modules.get(module) is not None:
523 continue
be0b20f2 524 self.script_ops[op].append(
a6f80f0e 525 msubdir + '/' + module)
d08d5f54 526 except:
f802fe3c 527 # continue reading
528 pass
a6f80f0e 529
a6f80f0e 530 def conv_iface_namelist_to_objlist(self, intf_list):
531 for intf in intf_list:
532 iface_obj = self.get_iface(intf)
d08d5f54 533 if not iface_obj:
a6f80f0e 534 raise ifupdownInvalidValue('no iface %s', intf)
a6f80f0e 535 iface_objs.append(iface_obj)
a6f80f0e 536 return iface_objs
537
538
d08d5f54 539 def run_without_dependents(self, ops, ifacenames):
540 """ Run interface list without their dependents """
541 if not ifacenames:
37c0543d 542 raise ifupdownInvalidValue('no interfaces found')
a6f80f0e 543
d08d5f54 544 self.logger.debug('run_without_dependents for ops %s for %s'
545 %(str(ops), str(ifacenames)))
a6f80f0e 546
be0b20f2 547 ifaceScheduler.run_iface_list(self, ifacenames, ops, parent=None,
d08d5f54 548 order=ifaceSchedulerFlags.INORDER
549 if 'down' in ops[0]
550 else ifaceSchedulerFlags.POSTORDER,
551 followdependents=False)
a6f80f0e 552
d08d5f54 553 def run_with_dependents(self, ops, ifacenames):
a6f80f0e 554 ret = 0
37c0543d 555 self.logger.debug('running \'%s\' with dependents for %s'
d08d5f54 556 %(str(ops), str(ifacenames)))
a6f80f0e 557
a6f80f0e 558 if ifacenames is None:
559 ifacenames = self.ifaceobjdict.keys()
560
f3215127 561 self.logger.info('dependency graph:')
562 self.logger.info(self.pp.pformat(self.dependency_graph))
a6f80f0e 563
564 if self.njobs > 1:
be0b20f2 565 ret = ifaceScheduler.run_iface_dependency_graph_parallel(self,
d08d5f54 566 self.dependency_graph, ops)
a6f80f0e 567 else:
be0b20f2 568 ret = ifaceScheduler.run_iface_dependency_graphs(self,
d08d5f54 569 self.dependency_graph, ops,
570 order=ifaceSchedulerFlags.INORDER
571 if 'down' in ops[0]
572 else ifaceSchedulerFlags.POSTORDER)
a6f80f0e 573 return ret
574
d08d5f54 575 def print_dependency(self, ifacenames, format):
739f665b 576 if ifacenames is None:
577 ifacenames = self.ifaceobjdict.keys()
578
739f665b 579 if format == 'list':
d08d5f54 580 for k,v in self.dependency_graph.items():
581 print '%s : %s' %(k, str(v))
739f665b 582 elif format == 'dot':
583 indegrees = {}
584 map(lambda i: indegrees.update({i :
585 self.get_iface_refcnt(i)}),
37c0543d 586 self.dependency_graph.keys())
587 graph.generate_dots(self.dependency_graph, indegrees)
a6f80f0e 588
589 def validate_ifaces(self, ifacenames):
590 """ validates interface list for config existance.
591
592 returns -1 if one or more interface not found. else, returns 0
593
594 """
595
596 err_iface = ''
597 for i in ifacenames:
598 ifaceobjs = self.get_iface_objs(i)
599 if ifaceobjs is None:
600 err_iface += ' ' + i
601
fe0a57d3 602 if err_iface:
37c0543d 603 self.logger.error('could not find interfaces: %s' %err_iface)
a6f80f0e 604 return -1
605
606 return 0
607
608
3e8ee54f 609 def iface_whitelisted(self, auto, allow_classes, excludepats, ifacename):
a6f80f0e 610 """ Checks if interface is whitelisted depending on set of parameters.
611
612
613 interfaces are checked against the allow_classes and auto lists.
614
615 """
3e8ee54f 616 # If the interface matches
fe0a57d3 617 if excludepats:
3e8ee54f 618 for e in excludepats:
d08d5f54 619 if re.search(e, ifacename):
3e8ee54f 620 return False
a6f80f0e 621
622 ifaceobjs = self.get_iface_objs(ifacename)
623 if ifaceobjs is None:
624 self.logger.debug('iface %s' %ifacename + ' not found')
625 return False
626
627 # We check classes first
fe0a57d3 628 if allow_classes:
a6f80f0e 629 for i in ifaceobjs:
fe0a57d3 630 if i.get_classes():
3e8ee54f 631 common = Set([allow_classes]).intersection(
a6f80f0e 632 Set(i.get_classes()))
fe0a57d3 633 if common:
a6f80f0e 634 return True
635 return False
636
d08d5f54 637 if auto:
a6f80f0e 638 for i in ifaceobjs:
d08d5f54 639 if i.get_auto():
a6f80f0e 640 return True
641 return False
642
643 return True
644
645 def generate_running_env(self, ifaceobj, op):
739f665b 646 """ Generates a dictionary with env variables required for
647 an interface. Used to support script execution for interfaces.
a6f80f0e 648 """
649
650 cenv = None
651 iface_env = ifaceobj.get_env()
652 if iface_env is not None:
653 cenv = os.environ
d08d5f54 654 if cenv:
a6f80f0e 655 cenv.update(iface_env)
656 else:
657 cenv = iface_env
658
659 cenv['MODE'] = self.compat_conv_op_to_mode(op)
660
661 return cenv
662
d08d5f54 663 def up(self, ops, auto=False, allow_classes=None, ifacenames=None,
664 excludepats=None, printdependency=None):
665 if auto:
a6f80f0e 666 self.ALL = True
cca03c30 667 self.WITH_DEPENDS = True
a6f80f0e 668
d08d5f54 669 try:
670 self.read_iface_config()
671 except Exception, e:
672 raise
a6f80f0e 673
cca03c30 674 if ifacenames is not None:
675 # If iface list is given by the caller, always check if iface
676 # is present
a6f80f0e 677 if self.validate_ifaces(ifacenames) != 0:
eab25b7c 678 raise Exception('all or some interfaces not found')
a6f80f0e 679
680 # if iface list not given by user, assume all from config file
681 if ifacenames is None: ifacenames = self.ifaceobjdict.keys()
682
683 # filter interfaces based on auto and allow classes
cca03c30 684 filtered_ifacenames = [i for i in ifacenames
685 if self.iface_whitelisted(auto, allow_classes,
d08d5f54 686 excludepats, i)]
fe0a57d3 687 if not filtered_ifacenames:
d08d5f54 688 raise Exception('no ifaces found matching given allow lists')
a6f80f0e 689
d08d5f54 690 self.populate_dependency_info(filtered_ifacenames, ops)
37c0543d 691
739f665b 692 if printdependency is not None:
d08d5f54 693 self.print_dependency(filtered_ifacenames, printdependency)
739f665b 694 return
695
d08d5f54 696 if self.WITH_DEPENDS:
697 self.run_with_dependents(ops, filtered_ifacenames)
cca03c30 698 else:
d08d5f54 699 self.run_without_dependents(ops, filtered_ifacenames)
a6f80f0e 700
e37ad4a6 701 if self.DRYRUN:
702 return
703
a6f80f0e 704 # Update persistant iface states
705 try:
d08d5f54 706 if self.ALL:
a6f80f0e 707 self.statemanager.flush_state(self.ifaceobjdict)
708 else:
709 self.statemanager.flush_state()
710 except Exception, e:
711 if self.logger.isEnabledFor(logging.DEBUG):
712 t = sys.exc_info()[2]
713 traceback.print_tb(t)
714 self.logger.warning('error saving state (%s)' %str(e))
715
d08d5f54 716 def down(self, ops, auto=False, allow_classes=None, ifacenames=None,
717 excludepats=None, printdependency=None):
718 loaded_newconfig = False
719 if auto:
720 self.ALL = True
721 self.WITH_DEPENDS = True
a6f80f0e 722
d08d5f54 723 # for down we need to look at old state
724 self.logger.debug('Looking at old state ..')
a6f80f0e 725
fe0a57d3 726 if self.statemanager.get_ifaceobjdict():
d08d5f54 727 self.read_old_iface_config()
fe0a57d3 728 else:
d08d5f54 729 # If no old state available
730 self.logger.info('old state not available. ' +
fe0a57d3 731 'Loading new iface config file')
d08d5f54 732 try:
733 self.read_iface_config()
734 except Exception, e:
735 raise Exception('error reading iface config (%s)' %str(e))
736 loaded_newconfig = True
d08d5f54 737
738 if ifacenames:
739 # If iface list is given by the caller, always check if iface
740 # is present
741 if self.validate_ifaces(ifacenames) != 0:
742 raise Exception('all or some interfaces not found')
743
744 # if iface list not given by user, assume all from config file
fe0a57d3 745 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
d08d5f54 746
747 # filter interfaces based on auto and allow classes
748 filtered_ifacenames = [i for i in ifacenames
749 if self.iface_whitelisted(auto, allow_classes,
750 excludepats, i)]
fe0a57d3 751 if not filtered_ifacenames:
d08d5f54 752 raise Exception('no ifaces found matching given allow lists')
753
754 self.populate_dependency_info(filtered_ifacenames, ops)
755 if printdependency:
756 self.print_dependency(filtered_ifacenames, printdependency)
757 return
758
759 if self.WITH_DEPENDS:
760 self.run_with_dependents(ops, filtered_ifacenames)
761 else:
762 self.run_without_dependents(ops, filtered_ifacenames)
763
e37ad4a6 764 if self.DRYRUN:
765 return
766
d08d5f54 767 if loaded_newconfig:
768 # Update persistant iface states
769 try:
770 if self.ALL:
771 self.statemanager.flush_state(self.ifaceobjdict)
772 else:
773 self.statemanager.flush_state()
774 except Exception, e:
775 if self.logger.isEnabledFor(logging.DEBUG):
776 t = sys.exc_info()[2]
777 traceback.print_tb(t)
778 self.logger.warning('error saving state (%s)' %str(e))
779
780 def query(self, ops, auto=False, allow_classes=None, ifacenames=None,
739f665b 781 excludepats=None, printdependency=None,
d08d5f54 782 format='native'):
783 if auto:
739f665b 784 self.logger.debug('setting flag ALL')
785 self.ALL = True
37c0543d 786 self.WITH_DEPENDS = True
739f665b 787
d08d5f54 788 if ops[0] == 'query-syntax':
789 self.modules_help()
790 return
791 elif ops[0] == 'query-running':
739f665b 792 # create fake devices to all dependents that dont have config
37c0543d 793 map(lambda i: self.create_n_save_ifaceobj(i, self.NOCONFIG),
794 ifacenames)
739f665b 795 else:
796 try:
797 self.read_iface_config()
798 except Exception:
799 raise
800
d08d5f54 801 if ifacenames is not None and ops[0] != 'query-running':
739f665b 802 # If iface list is given, always check if iface is present
803 if self.validate_ifaces(ifacenames) != 0:
804 raise Exception('all or some interfaces not found')
805
806 # if iface list not given by user, assume all from config file
807 if ifacenames is None: ifacenames = self.ifaceobjdict.keys()
808
809 # filter interfaces based on auto and allow classes
d08d5f54 810 if ops[0] == 'query-running':
739f665b 811 filtered_ifacenames = ifacenames
812 else:
813 filtered_ifacenames = [i for i in ifacenames
814 if self.iface_whitelisted(auto, allow_classes,
d08d5f54 815 excludepats, i)]
fe0a57d3 816 if not filtered_ifacenames:
739f665b 817 raise Exception('no ifaces found matching ' +
818 'given allow lists')
37c0543d 819
d08d5f54 820 self.populate_dependency_info(filtered_ifacenames, ops)
821 if ops[0] == 'query-dependency' and printdependency:
822 self.print_dependency(filtered_ifacenames, printdependency)
823 return
739f665b 824
75730152 825 if ops[0] == 'query':
826 return self.print_ifaceobjs_pretty(filtered_ifacenames, format)
827 elif ops[0] == 'query-raw':
828 return self.print_ifaceobjs_raw(filtered_ifacenames)
829
d08d5f54 830 if self.WITH_DEPENDS:
831 self.run_with_dependents(ops, filtered_ifacenames)
cca03c30 832 else:
d08d5f54 833 self.run_without_dependents(ops, filtered_ifacenames)
739f665b 834
d08d5f54 835 if ops[0] == 'query-checkcurr':
836 ret = self.print_ifaceobjscurr_pretty(filtered_ifacenames, format)
739f665b 837 if ret != 0:
838 # if any of the object has an error, signal that silently
839 raise Exception('')
d08d5f54 840 elif ops[0] == 'query-running':
841 self.print_ifaceobjsrunning_pretty(filtered_ifacenames, format)
739f665b 842 return
843
844 def reload(self, auto=False, allow=None,
37c0543d 845 ifacenames=None, excludepats=None, downchangediface=False):
739f665b 846 """ main ifupdown run method """
847 allow_classes = []
d08d5f54 848 upops = ['pre-up', 'up', 'post-up']
849 downops = ['pre-down', 'down', 'post-down']
739f665b 850
851 self.logger.debug('reloading interface config ..')
852
d08d5f54 853 if auto:
739f665b 854 self.ALL = True
37c0543d 855 self.WITH_DEPENDS = True
739f665b 856
857 try:
37c0543d 858 # Read the current interface config
739f665b 859 self.read_iface_config()
860 except Exception, e:
861 raise
862
37c0543d 863 # generate dependency graph of interfaces
d08d5f54 864 self.populate_dependency_info(ifacenames, upops)
37c0543d 865
866 # Save a copy of new iface objects and dependency_graph
d08d5f54 867 new_ifaceobjdict = dict(self.get_ifaceobjdict())
868 new_dependency_graph = dict(self.get_dependency_graph())
739f665b 869
fe0a57d3 870 if self.statemanager.get_ifaceobjdict():
739f665b 871 # if old state is present, read old state and mark op for 'down'
872 # followed by 'up' aka: reload
37c0543d 873 # old interface config is read into self.ifaceobjdict
874 #
739f665b 875 self.read_old_iface_config()
876 op = 'reload'
877 else:
878 # oldconfig not available, continue with 'up' with new config
879 op = 'up'
880
881 if ifacenames is None: ifacenames = self.ifaceobjdict.keys()
37c0543d 882
fe0a57d3 883 if op == 'reload' and ifacenames:
739f665b 884 filtered_ifacenames = [i for i in ifacenames
885 if self.iface_whitelisted(auto, allow_classes,
d08d5f54 886 excludepats, i)]
37c0543d 887
888 # Generate the interface down list
889 # Interfaces that go into the down list:
890 # - interfaces that were present in last config and are not
891 # present in the new config
892 # - interfaces that were changed between the last and current
893 # config
894 #
37c0543d 895 ifacedownlist = []
896 for ifname, lastifobjlist in self.ifaceobjdict.items():
897 objidx = 0
898
899 # If interface is not present in the new file
900 # append it to the down list
901 newifobjlist = new_ifaceobjdict.get(ifname)
902 if newifobjlist == None:
903 ifacedownlist.append(ifname)
904 continue
905
906 if downchangediface == False:
907 continue
908
909 # If interface has changed between the current file
910 # and the last installed append it to the down list
911 if len(newifobjlist) != len(lastifobjlist):
912 ifacedownlist.append(ifname)
913 continue
914
915 # compare object list
916 for objidx in range(0, len(lastifobjlist)):
917 oldobj = lastifobjlist[objidx]
918 newobj = newifobjlist[objidx]
d08d5f54 919 if newobj.is_different(oldobj):
37c0543d 920 ifacedownlist.append(ifname)
921 continue
922
923
fe0a57d3 924 if ifacedownlist:
37c0543d 925 self.logger.info('Executing down on interfaces: %s'
739f665b 926 %str(ifacedownlist))
37c0543d 927 # Generate dependency info for old config
d08d5f54 928 self.populate_dependency_info(ifacedownlist, downops)
f802fe3c 929 self.run_with_dependents(downops, ifacedownlist)
930
739f665b 931 # Update persistant iface states
932 try:
d08d5f54 933 if self.ALL:
739f665b 934 self.statemanager.flush_state(self.ifaceobjdict)
935 else:
936 self.statemanager.flush_state()
937 except Exception, e:
938 if self.logger.isEnabledFor(logging.DEBUG):
939 t = sys.exc_info()[2]
940 traceback.print_tb(t)
941 self.logger.warning('error saving state (%s)' %str(e))
37c0543d 942 else:
943 self.logger.debug('no interfaces to down ..')
739f665b 944
37c0543d 945 # Now, run up with new config dict
739f665b 946 self.set_ifaceobjdict(new_ifaceobjdict)
37c0543d 947 self.set_dependency_graph(new_dependency_graph)
948
739f665b 949 ifacenames = self.ifaceobjdict.keys()
950 filtered_ifacenames = [i for i in ifacenames
951 if self.iface_whitelisted(auto, allow_classes,
d08d5f54 952 excludepats, i)]
739f665b 953
37c0543d 954 self.logger.info('Executing up on interfaces: %s'
955 %str(filtered_ifacenames))
d08d5f54 956 if self.WITH_DEPENDS:
957 self.run_with_dependents(upops, filtered_ifacenames)
37c0543d 958 else:
d08d5f54 959 self.run_without_dependents(upops, filtered_ifacenames)
739f665b 960
e37ad4a6 961 if self.DRYRUN:
962 return
963
739f665b 964 # Update persistant iface states
965 try:
d08d5f54 966 if self.ALL:
739f665b 967 self.statemanager.flush_state(self.get_ifaceobjdict())
968 else:
969 self.statemanager.flush_state()
970 except Exception, e:
971 if self.logger.isEnabledFor(logging.DEBUG):
972 t = sys.exc_info()[2]
973 traceback.print_tb(t)
974 self.logger.warning('error saving state (%s)' %str(e))
a6f80f0e 975
976 def dump(self):
977 """ all state dump """
978
979 print 'ifupdown object dump'
980 print self.pp.pprint(self.modules)
981 print self.pp.pprint(self.ifaces)
982 self.state_manager.dump()
983
984 def print_state(self, ifacenames=None):
985 self.statemanager.dump(ifacenames)
986
739f665b 987 def print_ifaceobjs_raw(self, ifacenames):
988 for i in ifacenames:
75730152 989 for ifaceobj in self.get_iface_objs(i):
990 if (self.is_ifaceobj_builtin(ifaceobj) or
991 not ifaceobj.is_config_present()):
992 continue
993 ifaceobj.dump_raw(self.logger)
739f665b 994 print '\n'
75730152 995 if self.WITH_DEPENDS:
f3215127 996 dlist = ifaceobj.get_lowerifaces()
fe0a57d3 997 if not dlist: continue
75730152 998 self.print_ifaceobjs_pretty(dlist, format)
739f665b 999
d08d5f54 1000 def print_ifaceobjs_pretty(self, ifacenames, format='native'):
a6f80f0e 1001 for i in ifacenames:
75730152 1002 for ifaceobj in self.get_iface_objs(i):
be0b20f2 1003 if (self.is_ifaceobj_noconfig(ifaceobj)):
75730152 1004 continue
1005 if format == 'json':
1006 ifaceobj.dump_json()
1007 else:
1008 ifaceobj.dump_pretty()
1009
1010 if self.WITH_DEPENDS:
f3215127 1011 dlist = ifaceobj.get_lowerifaces()
fe0a57d3 1012 if not dlist: continue
75730152 1013 self.print_ifaceobjs_pretty(dlist, format)
739f665b 1014
1015 def dump_ifaceobjs(self, ifacenames):
1016 for i in ifacenames:
1017 ifaceobjs = self.get_iface_objs(i)
1018 for i in ifaceobjs:
1019 i.dump(self.logger)
eab25b7c 1020 print '\n'
a6f80f0e 1021
d08d5f54 1022 def print_ifaceobjscurr_pretty(self, ifacenames, format='native'):
eab25b7c 1023 """ Dumps current running state of interfaces.
1024
1025 returns 1 if any of the interface has an error,
1026 else returns 0
eab25b7c 1027 """
eab25b7c 1028 ret = 0
a6f80f0e 1029 for i in ifacenames:
1030 ifaceobj = self.get_ifaceobjcurr(i)
d08d5f54 1031 if not ifaceobj: continue
10720a53 1032 if ifaceobj.get_status() == ifaceStatus.NOTFOUND:
69f58278 1033 print 'iface %s %s\n' %(ifaceobj.get_name(),
1034 ifaceStatus.to_str(ifaceStatus.NOTFOUND))
10720a53 1035 ret = 1
1036 continue
1037 elif ifaceobj.get_status() == ifaceStatus.ERROR:
eab25b7c 1038 ret = 1
cca03c30 1039
be0b20f2 1040 if (self.is_ifaceobj_noconfig(ifaceobj)):
cca03c30 1041 continue
1042
d08d5f54 1043 if format == 'json':
69f58278 1044 ifaceobj.dump_json(with_status=True)
551a3627 1045 else:
69f58278 1046 ifaceobj.dump_pretty(with_status=True)
eab25b7c 1047
75730152 1048 if self.WITH_DEPENDS:
f3215127 1049 dlist = ifaceobj.get_lowerifaces()
fe0a57d3 1050 if not dlist: continue
cca03c30 1051 self.print_ifaceobjscurr_pretty(dlist, format)
eab25b7c 1052 return ret
a6f80f0e 1053
d08d5f54 1054 def print_ifaceobjsrunning_pretty(self, ifacenames, format='native'):
739f665b 1055 for i in ifacenames:
1056 ifaceobj = self.get_iface_obj_first(i)
1057 if ifaceobj.get_status() == ifaceStatus.NOTFOUND:
cca03c30 1058 print 'iface %s' %ifaceobj.get_name() + ' (not found)\n'
1059 continue
1060
1061 if ifaceobj.is_config_present() == False:
739f665b 1062 continue
1063
d08d5f54 1064 if format == 'json':
1065 ifaceobj.dump_json()
1066 else:
1067 ifaceobj.dump_pretty()
739f665b 1068
75730152 1069 if self.WITH_DEPENDS:
f3215127 1070 dlist = ifaceobj.get_lowerifaces()
fe0a57d3 1071 if not dlist: continue
cca03c30 1072 self.print_ifaceobjsrunning_pretty(dlist, format)
739f665b 1073 return