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