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