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