3 # Copyright 2014 Cumulus Networks, Inc. All rights reserved.
4 # Author: Roopa Prabhu, roopa@cumulusnetworks.com
18 from statemanager
import *
19 from networkinterfaces
import *
21 from scheduler
import *
22 from collections
import deque
23 from collections
import OrderedDict
28 .. module:: ifupdownmain
29 :synopsis: main module for ifupdown package
31 .. moduleauthor:: Roopa Prabhu <roopa@cumulusnetworks.com>
36 _crossmark
= u
'\u2717'
37 _success_sym
= _tickmark
38 _error_sym
= _crossmark
40 class ifupdownMain(ifupdownBase
):
41 """ ifupdown2 main class """
47 COMPAT_EXEC_SCRIPTS
= False
48 STATEMANAGER_ENABLE
= True
49 STATEMANAGER_UPDATE
= True
52 # priv flags to mark iface objects
56 scripts_dir
='/etc/network'
57 addon_modules_dir
='/usr/share/ifupdownaddons'
58 addon_modules_configfile
='/var/lib/ifupdownaddons/addons.conf'
60 # iface dictionary in the below format:
61 # { '<ifacename>' : [<ifaceobject1>, <ifaceobject2> ..] }
63 # { 'swp1' : [<iface swp1>, <iface swp2> ..] }
65 # Each ifaceobject corresponds to a configuration block for
67 # The value in the dictionary is a list because the network
68 # interface configuration file supports more than one iface section
69 # in the interfaces file
70 ifaceobjdict
= OrderedDict()
72 # iface dictionary representing the curr running state of an iface
73 # in the below format:
74 # {'<ifacename>' : <ifaceobject>}
75 ifaceobjcurrdict
= OrderedDict()
77 # Dictionary representing operation and modules
79 module_ops
= OrderedDict([('pre-up', []),
82 ('query-checkcurr', []),
83 ('query-running', []),
84 ('query-dependency', []),
91 # For old style /etc/network/ bash scripts
92 script_ops
= OrderedDict([('pre-up', []),
99 # Handlers for ops that ifupdown2 owns
100 def run_up(self
, ifaceobj
):
101 ifacename
= ifaceobj
.name
102 if self
.link_exists(ifacename
):
103 self
.link_up(ifacename
)
105 def run_down(self
, ifaceobj
):
106 ifacename
= ifaceobj
.name
107 if self
.link_exists(ifacename
):
108 self
.link_down(ifacename
)
110 # ifupdown object interface operation handlers
111 ops_handlers
= OrderedDict([('up', run_up
),
114 def run_sched_ifaceobj_posthook(self
, ifaceobj
, op
):
115 if ((ifaceobj
.priv_flags
& self
.BUILTIN
) or
116 (ifaceobj
.priv_flags
& self
.NOCONFIG
)):
118 if self
.STATEMANAGER_UPDATE
:
119 self
.statemanager
.ifaceobj_sync(ifaceobj
, op
)
121 # ifupdown object interface scheduler pre and posthooks
122 sched_hooks
= {'posthook' : run_sched_ifaceobj_posthook
}
124 def __init__(self
, config
={},
125 force
=False, dryrun
=False, nowait
=False,
126 perfmode
=False, withdepends
=False, njobs
=1,
127 cache
=False, addons_enable
=True, statemanager_enable
=True,
128 interfacesfile
='/etc/network/interfaces',
129 interfacesfileiobuf
=None,
130 interfacesfileformat
='native'):
131 """This member function initializes the ifupdownmain object.
134 config (dict): config dict from /etc/network/ifupdown2/ifupdown2.conf
135 force (bool): force interface configuration
136 dryrun (bool): dryrun interface configuration
137 withdepends (bool): apply interface configuration on all depends
138 interfacesfile (str): interfaces file. default is /etc/network/interfaces
139 interfacesfileformat (str): default is 'native'. Other choices are 'json'
142 AttributeError, KeyError """
144 self
.logger
= logging
.getLogger('ifupdown')
148 self
.PERFMODE
= perfmode
149 self
.WITH_DEPENDS
= withdepends
150 self
.STATEMANAGER_ENABLE
= statemanager_enable
152 self
.interfacesfile
= interfacesfile
153 self
.interfacesfileiobuf
= interfacesfileiobuf
154 self
.interfacesfileformat
= interfacesfileformat
156 self
.logger
.debug(self
.config
)
158 # Can be used to provide hints for caching
159 self
.CACHE_FLAGS
= 0x0
160 self
._DELETE
_DEPENDENT
_IFACES
_WITH
_NOCONFIG
= False
161 self
.ADDONS_ENABLE
= addons_enable
163 self
.ifaces
= OrderedDict()
165 self
.pp
= pprint
.PrettyPrinter(indent
=4)
166 self
.modules
= OrderedDict({})
167 self
.module_attrs
= {}
169 self
.load_addon_modules(self
.addon_modules_dir
)
170 if self
.COMPAT_EXEC_SCRIPTS
:
171 self
.load_scripts(self
.scripts_dir
)
172 self
.dependency_graph
= OrderedDict({})
174 if self
.STATEMANAGER_ENABLE
:
176 self
.statemanager
= stateManager()
177 self
.statemanager
.read_saved_state()
179 # XXX Maybe we should continue by ignoring old state
180 self
.logger
.warning('error reading state (%s)' %str
(e
))
183 self
.STATEMANAGER_UPDATE
= False
185 def get_ifaceobjs(self
, ifacename
):
186 return self
.ifaceobjdict
.get(ifacename
)
188 def get_ifaceobj_first(self
, ifacename
):
189 ifaceobjs
= self
.get_ifaceobjs(ifacename
)
194 def get_ifacenames(self
):
195 return self
.ifaceobjdict
.keys()
197 def get_iface_obj_last(self
, ifacename
):
198 return self
.ifaceobjdict
.get(ifacename
)[-1]
200 def create_n_save_ifaceobj(self
, ifacename
, priv_flags
=None,
202 """ creates a iface object and adds it to the iface dictionary """
204 ifaceobj
.name
= ifacename
205 ifaceobj
.priv_flags
= priv_flags
208 ifaceobj
.inc_refcnt()
209 self
.ifaceobjdict
[ifacename
] = [ifaceobj
]
212 def create_n_save_ifaceobjcurr(self
, ifaceobj
):
213 """ creates a copy of iface object and adds it to the iface
214 dict containing current iface objects
216 ifaceobjcurr
= iface()
217 ifaceobjcurr
.name
= ifaceobj
.name
218 ifaceobjcurr
.lowerifaces
= ifaceobj
.lowerifaces
219 ifaceobjcurr
.priv_flags
= ifaceobj
.priv_flags
220 ifaceobjcurr
.auto
= ifaceobj
.auto
221 self
.ifaceobjcurrdict
.setdefault(ifaceobj
.name
,
222 []).append(ifaceobjcurr
)
225 def get_ifaceobjcurr(self
, ifacename
, idx
=0):
226 ifaceobjlist
= self
.ifaceobjcurrdict
.get(ifacename
)
232 return ifaceobjlist
[idx
]
234 def get_ifaceobjrunning(self
, ifacename
):
235 return self
.ifaceobjrunningdict
.get(ifacename
)
237 def get_iface_refcnt(self
, ifacename
):
238 """ Return iface ref count """
240 ifaceobjs
= self
.get_ifaceobjs(ifacename
)
248 def is_iface_builtin_byname(self
, ifacename
):
249 """ Returns true if iface name is a builtin interface.
251 A builtin interface is an interface which ifupdown understands.
252 The following are currently considered builtin ifaces:
253 - vlan interfaces in the format <ifacename>.<vlanid>
255 return '.' in ifacename
257 def is_ifaceobj_builtin(self
, ifaceobj
):
258 """ Returns true if iface name is a builtin interface.
260 A builtin interface is an interface which ifupdown understands.
261 The following are currently considered builtin ifaces:
262 - vlan interfaces in the format <ifacename>.<vlanid>
264 return (ifaceobj
.priv_flags
& self
.BUILTIN
)
266 def is_ifaceobj_noconfig(self
, ifaceobj
):
267 """ Returns true if iface object did not have a user defined config.
269 These interfaces appear only when they are dependents of interfaces
270 which have user defined config
272 return (ifaceobj
.priv_flags
& self
.NOCONFIG
)
274 def is_iface_noconfig(self
, ifacename
):
275 """ Returns true if iface has no config """
277 ifaceobj
= self
.get_ifaceobj_first(ifacename
)
278 if not ifaceobj
: return True
279 return self
.is_ifaceobj_noconfig(ifaceobj
)
281 def preprocess_dependency_list(self
, upperifacename
, dlist
, ops
):
282 """ We go through the dependency list and
283 delete or add interfaces from the interfaces dict by
284 applying the following rules:
285 if flag _DELETE_DEPENDENT_IFACES_WITH_NOCONFIG is True:
286 we only consider devices whose configuration was
287 specified in the network interfaces file. We delete
288 any interface whose config was not specified except
289 for vlan devices. vlan devices get special treatment.
290 Even if they are not present they are created and added
292 elif flag _DELETE_DEPENDENT_IFACES_WITH_NOCONFIG is False:
293 we create objects for all dependent devices that are not
294 present in the ifacesdict
299 dilist
= self
.get_ifaceobjs(d
)
301 if self
.is_iface_builtin_byname(d
):
302 self
.create_n_save_ifaceobj(d
, self
.BUILTIN | self
.NOCONFIG
,
303 True).add_to_upperifaces(upperifacename
)
304 elif not self
._DELETE
_DEPENDENT
_IFACES
_WITH
_NOCONFIG
:
305 self
.create_n_save_ifaceobj(d
, self
.NOCONFIG
,
306 True).add_to_upperifaces(upperifacename
)
312 di
.add_to_upperifaces(upperifacename
)
317 def query_dependents(self
, ifaceobj
, ops
):
318 """ Gets iface dependents by calling into respective modules """
321 # Get dependents for interface by querying respective modules
322 for mname
, module
in self
.modules
.items():
323 module
= self
.modules
.get(mname
)
325 if ops
[0] == 'query-running':
326 if (not hasattr(module
,
327 'get_dependent_ifacenames_running')):
329 dlist
= module
.get_dependent_ifacenames_running(ifaceobj
)
331 if (not hasattr(module
, 'get_dependent_ifacenames')):
333 dlist
= module
.get_dependent_ifacenames(ifaceobj
,
334 self
.ifaceobjdict
.keys())
336 self
.logger
.warn('%s: error getting dependent interfaces (%s)'
337 %(ifaceobj
.name
, str(e
)))
344 def populate_dependency_info(self
, ops
, ifacenames
=None):
345 """ recursive function to generate iface dependency info """
348 ifacenames
= self
.ifaceobjdict
.keys()
350 iqueue
= deque(ifacenames
)
353 # Go through all modules and find dependent ifaces
355 ifaceobj
= self
.get_ifaceobj_first(i
)
358 dlist
= ifaceobj
.lowerifaces
360 dlist
= self
.query_dependents(ifaceobj
, ops
)
364 self
.preprocess_dependency_list(ifaceobj
.name
,
366 ifaceobj
.lowerifaces
= dlist
367 [iqueue
.append(d
) for d
in dlist
]
368 if not self
.dependency_graph
.get(i
):
369 self
.dependency_graph
[i
] = dlist
371 def _save_iface(self
, ifaceobj
):
372 currentifaceobjlist
= self
.ifaceobjdict
.get(ifaceobj
.name
)
373 if not currentifaceobjlist
:
374 self
.ifaceobjdict
[ifaceobj
.name
]= [ifaceobj
]
376 if ifaceobj
.compare(currentifaceobjlist
[0]):
377 self
.logger
.warn('duplicate interface %s found' %ifaceobj
.name
)
379 currentifaceobjlist
[0].flags |
= iface
.HAS_SIBLINGS
380 ifaceobj
.flags |
= iface
.HAS_SIBLINGS
381 self
.ifaceobjdict
[ifaceobj
.name
].append(ifaceobj
)
383 def _iface_configattr_syntax_checker(self
, attrname
, attrval
):
384 for m
, mdict
in self
.module_attrs
.items():
387 attrsdict
= mdict
.get('attrs')
389 if attrsdict
.get(attrname
):
391 except AttributeError:
395 def _ifaceobj_syntax_checker(self
, ifaceobj
):
397 for attrname
in ifaceobj
.config
:
399 for k
, v
in self
.module_attrs
.items():
400 if v
and v
.get('attrs', {}).get(attrname
):
405 self
.logger
.warn('%s: unsupported attribute \'%s\'' %attrname
)
409 def read_iface_config(self
):
410 """ Reads default network interface config /etc/network/interfaces. """
411 nifaces
= networkInterfaces(self
.interfacesfile
,
412 self
.interfacesfileiobuf
,
413 self
.interfacesfileformat
,
414 template_engine
=self
.config
.get('template_engine'),
415 template_lookuppath
=self
.config
.get('template_lookuppath'))
416 nifaces
.subscribe('iface_found', self
._save
_iface
)
417 nifaces
.subscribe('validateifaceattr',
418 self
._iface
_configattr
_syntax
_checker
)
419 nifaces
.subscribe('validateifaceobj', self
._ifaceobj
_syntax
_checker
)
422 def read_old_iface_config(self
):
423 """ Reads the saved iface config instead of default iface config.
424 And saved iface config is already read by the statemanager """
425 self
.ifaceobjdict
= copy
.deepcopy(self
.statemanager
.ifaceobjdict
)
427 def _load_addon_modules_config(self
):
428 """ Load addon modules config file """
430 with
open(self
.addon_modules_configfile
, 'r') as f
:
431 lines
= f
.readlines()
433 litems
= l
.rstrip(' \n\t\r').split(',')
434 operation
= litems
[0]
436 self
.module_ops
[operation
].append(mname
)
438 def load_addon_modules(self
, modules_dir
):
439 """ load python modules from modules_dir
441 Default modules_dir is /usr/share/ifupdownmodules
444 self
.logger
.info('loading builtin modules from %s' %modules_dir
)
445 self
._load
_addon
_modules
_config
()
446 if not modules_dir
in sys
.path
:
447 sys
.path
.append(modules_dir
)
449 for op
, mlist
in self
.module_ops
.items():
451 if self
.modules
.get(mname
):
453 mpath
= modules_dir
+ '/' + mname
+ '.py'
454 if os
.path
.exists(mpath
):
456 m
= __import__(mname
)
457 mclass
= getattr(m
, mname
)
460 minstance
= mclass(force
=self
.FORCE
,
463 perfmode
=self
.PERFMODE
,
465 cacheflags
=self
.CACHE_FLAGS
)
466 self
.modules
[mname
] = minstance
468 self
.module_attrs
[mname
] = minstance
.get_modinfo()
474 # Assign all modules to query operations
475 self
.module_ops
['query-checkcurr'] = self
.modules
.keys()
476 self
.module_ops
['query-running'] = self
.modules
.keys()
477 self
.module_ops
['query-dependency'] = self
.modules
.keys()
478 self
.module_ops
['query'] = self
.modules
.keys()
479 self
.module_ops
['query-raw'] = self
.modules
.keys()
482 def _modules_help(self
):
483 """ Prints addon modules supported syntax """
486 for m
, mdict
in self
.module_attrs
.items():
489 print('%s: %s' %(m
, mdict
.get('mhelp')))
490 attrdict
= mdict
.get('attrs')
494 for attrname
, attrvaldict
in attrdict
.items():
495 if attrvaldict
.get('compat', False):
497 print('%s%s' %(indent
, attrname
))
498 print('%shelp: %s' %(indent
+ ' ',
499 attrvaldict
.get('help', '')))
500 print ('%srequired: %s' %(indent
+ ' ',
501 attrvaldict
.get('required', False)))
502 default
= attrvaldict
.get('default')
504 print('%sdefault: %s' %(indent
+ ' ', default
))
506 validrange
= attrvaldict
.get('validrange')
508 print('%svalidrange: %s-%s'
509 %(indent
+ ' ', validrange
[0], validrange
[1]))
511 validvals
= attrvaldict
.get('validvals')
513 print('%svalidvals: %s'
514 %(indent
+ ' ', ','.join(validvals
)))
516 examples
= attrvaldict
.get('example')
520 print '%sexample:' %(indent
+ ' ')
522 print '%s%s' %(indent
+ ' ', e
)
527 def load_scripts(self
, modules_dir
):
528 """ loading user modules from /etc/network/.
530 Note that previously loaded python modules override modules found
531 under /etc/network if any
535 self
.logger
.info('looking for user scripts under %s' %modules_dir
)
536 for op
, mlist
in self
.script_ops
.items():
537 msubdir
= modules_dir
+ '/if-%s.d' %op
538 self
.logger
.info('loading scripts under %s ...' %msubdir
)
540 module_list
= os
.listdir(msubdir
)
541 for module
in module_list
:
542 if self
.modules
.get(module
) is not None:
544 self
.script_ops
[op
].append(
545 msubdir
+ '/' + module
)
550 def _sched_ifaces(self
, ifacenames
, ops
):
551 self
.logger
.debug('scheduling \'%s\' for %s'
552 %(str(ops
), str(ifacenames
)))
554 self
._pretty
_print
_ordered
_dict
('dependency graph',
555 self
.dependency_graph
)
556 return ifaceScheduler
.sched_ifaces(self
, ifacenames
, ops
,
557 dependency_graph
=self
.dependency_graph
,
558 order
=ifaceSchedulerFlags
.INORDER
560 else ifaceSchedulerFlags
.POSTORDER
,
561 followdependents
=True if self
.WITH_DEPENDS
else False)
563 def _validate_ifaces(self
, ifacenames
):
564 """ validates interface list for config existance.
566 returns -1 if one or more interface not found. else, returns 0
571 ifaceobjs
= self
.get_ifaceobjs(i
)
575 raise Exception('cannot find interfaces:%s' %err_iface
)
578 def _iface_whitelisted(self
, auto
, allow_classes
, excludepats
, ifacename
):
579 """ Checks if interface is whitelisted depending on set of parameters.
581 interfaces are checked against the allow_classes and auto lists.
586 for e
in excludepats
:
587 if re
.search(e
, ifacename
):
589 ifaceobjs
= self
.get_ifaceobjs(ifacename
)
591 self
.logger
.debug('iface %s' %ifacename
+ ' not found')
593 # We check classes first
597 common
= Set([allow_classes
]).intersection(
609 def _compat_conv_op_to_mode(self
, op
):
610 """ Returns old op name to work with existing scripts """
613 elif op
== 'pre-down':
618 def generate_running_env(self
, ifaceobj
, op
):
619 """ Generates a dictionary with env variables required for
620 an interface. Used to support script execution for interfaces.
624 iface_env
= ifaceobj
.env
628 cenv
.update(iface_env
)
631 cenv
['MODE'] = self
._compat
_conv
_op
_to
_mode
(op
)
634 def _save_state(self
):
635 if not self
.STATEMANAGER_ENABLE
or not self
.STATEMANAGER_UPDATE
:
638 # Update persistant iface states
639 self
.statemanager
.save_state()
641 if self
.logger
.isEnabledFor(logging
.DEBUG
):
642 t
= sys
.exc_info()[2]
643 traceback
.print_tb(t
)
644 self
.logger
.warning('error saving state (%s)' %str
(e
))
646 def up(self
, ops
, auto
=False, allow_classes
=None, ifacenames
=None,
647 excludepats
=None, printdependency
=None, syntaxcheck
=False):
648 """This brings the interface(s) up
651 ops (list): list of ops to perform on the interface(s). Eg: ['pre-up', 'up', 'post-up'
654 auto (bool): act on interfaces marked auto
655 allow_classes (list): act on interfaces belonging to classes in the list
656 ifacenames (list): act on interfaces specified in this list
657 excludepats (list): list of patterns of interfaces to exclude
658 syntaxcheck (bool): only perform syntax check
662 self
.IFACE_CLASS
= True
663 if not self
.ADDONS_ENABLE
: self
.STATEMANAGER_UPDATE
= False
666 self
.WITH_DEPENDS
= True
668 self
.read_iface_config()
672 # If only syntax check was requested, return here
677 # If iface list is given by the caller, always check if iface
679 self
._validate
_ifaces
(ifacenames
)
681 # if iface list not given by user, assume all from config file
682 if not ifacenames
: ifacenames
= self
.ifaceobjdict
.keys()
684 # filter interfaces based on auto and allow classes
685 filtered_ifacenames
= [i
for i
in ifacenames
686 if self
._iface
_whitelisted
(auto
, allow_classes
,
688 if not filtered_ifacenames
:
689 raise Exception('no ifaces found matching given allow lists')
692 self
.populate_dependency_info(ops
, filtered_ifacenames
)
693 self
.print_dependency(filtered_ifacenames
, printdependency
)
696 self
.populate_dependency_info(ops
)
699 self
._sched
_ifaces
(filtered_ifacenames
, ops
)
701 if not self
.DRYRUN
and self
.ADDONS_ENABLE
:
704 def down(self
, ops
, auto
=False, allow_classes
=None, ifacenames
=None,
705 excludepats
=None, printdependency
=None, usecurrentconfig
=False):
706 """ down an interface """
709 self
.IFACE_CLASS
= True
710 if not self
.ADDONS_ENABLE
: self
.STATEMANAGER_UPDATE
= False
713 self
.WITH_DEPENDS
= True
714 # For down we need to look at old state, unless usecurrentconfig
716 if (not usecurrentconfig
and self
.STATEMANAGER_ENABLE
and
717 self
.statemanager
.ifaceobjdict
):
718 # Since we are using state manager objects,
719 # skip the updating of state manager objects
720 self
.logger
.debug('Looking at old state ..')
721 self
.read_old_iface_config()
723 # If no old state available
725 self
.read_iface_config()
727 raise Exception('error reading iface config (%s)' %str
(e
))
729 # If iface list is given by the caller, always check if iface
732 self
._validate
_ifaces
(ifacenames
)
734 raise Exception('%s' %str
(e
) +
735 ' (interface was probably never up ?)')
737 # if iface list not given by user, assume all from config file
738 if not ifacenames
: ifacenames
= self
.ifaceobjdict
.keys()
740 # filter interfaces based on auto and allow classes
741 filtered_ifacenames
= [i
for i
in ifacenames
742 if self
._iface
_whitelisted
(auto
, allow_classes
,
744 if not filtered_ifacenames
:
745 raise Exception('no ifaces found matching given allow lists ' +
746 '(interfaces were probably never up)')
749 self
.populate_dependency_info(ops
, filtered_ifacenames
)
750 self
.print_dependency(filtered_ifacenames
, printdependency
)
753 self
.populate_dependency_info(ops
)
756 self
._sched
_ifaces
(filtered_ifacenames
, ops
)
758 if not self
.DRYRUN
and self
.ADDONS_ENABLE
:
761 def query(self
, ops
, auto
=False, allow_classes
=None, ifacenames
=None,
762 excludepats
=None, printdependency
=None,
764 """ query an interface """
767 self
.IFACE_CLASS
= True
768 if self
.STATEMANAGER_ENABLE
and ops
[0] == 'query-savedstate':
769 return self
.statemanager
.dump_pretty(ifacenames
)
770 self
.STATEMANAGER_UPDATE
= False
772 self
.logger
.debug('setting flag ALL')
774 self
.WITH_DEPENDS
= True
776 if ops
[0] == 'query-syntax':
779 elif ops
[0] == 'query-running':
780 # create fake devices to all dependents that dont have config
781 map(lambda i
: self
.create_n_save_ifaceobj(i
, self
.NOCONFIG
),
785 self
.read_iface_config()
789 if ifacenames
and ops
[0] != 'query-running':
790 # If iface list is given, always check if iface is present
791 self
._validate
_ifaces
(ifacenames
)
793 # if iface list not given by user, assume all from config file
794 if not ifacenames
: ifacenames
= self
.ifaceobjdict
.keys()
796 # filter interfaces based on auto and allow classes
797 if ops
[0] == 'query-running':
798 filtered_ifacenames
= ifacenames
800 filtered_ifacenames
= [i
for i
in ifacenames
801 if self
._iface
_whitelisted
(auto
, allow_classes
,
803 if not filtered_ifacenames
:
804 raise Exception('no ifaces found matching ' +
807 self
.populate_dependency_info(ops
, filtered_ifacenames
)
808 if ops
[0] == 'query-dependency' and printdependency
:
809 self
.print_dependency(filtered_ifacenames
, printdependency
)
812 if ops
[0] == 'query':
813 return self
.print_ifaceobjs_pretty(filtered_ifacenames
, format
)
814 elif ops
[0] == 'query-raw':
815 return self
.print_ifaceobjs_raw(filtered_ifacenames
)
817 self
._sched
_ifaces
(filtered_ifacenames
, ops
)
819 if ops
[0] == 'query-checkcurr':
820 ret
= self
.print_ifaceobjscurr_pretty(filtered_ifacenames
, format
)
822 # if any of the object has an error, signal that silently
824 elif ops
[0] == 'query-running':
825 self
.print_ifaceobjsrunning_pretty(filtered_ifacenames
, format
)
828 def reload(self
, upops
, downops
, auto
=False, allow
=None,
829 ifacenames
=None, excludepats
=None, usecurrentconfig
=False):
830 """ reload interface config """
832 new_ifaceobjdict
= {}
834 self
.logger
.debug('reloading interface config ..')
837 self
.WITH_DEPENDS
= True
840 self
.read_iface_config()
844 if not self
.ifaceobjdict
:
845 self
.logger
.warn("nothing to reload ..exiting.")
848 # generate dependency graph of interfaces
849 self
.populate_dependency_info(upops
)
850 if (not usecurrentconfig
and self
.STATEMANAGER_ENABLE
851 and self
.statemanager
.ifaceobjdict
):
852 # Save a copy of new iface objects and dependency_graph
853 new_ifaceobjdict
= dict(self
.ifaceobjdict
)
854 new_dependency_graph
= dict(self
.dependency_graph
)
856 # if old state is present, read old state and mark op for 'down'
857 # followed by 'up' aka: reload
858 # old interface config is read into self.ifaceobjdict
859 self
.read_old_iface_config()
862 # oldconfig not available, continue with 'up' with new config
865 if not ifacenames
: ifacenames
= self
.ifaceobjdict
.keys()
866 if op
== 'reload' and ifacenames
:
867 filtered_ifacenames
= [i
for i
in ifacenames
868 if self
._iface
_whitelisted
(auto
, allow_classes
,
870 # Generate the interface down list
871 # Interfaces that go into the down list:
872 # - interfaces that were present in last config and are not
873 # present in the new config
874 # - interfaces that were changed between the last and current
878 for ifname
, lastifaceobjlist
in self
.ifaceobjdict
.items():
880 # If interface is not present in the new file
881 # append it to the down list
882 newifaceobjlist
= new_ifaceobjdict
.get(ifname
)
883 if not newifaceobjlist
:
884 ifacedownlist
.append(ifname
)
886 # If interface has changed between the current file
887 # and the last installed append it to the down list
888 if len(newifaceobjlist
) != len(lastifaceobjlist
):
889 ifacedownlist
.append(ifname
)
891 # compare object list
892 for objidx
in range(0, len(lastifaceobjlist
)):
893 oldobj
= lastifaceobjlist
[objidx
]
894 newobj
= newifaceobjlist
[objidx
]
895 if not newobj
.compare(oldobj
):
896 ifacedownlist
.append(ifname
)
900 self
.logger
.info('Executing down on interfaces: %s'
902 # reinitialize dependency graph
903 self
.dependency_graph
= OrderedDict({})
904 # Generate dependency info for old config
905 self
.populate_dependency_info(downops
, ifacedownlist
)
906 self
._sched
_ifaces
(ifacedownlist
, downops
)
908 self
.logger
.debug('no interfaces to down ..')
910 # Now, run 'up' with new config dict
911 # reset statemanager update flag to default
912 if not new_ifaceobjdict
:
914 self
.ifaceobjdict
= new_ifaceobjdict
915 self
.dependency_graph
= new_dependency_graph
916 ifacenames
= self
.ifaceobjdict
.keys()
917 filtered_ifacenames
= [i
for i
in ifacenames
918 if self
._iface
_whitelisted
(auto
, allow_classes
,
921 self
.logger
.info('Scheduling up on interfaces: %s'
922 %str
(filtered_ifacenames
))
923 self
._sched
_ifaces
(filtered_ifacenames
, upops
)
928 def _pretty_print_ordered_dict(self
, prefix
, argdict
):
929 outbuf
= prefix
+ ' {\n'
930 for k
, vlist
in argdict
.items():
931 outbuf
+= '\t%s : %s\n' %(k
, str(vlist
))
932 self
.logger
.debug(outbuf
+ '}')
934 def print_dependency(self
, ifacenames
, format
):
935 """ prints iface dependency information """
938 ifacenames
= self
.ifaceobjdict
.keys()
940 for k
,v
in self
.dependency_graph
.items():
941 print '%s : %s' %(k
, str(v
))
942 elif format
== 'dot':
944 map(lambda i
: indegrees
.update({i
:
945 self
.get_iface_refcnt(i
)}),
946 self
.dependency_graph
.keys())
947 graph
.generate_dots(self
.dependency_graph
, indegrees
)
949 def print_ifaceobjs_raw(self
, ifacenames
):
950 """ prints raw lines for ifaces from config file """
953 for ifaceobj
in self
.get_ifaceobjs(i
):
954 if (self
.is_ifaceobj_builtin(ifaceobj
) or
955 not ifaceobj
.is_config_present()):
957 ifaceobj
.dump_raw(self
.logger
)
959 if self
.WITH_DEPENDS
and not self
.ALL
:
960 dlist
= ifaceobj
.lowerifaces
961 if not dlist
: continue
962 self
.print_ifaceobjs_raw(dlist
)
964 def _get_ifaceobjs_pretty(self
, ifacenames
, ifaceobjs
, running
=False):
965 """ returns iface obj list """
968 for ifaceobj
in self
.get_ifaceobjs(i
):
969 if ((not running
and self
.is_ifaceobj_noconfig(ifaceobj
)) or
970 (running
and not ifaceobj
.is_config_present())):
972 ifaceobjs
.append(ifaceobj
)
973 if self
.WITH_DEPENDS
and not self
.ALL
:
974 dlist
= ifaceobj
.lowerifaces
975 if not dlist
: continue
976 self
._get
_ifaceobjs
_pretty
(dlist
, ifaceobjs
, running
)
978 def print_ifaceobjs_pretty(self
, ifacenames
, format
='native'):
979 """ pretty prints iface in format given by keyword arg format """
982 self
._get
_ifaceobjs
_pretty
(ifacenames
, ifaceobjs
)
983 if not ifaceobjs
: return
985 print json
.dumps(ifaceobjs
, cls
=ifaceJsonEncoder
,
986 indent
=4, separators
=(',', ': '))
988 map(lambda i
: i
.dump_pretty(), ifaceobjs
)
990 def _get_ifaceobjscurr_pretty(self
, ifacenames
, ifaceobjs
):
993 ifaceobjscurr
= self
.get_ifaceobjcurr(i
)
994 if not ifaceobjscurr
: continue
995 for ifaceobj
in ifaceobjscurr
:
996 if (ifaceobj
.status
== ifaceStatus
.NOTFOUND
or
997 ifaceobj
.status
== ifaceStatus
.ERROR
):
999 if self
.is_ifaceobj_noconfig(ifaceobj
):
1001 ifaceobjs
.append(ifaceobj
)
1002 if self
.WITH_DEPENDS
and not self
.ALL
:
1003 dlist
= ifaceobj
.lowerifaces
1004 if not dlist
: continue
1005 dret
= self
._get
_ifaceobjscurr
_pretty
(dlist
, ifaceobjs
)
1009 def print_ifaceobjscurr_pretty(self
, ifacenames
, format
='native'):
1010 """ pretty prints current running state of interfaces with status.
1012 returns 1 if any of the interface has an error,
1017 ret
= self
._get
_ifaceobjscurr
_pretty
(ifacenames
, ifaceobjs
)
1018 if not ifaceobjs
: return
1019 self
.logger
.debug(ifaceobjs
)
1020 if format
== 'json':
1021 print json
.dumps(ifaceobjs
, cls
=ifaceJsonEncoder
, indent
=2,
1022 separators
=(',', ': '))
1024 map(lambda i
: i
.dump_pretty(with_status
=True,
1025 successstr
=self
.config
.get('check_success_str',
1027 errorstr
=self
.config
.get('check_error_str', _error_sym
)),
1031 def print_ifaceobjsrunning_pretty(self
, ifacenames
, format
='native'):
1032 """ pretty prints iface running state """
1035 self
._get
_ifaceobjs
_pretty
(ifacenames
, ifaceobjs
, running
=True)
1036 if not ifaceobjs
: return
1037 if format
== 'json':
1038 print json
.dumps(ifaceobjs
, cls
=ifaceJsonEncoder
, indent
=2,
1039 separators
=(',', ': '))
1041 map(lambda i
: i
.dump_pretty(), ifaceobjs
)
1044 print 'ifupdown main object dump'
1045 print self
.pp
.pprint(self
.modules
)
1046 print self
.pp
.pprint(self
.ifaceobjdict
)
1048 def _dump_ifaceobjs(self
, ifacenames
):
1049 for i
in ifacenames
:
1050 ifaceobjs
= self
.get_ifaceobjs(i
)