]> git.proxmox.com Git - mirror_ifupdown2.git/blob - ifupdown/ifupdownmain.py
Make ifupdown2 print meaningful error when interface name length exceeds 15 characters
[mirror_ifupdown2.git] / 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 if upperifaceobj.link_kind & \
443 (ifaceLinkKind.BOND | ifaceLinkKind.BRIDGE):
444 ni.role |= ifaceRole.SLAVE
445 ni.add_to_upperifaces(upperifaceobj.name)
446 if upperifaceobj.link_type == ifaceLinkType.LINK_MASTER:
447 ni.link_type = ifaceLinkType.LINK_SLAVE
448 else:
449 for di in dilist:
450 di.inc_refcnt()
451 di.add_to_upperifaces(upperifaceobj.name)
452 if upperifaceobj.link_kind & \
453 (ifaceLinkKind.BOND | ifaceLinkKind.BRIDGE):
454 di.role |= ifaceRole.SLAVE
455 if upperifaceobj.link_type == ifaceLinkType.LINK_MASTER:
456 di.link_type = ifaceLinkType.LINK_SLAVE
457 for d in del_list:
458 dlist.remove(d)
459
460 def query_dependents(self, ifaceobj, ops, ifacenames, type=None):
461 """ Gets iface dependents by calling into respective modules """
462 ret_dlist = []
463
464 # Get dependents for interface by querying respective modules
465 for module in self.modules.values():
466 try:
467 if ops[0] == 'query-running':
468 if (not hasattr(module,
469 'get_dependent_ifacenames_running')):
470 continue
471 dlist = module.get_dependent_ifacenames_running(ifaceobj)
472 else:
473 if (not hasattr(module, 'get_dependent_ifacenames')):
474 continue
475 dlist = module.get_dependent_ifacenames(ifaceobj,
476 ifacenames)
477 except Exception, e:
478 self.logger.warn('%s: error getting dependent interfaces (%s)'
479 %(ifaceobj.name, str(e)))
480 dlist = None
481 pass
482 if dlist: ret_dlist.extend(dlist)
483 return list(set(ret_dlist))
484
485
486 def populate_dependency_info(self, ops, ifacenames=None):
487 """ recursive function to generate iface dependency info """
488
489 if not ifacenames:
490 ifacenames = self.ifaceobjdict.keys()
491
492 iqueue = deque(ifacenames)
493 while iqueue:
494 i = iqueue.popleft()
495 # Go through all modules and find dependent ifaces
496 dlist = None
497 ifaceobj = self.get_ifaceobj_first(i)
498 if not ifaceobj:
499 continue
500 if ifaceobj.blacklisted:
501 continue
502 dlist = ifaceobj.lowerifaces
503 if not dlist:
504 dlist = self.query_dependents(ifaceobj, ops, ifacenames)
505 else:
506 continue
507 if dlist:
508 self.preprocess_dependency_list(ifaceobj,
509 dlist, ops)
510 ifaceobj.lowerifaces = dlist
511 [iqueue.append(d) for d in dlist]
512 if not self.dependency_graph.get(i):
513 self.dependency_graph[i] = dlist
514
515 def _check_config_no_repeats(self, ifaceobj):
516 """ check if object has an attribute that is
517 restricted to a single object in the system.
518 if yes, warn and return """
519 for k,v in self._cache_no_repeats.items():
520 iv = ifaceobj.config.get(k)
521 if iv and iv[0] == v:
522 self.logger.error('ignoring interface %s. ' %ifaceobj.name +
523 'Only one object with attribute ' +
524 '\'%s %s\' allowed.' %(k, v))
525 return True
526 for k, v in self.config.get('no_repeats', {}).items():
527 iv = ifaceobj.config.get(k)
528 if iv and iv[0] == v:
529 self._cache_no_repeats[k] = v
530 return False
531
532 def _save_iface(self, ifaceobj):
533 if self._check_config_no_repeats(ifaceobj):
534 return
535 if not self._link_master_slave:
536 ifaceobj.link_type = ifaceLinkType.LINK_NA
537 currentifaceobjlist = self.ifaceobjdict.get(ifaceobj.name)
538 if not currentifaceobjlist:
539 self.ifaceobjdict[ifaceobj.name]= [ifaceobj]
540 return
541 if ifaceobj.compare(currentifaceobjlist[0]):
542 self.logger.warn('duplicate interface %s found' %ifaceobj.name)
543 return
544 if currentifaceobjlist[0].type == ifaceobj.type:
545 currentifaceobjlist[0].flags |= iface.HAS_SIBLINGS
546 ifaceobj.flags |= iface.HAS_SIBLINGS
547 self.ifaceobjdict[ifaceobj.name].append(ifaceobj)
548
549 def _iface_configattr_syntax_checker(self, attrname, attrval):
550 for m, mdict in self.module_attrs.items():
551 if not mdict:
552 continue
553 attrsdict = mdict.get('attrs')
554 try:
555 if attrsdict.get(attrname):
556 return True
557 except AttributeError:
558 pass
559 return False
560
561 def _ifaceobj_syntax_checker(self, ifaceobj):
562 err = False
563 for attrname, attrvalue in ifaceobj.config.items():
564 found = False
565 for k, v in self.module_attrs.items():
566 if v and v.get('attrs', {}).get(attrname):
567 found = True
568 break
569 if not found:
570 err = True
571 self.logger.warn('%s: unsupported attribute \'%s\'' \
572 % (ifaceobj.name, attrname))
573 continue
574 return err
575
576 def read_iface_config(self):
577 """ Reads default network interface config /etc/network/interfaces. """
578 nifaces = networkInterfaces(self.interfacesfile,
579 self.interfacesfileiobuf,
580 self.interfacesfileformat,
581 template_engine=self.config.get('template_engine'),
582 template_lookuppath=self.config.get('template_lookuppath'))
583 nifaces.subscribe('iface_found', self._save_iface)
584 nifaces.subscribe('validateifaceattr',
585 self._iface_configattr_syntax_checker)
586 nifaces.subscribe('validateifaceobj', self._ifaceobj_syntax_checker)
587 nifaces.load()
588
589 def read_old_iface_config(self):
590 """ Reads the saved iface config instead of default iface config.
591 And saved iface config is already read by the statemanager """
592 self.ifaceobjdict = copy.deepcopy(self.statemanager.ifaceobjdict)
593
594 def _load_addon_modules_config(self):
595 """ Load addon modules config file """
596
597 with open(self.addon_modules_configfile, 'r') as f:
598 lines = f.readlines()
599 for l in lines:
600 try:
601 litems = l.strip(' \n\t\r').split(',')
602 if not litems or len(litems) < 2:
603 continue
604 operation = litems[0]
605 mname = litems[1]
606 self.module_ops[operation].append(mname)
607 except Exception, e:
608 self.logger.warn('error reading line \'%s\'' %(l, str(e)))
609 continue
610
611 def load_addon_modules(self, modules_dir):
612 """ load python modules from modules_dir
613
614 Default modules_dir is /usr/share/ifupdownmodules
615
616 """
617 self.logger.info('loading builtin modules from %s' %modules_dir)
618 self._load_addon_modules_config()
619 if not modules_dir in sys.path:
620 sys.path.append(modules_dir)
621 try:
622 for op, mlist in self.module_ops.items():
623 for mname in mlist:
624 if self.modules.get(mname):
625 continue
626 mpath = modules_dir + '/' + mname + '.py'
627 if os.path.exists(mpath):
628 try:
629 m = __import__(mname)
630 mclass = getattr(m, mname)
631 except:
632 raise
633 minstance = mclass(force=self.FORCE,
634 dryrun=self.DRYRUN,
635 nowait=self.NOWAIT,
636 perfmode=self.PERFMODE,
637 cache=self.CACHE,
638 cacheflags=self.CACHE_FLAGS)
639 self.modules[mname] = minstance
640 try:
641 self.module_attrs[mname] = minstance.get_modinfo()
642 except:
643 pass
644 except:
645 raise
646
647 # Assign all modules to query operations
648 self.module_ops['query-checkcurr'] = self.modules.keys()
649 self.module_ops['query-running'] = self.modules.keys()
650 self.module_ops['query-dependency'] = self.modules.keys()
651 self.module_ops['query'] = self.modules.keys()
652 self.module_ops['query-raw'] = self.modules.keys()
653
654
655 def _modules_help(self):
656 """ Prints addon modules supported syntax """
657
658 indent = ' '
659 for m, mdict in self.module_attrs.items():
660 if not mdict:
661 continue
662 print('%s: %s' %(m, mdict.get('mhelp')))
663 attrdict = mdict.get('attrs')
664 if not attrdict:
665 continue
666 try:
667 for attrname, attrvaldict in attrdict.items():
668 if attrvaldict.get('compat', False):
669 continue
670 print('%s%s' %(indent, attrname))
671 print('%shelp: %s' %(indent + ' ',
672 attrvaldict.get('help', '')))
673 print ('%srequired: %s' %(indent + ' ',
674 attrvaldict.get('required', False)))
675 default = attrvaldict.get('default')
676 if default:
677 print('%sdefault: %s' %(indent + ' ', default))
678
679 validrange = attrvaldict.get('validrange')
680 if validrange:
681 print('%svalidrange: %s-%s'
682 %(indent + ' ', validrange[0], validrange[1]))
683
684 validvals = attrvaldict.get('validvals')
685 if validvals:
686 print('%svalidvals: %s'
687 %(indent + ' ', ','.join(validvals)))
688
689 examples = attrvaldict.get('example')
690 if not examples:
691 continue
692
693 print '%sexample:' %(indent + ' ')
694 for e in examples:
695 print '%s%s' %(indent + ' ', e)
696 except:
697 pass
698 print ''
699
700 def load_scripts(self, modules_dir):
701 """ loading user modules from /etc/network/.
702
703 Note that previously loaded python modules override modules found
704 under /etc/network if any
705
706 """
707
708 self.logger.info('looking for user scripts under %s' %modules_dir)
709 for op, mlist in self.script_ops.items():
710 msubdir = modules_dir + '/if-%s.d' %op
711 self.logger.info('loading scripts under %s ...' %msubdir)
712 try:
713 module_list = os.listdir(msubdir)
714 for module in module_list:
715 if self.modules.get(module) is not None:
716 continue
717 self.script_ops[op].append(
718 msubdir + '/' + module)
719 except:
720 # continue reading
721 pass
722
723 def _sched_ifaces(self, ifacenames, ops, skipupperifaces=False,
724 followdependents=True, sort=False):
725 self.logger.debug('scheduling \'%s\' for %s'
726 %(str(ops), str(ifacenames)))
727 self._pretty_print_ordered_dict('dependency graph',
728 self.dependency_graph)
729 return ifaceScheduler.sched_ifaces(self, ifacenames, ops,
730 dependency_graph=self.dependency_graph,
731 order=ifaceSchedulerFlags.INORDER
732 if 'down' in ops[0]
733 else ifaceSchedulerFlags.POSTORDER,
734 followdependents=followdependents,
735 skipupperifaces=skipupperifaces,
736 sort=True if (sort or self.IFACE_CLASS) else False)
737
738 def _render_ifacename(self, ifacename):
739 new_ifacenames = []
740 vlan_match = re.match("^([\d]+)-([\d]+)", ifacename)
741 if vlan_match:
742 vlan_groups = vlan_match.groups()
743 if vlan_groups[0] and vlan_groups[1]:
744 [new_ifacenames.append('%d' %v)
745 for v in range(int(vlan_groups[0]),
746 int(vlan_groups[1])+1)]
747 return new_ifacenames
748
749 def _preprocess_ifacenames(self, ifacenames):
750 """ validates interface list for config existance.
751
752 returns -1 if one or more interface not found. else, returns 0
753
754 """
755 new_ifacenames = []
756 err_iface = ''
757 ifnamsiz_error = ''
758 for i in ifacenames:
759 ifaceobjs = self.get_ifaceobjs(i)
760 if not ifaceobjs:
761 # if name not available, render interface name and check again
762 rendered_ifacenames = utils.expand_iface_range(i)
763 if rendered_ifacenames:
764 for ri in rendered_ifacenames:
765 ifaceobjs = self.get_ifaceobjs(ri)
766 if not ifaceobjs:
767 err_iface += ' ' + ri
768 else:
769 if utils.check_ifname_size_invalid(ri):
770 ifnamsiz_error += ' ' + ri
771 new_ifacenames.append(ri)
772 else:
773 err_iface += ' ' + i
774 else:
775 if utils.check_ifname_size_invalid(i):
776 ifnamsiz_error += ' ' + i
777 new_ifacenames.append(i)
778 if err_iface:
779 raise Exception('cannot find interfaces:%s' %err_iface)
780 if ifnamsiz_error:
781 raise Exception('the following interface names are too long:%s' %ifnamsiz_error)
782 return new_ifacenames
783
784 def _iface_whitelisted(self, auto, allow_classes, excludepats, ifacename):
785 """ Checks if interface is whitelisted depending on set of parameters.
786
787 interfaces are checked against the allow_classes and auto lists.
788
789 """
790 ret = True
791
792 # Check if interface matches the exclude patter
793 if excludepats:
794 for e in excludepats:
795 if re.search(e, ifacename):
796 ret = False
797 ifaceobjs = self.get_ifaceobjs(ifacename)
798 if not ifaceobjs:
799 if ret:
800 self.logger.debug('iface %s' %ifacename + ' not found')
801 return ret
802 # If matched exclude pattern, return false
803 if not ret:
804 for i in ifaceobjs:
805 i.blacklisted = True
806 return ret
807 # Check if interface belongs to the class
808 # the user is interested in, if not return false
809 if allow_classes:
810 for i in ifaceobjs:
811 if i.classes:
812 common = Set([allow_classes]).intersection(
813 Set(i.classes))
814 if common:
815 ret = True
816 else:
817 i.blacklisted = True
818 if not ret:
819 return ret
820 # If the user has requested auto class, check if the interface
821 # is marked auto
822 if auto:
823 for i in ifaceobjs:
824 if i.auto:
825 ret = True
826 else:
827 i.blacklisted = True
828 return ret
829
830 def _compat_conv_op_to_mode(self, op):
831 """ Returns old op name to work with existing scripts """
832 if op == 'pre-up':
833 return 'start'
834 elif op == 'pre-down':
835 return 'stop'
836 else:
837 return op
838
839 def generate_running_env(self, ifaceobj, op):
840 """ Generates a dictionary with env variables required for
841 an interface. Used to support script execution for interfaces.
842 """
843
844 cenv = None
845 iface_env = ifaceobj.env
846 if iface_env:
847 cenv = os.environ
848 if cenv:
849 cenv.update(iface_env)
850 else:
851 cenv = iface_env
852 cenv['MODE'] = self._compat_conv_op_to_mode(op)
853 return cenv
854
855 def _save_state(self):
856 if not self.STATEMANAGER_ENABLE or not self.STATEMANAGER_UPDATE:
857 return
858 try:
859 # Update persistant iface states
860 self.statemanager.save_state()
861 except Exception, e:
862 if self.logger.isEnabledFor(logging.DEBUG):
863 t = sys.exc_info()[2]
864 traceback.print_tb(t)
865 self.logger.warning('error saving state (%s)' %str(e))
866
867 def set_type(self, type):
868 if type == 'iface':
869 self.type = ifaceType.IFACE
870 elif type == 'vlan':
871 self.type = ifaceType.BRIDGE_VLAN
872 else:
873 self.type = ifaceType.UNKNOWN
874
875 def _process_delay_admin_state_queue(self, op):
876 if not self._delay_admin_state_iface_queue:
877 return
878 if op == 'up':
879 func = self.link_up
880 elif op == 'down':
881 func = self.link_down
882 else:
883 return
884 for i in self._delay_admin_state_iface_queue:
885 try:
886 if self.link_exists(i):
887 func(i)
888 except Exception, e:
889 self.logger.warn(str(e))
890 pass
891
892 def up(self, ops, auto=False, allow_classes=None, ifacenames=None,
893 excludepats=None, printdependency=None, syntaxcheck=False,
894 type=None, skipupperifaces=False):
895 """This brings the interface(s) up
896
897 Args:
898 ops (list): list of ops to perform on the interface(s).
899 Eg: ['pre-up', 'up', 'post-up'
900
901 Kwargs:
902 auto (bool): act on interfaces marked auto
903 allow_classes (list): act on interfaces belonging to classes in the list
904 ifacenames (list): act on interfaces specified in this list
905 excludepats (list): list of patterns of interfaces to exclude
906 syntaxcheck (bool): only perform syntax check
907 """
908
909 self.set_type(type)
910
911 if allow_classes:
912 self.IFACE_CLASS = True
913 if not self.ADDONS_ENABLE: self.STATEMANAGER_UPDATE = False
914 if auto:
915 self.ALL = True
916 self.WITH_DEPENDS = True
917 try:
918 self.read_iface_config()
919 except Exception:
920 raise
921
922 # If only syntax check was requested, return here
923 if syntaxcheck:
924 return
925
926 if ifacenames:
927 ifacenames = self._preprocess_ifacenames(ifacenames)
928
929 # if iface list not given by user, assume all from config file
930 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
931
932 # filter interfaces based on auto and allow classes
933 filtered_ifacenames = [i for i in ifacenames
934 if self._iface_whitelisted(auto, allow_classes,
935 excludepats, i)]
936 if not filtered_ifacenames:
937 raise Exception('no ifaces found matching given allow lists')
938
939 if printdependency:
940 self.populate_dependency_info(ops, filtered_ifacenames)
941 self.print_dependency(filtered_ifacenames, printdependency)
942 return
943 else:
944 self.populate_dependency_info(ops)
945
946 if filtered_ifacenames:
947 filtered_ifacenames = self._preprocess_ifacenames(filtered_ifacenames)
948 try:
949 self._sched_ifaces(filtered_ifacenames, ops,
950 skipupperifaces=skipupperifaces,
951 followdependents=True if self.WITH_DEPENDS else False)
952 finally:
953 self._process_delay_admin_state_queue('up')
954 if not self.DRYRUN and self.ADDONS_ENABLE:
955 self._save_state()
956
957 def down(self, ops, auto=False, allow_classes=None, ifacenames=None,
958 excludepats=None, printdependency=None, usecurrentconfig=False,
959 type=None):
960 """ down an interface """
961
962 self.set_type(type)
963
964 if allow_classes:
965 self.IFACE_CLASS = True
966 if not self.ADDONS_ENABLE: self.STATEMANAGER_UPDATE = False
967 if auto:
968 self.ALL = True
969 self.WITH_DEPENDS = True
970 # For down we need to look at old state, unless usecurrentconfig
971 # is set
972 if (not usecurrentconfig and self.STATEMANAGER_ENABLE and
973 self.statemanager.ifaceobjdict):
974 # Since we are using state manager objects,
975 # skip the updating of state manager objects
976 self.logger.debug('Looking at old state ..')
977 self.read_old_iface_config()
978 else:
979 # If no old state available
980 try:
981 self.read_iface_config()
982 except Exception, e:
983 raise Exception('error reading iface config (%s)' %str(e))
984 if ifacenames:
985 # If iface list is given by the caller, always check if iface
986 # is present
987 try:
988 ifacenames = self._preprocess_ifacenames(ifacenames)
989 except Exception, e:
990 raise Exception('%s' %str(e) +
991 ' (interface was probably never up ?)')
992
993 # if iface list not given by user, assume all from config file
994 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
995
996 # filter interfaces based on auto and allow classes
997 filtered_ifacenames = [i for i in ifacenames
998 if self._iface_whitelisted(auto, allow_classes,
999 excludepats, i)]
1000 if not filtered_ifacenames:
1001 raise Exception('no ifaces found matching given allow lists ' +
1002 '(or interfaces were probably never up ?)')
1003
1004 if printdependency:
1005 self.populate_dependency_info(ops, filtered_ifacenames)
1006 self.print_dependency(filtered_ifacenames, printdependency)
1007 return
1008 else:
1009 self.populate_dependency_info(ops)
1010
1011 try:
1012 self._sched_ifaces(filtered_ifacenames, ops,
1013 followdependents=True if self.WITH_DEPENDS else False)
1014 finally:
1015 self._process_delay_admin_state_queue('down')
1016 if not self.DRYRUN and self.ADDONS_ENABLE:
1017 self._save_state()
1018
1019 def query(self, ops, auto=False, allow_classes=None, ifacenames=None,
1020 excludepats=None, printdependency=None,
1021 format='native', type=None):
1022 """ query an interface """
1023
1024 self.set_type(type)
1025
1026 if allow_classes:
1027 self.IFACE_CLASS = True
1028 if self.STATEMANAGER_ENABLE and ops[0] == 'query-savedstate':
1029 return self.statemanager.dump_pretty(ifacenames)
1030 self.STATEMANAGER_UPDATE = False
1031 if auto:
1032 self.logger.debug('setting flag ALL')
1033 self.ALL = True
1034 self.WITH_DEPENDS = True
1035
1036 if ops[0] == 'query-syntax':
1037 self._modules_help()
1038 return
1039 elif ops[0] == 'query-running':
1040 # create fake devices to all dependents that dont have config
1041 map(lambda i: self.create_n_save_ifaceobj(i, self.NOCONFIG),
1042 ifacenames)
1043 else:
1044 try:
1045 self.read_iface_config()
1046 except Exception:
1047 raise
1048
1049 if ifacenames and ops[0] != 'query-running':
1050 # If iface list is given, always check if iface is present
1051 ifacenames = self._preprocess_ifacenames(ifacenames)
1052
1053 # if iface list not given by user, assume all from config file
1054 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
1055
1056 # filter interfaces based on auto and allow classes
1057 if ops[0] == 'query-running':
1058 filtered_ifacenames = ifacenames
1059 else:
1060 filtered_ifacenames = [i for i in ifacenames
1061 if self._iface_whitelisted(auto, allow_classes,
1062 excludepats, i)]
1063 if not filtered_ifacenames:
1064 raise Exception('no ifaces found matching ' +
1065 'given allow lists')
1066
1067 self.populate_dependency_info(ops)
1068 if ops[0] == 'query-dependency' and printdependency:
1069 self.print_dependency(filtered_ifacenames, printdependency)
1070 return
1071
1072 if ops[0] == 'query':
1073 return self.print_ifaceobjs_pretty(filtered_ifacenames, format)
1074 elif ops[0] == 'query-raw':
1075 return self.print_ifaceobjs_raw(filtered_ifacenames)
1076
1077 if filtered_ifacenames:
1078 filtered_ifacenames = self._preprocess_ifacenames(filtered_ifacenames)
1079 self._sched_ifaces(filtered_ifacenames, ops,
1080 followdependents=True if self.WITH_DEPENDS else False)
1081
1082 if ops[0] == 'query-checkcurr':
1083 ret = self.print_ifaceobjscurr_pretty(filtered_ifacenames, format)
1084 if ret != 0:
1085 # if any of the object has an error, signal that silently
1086 raise Exception('')
1087 elif ops[0] == 'query-running':
1088 self.print_ifaceobjsrunning_pretty(filtered_ifacenames, format)
1089 return
1090
1091 def _reload_currentlyup(self, upops, downops, auto=True, allow=None,
1092 ifacenames=None, excludepats=None, usecurrentconfig=False,
1093 **extra_args):
1094 """ reload currently up interfaces """
1095 allow_classes = []
1096 new_ifaceobjdict = {}
1097
1098 # Override auto to true
1099 auto = True
1100 try:
1101 self.read_iface_config()
1102 except:
1103 raise
1104 if not self.ifaceobjdict:
1105 self.logger.warn("nothing to reload ..exiting.")
1106 return
1107 already_up_ifacenames = []
1108 # generate dependency graph of interfaces
1109 self.populate_dependency_info(upops)
1110 if (not usecurrentconfig and self.STATEMANAGER_ENABLE
1111 and self.statemanager.ifaceobjdict):
1112 already_up_ifacenames = self.statemanager.ifaceobjdict.keys()
1113
1114 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
1115 filtered_ifacenames = [i for i in ifacenames
1116 if self._iface_whitelisted(auto, allow_classes,
1117 excludepats, i)]
1118
1119 # Get already up interfaces that still exist in the interfaces file
1120 already_up_ifacenames_not_present = Set(
1121 already_up_ifacenames).difference(ifacenames)
1122 already_up_ifacenames_still_present = Set(
1123 already_up_ifacenames).difference(
1124 already_up_ifacenames_not_present)
1125 interfaces_to_up = Set(already_up_ifacenames_still_present).union(
1126 filtered_ifacenames)
1127
1128 if (already_up_ifacenames_not_present and
1129 self.config.get('ifreload_currentlyup_down_notpresent') == '1'):
1130 self.logger.info('reload: schedule down on interfaces: %s'
1131 %str(already_up_ifacenames_not_present))
1132
1133 # Save a copy of new iface objects and dependency_graph
1134 new_ifaceobjdict = dict(self.ifaceobjdict)
1135 new_dependency_graph = dict(self.dependency_graph)
1136
1137 # old interface config is read into self.ifaceobjdict
1138 self.read_old_iface_config()
1139
1140 # reinitialize dependency graph
1141 self.dependency_graph = OrderedDict({})
1142 self.populate_dependency_info(downops,
1143 already_up_ifacenames_not_present)
1144 self._sched_ifaces(already_up_ifacenames_not_present, downops,
1145 followdependents=False, sort=True)
1146 else:
1147 self.logger.debug('no interfaces to down ..')
1148
1149 # Now, run 'up' with new config dict
1150 # reset statemanager update flag to default
1151 if auto:
1152 self.ALL = True
1153 self.WITH_DEPENDS = True
1154 if new_ifaceobjdict:
1155 # and now, ifaceobjdict is back to current config
1156 self.ifaceobjdict = new_ifaceobjdict
1157 self.dependency_graph = new_dependency_graph
1158
1159 if not self.ifaceobjdict:
1160 return
1161 self.logger.info('reload: scheduling up on interfaces: %s'
1162 %str(interfaces_to_up))
1163 interfaces_to_up = self._preprocess_ifacenames(interfaces_to_up)
1164 self._sched_ifaces(interfaces_to_up, upops,
1165 followdependents=True if self.WITH_DEPENDS else False)
1166 if self.DRYRUN:
1167 return
1168 self._save_state()
1169
1170 def _reload_default(self, upops, downops, auto=False, allow=None,
1171 ifacenames=None, excludepats=None, usecurrentconfig=False,
1172 **extra_args):
1173 """ reload interface config """
1174 allow_classes = []
1175 new_ifaceobjdict = {}
1176
1177 try:
1178 self.read_iface_config()
1179 except:
1180 raise
1181
1182 if not self.ifaceobjdict:
1183 self.logger.warn("nothing to reload ..exiting.")
1184 return
1185 # generate dependency graph of interfaces
1186 self.populate_dependency_info(upops)
1187 if (not usecurrentconfig and self.STATEMANAGER_ENABLE
1188 and self.statemanager.ifaceobjdict):
1189 # Save a copy of new iface objects and dependency_graph
1190 new_ifaceobjdict = dict(self.ifaceobjdict)
1191 new_dependency_graph = dict(self.dependency_graph)
1192
1193 # if old state is present, read old state and mark op for 'down'
1194 # followed by 'up' aka: reload
1195 # old interface config is read into self.ifaceobjdict
1196 self.read_old_iface_config()
1197 op = 'reload'
1198 else:
1199 # oldconfig not available, continue with 'up' with new config
1200 op = 'up'
1201
1202 if not ifacenames: ifacenames = self.ifaceobjdict.keys()
1203 if op == 'reload' and ifacenames:
1204 filtered_ifacenames = [i for i in ifacenames
1205 if self._iface_whitelisted(auto, allow_classes,
1206 excludepats, i)]
1207
1208 # if config file had 'ifreload_down_changed' variable
1209 # set, also look for interfaces that changed to down them
1210 down_changed = int(self.config.get('ifreload_down_changed', '1'))
1211
1212 # Generate the interface down list
1213 # Interfaces that go into the down list:
1214 # - interfaces that were present in last config and are not
1215 # present in the new config
1216 # - interfaces that were changed between the last and current
1217 # config
1218 ifacedownlist = []
1219 for ifname in filtered_ifacenames:
1220 lastifaceobjlist = self.ifaceobjdict.get(ifname)
1221 objidx = 0
1222 # If interface is not present in the new file
1223 # append it to the down list
1224 newifaceobjlist = new_ifaceobjdict.get(ifname)
1225 if not newifaceobjlist:
1226 ifacedownlist.append(ifname)
1227 continue
1228 if not down_changed:
1229 continue
1230 if len(newifaceobjlist) != len(lastifaceobjlist):
1231 ifacedownlist.append(ifname)
1232 continue
1233
1234 # If interface has changed between the current file
1235 # and the last installed append it to the down list
1236 # compare object list
1237 for objidx in range(0, len(lastifaceobjlist)):
1238 oldobj = lastifaceobjlist[objidx]
1239 newobj = newifaceobjlist[objidx]
1240 if not newobj.compare(oldobj):
1241 ifacedownlist.append(ifname)
1242 continue
1243
1244 if ifacedownlist:
1245 self.logger.info('reload: scheduling down on interfaces: %s'
1246 %str(ifacedownlist))
1247 # reinitialize dependency graph
1248 self.dependency_graph = OrderedDict({})
1249 # Generate dependency info for old config
1250 self.populate_dependency_info(downops, ifacedownlist)
1251 try:
1252 self._sched_ifaces(ifacedownlist, downops,
1253 followdependents=False,
1254 sort=True)
1255 except Exception, e:
1256 self.logger.error(str(e))
1257 pass
1258 finally:
1259 self._process_delay_admin_state_queue('down')
1260 else:
1261 self.logger.debug('no interfaces to down ..')
1262
1263 # Now, run 'up' with new config dict
1264 # reset statemanager update flag to default
1265 if not new_ifaceobjdict:
1266 return
1267
1268 if auto:
1269 self.ALL = True
1270 self.WITH_DEPENDS = True
1271 # and now, we are back to the current config in ifaceobjdict
1272 self.ifaceobjdict = new_ifaceobjdict
1273 self.dependency_graph = new_dependency_graph
1274 ifacenames = self.ifaceobjdict.keys()
1275 filtered_ifacenames = [i for i in ifacenames
1276 if self._iface_whitelisted(auto, allow_classes,
1277 excludepats, i)]
1278
1279 self.logger.info('reload: scheduling up on interfaces: %s'
1280 %str(filtered_ifacenames))
1281 filtered_ifacenames = self._preprocess_ifacenames(filtered_ifacenames)
1282 try:
1283 self._sched_ifaces(filtered_ifacenames, upops,
1284 followdependents=True if self.WITH_DEPENDS else False)
1285 except Exception, e:
1286 self.logger.error(str(e))
1287 pass
1288 finally:
1289 self._process_delay_admin_state_queue('up')
1290 if self.DRYRUN:
1291 return
1292 self._save_state()
1293
1294 def reload(self, *args, **kargs):
1295 """ reload interface config """
1296 self.logger.debug('reloading interface config ..')
1297 if kargs.get('currentlyup', False):
1298 self._reload_currentlyup(*args, **kargs)
1299 else:
1300 self._reload_default(*args, **kargs)
1301
1302 def _pretty_print_ordered_dict(self, prefix, argdict):
1303 outbuf = prefix + ' {\n'
1304 for k, vlist in argdict.items():
1305 outbuf += '\t%s : %s\n' %(k, str(vlist))
1306 self.logger.debug(outbuf + '}')
1307
1308 def print_dependency(self, ifacenames, format):
1309 """ prints iface dependency information """
1310
1311 if not ifacenames:
1312 ifacenames = self.ifaceobjdict.keys()
1313 if format == 'list':
1314 for k,v in self.dependency_graph.items():
1315 print '%s : %s' %(k, str(v))
1316 elif format == 'dot':
1317 indegrees = {}
1318 map(lambda i: indegrees.update({i :
1319 self.get_iface_refcnt(i)}),
1320 self.dependency_graph.keys())
1321 graph.generate_dots(self.dependency_graph, indegrees)
1322
1323 def print_ifaceobjs_raw(self, ifacenames):
1324 """ prints raw lines for ifaces from config file """
1325
1326 for i in ifacenames:
1327 for ifaceobj in self.get_ifaceobjs(i):
1328 if (self.is_ifaceobj_builtin(ifaceobj) or
1329 not ifaceobj.is_config_present()):
1330 continue
1331 ifaceobj.dump_raw(self.logger)
1332 print '\n'
1333 if self.WITH_DEPENDS and not self.ALL:
1334 dlist = ifaceobj.lowerifaces
1335 if not dlist: continue
1336 self.print_ifaceobjs_raw(dlist)
1337
1338 def _get_ifaceobjs_pretty(self, ifacenames, ifaceobjs, running=False):
1339 """ returns iface obj list """
1340
1341 for i in ifacenames:
1342 for ifaceobj in self.get_ifaceobjs(i):
1343 if ((not running and self.is_ifaceobj_noconfig(ifaceobj)) or
1344 (running and not ifaceobj.is_config_present())):
1345 continue
1346 ifaceobjs.append(ifaceobj)
1347 if self.WITH_DEPENDS and not self.ALL:
1348 dlist = ifaceobj.lowerifaces
1349 if not dlist: continue
1350 self._get_ifaceobjs_pretty(dlist, ifaceobjs, running)
1351
1352 def print_ifaceobjs_pretty(self, ifacenames, format='native'):
1353 """ pretty prints iface in format given by keyword arg format """
1354
1355 ifaceobjs = []
1356 self._get_ifaceobjs_pretty(ifacenames, ifaceobjs)
1357 if not ifaceobjs: return
1358 if format == 'json':
1359 print json.dumps(ifaceobjs, cls=ifaceJsonEncoder,
1360 indent=4, separators=(',', ': '))
1361 else:
1362 expand = int(self.config.get('ifquery_ifacename_expand_range', '0'))
1363 for i in ifaceobjs:
1364 if not expand and (i.flags & iface.IFACERANGE_ENTRY):
1365 # print only the first one
1366 if i.flags & iface.IFACERANGE_START:
1367 i.dump_pretty(use_realname=True)
1368 else:
1369 i.dump_pretty()
1370
1371 def _get_ifaceobjscurr_pretty(self, ifacenames, ifaceobjs):
1372 ret = 0
1373 for i in ifacenames:
1374 ifaceobjscurr = self.get_ifaceobjcurr(i)
1375 if not ifaceobjscurr: continue
1376 for ifaceobj in ifaceobjscurr:
1377 if (ifaceobj.status == ifaceStatus.NOTFOUND or
1378 ifaceobj.status == ifaceStatus.ERROR):
1379 ret = 1
1380 if self.is_ifaceobj_noconfig(ifaceobj):
1381 continue
1382 ifaceobjs.append(ifaceobj)
1383 if self.WITH_DEPENDS and not self.ALL:
1384 dlist = ifaceobj.lowerifaces
1385 if not dlist: continue
1386 dret = self._get_ifaceobjscurr_pretty(dlist, ifaceobjs)
1387 if dret: ret = 1
1388 return ret
1389
1390 def print_ifaceobjscurr_pretty(self, ifacenames, format='native'):
1391 """ pretty prints current running state of interfaces with status.
1392
1393 returns 1 if any of the interface has an error,
1394 else returns 0
1395 """
1396
1397 ifaceobjs = []
1398 ret = self._get_ifaceobjscurr_pretty(ifacenames, ifaceobjs)
1399 if not ifaceobjs: return
1400 if format == 'json':
1401 print json.dumps(ifaceobjs, cls=ifaceJsonEncoder, indent=2,
1402 separators=(',', ': '))
1403 else:
1404 map(lambda i: i.dump_pretty(with_status=True,
1405 successstr=self.config.get('ifquery_check_success_str',
1406 _success_sym),
1407 errorstr=self.config.get('ifquery_check_error_str', _error_sym),
1408 unknownstr=self.config.get('ifquery_check_unknown_str', '')),
1409 ifaceobjs)
1410 return ret
1411
1412 def print_ifaceobjsrunning_pretty(self, ifacenames, format='native'):
1413 """ pretty prints iface running state """
1414
1415 ifaceobjs = []
1416 self._get_ifaceobjs_pretty(ifacenames, ifaceobjs, running=True)
1417 if not ifaceobjs: return
1418 if format == 'json':
1419 print json.dumps(ifaceobjs, cls=ifaceJsonEncoder, indent=2,
1420 separators=(',', ': '))
1421 else:
1422 map(lambda i: i.dump_pretty(), ifaceobjs)
1423
1424 def _dump(self):
1425 print 'ifupdown main object dump'
1426 print self.pp.pprint(self.modules)
1427 print self.pp.pprint(self.ifaceobjdict)
1428
1429 def _dump_ifaceobjs(self, ifacenames):
1430 for i in ifacenames:
1431 ifaceobjs = self.get_ifaceobjs(i)
1432 for i in ifaceobjs:
1433 i.dump(self.logger)
1434 print '\n'