]> git.proxmox.com Git - mirror_ifupdown2.git/blob - ifupdown2/ifupdown/ifupdownmain.py
add new ifupdown2.conf option ifreload_down_changed to control ifreload
[mirror_ifupdown2.git] / ifupdown2 / ifupdown / ifupdownmain.py
1 #!/usr/bin/python
2 #
3 # Copyright 2014 Cumulus Networks, Inc. All rights reserved.
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 import copy
17 import json
18 from statemanager import *
19 from networkinterfaces import *
20 from iface import *
21 from scheduler import *
22 from collections import deque
23 from collections import OrderedDict
24 from graph import *
25 from sets import Set
26
27 """
28 .. module:: ifupdownmain
29 :synopsis: main module for ifupdown package
30
31 .. moduleauthor:: Roopa Prabhu <roopa@cumulusnetworks.com>
32
33 """
34
35 _tickmark = u'\u2713'
36 _crossmark = u'\u2717'
37 _success_sym = '(%s)' %_tickmark
38 _error_sym = '(%s)' %_crossmark
39
40 class ifupdownFlags():
41 FORCE = False
42 DRYRUN = False
43 NOWAIT = False
44 PERFMODE = False
45 CACHE = False
46
47 # Flags
48 CACHE_FLAGS = 0x0
49
50 class ifupdownMain(ifupdownBase):
51 """ ifupdown2 main class """
52
53 # Flags
54 WITH_DEPENDS = False
55 ALL = False
56 IFACE_CLASS = False
57 COMPAT_EXEC_SCRIPTS = False
58 STATEMANAGER_ENABLE = True
59 STATEMANAGER_UPDATE = True
60 ADDONS_ENABLE = False
61
62 # priv flags to mark iface objects
63 BUILTIN = 0x0001
64 NOCONFIG = 0x0010
65
66 scripts_dir='/etc/network'
67 addon_modules_dir='/usr/share/ifupdownaddons'
68 addon_modules_configfile='/var/lib/ifupdownaddons/addons.conf'
69
70 # iface dictionary in the below format:
71 # { '<ifacename>' : [<ifaceobject1>, <ifaceobject2> ..] }
72 # eg:
73 # { 'swp1' : [<iface swp1>, <iface swp2> ..] }
74 #
75 # Each ifaceobject corresponds to a configuration block for
76 # that interface
77 # The value in the dictionary is a list because the network
78 # interface configuration file supports more than one iface section
79 # in the interfaces file
80 ifaceobjdict = OrderedDict()
81
82 # iface dictionary representing the curr running state of an iface
83 # in the below format:
84 # {'<ifacename>' : <ifaceobject>}
85 ifaceobjcurrdict = OrderedDict()
86
87 # Dictionary representing operation and modules
88 # for every operation
89 module_ops = OrderedDict([('pre-up', []),
90 ('up' , []),
91 ('post-up' , []),
92 ('query-checkcurr', []),
93 ('query-running', []),
94 ('query-dependency', []),
95 ('query', []),
96 ('query-raw', []),
97 ('pre-down', []),
98 ('down' , []),
99 ('post-down' , [])])
100
101 # For old style /etc/network/ bash scripts
102 script_ops = OrderedDict([('pre-up', []),
103 ('up' , []),
104 ('post-up' , []),
105 ('pre-down', []),
106 ('down' , []),
107 ('post-down' , [])])
108
109 # Handlers for ops that ifupdown2 owns
110 def run_up(self, ifaceobj):
111 # Skip link sets on ifaceobjs of type 'vlan' (used for l2 attrs).
112 # there is no real interface behind it
113 if ifaceobj.type == ifaceType.BRIDGE_VLAN:
114 return
115 if (ifaceobj.addr_method and
116 ifaceobj.addr_method == 'manual'):
117 return
118 if self._delay_admin_state:
119 self._delay_admin_state_iface_queue.append(ifaceobj.name)
120 return
121 # If this object is a link slave, ie its link is controlled
122 # by its link master interface, then dont set the link state.
123 # But do allow user to change state of the link if the interface
124 # is already with its link master (hence the master check).
125 if ifaceobj.link_type == ifaceLinkType.LINK_SLAVE:
126 return
127 if not self.link_exists(ifaceobj.name):
128 return
129 self.link_up(ifaceobj.name)
130
131 def run_down(self, ifaceobj):
132 # Skip link sets on ifaceobjs of type 'vlan' (used for l2 attrs)
133 # there is no real interface behind it
134 if ifaceobj.type == ifaceType.BRIDGE_VLAN:
135 return
136 if (ifaceobj.addr_method and
137 ifaceobj.addr_method == 'manual'):
138 return
139 if self._delay_admin_state:
140 self._delay_admin_state_iface_queue.append(ifaceobj.name)
141 return
142 # If this object is a link slave, ie its link is controlled
143 # by its link master interface, then dont set the link state.
144 # But do allow user to change state of the link if the interface
145 # is already with its link master (hence the master check).
146 if ifaceobj.link_type == ifaceLinkType.LINK_SLAVE:
147 return
148 if not self.link_exists(ifaceobj.name):
149 return
150 self.link_down(ifaceobj.name)
151
152 # ifupdown object interface operation handlers
153 ops_handlers = OrderedDict([('up', run_up),
154 ('down', run_down)])
155
156 def run_sched_ifaceobj_posthook(self, ifaceobj, op):
157 if ((ifaceobj.priv_flags & self.BUILTIN) or
158 (ifaceobj.priv_flags & self.NOCONFIG)):
159 return
160 if self.STATEMANAGER_UPDATE:
161 self.statemanager.ifaceobj_sync(ifaceobj, op)
162
163 # ifupdown object interface scheduler pre and posthooks
164 sched_hooks = {'posthook' : run_sched_ifaceobj_posthook}
165
166 def __init__(self, config={},
167 force=False, dryrun=False, nowait=False,
168 perfmode=False, withdepends=False, njobs=1,
169 cache=False, addons_enable=True, statemanager_enable=True,
170 interfacesfile='/etc/network/interfaces',
171 interfacesfileiobuf=None,
172 interfacesfileformat='native'):
173 """This member function initializes the ifupdownmain object.
174
175 Kwargs:
176 config (dict): config dict from /etc/network/ifupdown2/ifupdown2.conf
177 force (bool): force interface configuration
178 dryrun (bool): dryrun interface configuration
179 withdepends (bool): apply interface configuration on all depends
180 interfacesfile (str): interfaces file. default is /etc/network/interfaces
181 interfacesfileformat (str): default is 'native'. Other choices are 'json'
182
183 Raises:
184 AttributeError, KeyError """
185
186 self.logger = logging.getLogger('ifupdown')
187 self.FORCE = force
188 self.DRYRUN = dryrun
189 self.NOWAIT = nowait
190 self.PERFMODE = perfmode
191 self.WITH_DEPENDS = withdepends
192 self.STATEMANAGER_ENABLE = statemanager_enable
193 self.CACHE = cache
194 self.interfacesfile = interfacesfile
195 self.interfacesfileiobuf = interfacesfileiobuf
196 self.interfacesfileformat = interfacesfileformat
197 self.config = config
198 self.logger.debug(self.config)
199
200 self.type = ifaceType.UNKNOWN
201
202 # Can be used to provide hints for caching
203 self.CACHE_FLAGS = 0x0
204 self._DELETE_DEPENDENT_IFACES_WITH_NOCONFIG = False
205 self.ADDONS_ENABLE = addons_enable
206
207 # Copy flags into ifupdownFlags
208 # XXX: before we transition fully to ifupdownFlags
209 ifupdownFlags.FORCE = force
210 ifupdownFlags.DRYRUN = dryrun
211 ifupdownFlags.NOWAIT = nowait
212 ifupdownFlags.PERFMODE = perfmode
213 ifupdownFlags.CACHE = cache
214
215 self.ifaces = OrderedDict()
216 self.njobs = njobs
217 self.pp = pprint.PrettyPrinter(indent=4)
218 self.modules = OrderedDict({})
219 self.module_attrs = {}
220
221 self.load_addon_modules(self.addon_modules_dir)
222 if self.COMPAT_EXEC_SCRIPTS:
223 self.load_scripts(self.scripts_dir)
224 self.dependency_graph = OrderedDict({})
225
226 self._cache_no_repeats = {}
227
228 if self.STATEMANAGER_ENABLE:
229 try:
230 self.statemanager = stateManager()
231 self.statemanager.read_saved_state()
232 except Exception, e:
233 # XXX Maybe we should continue by ignoring old state
234 self.logger.warning('error reading state (%s)' %str(e))
235 raise
236 else:
237 self.STATEMANAGER_UPDATE = False
238 self._delay_admin_state = True if self.config.get(
239 'delay_admin_state_change', '0') == '1' else False
240 self._delay_admin_state_iface_queue = []
241 if self._delay_admin_state:
242 self.logger.info('\'delay_admin_state_change\' is set. admin ' +
243 'state changes will be delayed till the end.')
244
245 self._link_master_slave = True if self.config.get(
246 'link_master_slave', '0') == '1' else False
247 if self._link_master_slave:
248 self.logger.info('\'link_master_slave\' is set. slave admin ' +
249 'state changes will be delayed till the ' +
250 'masters admin state change.')
251
252 def link_master_slave_ignore_error(self, errorstr):
253 # If link master slave flag is set,
254 # there may be cases where the lowerdev may not be
255 # up resulting in 'Network is down' error
256 # This can happen if the lowerdev is a LINK_SLAVE
257 # of another interface which is not up yet
258 # example of such a case:
259 # bringing up a vlan on a bond interface and the bond
260 # is a LINK_SLAVE of a bridge (in other words the bond is
261 # part of a bridge) which is not up yet
262 if self._link_master_slave:
263 if 'Network is down':
264 return True
265 return False
266
267 def get_ifaceobjs(self, ifacename):
268 return self.ifaceobjdict.get(ifacename)
269
270 def get_ifaceobjs_saved(self, ifacename):
271 """ Return ifaceobjects from statemanager """
272 if self.STATEMANAGER_ENABLE:
273 return self.statemanager.get_ifaceobjs(ifacename)
274 else:
275 None
276
277 def get_ifaceobj_first(self, ifacename):
278 ifaceobjs = self.get_ifaceobjs(ifacename)
279 if ifaceobjs:
280 return ifaceobjs[0]
281 return None
282
283 def get_ifacenames(self):
284 return self.ifaceobjdict.keys()
285
286 def get_iface_obj_last(self, ifacename):
287 return self.ifaceobjdict.get(ifacename)[-1]
288
289
290 def must_follow_upperifaces(self, ifacename):
291 #
292 # XXX: This bleeds the knowledge of iface
293 # types in the infrastructure module.
294 # Cant think of a better fix at the moment.
295 # In future maybe the module can set a flag
296 # to indicate if we should follow upperifaces
297 #
298 ifaceobj = self.get_ifaceobj_first(ifacename)
299 if ifaceobj.type == ifaceType.BRIDGE_VLAN:
300 return False
301 return True
302
303 def create_n_save_ifaceobj(self, ifacename, priv_flags=None,
304 increfcnt=False):
305 """ creates a iface object and adds it to the iface dictionary """
306 ifaceobj = iface()
307 ifaceobj.name = ifacename
308 ifaceobj.priv_flags = priv_flags
309 ifaceobj.auto = True
310 if not self._link_master_slave:
311 ifaceobj.link_type = ifaceLinkType.LINK_NA
312 if increfcnt:
313 ifaceobj.inc_refcnt()
314 self.ifaceobjdict[ifacename] = [ifaceobj]
315 return ifaceobj
316
317 def create_n_save_ifaceobjcurr(self, ifaceobj):
318 """ creates a copy of iface object and adds it to the iface
319 dict containing current iface objects
320 """
321 ifaceobjcurr = iface()
322 ifaceobjcurr.name = ifaceobj.name
323 ifaceobjcurr.type = ifaceobj.type
324 ifaceobjcurr.lowerifaces = ifaceobj.lowerifaces
325 ifaceobjcurr.priv_flags = ifaceobj.priv_flags
326 ifaceobjcurr.auto = ifaceobj.auto
327 self.ifaceobjcurrdict.setdefault(ifaceobj.name,
328 []).append(ifaceobjcurr)
329 return ifaceobjcurr
330
331 def get_ifaceobjcurr(self, ifacename, idx=0):
332 ifaceobjlist = self.ifaceobjcurrdict.get(ifacename)
333 if not ifaceobjlist:
334 return None
335 if not idx:
336 return ifaceobjlist
337 else:
338 return ifaceobjlist[idx]
339
340 def get_ifaceobjrunning(self, ifacename):
341 return self.ifaceobjrunningdict.get(ifacename)
342
343 def get_iface_refcnt(self, ifacename):
344 """ Return iface ref count """
345 max = 0
346 ifaceobjs = self.get_ifaceobjs(ifacename)
347 if not ifaceobjs:
348 return 0
349 for i in ifaceobjs:
350 if i.refcnt > max:
351 max = i.refcnt
352 return max
353
354 def is_iface_builtin_byname(self, ifacename):
355 """ Returns true if iface name is a builtin interface.
356
357 A builtin interface is an interface which ifupdown understands.
358 The following are currently considered builtin ifaces:
359 - vlan interfaces in the format <ifacename>.<vlanid>
360 """
361 return '.' in ifacename
362
363 def is_ifaceobj_builtin(self, ifaceobj):
364 """ Returns true if iface name is a builtin interface.
365
366 A builtin interface is an interface which ifupdown understands.
367 The following are currently considered builtin ifaces:
368 - vlan interfaces in the format <ifacename>.<vlanid>
369 """
370 return (ifaceobj.priv_flags & self.BUILTIN)
371
372 def is_ifaceobj_noconfig(self, ifaceobj):
373 """ Returns true if iface object did not have a user defined config.
374
375 These interfaces appear only when they are dependents of interfaces
376 which have user defined config
377 """
378 return (ifaceobj.priv_flags & self.NOCONFIG)
379
380 def is_iface_noconfig(self, ifacename):
381 """ Returns true if iface has no config """
382
383 ifaceobj = self.get_ifaceobj_first(ifacename)
384 if not ifaceobj: return True
385 return self.is_ifaceobj_noconfig(ifaceobj)
386
387 def check_shared_dependents(self, ifaceobj, dlist):
388 """ Check if dlist intersects with any other
389 interface with slave dependents.
390 example: bond and bridges.
391 This function logs such errors """
392 setdlist = Set(dlist)
393 for ifacename, ifacedlist in self.dependency_graph.items():
394 if not ifacedlist:
395 continue
396 check_depends = False
397 iobjs = self.get_ifaceobjs(ifacename)
398 for i in iobjs:
399 if (i.dependency_type == ifaceDependencyType.MASTER_SLAVE):
400 check_depends = True
401 if check_depends:
402 common = Set(ifacedlist).intersection(setdlist)
403 if common:
404 self.logger.error('misconfig..?. iface %s and %s '
405 %(ifaceobj.name, ifacename) +
406 'seem to share dependents/ports %s' %str(list(common)))
407
408 def preprocess_dependency_list(self, upperifaceobj, dlist, ops):
409 """ We go through the dependency list and
410 delete or add interfaces from the interfaces dict by
411 applying the following rules:
412 if flag _DELETE_DEPENDENT_IFACES_WITH_NOCONFIG is True:
413 we only consider devices whose configuration was
414 specified in the network interfaces file. We delete
415 any interface whose config was not specified except
416 for vlan devices. vlan devices get special treatment.
417 Even if they are not present they are created and added
418 to the ifacesdict
419 elif flag _DELETE_DEPENDENT_IFACES_WITH_NOCONFIG is False:
420 we create objects for all dependent devices that are not
421 present in the ifacesdict
422 """
423 del_list = []
424
425 if (upperifaceobj.dependency_type ==
426 ifaceDependencyType.MASTER_SLAVE):
427 self.check_shared_dependents(upperifaceobj, dlist)
428
429 for d in dlist:
430 dilist = self.get_ifaceobjs(d)
431 if not dilist:
432 ni = None
433 if self.is_iface_builtin_byname(d):
434 ni = self.create_n_save_ifaceobj(d,
435 self.BUILTIN | self.NOCONFIG, True)
436 elif not self._DELETE_DEPENDENT_IFACES_WITH_NOCONFIG:
437 ni = self.create_n_save_ifaceobj(d, self.NOCONFIG,
438 True)
439 else:
440 del_list.append(d)
441 if ni:
442 ni.add_to_upperifaces(upperifaceobj.name)
443 if upperifaceobj.link_type == ifaceLinkType.LINK_MASTER:
444 ni.link_type = ifaceLinkType.LINK_SLAVE
445 else:
446 for di in dilist:
447 di.inc_refcnt()
448 di.add_to_upperifaces(upperifaceobj.name)
449 if upperifaceobj.link_type == ifaceLinkType.LINK_MASTER:
450 di.link_type = ifaceLinkType.LINK_SLAVE
451 for d in del_list:
452 dlist.remove(d)
453
454 def query_dependents(self, ifaceobj, ops, ifacenames, type=None):
455 """ Gets iface dependents by calling into respective modules """
456 ret_dlist = []
457
458 # Get dependents for interface by querying respective modules
459 for module in self.modules.values():
460 try:
461 if ops[0] == 'query-running':
462 if (not hasattr(module,
463 'get_dependent_ifacenames_running')):
464 continue
465 dlist = module.get_dependent_ifacenames_running(ifaceobj)
466 else:
467 if (not hasattr(module, 'get_dependent_ifacenames')):
468 continue
469 dlist = module.get_dependent_ifacenames(ifaceobj,
470 ifacenames)
471 except Exception, e:
472 self.logger.warn('%s: error getting dependent interfaces (%s)'
473 %(ifaceobj.name, str(e)))
474 dlist = None
475 pass
476 if dlist: ret_dlist.extend(dlist)
477 return list(set(ret_dlist))
478
479
480 def populate_dependency_info(self, ops, ifacenames=None):
481 """ recursive function to generate iface dependency info """
482
483 if not ifacenames:
484 ifacenames = self.ifaceobjdict.keys()
485
486 iqueue = deque(ifacenames)
487 while iqueue:
488 i = iqueue.popleft()
489 # Go through all modules and find dependent ifaces
490 dlist = None
491 ifaceobj = self.get_ifaceobj_first(i)
492 if not ifaceobj:
493 continue
494 dlist = ifaceobj.lowerifaces
495 if not dlist:
496 dlist = self.query_dependents(ifaceobj, ops, ifacenames)
497 else:
498 continue
499 if dlist:
500 self.preprocess_dependency_list(ifaceobj,
501 dlist, ops)
502 ifaceobj.lowerifaces = dlist
503 [iqueue.append(d) for d in dlist]
504 if not self.dependency_graph.get(i):
505 self.dependency_graph[i] = dlist
506
507 def _check_config_no_repeats(self, ifaceobj):
508 """ check if object has an attribute that is
509 restricted to a single object in the system.
510 if yes, warn and return """
511 for k,v in self._cache_no_repeats.items():
512 iv = ifaceobj.config.get(k)
513 if iv and iv[0] == v:
514 self.logger.error('ignoring interface %s. ' %ifaceobj.name +
515 'Only one object with attribute ' +
516 '\'%s %s\' allowed.' %(k, v))
517 return True
518 for k, v in self.config.get('no_repeats', {}).items():
519 iv = ifaceobj.config.get(k)
520 if iv and iv[0] == v:
521 self._cache_no_repeats[k] = v
522 return False
523
524 def _save_iface(self, ifaceobj):
525 if self._check_config_no_repeats(ifaceobj):
526 return
527 if not self._link_master_slave:
528 ifaceobj.link_type = ifaceLinkType.LINK_NA
529 currentifaceobjlist = self.ifaceobjdict.get(ifaceobj.name)
530 if not currentifaceobjlist:
531 self.ifaceobjdict[ifaceobj.name]= [ifaceobj]
532 return
533 if ifaceobj.compare(currentifaceobjlist[0]):
534 self.logger.warn('duplicate interface %s found' %ifaceobj.name)
535 return
536 if currentifaceobjlist[0].type == ifaceobj.type:
537 currentifaceobjlist[0].flags |= iface.HAS_SIBLINGS
538 ifaceobj.flags |= iface.HAS_SIBLINGS
539 self.ifaceobjdict[ifaceobj.name].append(ifaceobj)
540
541 def _iface_configattr_syntax_checker(self, attrname, attrval):
542 for m, mdict in self.module_attrs.items():
543 if not mdict:
544 continue
545 attrsdict = mdict.get('attrs')
546 try:
547 if attrsdict.get(attrname):
548 return True
549 except AttributeError:
550 pass
551 return False
552
553 def _ifaceobj_syntax_checker(self, ifaceobj):
554 err = False
555 for attrname, attrvalue in ifaceobj.config.items():
556 found = False
557 for k, v in self.module_attrs.items():
558 if v and v.get('attrs', {}).get(attrname):
559 found = True
560 break
561 if not found:
562 err = True
563 self.logger.warn('%s: unsupported attribute \'%s\'' \
564 % (ifaceobj.name, attrname))
565 continue
566 return err
567
568 def read_iface_config(self):
569 """ Reads default network interface config /etc/network/interfaces. """
570 nifaces = networkInterfaces(self.interfacesfile,
571 self.interfacesfileiobuf,
572 self.interfacesfileformat,
573 template_engine=self.config.get('template_engine'),
574 template_lookuppath=self.config.get('template_lookuppath'))
575 nifaces.subscribe('iface_found', self._save_iface)
576 nifaces.subscribe('validateifaceattr',
577 self._iface_configattr_syntax_checker)
578 nifaces.subscribe('validateifaceobj', self._ifaceobj_syntax_checker)
579 nifaces.load()
580
581 def read_old_iface_config(self):
582 """ Reads the saved iface config instead of default iface config.
583 And saved iface config is already read by the statemanager """
584 self.ifaceobjdict = copy.deepcopy(self.statemanager.ifaceobjdict)
585
586 def _load_addon_modules_config(self):
587 """ Load addon modules config file """
588
589 with open(self.addon_modules_configfile, 'r') as f:
590 lines = f.readlines()
591 for l in lines:
592 try:
593 litems = l.strip(' \n\t\r').split(',')
594 if not litems or len(litems) < 2:
595 continue
596 operation = litems[0]
597 mname = litems[1]
598 self.module_ops[operation].append(mname)
599 except Exception, e:
600 self.logger.warn('error reading line \'%s\'' %(l, str(e)))
601 continue
602
603 def load_addon_modules(self, modules_dir):
604 """ load python modules from modules_dir
605
606 Default modules_dir is /usr/share/ifupdownmodules
607
608 """
609 self.logger.info('loading builtin modules from %s' %modules_dir)
610 self._load_addon_modules_config()
611 if not modules_dir in sys.path:
612 sys.path.append(modules_dir)
613 try:
614 for op, mlist in self.module_ops.items():
615 for mname in mlist:
616 if self.modules.get(mname):
617 continue
618 mpath = modules_dir + '/' + mname + '.py'
619 if os.path.exists(mpath):
620 try:
621 m = __import__(mname)
622 mclass = getattr(m, mname)
623 except:
624 raise
625 minstance = mclass(force=self.FORCE,
626 dryrun=self.DRYRUN,
627 nowait=self.NOWAIT,
628 perfmode=self.PERFMODE,
629 cache=self.CACHE,
630 cacheflags=self.CACHE_FLAGS)
631 self.modules[mname] = minstance
632 try:
633 self.module_attrs[mname] = minstance.get_modinfo()
634 except:
635 pass
636 except:
637 raise
638
639 # Assign all modules to query operations
640 self.module_ops['query-checkcurr'] = self.modules.keys()
641 self.module_ops['query-running'] = self.modules.keys()
642 self.module_ops['query-dependency'] = self.modules.keys()
643 self.module_ops['query'] = self.modules.keys()
644 self.module_ops['query-raw'] = self.modules.keys()
645
646
647 def _modules_help(self):
648 """ Prints addon modules supported syntax """
649
650 indent = ' '
651 for m, mdict in self.module_attrs.items():
652 if not mdict:
653 continue
654 print('%s: %s' %(m, mdict.get('mhelp')))
655 attrdict = mdict.get('attrs')
656 if not attrdict:
657 continue
658 try:
659 for attrname, attrvaldict in attrdict.items():
660 if attrvaldict.get('compat', False):
661 continue
662 print('%s%s' %(indent, attrname))
663 print('%shelp: %s' %(indent + ' ',
664 attrvaldict.get('help', '')))
665 print ('%srequired: %s' %(indent + ' ',
666 attrvaldict.get('required', False)))
667 default = attrvaldict.get('default')
668 if default:
669 print('%sdefault: %s' %(indent + ' ', default))
670
671 validrange = attrvaldict.get('validrange')
672 if validrange:
673 print('%svalidrange: %s-%s'
674 %(indent + ' ', validrange[0], validrange[1]))
675
676 validvals = attrvaldict.get('validvals')
677 if validvals:
678 print('%svalidvals: %s'
679 %(indent + ' ', ','.join(validvals)))
680
681 examples = attrvaldict.get('example')
682 if not examples:
683 continue
684
685 print '%sexample:' %(indent + ' ')
686 for e in examples:
687 print '%s%s' %(indent + ' ', e)
688 except:
689 pass
690 print ''
691
692 def load_scripts(self, modules_dir):
693 """ loading user modules from /etc/network/.
694
695 Note that previously loaded python modules override modules found
696 under /etc/network if any
697
698 """
699
700 self.logger.info('looking for user scripts under %s' %modules_dir)
701 for op, mlist in self.script_ops.items():
702 msubdir = modules_dir + '/if-%s.d' %op
703 self.logger.info('loading scripts under %s ...' %msubdir)
704 try:
705 module_list = os.listdir(msubdir)
706 for module in module_list:
707 if self.modules.get(module) is not None:
708 continue
709 self.script_ops[op].append(
710 msubdir + '/' + module)
711 except:
712 # continue reading
713 pass
714
715 def _sched_ifaces(self, ifacenames, ops, skipupperifaces=False,
716 followdependents=True, sort=False):
717 self.logger.debug('scheduling \'%s\' for %s'
718 %(str(ops), str(ifacenames)))
719 self._pretty_print_ordered_dict('dependency graph',
720 self.dependency_graph)
721 return ifaceScheduler.sched_ifaces(self, ifacenames, ops,
722 dependency_graph=self.dependency_graph,
723 order=ifaceSchedulerFlags.INORDER
724 if 'down' in ops[0]
725 else ifaceSchedulerFlags.POSTORDER,
726 followdependents=followdependents,
727 skipupperifaces=skipupperifaces,
728 sort=True if (sort or self.IFACE_CLASS) else False)
729
730 def _render_ifacename(self, ifacename):
731 new_ifacenames = []
732 vlan_match = re.match("^([\d]+)-([\d]+)", ifacename)
733 if vlan_match:
734 vlan_groups = vlan_match.groups()
735 if vlan_groups[0] and vlan_groups[1]:
736 [new_ifacenames.append('%d' %v)
737 for v in range(int(vlan_groups[0]),
738 int(vlan_groups[1])+1)]
739 return new_ifacenames
740
741 def _preprocess_ifacenames(self, ifacenames):
742 """ validates interface list for config existance.
743
744 returns -1 if one or more interface not found. else, returns 0
745
746 """
747 new_ifacenames = []
748 err_iface = ''
749 for i in ifacenames:
750 ifaceobjs = self.get_ifaceobjs(i)
751 if not ifaceobjs:
752 # if name not available, render interface name and check again
753 rendered_ifacenames = utils.expand_iface_range(i)
754 if rendered_ifacenames:
755 for ri in rendered_ifacenames:
756 ifaceobjs = self.get_ifaceobjs(ri)
757 if not ifaceobjs:
758 err_iface += ' ' + ri
759 else:
760 new_ifacenames.append(ri)
761 else:
762 err_iface += ' ' + i
763 else:
764 new_ifacenames.append(i)
765 if err_iface:
766 raise Exception('cannot find interfaces:%s' %err_iface)
767 return new_ifacenames
768
769 def _iface_whitelisted(self, auto, allow_classes, excludepats, ifacename):
770 """ Checks if interface is whitelisted depending on set of parameters.
771
772 interfaces are checked against the allow_classes and auto lists.
773
774 """
775 if excludepats:
776 for e in excludepats:
777 if re.search(e, ifacename):
778 return False
779 ifaceobjs = self.get_ifaceobjs(ifacename)
780 if not ifaceobjs:
781 self.logger.debug('iface %s' %ifacename + ' not found')
782 return False
783 # We check classes first
784 if allow_classes:
785 for i in ifaceobjs:
786 if i.classes:
787 common = Set([allow_classes]).intersection(
788 Set(i.classes))
789 if common:
790 return True
791 return False
792 if auto:
793 for i in ifaceobjs:
794 if i.auto:
795 return True
796 return False
797 return True
798
799 def _compat_conv_op_to_mode(self, op):
800 """ Returns old op name to work with existing scripts """
801 if op == 'pre-up':
802 return 'start'
803 elif op == 'pre-down':
804 return 'stop'
805 else:
806 return op
807
808 def generate_running_env(self, ifaceobj, op):
809 """ Generates a dictionary with env variables required for
810 an interface. Used to support script execution for interfaces.
811 """
812
813 cenv = None
814 iface_env = ifaceobj.env
815 if iface_env:
816 cenv = os.environ
817 if cenv:
818 cenv.update(iface_env)
819 else:
820 cenv = iface_env
821 cenv['MODE'] = self._compat_conv_op_to_mode(op)
822 return cenv
823
824 def _save_state(self):
825 if not self.STATEMANAGER_ENABLE or not self.STATEMANAGER_UPDATE:
826 return
827 try:
828 # Update persistant iface states
829 self.statemanager.save_state()
830 except Exception, e:
831 if self.logger.isEnabledFor(logging.DEBUG):
832 t = sys.exc_info()[2]
833 traceback.print_tb(t)
834 self.logger.warning('error saving state (%s)' %str(e))
835
836 def set_type(self, type):
837 if type == 'iface':
838 self.type = ifaceType.IFACE
839 elif type == 'vlan':
840 self.type = ifaceType.BRIDGE_VLAN
841 else:
842 self.type = ifaceType.UNKNOWN
843
844 def _process_delay_admin_state_queue(self, op):
845 if not self._delay_admin_state_iface_queue:
846 return
847 if op == 'up':
848 func = self.link_up
849 elif op == 'down':
850 func = self.link_down
851 else:
852 return
853 for i in self._delay_admin_state_iface_queue:
854 try:
855 if self.link_exists(i):
856 func(i)
857 except Exception, e:
858 self.logger.warn(str(e))
859 pass
860
861 def up(self, ops, auto=False, allow_classes=None, ifacenames=None,
862 excludepats=None, printdependency=None, syntaxcheck=False,
863 type=None, skipupperifaces=False):
864 """This brings the interface(s) up
865
866 Args:
867 ops (list): list of ops to perform on the interface(s).
868 Eg: ['pre-up', 'up', 'post-up'
869
870 Kwargs:
871 auto (bool): act on interfaces marked auto
872 allow_classes (list): act on interfaces belonging to classes in the list
873 ifacenames (list): act on interfaces specified in this list
874 excludepats (list): list of patterns of interfaces to exclude
875 syntaxcheck (bool): only perform syntax check
876 """
877
878 self.set_type(type)
879
880 if allow_classes:
881 self.IFACE_CLASS = True
882 if not self.ADDONS_ENABLE: self.STATEMANAGER_UPDATE = False
883 if auto:
884 self.ALL = True
885 self.WITH_DEPENDS = True
886 try:
887 self.read_iface_config()
888 except Exception:
889 raise
890
891 # If only syntax check was requested, return here
892 if syntaxcheck:
893 return
894
895 if ifacenames:
896 ifacenames = self._preprocess_ifacenames(ifacenames)
897
898 # if iface list not given by user, assume all from config file
899 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
900
901 # filter interfaces based on auto and allow classes
902 filtered_ifacenames = [i for i in ifacenames
903 if self._iface_whitelisted(auto, allow_classes,
904 excludepats, i)]
905 if not filtered_ifacenames:
906 raise Exception('no ifaces found matching given allow lists')
907
908 if printdependency:
909 self.populate_dependency_info(ops, filtered_ifacenames)
910 self.print_dependency(filtered_ifacenames, printdependency)
911 return
912 else:
913 self.populate_dependency_info(ops)
914
915 try:
916 self._sched_ifaces(filtered_ifacenames, ops,
917 skipupperifaces=skipupperifaces,
918 followdependents=True if self.WITH_DEPENDS else False)
919 finally:
920 self._process_delay_admin_state_queue('up')
921 if not self.DRYRUN and self.ADDONS_ENABLE:
922 self._save_state()
923
924 def down(self, ops, auto=False, allow_classes=None, ifacenames=None,
925 excludepats=None, printdependency=None, usecurrentconfig=False,
926 type=None):
927 """ down an interface """
928
929 self.set_type(type)
930
931 if allow_classes:
932 self.IFACE_CLASS = True
933 if not self.ADDONS_ENABLE: self.STATEMANAGER_UPDATE = False
934 if auto:
935 self.ALL = True
936 self.WITH_DEPENDS = True
937 # For down we need to look at old state, unless usecurrentconfig
938 # is set
939 if (not usecurrentconfig and self.STATEMANAGER_ENABLE and
940 self.statemanager.ifaceobjdict):
941 # Since we are using state manager objects,
942 # skip the updating of state manager objects
943 self.logger.debug('Looking at old state ..')
944 self.read_old_iface_config()
945 else:
946 # If no old state available
947 try:
948 self.read_iface_config()
949 except Exception, e:
950 raise Exception('error reading iface config (%s)' %str(e))
951 if ifacenames:
952 # If iface list is given by the caller, always check if iface
953 # is present
954 try:
955 ifacenames = self._preprocess_ifacenames(ifacenames)
956 except Exception, e:
957 raise Exception('%s' %str(e) +
958 ' (interface was probably never up ?)')
959
960 # if iface list not given by user, assume all from config file
961 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
962
963 # filter interfaces based on auto and allow classes
964 filtered_ifacenames = [i for i in ifacenames
965 if self._iface_whitelisted(auto, allow_classes,
966 excludepats, i)]
967 if not filtered_ifacenames:
968 raise Exception('no ifaces found matching given allow lists ' +
969 '(or interfaces were probably never up ?)')
970
971 if printdependency:
972 self.populate_dependency_info(ops, filtered_ifacenames)
973 self.print_dependency(filtered_ifacenames, printdependency)
974 return
975 else:
976 self.populate_dependency_info(ops)
977
978 try:
979 self._sched_ifaces(filtered_ifacenames, ops,
980 followdependents=True if self.WITH_DEPENDS else False)
981 finally:
982 self._process_delay_admin_state_queue('down')
983 if not self.DRYRUN and self.ADDONS_ENABLE:
984 self._save_state()
985
986 def query(self, ops, auto=False, allow_classes=None, ifacenames=None,
987 excludepats=None, printdependency=None,
988 format='native', type=None):
989 """ query an interface """
990
991 self.set_type(type)
992
993 if allow_classes:
994 self.IFACE_CLASS = True
995 if self.STATEMANAGER_ENABLE and ops[0] == 'query-savedstate':
996 return self.statemanager.dump_pretty(ifacenames)
997 self.STATEMANAGER_UPDATE = False
998 if auto:
999 self.logger.debug('setting flag ALL')
1000 self.ALL = True
1001 self.WITH_DEPENDS = True
1002
1003 if ops[0] == 'query-syntax':
1004 self._modules_help()
1005 return
1006 elif ops[0] == 'query-running':
1007 # create fake devices to all dependents that dont have config
1008 map(lambda i: self.create_n_save_ifaceobj(i, self.NOCONFIG),
1009 ifacenames)
1010 else:
1011 try:
1012 self.read_iface_config()
1013 except Exception:
1014 raise
1015
1016 if ifacenames and ops[0] != 'query-running':
1017 # If iface list is given, always check if iface is present
1018 ifacenames = self._preprocess_ifacenames(ifacenames)
1019
1020 # if iface list not given by user, assume all from config file
1021 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
1022
1023 # filter interfaces based on auto and allow classes
1024 if ops[0] == 'query-running':
1025 filtered_ifacenames = ifacenames
1026 else:
1027 filtered_ifacenames = [i for i in ifacenames
1028 if self._iface_whitelisted(auto, allow_classes,
1029 excludepats, i)]
1030 if not filtered_ifacenames:
1031 raise Exception('no ifaces found matching ' +
1032 'given allow lists')
1033
1034 self.populate_dependency_info(ops)
1035 if ops[0] == 'query-dependency' and printdependency:
1036 self.print_dependency(filtered_ifacenames, printdependency)
1037 return
1038
1039 if ops[0] == 'query':
1040 return self.print_ifaceobjs_pretty(filtered_ifacenames, format)
1041 elif ops[0] == 'query-raw':
1042 return self.print_ifaceobjs_raw(filtered_ifacenames)
1043
1044 self._sched_ifaces(filtered_ifacenames, ops,
1045 followdependents=True if self.WITH_DEPENDS else False)
1046
1047 if ops[0] == 'query-checkcurr':
1048 ret = self.print_ifaceobjscurr_pretty(filtered_ifacenames, format)
1049 if ret != 0:
1050 # if any of the object has an error, signal that silently
1051 raise Exception('')
1052 elif ops[0] == 'query-running':
1053 self.print_ifaceobjsrunning_pretty(filtered_ifacenames, format)
1054 return
1055
1056 def _reload_currentlyup(self, upops, downops, auto=True, allow=None,
1057 ifacenames=None, excludepats=None, usecurrentconfig=False,
1058 **extra_args):
1059 """ reload currently up interfaces """
1060 allow_classes = []
1061 new_ifaceobjdict = {}
1062
1063 # Override auto to true
1064 auto = True
1065 try:
1066 self.read_iface_config()
1067 except:
1068 raise
1069 if not self.ifaceobjdict:
1070 self.logger.warn("nothing to reload ..exiting.")
1071 return
1072 already_up_ifacenames = []
1073 # generate dependency graph of interfaces
1074 self.populate_dependency_info(upops)
1075 if (not usecurrentconfig and self.STATEMANAGER_ENABLE
1076 and self.statemanager.ifaceobjdict):
1077 already_up_ifacenames = self.statemanager.ifaceobjdict.keys()
1078
1079 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
1080 filtered_ifacenames = [i for i in ifacenames
1081 if self._iface_whitelisted(auto, allow_classes,
1082 excludepats, i)]
1083
1084 # Get already up interfaces that still exist in the interfaces file
1085 already_up_ifacenames_not_present = Set(
1086 already_up_ifacenames).difference(ifacenames)
1087 already_up_ifacenames_still_present = Set(
1088 already_up_ifacenames).difference(
1089 already_up_ifacenames_not_present)
1090 interfaces_to_up = Set(already_up_ifacenames_still_present).union(
1091 filtered_ifacenames)
1092
1093 if (already_up_ifacenames_not_present and
1094 self.config.get('ifreload_currentlyup_down_notpresent') == '1'):
1095 self.logger.info('reload: schedule down on interfaces: %s'
1096 %str(already_up_ifacenames_not_present))
1097
1098 # Save a copy of new iface objects and dependency_graph
1099 new_ifaceobjdict = dict(self.ifaceobjdict)
1100 new_dependency_graph = dict(self.dependency_graph)
1101
1102 # old interface config is read into self.ifaceobjdict
1103 self.read_old_iface_config()
1104
1105 # reinitialize dependency graph
1106 self.dependency_graph = OrderedDict({})
1107 self.populate_dependency_info(downops,
1108 already_up_ifacenames_not_present)
1109 self._sched_ifaces(already_up_ifacenames_not_present, downops,
1110 followdependents=False, sort=True)
1111 else:
1112 self.logger.debug('no interfaces to down ..')
1113
1114 # Now, run 'up' with new config dict
1115 # reset statemanager update flag to default
1116 if auto:
1117 self.ALL = True
1118 self.WITH_DEPENDS = True
1119 if new_ifaceobjdict:
1120 self.ifaceobjdict = new_ifaceobjdict
1121 self.dependency_graph = new_dependency_graph
1122
1123 if not self.ifaceobjdict:
1124 return
1125 self.logger.info('reload: scheduling up on interfaces: %s'
1126 %str(interfaces_to_up))
1127 self._sched_ifaces(interfaces_to_up, upops,
1128 followdependents=True if self.WITH_DEPENDS else False)
1129 if self.DRYRUN:
1130 return
1131 self._save_state()
1132
1133 def _reload_default(self, upops, downops, auto=False, allow=None,
1134 ifacenames=None, excludepats=None, usecurrentconfig=False,
1135 **extra_args):
1136 """ reload interface config """
1137 allow_classes = []
1138 new_ifaceobjdict = {}
1139
1140 try:
1141 self.read_iface_config()
1142 except:
1143 raise
1144
1145 if not self.ifaceobjdict:
1146 self.logger.warn("nothing to reload ..exiting.")
1147 return
1148 # generate dependency graph of interfaces
1149 self.populate_dependency_info(upops)
1150 if (not usecurrentconfig and self.STATEMANAGER_ENABLE
1151 and self.statemanager.ifaceobjdict):
1152 # Save a copy of new iface objects and dependency_graph
1153 new_ifaceobjdict = dict(self.ifaceobjdict)
1154 new_dependency_graph = dict(self.dependency_graph)
1155
1156 # if old state is present, read old state and mark op for 'down'
1157 # followed by 'up' aka: reload
1158 # old interface config is read into self.ifaceobjdict
1159 self.read_old_iface_config()
1160 op = 'reload'
1161 else:
1162 # oldconfig not available, continue with 'up' with new config
1163 op = 'up'
1164
1165 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
1166 if op == 'reload' and ifacenames:
1167 filtered_ifacenames = [i for i in ifacenames
1168 if self._iface_whitelisted(auto, allow_classes,
1169 excludepats, i)]
1170
1171 # if config file had 'ifreload_down_changed' variable
1172 # set, also look for interfaces that changed to down them
1173 down_changed = int(self.config.get('ifreload_down_changed', '1'))
1174
1175 # Generate the interface down list
1176 # Interfaces that go into the down list:
1177 # - interfaces that were present in last config and are not
1178 # present in the new config
1179 # - interfaces that were changed between the last and current
1180 # config
1181 ifacedownlist = []
1182 for ifname in filtered_ifacenames:
1183 lastifaceobjlist = self.ifaceobjdict.get(ifname)
1184 objidx = 0
1185 # If interface is not present in the new file
1186 # append it to the down list
1187 newifaceobjlist = new_ifaceobjdict.get(ifname)
1188 if not newifaceobjlist:
1189 ifacedownlist.append(ifname)
1190 continue
1191 if len(newifaceobjlist) != len(lastifaceobjlist):
1192 ifacedownlist.append(ifname)
1193 continue
1194 if not down_changed:
1195 continue
1196
1197 # If interface has changed between the current file
1198 # and the last installed append it to the down list
1199 # compare object list
1200 for objidx in range(0, len(lastifaceobjlist)):
1201 oldobj = lastifaceobjlist[objidx]
1202 newobj = newifaceobjlist[objidx]
1203 if not newobj.compare(oldobj):
1204 ifacedownlist.append(ifname)
1205 continue
1206
1207 if ifacedownlist:
1208 self.logger.info('reload: scheduling down on interfaces: %s'
1209 %str(ifacedownlist))
1210 # reinitialize dependency graph
1211 self.dependency_graph = OrderedDict({})
1212 # Generate dependency info for old config
1213 self.populate_dependency_info(downops, ifacedownlist)
1214 try:
1215 self._sched_ifaces(ifacedownlist, downops,
1216 followdependents=False,
1217 sort=True)
1218 except Exception, e:
1219 self.logger.error(str(e))
1220 pass
1221 finally:
1222 self._process_delay_admin_state_queue('down')
1223 else:
1224 self.logger.debug('no interfaces to down ..')
1225
1226 # Now, run 'up' with new config dict
1227 # reset statemanager update flag to default
1228 if not new_ifaceobjdict:
1229 return
1230
1231 if auto:
1232 self.ALL = True
1233 self.WITH_DEPENDS = True
1234 self.ifaceobjdict = new_ifaceobjdict
1235 self.dependency_graph = new_dependency_graph
1236 ifacenames = self.ifaceobjdict.keys()
1237 filtered_ifacenames = [i for i in ifacenames
1238 if self._iface_whitelisted(auto, allow_classes,
1239 excludepats, i)]
1240
1241 self.logger.info('reload: scheduling up on interfaces: %s'
1242 %str(filtered_ifacenames))
1243 try:
1244 self._sched_ifaces(filtered_ifacenames, upops,
1245 followdependents=True if self.WITH_DEPENDS else False)
1246 except Exception, e:
1247 self.logger.error(str(e))
1248 pass
1249 finally:
1250 self._process_delay_admin_state_queue('up')
1251 if self.DRYRUN:
1252 return
1253 self._save_state()
1254
1255 def reload(self, *args, **kargs):
1256 """ reload interface config """
1257 self.logger.debug('reloading interface config ..')
1258 if kargs.get('currentlyup', False):
1259 self._reload_currentlyup(*args, **kargs)
1260 else:
1261 self._reload_default(*args, **kargs)
1262
1263 def _pretty_print_ordered_dict(self, prefix, argdict):
1264 outbuf = prefix + ' {\n'
1265 for k, vlist in argdict.items():
1266 outbuf += '\t%s : %s\n' %(k, str(vlist))
1267 self.logger.debug(outbuf + '}')
1268
1269 def print_dependency(self, ifacenames, format):
1270 """ prints iface dependency information """
1271
1272 if not ifacenames:
1273 ifacenames = self.ifaceobjdict.keys()
1274 if format == 'list':
1275 for k,v in self.dependency_graph.items():
1276 print '%s : %s' %(k, str(v))
1277 elif format == 'dot':
1278 indegrees = {}
1279 map(lambda i: indegrees.update({i :
1280 self.get_iface_refcnt(i)}),
1281 self.dependency_graph.keys())
1282 graph.generate_dots(self.dependency_graph, indegrees)
1283
1284 def print_ifaceobjs_raw(self, ifacenames):
1285 """ prints raw lines for ifaces from config file """
1286
1287 for i in ifacenames:
1288 for ifaceobj in self.get_ifaceobjs(i):
1289 if (self.is_ifaceobj_builtin(ifaceobj) or
1290 not ifaceobj.is_config_present()):
1291 continue
1292 ifaceobj.dump_raw(self.logger)
1293 print '\n'
1294 if self.WITH_DEPENDS and not self.ALL:
1295 dlist = ifaceobj.lowerifaces
1296 if not dlist: continue
1297 self.print_ifaceobjs_raw(dlist)
1298
1299 def _get_ifaceobjs_pretty(self, ifacenames, ifaceobjs, running=False):
1300 """ returns iface obj list """
1301
1302 for i in ifacenames:
1303 for ifaceobj in self.get_ifaceobjs(i):
1304 if ((not running and self.is_ifaceobj_noconfig(ifaceobj)) or
1305 (running and not ifaceobj.is_config_present())):
1306 continue
1307 ifaceobjs.append(ifaceobj)
1308 if self.WITH_DEPENDS and not self.ALL:
1309 dlist = ifaceobj.lowerifaces
1310 if not dlist: continue
1311 self._get_ifaceobjs_pretty(dlist, ifaceobjs, running)
1312
1313 def print_ifaceobjs_pretty(self, ifacenames, format='native'):
1314 """ pretty prints iface in format given by keyword arg format """
1315
1316 ifaceobjs = []
1317 self._get_ifaceobjs_pretty(ifacenames, ifaceobjs)
1318 if not ifaceobjs: return
1319 if format == 'json':
1320 print json.dumps(ifaceobjs, cls=ifaceJsonEncoder,
1321 indent=4, separators=(',', ': '))
1322 else:
1323 expand = int(self.config.get('ifquery_ifacename_expand_range', '0'))
1324 for i in ifaceobjs:
1325 if not expand and (i.flags & iface.IFACERANGE_ENTRY):
1326 # print only the first one
1327 if i.flags & iface.IFACERANGE_START:
1328 i.dump_pretty(use_realname=True)
1329 else:
1330 i.dump_pretty()
1331
1332 def _get_ifaceobjscurr_pretty(self, ifacenames, ifaceobjs):
1333 ret = 0
1334 for i in ifacenames:
1335 ifaceobjscurr = self.get_ifaceobjcurr(i)
1336 if not ifaceobjscurr: continue
1337 for ifaceobj in ifaceobjscurr:
1338 if (ifaceobj.status == ifaceStatus.NOTFOUND or
1339 ifaceobj.status == ifaceStatus.ERROR):
1340 ret = 1
1341 if self.is_ifaceobj_noconfig(ifaceobj):
1342 continue
1343 ifaceobjs.append(ifaceobj)
1344 if self.WITH_DEPENDS and not self.ALL:
1345 dlist = ifaceobj.lowerifaces
1346 if not dlist: continue
1347 dret = self._get_ifaceobjscurr_pretty(dlist, ifaceobjs)
1348 if dret: ret = 1
1349 return ret
1350
1351 def print_ifaceobjscurr_pretty(self, ifacenames, format='native'):
1352 """ pretty prints current running state of interfaces with status.
1353
1354 returns 1 if any of the interface has an error,
1355 else returns 0
1356 """
1357
1358 ifaceobjs = []
1359 ret = self._get_ifaceobjscurr_pretty(ifacenames, ifaceobjs)
1360 if not ifaceobjs: return
1361 if format == 'json':
1362 print json.dumps(ifaceobjs, cls=ifaceJsonEncoder, indent=2,
1363 separators=(',', ': '))
1364 else:
1365 map(lambda i: i.dump_pretty(with_status=True,
1366 successstr=self.config.get('ifquery_check_success_str',
1367 _success_sym),
1368 errorstr=self.config.get('ifquery_check_error_str', _error_sym),
1369 unknownstr=self.config.get('ifquery_check_unknown_str', '')),
1370 ifaceobjs)
1371 return ret
1372
1373 def print_ifaceobjsrunning_pretty(self, ifacenames, format='native'):
1374 """ pretty prints iface running state """
1375
1376 ifaceobjs = []
1377 self._get_ifaceobjs_pretty(ifacenames, ifaceobjs, running=True)
1378 if not ifaceobjs: return
1379 if format == 'json':
1380 print json.dumps(ifaceobjs, cls=ifaceJsonEncoder, indent=2,
1381 separators=(',', ': '))
1382 else:
1383 map(lambda i: i.dump_pretty(), ifaceobjs)
1384
1385 def _dump(self):
1386 print 'ifupdown main object dump'
1387 print self.pp.pprint(self.modules)
1388 print self.pp.pprint(self.ifaceobjdict)
1389
1390 def _dump_ifaceobjs(self, ifacenames):
1391 for i in ifacenames:
1392 ifaceobjs = self.get_ifaceobjs(i)
1393 for i in ifaceobjs:
1394 i.dump(self.logger)
1395 print '\n'