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