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