3 # Copyright 2013. Cumulus Networks, Inc.
4 # Author: Roopa Prabhu, roopa@cumulusnetworks.com
16 from statemanager
import *
17 from networkinterfaces
import *
19 from scheduler
import *
20 from collections
import deque
21 from collections
import OrderedDict
25 class ifupdownMain(ifupdownBase
):
30 COMPAT_EXEC_SCRIPTS
= False
31 STATEMANAGER_ENABLE
= True
32 STATEMANAGER_UPDATE
= True
35 # priv flags to mark iface objects
39 scripts_dir
='/etc/network'
40 addon_modules_dir
='/usr/share/ifupdownaddons'
41 addon_modules_configfile
='/etc/network/.addons.conf'
43 # iface dictionary in the below format:
44 # { '<ifacename>' : [<ifaceobject1>, <ifaceobject2> ..] }
46 # { 'swp1' : [<ifaceobject1>, <ifaceobject2> ..] }
48 # Each ifaceobject corresponds to a configuration block for
50 ifaceobjdict
= OrderedDict()
53 # iface dictionary representing the curr running state of an iface
54 # in the below format:
55 # {'<ifacename>' : <ifaceobject>}
56 ifaceobjcurrdict
= OrderedDict()
58 # Dictionary representing operation and modules
60 module_ops
= OrderedDict([('pre-up', []),
63 ('query-checkcurr', []),
64 ('query-running', []),
65 ('query-dependency', []),
72 # For old style /etc/network/ bash scripts
73 script_ops
= OrderedDict([('pre-up', []),
80 # Handlers for ops that ifupdown2 owns
81 def run_up(self
, ifaceobj
):
82 ifacename
= ifaceobj
.get_name()
83 if self
.link_exists(ifacename
):
84 self
.link_up(ifacename
)
86 def run_down(self
, ifaceobj
):
87 ifacename
= ifaceobj
.get_name()
88 if self
.link_exists(ifacename
):
89 self
.link_down(ifacename
)
91 # ifupdown object interface operation handlers
92 ops_handlers
= OrderedDict([('up', run_up
),
95 def run_sched_ifaceobj_posthook(self
, ifaceobj
):
96 if ((ifaceobj
.priv_flags
& self
.BUILTIN
) or
97 (ifaceobj
.priv_flags
& self
.NOCONFIG
)):
99 if self
.STATEMANAGER_UPDATE
:
100 self
.statemanager
.ifaceobj_sync(ifaceobj
)
102 # ifupdown object interface scheduler pre and posthooks
103 sched_hooks
= {'posthook' : run_sched_ifaceobj_posthook
}
105 def __init__(self
, force
=False, dryrun
=False, nowait
=False,
106 perfmode
=False, withdepends
=False, njobs
=1,
107 cache
=False, addons_enable
=True, statemanager_enable
=True):
108 self
.logger
= logging
.getLogger('ifupdown')
112 self
.PERFMODE
= perfmode
113 self
.WITH_DEPENDS
= withdepends
114 self
.STATEMANAGER_ENABLE
= statemanager_enable
117 # Can be used to provide hints for caching
118 self
.CACHE_FLAGS
= 0x0
119 self
._DELETE
_DEPENDENT
_IFACES
_WITH
_NOCONFIG
= False
120 self
.ADDONS_ENABLE
= addons_enable
122 self
.ifaces
= OrderedDict()
124 self
.pp
= pprint
.PrettyPrinter(indent
=4)
125 self
.modules
= OrderedDict({})
126 self
.module_attrs
= {}
128 self
.load_addon_modules(self
.addon_modules_dir
)
129 if self
.COMPAT_EXEC_SCRIPTS
:
130 self
.load_scripts(self
.scripts_dir
)
131 self
.dependency_graph
= OrderedDict({})
133 if self
.STATEMANAGER_ENABLE
:
135 self
.statemanager
= stateManager()
136 self
.statemanager
.read_saved_state()
138 # XXX Maybe we should continue by ignoring old state
139 self
.logger
.warning('error reading state (%s)' %str
(e
))
142 self
.STATEMANAGER_UPDATE
= False
144 def get_subops(self
, op
):
145 """ Returns sub-operation list """
146 return self
.module_ops
.get(op
).keys()
148 def compat_conv_op_to_mode(self
, op
):
149 """ Returns old op name to work with existing scripts """
152 elif op
== 'pre-down':
157 def set_force(self
, force
):
158 """ Set force flag. """
162 """ return force flag. """
165 def set_dryrun(self
, dryrun
):
168 def get_dryrun(self
):
174 def get_ifaceobjdict(self
):
175 return self
.ifaceobjdict
177 def set_ifaceobjdict(self
, ifaceobjdict
):
178 self
.ifaceobjdict
= ifaceobjdict
180 def set_dependency_graph(self
, dependency_graph
):
181 self
.dependency_graph
= dependency_graph
183 def get_dependency_graph(self
):
184 return self
.dependency_graph
186 def set_perfmode(self
, perfmode
):
187 self
.PERFMODE
= perfmode
189 def get_perfmode(self
):
192 def set_nowait(self
, nowait
):
195 def get_nowait(self
):
198 def set_njobs(self
, njobs
):
199 self
.logger
.debug('setting njobs to %d' %njobs
)
205 def get_withdepends(self
):
206 return self
.WITH_DEPENDS
208 def set_withdepends(self
, withdepends
):
209 self
.logger
.debug('setting withdepends to true')
210 self
.WITH_DEPENDS
= withdepends
212 def get_ifaceobjs(self
, ifacename
):
213 return self
.ifaceobjdict
.get(ifacename
)
215 def get_ifaceobj_first(self
, ifacename
):
216 ifaceobjs
= self
.get_ifaceobjs(ifacename
)
221 def get_ifacenames(self
):
222 return self
.ifaceobjdict
.keys()
224 def get_iface_obj_last(self
, ifacename
):
225 return self
.ifaceobjdict
.get(ifacename
)[-1]
227 def create_n_save_ifaceobjcurr(self
, ifaceobj
):
228 ifacename
= ifaceobj
.get_name()
229 ifaceobjcurr
= self
.get_ifaceobjcurr(ifacename
)
233 ifaceobjcurr
= iface()
234 ifaceobjcurr
.set_name(ifacename
)
235 ifaceobjcurr
.set_lowerifaces(ifaceobj
.get_lowerifaces())
236 ifaceobjcurr
.set_priv_flags(ifaceobj
.get_priv_flags())
237 self
.ifaceobjcurrdict
[ifacename
] = ifaceobjcurr
241 def get_ifaceobjcurr(self
, ifacename
):
242 return self
.ifaceobjcurrdict
.get(ifacename
)
244 def get_ifaceobjrunning(self
, ifacename
):
245 return self
.ifaceobjrunningdict
.get(ifacename
)
247 def get_iface_status(self
, ifacename
):
248 ifaceobjs
= self
.get_ifaceobjs(ifacename
)
250 if i
.get_status() != ifaceStatus
.SUCCESS
:
251 return i
.get_status()
252 return ifaceStatus
.SUCCESS
254 def get_iface_refcnt(self
, ifacename
):
256 ifaceobjs
= self
.get_ifaceobjs(ifacename
)
260 if i
.get_refcnt() > max:
264 def create_n_save_ifaceobj(self
, ifacename
, priv_flags
=None,
266 """ creates and returns a fake vlan iface object.
267 This was added to support creation of simple vlan
268 devices without any user specified configuration.
271 ifaceobj
.set_name(ifacename
)
272 ifaceobj
.priv_flags
= priv_flags
275 ifaceobj
.inc_refcnt()
276 self
.ifaceobjdict
[ifacename
] = [ifaceobj
]
280 def is_iface_builtin_byname(self
, ifacename
):
281 """ Returns true if iface name is a builtin interface.
283 A builtin interface is an interface which ifupdown understands.
284 The following are currently considered builtin ifaces:
285 - vlan interfaces in the format <ifacename>.<vlanid>
287 return '.' in ifacename
289 def is_ifaceobj_builtin(self
, ifaceobj
):
290 """ Returns true if iface name is a builtin interface.
292 A builtin interface is an interface which ifupdown understands.
293 The following are currently considered builtin ifaces:
294 - vlan interfaces in the format <ifacename>.<vlanid>
296 return (ifaceobj
.priv_flags
& self
.BUILTIN
)
298 def is_ifaceobj_noconfig(self
, ifaceobj
):
299 """ Returns true if iface name did not have a user defined config.
301 These interfaces appear only when they are dependents of interfaces
302 which have user defined config
304 return (ifaceobj
.priv_flags
& self
.NOCONFIG
)
306 def is_iface_noconfig(self
, ifacename
):
307 """ Returns true if iface has no config """
309 ifaceobj
= self
.get_ifaceobj_first(ifacename
)
310 if not ifaceobj
: return True
312 return self
.is_ifaceobj_noconfig(ifaceobj
)
314 def preprocess_dependency_list(self
, upperifacename
, dlist
, ops
):
315 """ We go through the dependency list and
316 delete or add interfaces from the interfaces dict by
317 applying the following rules:
318 if flag _DELETE_DEPENDENT_IFACES_WITH_NOCONFIG is True:
319 we only consider devices whose configuration was
320 specified in the network interfaces file. We delete
321 any interface whose config was not specified except
322 for vlan devices. vlan devices get special treatment.
323 Even if they are not present they are created and added
325 elif flag _DELETE_DEPENDENT_IFACES_WITH_NOCONFIG is False:
326 we create objects for all dependent devices that are not
327 present in the ifacesdict
332 dilist
= self
.get_ifaceobjs(d
)
334 if self
.is_iface_builtin_byname(d
):
335 self
.create_n_save_ifaceobj(d
, self
.BUILTIN | self
.NOCONFIG
,
336 True).add_to_upperifaces(upperifacename
)
337 elif not self
._DELETE
_DEPENDENT
_IFACES
_WITH
_NOCONFIG
:
338 self
.create_n_save_ifaceobj(d
, self
.NOCONFIG
,
339 True).add_to_upperifaces(upperifacename
)
345 di
.add_to_upperifaces(upperifacename
)
350 def query_dependents(self
, ifaceobj
, ops
):
351 """ Gets iface dependents by calling into respective modules """
354 # Get dependents for interface by querying respective modules
355 for mname
, module
in self
.modules
.items():
356 module
= self
.modules
.get(mname
)
357 if ops
[0] == 'query-running':
358 if (not hasattr(module
,
359 'get_dependent_ifacenames_running')):
361 dlist
= module
.get_dependent_ifacenames_running(ifaceobj
)
363 if (not hasattr(module
, 'get_dependent_ifacenames')):
365 dlist
= module
.get_dependent_ifacenames(ifaceobj
,
366 self
.ifaceobjdict
.keys())
368 self
.logger
.debug('%s: ' %ifaceobj
.get_name() +
369 'got lowerifaces/dependents: %s' %str
(dlist
))
373 def populate_dependency_info(self
, ops
, ifacenames
=None):
374 """ recursive function to generate iface dependency info """
377 ifacenames
= self
.ifaceobjdict
.keys()
379 self
.logger
.debug('populating dependency info for %s' %str
(ifacenames
))
380 iqueue
= deque(ifacenames
)
383 # Go through all modules and find dependent ifaces
385 ifaceobj
= self
.get_ifaceobj_first(i
)
388 dlist
= ifaceobj
.get_lowerifaces()
390 dlist
= self
.query_dependents(ifaceobj
, ops
)
394 self
.preprocess_dependency_list(ifaceobj
.get_name(),
396 self
.logger
.debug('%s: lowerifaces/dependents after processing: %s'
398 ifaceobj
.set_lowerifaces(dlist
)
399 [iqueue
.append(d
) for d
in dlist
]
400 if not self
.dependency_graph
.get(i
):
401 self
.dependency_graph
[i
] = dlist
403 def _save_iface(self
, ifaceobj
):
404 if not self
.ifaceobjdict
.get(ifaceobj
.get_name()):
405 self
.ifaceobjdict
[ifaceobj
.get_name()] = [ifaceobj
]
407 self
.ifaceobjdict
[ifaceobj
.get_name()].append(ifaceobj
)
409 def _module_syntax_checker(self
, attrname
, attrval
):
410 for m
, mdict
in self
.module_attrs
.items():
411 attrsdict
= mdict
.get('attrs')
412 if attrsdict
and attrname
in attrsdict
.keys(): return True
415 def read_default_iface_config(self
):
416 """ Reads default network interface config /etc/network/interfaces. """
417 nifaces
= networkInterfaces()
418 nifaces
.subscribe('iface_found', self
._save
_iface
)
419 nifaces
.subscribe('validate', self
._module
_syntax
_checker
)
422 def read_iface_config(self
):
423 return self
.read_default_iface_config()
425 def read_old_iface_config(self
):
426 """ Reads the saved iface config instead of default iface config. """
428 # Read it from the statemanager
429 self
.ifaceobjdict
= self
.statemanager
.get_ifaceobjdict()
431 def load_addon_modules_config(self
):
432 with
open(self
.addon_modules_configfile
, 'r') as f
:
433 lines
= f
.readlines()
435 litems
= l
.rstrip(' \n').split(',')
436 operation
= litems
[0]
438 self
.module_ops
[operation
].append(mname
)
440 def load_addon_modules(self
, modules_dir
):
441 """ load python modules from modules_dir
443 Default modules_dir is /usr/share/ifupdownmodules
446 self
.logger
.info('loading builtin modules from %s' %modules_dir
)
447 self
.load_addon_modules_config()
448 if not modules_dir
in sys
.path
:
449 sys
.path
.append(modules_dir
)
451 for op
, mlist
in self
.module_ops
.items():
453 if self
.modules
.get(mname
) is not None:
455 mpath
= modules_dir
+ '/' + mname
+ '.py'
456 if os
.path
.exists(mpath
):
458 m
= __import__(mname
)
459 mclass
= getattr(m
, mname
)
462 minstance
= mclass(force
=self
.FORCE
,
465 perfmode
=self
.PERFMODE
,
467 cacheflags
=self
.CACHE_FLAGS
)
468 self
.modules
[mname
] = minstance
469 if hasattr(minstance
, 'get_modinfo'):
470 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()
481 def modules_help(self
):
483 for m
, mdict
in self
.module_attrs
.items():
486 print('%s: %s' %(m
, mdict
.get('mhelp')))
487 attrdict
= mdict
.get('attrs')
491 for attrname
, attrvaldict
in attrdict
.items():
492 if attrvaldict
.get('compat', False):
494 print('%s%s' %(indent
, attrname
))
495 print('%shelp: %s' %(indent
+ ' ',
496 attrvaldict
.get('help', '')))
497 print ('%srequired: %s' %(indent
+ ' ',
498 attrvaldict
.get('required', False)))
499 default
= attrvaldict
.get('default')
501 print('%sdefault: %s' %(indent
+ ' ', default
))
503 validrange
= attrvaldict
.get('validrange')
505 print('%svalidrange: %s'
506 %(indent
+ ' ', '-'.join(validrange
)))
508 validvals
= attrvaldict
.get('validvals')
510 print('%svalidvals: %s'
511 %(indent
+ ' ', ','.join(validvals
)))
513 examples
= attrvaldict
.get('example')
517 print '%sexample:' %(indent
+ ' ')
519 print '%s%s' %(indent
+ ' ', e
)
524 def load_scripts(self
, modules_dir
):
525 """ loading user modules from /etc/network/.
527 Note that previously loaded python modules override modules found
528 under /etc/network if any
532 self
.logger
.info('looking for user scripts under %s' %modules_dir
)
533 for op
, mlist
in self
.script_ops
.items():
534 msubdir
= modules_dir
+ '/if-%s.d' %op
535 self
.logger
.info('loading scripts under %s ...' %msubdir
)
537 module_list
= os
.listdir(msubdir
)
538 for module
in module_list
:
539 if self
.modules
.get(module
) is not None:
541 self
.script_ops
[op
].append(
542 msubdir
+ '/' + module
)
547 def conv_iface_namelist_to_objlist(self
, intf_list
):
548 for intf
in intf_list
:
549 iface_obj
= self
.get_iface(intf
)
551 raise ifupdownInvalidValue('no iface %s', intf
)
552 iface_objs
.append(iface_obj
)
555 def _pretty_print_ordered_dict(self
, argdict
):
556 for k
, vlist
in argdict
.items():
557 self
.logger
.info('%s : %s' %(k
, str(vlist
)))
559 def sched_ifaces(self
, ifacenames
, ops
):
560 self
.logger
.debug('scheduling \'%s\' for %s'
561 %(str(ops
), str(ifacenames
)))
563 self
.logger
.info('dependency graph:')
564 self
._pretty
_print
_ordered
_dict
(self
.dependency_graph
)
566 return ifaceScheduler
.sched_ifaces(self
, ifacenames
, ops
,
567 dependency_graph
=self
.dependency_graph
,
568 order
=ifaceSchedulerFlags
.INORDER
570 else ifaceSchedulerFlags
.POSTORDER
,
571 followdependents
=True if self
.WITH_DEPENDS
else False)
573 def print_dependency(self
, ifacenames
, format
):
575 ifacenames
= self
.ifaceobjdict
.keys()
578 for k
,v
in self
.dependency_graph
.items():
579 print '%s : %s' %(k
, str(v
))
580 elif format
== 'dot':
582 map(lambda i
: indegrees
.update({i
:
583 self
.get_iface_refcnt(i
)}),
584 self
.dependency_graph
.keys())
585 graph
.generate_dots(self
.dependency_graph
, indegrees
)
587 def validate_ifaces(self
, ifacenames
):
588 """ validates interface list for config existance.
590 returns -1 if one or more interface not found. else, returns 0
595 ifaceobjs
= self
.get_ifaceobjs(i
)
599 self
.logger
.error('could not find interfaces: %s' %err_iface
)
603 def iface_whitelisted(self
, auto
, allow_classes
, excludepats
, ifacename
):
604 """ Checks if interface is whitelisted depending on set of parameters.
606 interfaces are checked against the allow_classes and auto lists.
609 # If the interface matches
611 for e
in excludepats
:
612 if re
.search(e
, ifacename
):
614 ifaceobjs
= self
.get_ifaceobjs(ifacename
)
616 self
.logger
.debug('iface %s' %ifacename
+ ' not found')
618 # We check classes first
622 common
= Set([allow_classes
]).intersection(
623 Set(i
.get_classes()))
634 def generate_running_env(self
, ifaceobj
, op
):
635 """ Generates a dictionary with env variables required for
636 an interface. Used to support script execution for interfaces.
640 iface_env
= ifaceobj
.get_env()
641 if iface_env
is not None:
644 cenv
.update(iface_env
)
647 cenv
['MODE'] = self
.compat_conv_op_to_mode(op
)
650 def save_state(self
):
651 if not self
.STATEMANAGER_ENABLE
or not self
.STATEMANAGER_UPDATE
:
654 # Update persistant iface states
655 self
.statemanager
.save_state()
657 if self
.logger
.isEnabledFor(logging
.DEBUG
):
658 t
= sys
.exc_info()[2]
659 traceback
.print_tb(t
)
660 self
.logger
.warning('error saving state (%s)' %str
(e
))
662 def up(self
, ops
, auto
=False, allow_classes
=None, ifacenames
=None,
663 excludepats
=None, printdependency
=None):
666 self
.WITH_DEPENDS
= True
669 self
.read_iface_config()
674 # If iface list is given by the caller, always check if iface
676 if self
.validate_ifaces(ifacenames
) != 0:
677 raise Exception('all or some interfaces not found')
679 # if iface list not given by user, assume all from config file
680 if not ifacenames
: ifacenames
= self
.ifaceobjdict
.keys()
682 # filter interfaces based on auto and allow classes
683 filtered_ifacenames
= [i
for i
in ifacenames
684 if self
.iface_whitelisted(auto
, allow_classes
,
686 if not filtered_ifacenames
:
687 raise Exception('no ifaces found matching given allow lists')
690 self
.populate_dependency_info(ops
, filtered_ifacenames
)
691 self
.print_dependency(filtered_ifacenames
, printdependency
)
694 self
.populate_dependency_info(ops
)
696 self
.sched_ifaces(filtered_ifacenames
, ops
)
698 if self
.DRYRUN
and self
.ADDONS_ENABLE
:
703 def down(self
, ops
, auto
=False, allow_classes
=None, ifacenames
=None,
704 excludepats
=None, printdependency
=None, usecurrentconfig
=False):
705 if self
.ADDONS_ENABLE
: self
.STATEMANAGER_UPDATE
= False
708 self
.WITH_DEPENDS
= True
709 # For down we need to look at old state, unless usecurrentconfig
711 if (not usecurrentconfig
and self
.STATEMANAGER_ENABLE
and
712 self
.statemanager
.get_ifaceobjdict()):
713 # Since we are using state manager objects,
714 # skip the updating of state manager objects
715 self
.STATEMANAGER_UPDATE
= False
716 self
.logger
.debug('Looking at old state ..')
717 self
.read_old_iface_config()
719 # If no old state available
720 self
.logger
.info('Loading current iface config file')
722 self
.read_iface_config()
724 raise Exception('error reading iface config (%s)' %str
(e
))
726 # If iface list is given by the caller, always check if iface
728 if self
.validate_ifaces(ifacenames
) != 0:
729 raise Exception('all or some interfaces not found')
730 # if iface list not given by user, assume all from config file
731 if not ifacenames
: ifacenames
= self
.ifaceobjdict
.keys()
732 # filter interfaces based on auto and allow classes
733 filtered_ifacenames
= [i
for i
in ifacenames
734 if self
.iface_whitelisted(auto
, allow_classes
,
736 if not filtered_ifacenames
:
737 raise Exception('no ifaces found matching given allow lists')
740 self
.populate_dependency_info(ops
, filtered_ifacenames
)
741 self
.print_dependency(filtered_ifacenames
, printdependency
)
744 self
.populate_dependency_info(ops
)
746 self
.sched_ifaces(filtered_ifacenames
, ops
)
747 if self
.DRYRUN
and self
.ADDONS_ENABLE
:
752 def query(self
, ops
, auto
=False, allow_classes
=None, ifacenames
=None,
753 excludepats
=None, printdependency
=None,
755 if self
.STATEMANAGER_ENABLE
and ops
[0] == 'query-savedstate':
756 return self
.statemanager
.dump_pretty(ifacenames
)
758 self
.STATEMANAGER_UPDATE
= False
760 self
.logger
.debug('setting flag ALL')
762 self
.WITH_DEPENDS
= True
764 if ops
[0] == 'query-syntax':
767 elif ops
[0] == 'query-running':
768 # create fake devices to all dependents that dont have config
769 map(lambda i
: self
.create_n_save_ifaceobj(i
, self
.NOCONFIG
),
773 self
.read_iface_config()
777 if ifacenames
is not None and ops
[0] != 'query-running':
778 # If iface list is given, always check if iface is present
779 if self
.validate_ifaces(ifacenames
) != 0:
780 raise Exception('all or some interfaces not found')
782 # if iface list not given by user, assume all from config file
783 if not ifacenames
: ifacenames
= self
.ifaceobjdict
.keys()
785 # filter interfaces based on auto and allow classes
786 if ops
[0] == 'query-running':
787 filtered_ifacenames
= ifacenames
789 filtered_ifacenames
= [i
for i
in ifacenames
790 if self
.iface_whitelisted(auto
, allow_classes
,
792 if not filtered_ifacenames
:
793 raise Exception('no ifaces found matching ' +
796 if ops
[0] == 'query-dependency' and printdependency
:
797 self
.populate_dependency_info(ops
, filtered_ifacenames
)
798 self
.print_dependency(filtered_ifacenames
, printdependency
)
801 self
.populate_dependency_info(ops
)
803 if ops
[0] == 'query':
804 return self
.print_ifaceobjs_pretty(filtered_ifacenames
, format
)
805 elif ops
[0] == 'query-raw':
806 return self
.print_ifaceobjs_raw(filtered_ifacenames
)
808 self
.sched_ifaces(filtered_ifacenames
, ops
)
810 if ops
[0] == 'query-checkcurr':
811 ret
= self
.print_ifaceobjscurr_pretty(filtered_ifacenames
, format
)
813 # if any of the object has an error, signal that silently
815 elif ops
[0] == 'query-running':
816 self
.print_ifaceobjsrunning_pretty(filtered_ifacenames
, format
)
819 def reload(self
, upops
, downops
, auto
=False, allow
=None,
820 ifacenames
=None, excludepats
=None, downchangediface
=False):
821 """ main ifupdown run method """
824 self
.logger
.debug('reloading interface config ..')
827 self
.WITH_DEPENDS
= True
830 # Read the current interface config
831 self
.read_iface_config()
835 # generate dependency graph of interfaces
836 self
.populate_dependency_info(upops
)
838 # Save a copy of new iface objects and dependency_graph
839 new_ifaceobjdict
= dict(self
.get_ifaceobjdict())
840 new_dependency_graph
= dict(self
.get_dependency_graph())
842 if self
.STATEMANAGER_ENABLE
and self
.statemanager
.get_ifaceobjdict():
843 # if old state is present, read old state and mark op for 'down'
844 # followed by 'up' aka: reload
845 # old interface config is read into self.ifaceobjdict
847 self
.STATEMANAGER_UPDATE
= False
848 self
.read_old_iface_config()
851 # oldconfig not available, continue with 'up' with new config
854 if not ifacenames
: ifacenames
= self
.ifaceobjdict
.keys()
855 if op
== 'reload' and ifacenames
:
856 filtered_ifacenames
= [i
for i
in ifacenames
857 if self
.iface_whitelisted(auto
, allow_classes
,
859 # Generate the interface down list
860 # Interfaces that go into the down list:
861 # - interfaces that were present in last config and are not
862 # present in the new config
863 # - interfaces that were changed between the last and current
867 for ifname
, lastifobjlist
in self
.ifaceobjdict
.items():
869 # If interface is not present in the new file
870 # append it to the down list
871 newifobjlist
= new_ifaceobjdict
.get(ifname
)
873 ifacedownlist
.append(ifname
)
875 if not downchangediface
:
877 # If interface has changed between the current file
878 # and the last installed append it to the down list
879 if len(newifobjlist
) != len(lastifobjlist
):
880 ifacedownlist
.append(ifname
)
882 # compare object list
883 for objidx
in range(0, len(lastifobjlist
)):
884 oldobj
= lastifobjlist
[objidx
]
885 newobj
= newifobjlist
[objidx
]
886 if newobj
.is_different(oldobj
):
887 ifacedownlist
.append(ifname
)
891 self
.logger
.info('Executing down on interfaces: %s'
893 # reinitialize dependency graph
894 self
.dependency_graph
= OrderedDict({})
895 # Generate dependency info for old config
896 self
.populate_dependency_info(downops
)
897 self
.sched_ifaces(ifacedownlist
, downops
)
899 self
.logger
.debug('no interfaces to down ..')
901 # Now, run 'up' with new config dict
902 # reset statemanager update flag to default
903 self
.STATEMANAGER_UPDATE
= True
904 self
.set_ifaceobjdict(new_ifaceobjdict
)
905 self
.set_dependency_graph(new_dependency_graph
)
906 ifacenames
= self
.ifaceobjdict
.keys()
907 filtered_ifacenames
= [i
for i
in ifacenames
908 if self
.iface_whitelisted(auto
, allow_classes
,
910 self
.logger
.info('Executing up on interfaces: %s'
911 %str
(filtered_ifacenames
))
913 self
.sched_ifaces(filtered_ifacenames
, upops
)
920 """ all state dump """
922 print 'ifupdown object dump'
923 print self
.pp
.pprint(self
.modules
)
924 print self
.pp
.pprint(self
.ifaceobjdict
)
925 #self.state_manager.dump()
927 def print_state(self
, ifacenames
=None):
928 self
.statemanager
.dump(ifacenames
)
930 def print_ifaceobjs_raw(self
, ifacenames
):
932 for ifaceobj
in self
.get_ifaceobjs(i
):
933 if (self
.is_ifaceobj_builtin(ifaceobj
) or
934 not ifaceobj
.is_config_present()):
936 ifaceobj
.dump_raw(self
.logger
)
938 if self
.WITH_DEPENDS
:
939 dlist
= ifaceobj
.get_lowerifaces()
940 if not dlist
: continue
941 self
.print_ifaceobjs_pretty(dlist
, format
)
943 def print_ifaceobjs_pretty(self
, ifacenames
, format
='native'):
945 for ifaceobj
in self
.get_ifaceobjs(i
):
946 if (self
.is_ifaceobj_noconfig(ifaceobj
)):
951 ifaceobj
.dump_pretty()
952 if self
.WITH_DEPENDS
:
953 dlist
= ifaceobj
.get_lowerifaces()
954 if not dlist
: continue
955 self
.print_ifaceobjs_pretty(dlist
, format
)
957 def dump_ifaceobjs(self
, ifacenames
):
959 ifaceobjs
= self
.get_ifaceobjs(i
)
964 def print_ifaceobjscurr_pretty(self
, ifacenames
, format
='native'):
965 """ Dumps current running state of interfaces.
967 returns 1 if any of the interface has an error,
972 ifaceobj
= self
.get_ifaceobjcurr(i
)
973 if not ifaceobj
: continue
974 if ifaceobj
.get_status() == ifaceStatus
.NOTFOUND
:
975 print 'iface %s %s\n' %(ifaceobj
.get_name(),
976 ifaceStatus
.to_str(ifaceStatus
.NOTFOUND
))
979 elif ifaceobj
.get_status() == ifaceStatus
.ERROR
:
982 if (self
.is_ifaceobj_noconfig(ifaceobj
)):
986 ifaceobj
.dump_json(with_status
=True)
988 ifaceobj
.dump_pretty(with_status
=True)
990 if self
.WITH_DEPENDS
:
991 dlist
= ifaceobj
.get_lowerifaces()
992 if not dlist
: continue
993 self
.print_ifaceobjscurr_pretty(dlist
, format
)
996 def print_ifaceobjsrunning_pretty(self
, ifacenames
, format
='native'):
998 ifaceobj
= self
.get_ifaceobj_first(i
)
999 if ifaceobj
.get_status() == ifaceStatus
.NOTFOUND
:
1000 print 'iface %s' %ifaceobj
.get_name() + ' (not found)\n'
1002 if not ifaceobj
.is_config_present():
1004 if format
== 'json':
1005 ifaceobj
.dump_json()
1007 ifaceobj
.dump_pretty()
1008 if self
.WITH_DEPENDS
:
1009 dlist
= ifaceobj
.get_lowerifaces()
1010 if not dlist
: continue
1011 self
.print_ifaceobjsrunning_pretty(dlist
, format
)