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