From 5c72192578d4ef500c5299203be9cb8d51b45188 Mon Sep 17 00:00:00 2001 From: roopa Date: Thu, 6 Mar 2014 06:41:28 -0800 Subject: [PATCH] A few state manager optimizations + and some other fixes Ticket: CM-1438 Reviewed By: Testing Done: This also fixes a bug with address handling: - If the user changed a primary address, flush all the addresses and re-add them. Previously, if user added a new primary address, it would ust get appended to the end of the address list as a secondary address. --- pkg/iface.py | 23 ++++++++++++---------- pkg/ifupdownmain.py | 42 ++++++++++++--------------------------- pkg/statemanager.py | 48 +++++++++++++++++++-------------------------- sbin/ifupdown | 24 ++++++++++++++++++----- 4 files changed, 64 insertions(+), 73 deletions(-) diff --git a/pkg/iface.py b/pkg/iface.py index a892196..ee6e5ea 100644 --- a/pkg/iface.py +++ b/pkg/iface.py @@ -107,7 +107,6 @@ class ifaceState(): elif state_str == 'query-running': return cls.QUERY_RUNNING - class ifaceJsonEncoder(json.JSONEncoder): def default(self, o): retconfig = {} @@ -139,7 +138,6 @@ class iface(): self.config_status = {} self.state = ifaceState.NEW self.status = ifaceStatus.UNKNOWN - self.errstr = '' self.flags = 0x0 self.priv_flags = 0x0 self.refcnt = 0 @@ -148,7 +146,6 @@ class iface(): self.auto = False self.classes = [] self.env = None - self.config_current = {} self.raw_lines = [] self.linkstate = None @@ -199,12 +196,6 @@ class iface(): else: return True - def set_config_current(self, config_current): - self.config_current = config_current - - def get_config_current(self): - return self.config_current - def get_auto(self): return self.auto @@ -228,7 +219,6 @@ class iface(): def belongs_to_class(self, intfclass): if intfclass in self.classes: return True - return False def set_priv_flags(self, priv_flags): @@ -393,15 +383,28 @@ class iface(): del odict['status'] del odict['lowerifaces'] del odict['refcnt'] + del odict['config_status'] + del odict['flags'] + del odict['priv_flags'] + del odict['upperifaces'] + del odict['raw_lines'] + del odict['linkstate'] + del odict['env'] return odict def __setstate__(self, dict): self.__dict__.update(dict) + self.config_status = {} self.state = ifaceState.NEW self.status = ifaceStatus.UNKNOWN self.refcnt = 0 + self.flags = 0 self.lowerifaces = None + self.upperifaces = None self.linkstate = None + self.env = None + self.priv_flags = 0 + self.raw_lines = [] self.flags |= self.PICKLED def dump_raw(self, logger): diff --git a/pkg/ifupdownmain.py b/pkg/ifupdownmain.py index ea7a94e..3134093 100644 --- a/pkg/ifupdownmain.py +++ b/pkg/ifupdownmain.py @@ -94,6 +94,9 @@ class ifupdownMain(ifupdownBase): ('down', run_down)]) def run_sched_ifaceobj_posthook(self, ifaceobj): + if ((ifaceobj.priv_flags & self.BUILTIN) or + (ifaceobj.priv_flags & self.NOCONFIG)): + return if self.STATEMANAGER_UPDATE: self.statemanager.ifaceobj_sync(ifaceobj) @@ -365,30 +368,6 @@ class ifupdownMain(ifupdownBase): break return dlist - def query_dependents_old(self, ifaceobj, ops): - """ Gets iface dependents by calling into respective modules """ - dlist = None - - # Get dependents for interface by querying respective modules - for op in ops: - for mname in self.module_ops.get(op): - module = self.modules.get(mname) - if op == 'query-running': - if (hasattr(module, - 'get_dependent_ifacenames_running') == False): - continue - dlist = module.get_dependent_ifacenames_running(ifaceobj) - else: - if (hasattr(module, 'get_dependent_ifacenames') == False): - continue - dlist = module.get_dependent_ifacenames(ifaceobj, - self.ifaceobjdict.keys()) - if dlist: - self.logger.debug('%s: ' %ifaceobj.get_name() + - 'got lowerifaces/dependents: %s' %str(dlist)) - break - return dlist - def populate_dependency_info(self, ifacenames, ops): """ recursive function to generate iface dependency info """ @@ -744,22 +723,23 @@ class ifupdownMain(ifupdownBase): self.save_state() def down(self, ops, auto=False, allow_classes=None, ifacenames=None, - excludepats=None, printdependency=None): + excludepats=None, printdependency=None, usecurrentconfig=False): if self.ADDONS_ENABLE: self.STATEMANAGER_UPDATE = False if auto: self.ALL = True self.WITH_DEPENDS = True - # for down we need to look at old state - self.logger.debug('Looking at old state ..') - if self.STATEMANAGER_ENABLE and self.statemanager.get_ifaceobjdict(): + # For down we need to look at old state, unless usecurrentconfig + # is set + if (not usecurrentconfig and self.STATEMANAGER_ENABLE and + self.statemanager.get_ifaceobjdict()): # Since we are using state manager objects, # skip the updating of state manager objects self.STATEMANAGER_UPDATE = False + self.logger.debug('Looking at old state ..') self.read_old_iface_config() else: # If no old state available - self.logger.info('old state not available. ' + - 'Loading current iface config file') + self.logger.info('Loading current iface config file') try: self.read_iface_config() except Exception, e: @@ -796,6 +776,8 @@ class ifupdownMain(ifupdownBase): def query(self, ops, auto=False, allow_classes=None, ifacenames=None, excludepats=None, printdependency=None, format='native'): + if self.STATEMANAGER_ENABLE and ops[0] == 'query-savedstate': + return self.statemanager.dump_pretty(ifacenames) self.STATEMANAGER_UPDATE = False if auto: diff --git a/pkg/statemanager.py b/pkg/statemanager.py index 289bb20..9c59f0e 100644 --- a/pkg/statemanager.py +++ b/pkg/statemanager.py @@ -12,6 +12,7 @@ import logging import os from iface import * import copy +import marshal class pickling(): @@ -20,14 +21,14 @@ class pickling(): try: with open(filename, 'w') as f: for obj in list_of_objects: - cPickle.dump(obj, f) + cPickle.dump(obj, f, cPickle.HIGHEST_PROTOCOL) except: raise @classmethod def save_obj(cls, f, obj): try: - cPickle.dump(obj, f) + cPickle.dump(obj, f, cPickle.HIGHEST_PROTOCOL) except: raise @@ -53,10 +54,8 @@ class stateManager(): self.state_file = self.state_dir + self.state_filename def save_ifaceobj(self, ifaceobj): - if self.ifaceobjdict.get(ifaceobj.get_name()) is None: - self.ifaceobjdict[ifaceobj.get_name()] = [ifaceobj] - else: - self.ifaceobjdict[ifaceobj.get_name()].append(ifaceobj) + self.ifaceobjdict.setdefault(ifaceobj.get_name(), + []).append(ifaceobj) def read_saved_state(self, filename=None): pickle_filename = filename @@ -75,6 +74,9 @@ class stateManager(): def get_ifaceobjdict(self): return self.ifaceobjdict + def get_ifaceobjs(self, ifacename): + return self.ifaceobjdict.get(ifacename) + def compare_iface_state(ifaceobj1, ifaceobj2): ifaceobj1_state = ifaceobj1.get_state() ifaceobj2_state = ifaceobj2.get_state() @@ -154,28 +156,18 @@ class stateManager(): except: raise - def print_state(self, ifaceobj, prefix, indent): - print (indent + '%s' %prefix + - '%s' %ifaceobj.get_state_str() + - ', %s' %ifaceobj.get_status_str()) - - def print_state_pretty(self, ifacenames, logger): - for ifacename in ifacenames: - old_ifaceobjs = self.ifaceobjdict.get(ifacename) - if old_ifaceobjs is not None: - firstifaceobj = old_ifaceobjs[0] - self.print_state(firstifaceobj, - '%s: ' %firstifaceobj.get_name(), '') - - def print_state_detailed_pretty(self, ifacenames, logger): - indent = '\t' - for ifacename in ifacenames: - old_ifaceobjs = self.ifaceobjdict.get(ifacename) - if old_ifaceobjs is not None: - for i in old_ifaceobjs: - i.dump_pretty(logger) - self.print_state(i, '', indent) - print '\n' + def dump_pretty(self, ifacenames, format='native'): + if not ifacenames: + ifacenames = self.ifaceobjdict.keys() + for i in ifacenames: + ifaceobjs = self.get_ifaceobjs(i) + if not ifaceobjs: + continue + for ifaceobj in ifaceobjs: + if format == 'json': + ifaceobj.dump_json() + else: + ifaceobj.dump_pretty() def dump(self, ifacenames=None): self.logger.debug('statemanager iface state:') diff --git a/sbin/ifupdown b/sbin/ifupdown index 6adffb7..07cfc92 100755 --- a/sbin/ifupdown +++ b/sbin/ifupdown @@ -63,7 +63,8 @@ def run_down(args): ifupdown_handle.down(['pre-down', 'down', 'post-down'], args.all, args.CLASS, iflist, excludepats=args.excludepats, - printdependency=args.printdependency) + printdependency=args.printdependency, + usecurrentconfig=args.usecurrentconfig) except: raise @@ -85,9 +86,10 @@ def run_query(args): qop = 'query-syntax' elif args.printdependency: qop = 'query-dependency' + elif args.printsavedstate: + qop = 'query-savedstate' else: qop='query' - cachearg=(False if (iflist or args.nocache or args.perfmode or args.syntaxhelp or (qop != 'query-checkcurr' and @@ -182,13 +184,14 @@ def update_ifupdown_argparser(argparser): argparser.add_argument('-f', '--force', dest='force', action='store_true', help='force run all operations') - argparser.add_argument('-n', '--no-act', dest='noact', + group = argparser.add_mutually_exclusive_group(required=False) + group.add_argument('-n', '--no-act', dest='noact', action='store_true', help='print out what would happen,' + 'but don\'t do it') - argparser.add_argument('--print-dependency', + group.add_argument('--print-dependency', dest='printdependency', choices=['list', 'dot'], help='print iface dependency') - argparser.add_argument('--no-scripts', '--no-addons', + group.add_argument('--no-scripts', '--no-addons', dest='noaddons', action='store_true', help='dont run any addon modules or scripts. Runs only link ' + 'up/down') @@ -198,6 +201,14 @@ def update_ifup_argparser(argparser): def update_ifdown_argparser(argparser): update_ifupdown_argparser(argparser) + argparser.add_argument('--use-current-config', + dest='usecurrentconfig', action='store_true', + help=argparse.SUPPRESS) + #help='By default ifdown looks at the saved state for ' + + #'interfaces to bring down. This option allows ifdown to ' + + #'look at the current interfaces file. Useful when your ' + + #'state file is corrupted or you want down to use the latest ' + #'from the interfaces file') def update_ifquery_argparser(argparser): """ arg parser for ifquery options """ @@ -215,6 +226,9 @@ def update_ifquery_argparser(argparser): 'running state of an interface') group.add_argument('--raw', action='store_true', dest='raw', help='print raw config file entries') + group.add_argument('--print-savedstate', action='store_true', + dest='printsavedstate', + help=argparse.SUPPRESS) argparser.add_argument('--format', dest='format', default='native', choices=['native', 'json'], help=argparse.SUPPRESS) argparser.add_argument('--print-dependency',