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