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