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