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