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