From 31a5f4c364a5232db0a26980a75173cd15c8c8a3 Mon Sep 17 00:00:00 2001 From: roopa Date: Mon, 24 Feb 2014 11:07:59 -0800 Subject: [PATCH] cleanup state manager + remove some dead code Ticket: CM-1438 Reviewed By: Testing Done: --- init.d/networking | 3 +- pkg/iface.py | 15 ++++-- pkg/ifupdownbase.py | 3 +- pkg/ifupdownmain.py | 129 ++++++++++++++++++-------------------------- pkg/scheduler.py | 35 ++++++------ pkg/statemanager.py | 107 +++++++----------------------------- 6 files changed, 98 insertions(+), 194 deletions(-) diff --git a/init.d/networking b/init.d/networking index 00c1eb4..89aad5a 100644 --- a/init.d/networking +++ b/init.d/networking @@ -125,7 +125,7 @@ start) exclusions=$(process_exclusions) perfoptions=$(perf_options) log_action_begin_msg "Configuring network interfaces" - if ifup -a $verbose $perfoptions + if ifup -d -a $verbose $perfoptions then log_action_end_msg $? else @@ -183,6 +183,7 @@ restart) ifupdown_init + log_action_begin_msg "Reconfiguring network interfaces" ifdown -a --exclude=lo $verbose --perfmode || true set -f diff --git a/pkg/iface.py b/pkg/iface.py index 61f3e1c..a892196 100644 --- a/pkg/iface.py +++ b/pkg/iface.py @@ -125,9 +125,9 @@ class ifaceJsonEncoder(json.JSONEncoder): 'config' : retconfig}) class iface(): - """ config flags """ - AUTO = 0x1 - HOT_PLUG = 0x2 + """ flags """ + # flag to indicate that the object was created from pickled state + PICKLED = 0x1 version = '0.1' @@ -255,6 +255,10 @@ class iface(): def set_status(self, status): self.status = status + def set_state_n_status(self, state, status): + self.state = state + self.status = status + def state_str_to_hex(self, state_str): return self.state_str_map.get(state_str) @@ -389,7 +393,6 @@ class iface(): del odict['status'] del odict['lowerifaces'] del odict['refcnt'] - return odict def __setstate__(self, dict): @@ -399,6 +402,7 @@ class iface(): self.refcnt = 0 self.lowerifaces = None self.linkstate = None + self.flags |= self.PICKLED def dump_raw(self, logger): indent = ' ' @@ -411,12 +415,13 @@ class iface(): logger.info(self.get_name() + ' : {') logger.info(indent + 'family: %s' %self.get_addr_family()) logger.info(indent + 'method: %s' %self.get_addr_method()) + logger.info(indent + 'flags: %x' %self.flags) logger.info(indent + 'state: %s' %ifaceState.to_str(self.get_state())) logger.info(indent + 'status: %s' %ifaceStatus.to_str(self.get_status())) logger.info(indent + 'refcnt: %d' %self.get_refcnt()) - d = self.get_lowerdevs() + d = self.get_lowerifaces() if d: logger.info(indent + 'lowerdevs: %s' %str(d)) else: diff --git a/pkg/ifupdownbase.py b/pkg/ifupdownbase.py index d8be16c..a6efb23 100644 --- a/pkg/ifupdownbase.py +++ b/pkg/ifupdownbase.py @@ -66,8 +66,7 @@ class ifupdownBase(object): return os.path.exists('/sys/class/net/%s' %ifacename) def link_up(self, ifacename): - #self.exec_command('ip link set dev %s up' %ifacename) - self.exec_command('ifconfig %s up' %ifacename) + self.exec_command('ip link set dev %s up' %ifacename) def link_down(self, ifacename): self.exec_command('ip link set dev %s down' %ifacename) diff --git a/pkg/ifupdownmain.py b/pkg/ifupdownmain.py index 240fb4b..a1cbf6a 100644 --- a/pkg/ifupdownmain.py +++ b/pkg/ifupdownmain.py @@ -29,6 +29,7 @@ class ifupdownMain(ifupdownBase): ALL = False STATE_CHECK = False COMPAT_EXEC_SCRIPTS = False + UPDATE_STATEMANAGER = True # priv flags to mark iface objects BUILTIN = 0x1 @@ -86,9 +87,18 @@ class ifupdownMain(ifupdownBase): if self.link_exists(ifacename): self.link_down(ifacename) + # ifupdown object interface operation handlers ops_handlers = OrderedDict([('up', run_up), ('down', run_down)]) + + def run_sched_ifaceobj_posthook(self, ifaceobj): + if self.UPDATE_STATEMANAGER: + self.statemanager.ifaceobj_sync(ifaceobj) + + # ifupdown object interface scheduler pre and posthooks + sched_hooks = {'posthook' : run_sched_ifaceobj_posthook} + def __init__(self, force=False, dryrun=False, nowait=False, perfmode=False, withdepends=False, njobs=1, cache=False): @@ -188,17 +198,12 @@ class ifupdownMain(ifupdownBase): self.logger.debug('setting withdepends to true') self.WITH_DEPENDS = withdepends - def set_iface_state(self, ifaceobj, state, status): - ifaceobj.set_state(state) - ifaceobj.set_status(status) - self.statemanager.update_iface_state(ifaceobj) - - def get_iface_objs(self, ifacename): + def get_ifaceobjs(self, ifacename): return self.ifaceobjdict.get(ifacename) - def get_iface_obj_first(self, ifacename): - ifaceobjs = self.get_iface_objs(ifacename) - if ifaceobjs is not None: + def get_ifaceobj_first(self, ifacename): + ifaceobjs = self.get_ifaceobjs(ifacename) + if ifaceobjs: return ifaceobjs[0] return None @@ -226,16 +231,15 @@ class ifupdownMain(ifupdownBase): return self.ifaceobjrunningdict.get(ifacename) def get_iface_status(self, ifacename): - ifaceobjs = self.get_iface_objs(ifacename) + ifaceobjs = self.get_ifaceobjs(ifacename) for i in ifaceobjs: if i.get_status() != ifaceStatus.SUCCESS: return i.get_status() - return ifaceStatus.SUCCESS def get_iface_refcnt(self, ifacename): max = 0 - ifaceobjs = self.get_iface_objs(ifacename) + ifaceobjs = self.get_ifaceobjs(ifacename) for i in ifaceobjs: if i.get_refcnt() > max: max = i.get_refcnt() @@ -286,7 +290,7 @@ class ifupdownMain(ifupdownBase): def is_iface_noconfig(self, ifacename): """ Returns true if iface has no config """ - ifaceobj = self.get_iface_obj_first(ifacename) + ifaceobj = self.get_ifaceobj_first(ifacename) if not ifaceobj: return True return self.is_ifaceobj_noconfig(ifaceobj) @@ -309,7 +313,7 @@ class ifupdownMain(ifupdownBase): del_list = [] for d in dlist: - dilist = self.get_iface_objs(d) + dilist = self.get_ifaceobjs(d) if not dilist: if self.is_iface_builtin_byname(d): self.create_n_save_ifaceobj(d, self.BUILTIN | self.NOCONFIG, @@ -353,37 +357,30 @@ class ifupdownMain(ifupdownBase): def populate_dependency_info(self, ifacenames, ops): """ recursive function to generate iface dependency info """ - - if ifacenames is None: + if not ifacenames: ifacenames = self.ifaceobjdict.keys() - self.logger.debug('populating dependency info for %s' %str(ifacenames)) - iqueue = deque(ifacenames) while iqueue: i = iqueue.popleft() - # Go through all modules and find dependent ifaces dlist = None - ifaceobj = self.get_iface_obj_first(i) - if ifaceobj is None: + ifaceobj = self.get_ifaceobj_first(i) + if not ifaceobj: continue - dlist = ifaceobj.get_lowerifaces() - if dlist is None: + if not dlist: dlist = self.query_dependents(ifaceobj, ops) else: continue - - if dlist is not None: + if dlist: self.preprocess_dependency_list(ifaceobj.get_name(), dlist, ops) self.logger.debug('%s: lowerifaces/dependents after processing: %s' %(i, str(dlist))) ifaceobj.set_lowerifaces(dlist) [iqueue.append(d) for d in dlist] - - if self.dependency_graph.get(i) is None: + if not self.dependency_graph.get(i): self.dependency_graph[i] = dlist def _save_iface(self, ifaceobj): @@ -594,24 +591,19 @@ class ifupdownMain(ifupdownBase): returns -1 if one or more interface not found. else, returns 0 """ - err_iface = '' for i in ifacenames: - ifaceobjs = self.get_iface_objs(i) - if ifaceobjs is None: + ifaceobjs = self.get_ifaceobjs(i) + if not ifaceobjs: err_iface += ' ' + i - if err_iface: self.logger.error('could not find interfaces: %s' %err_iface) return -1 - return 0 - def iface_whitelisted(self, auto, allow_classes, excludepats, ifacename): """ Checks if interface is whitelisted depending on set of parameters. - interfaces are checked against the allow_classes and auto lists. """ @@ -620,12 +612,10 @@ class ifupdownMain(ifupdownBase): for e in excludepats: if re.search(e, ifacename): return False - - ifaceobjs = self.get_iface_objs(ifacename) - if ifaceobjs is None: + ifaceobjs = self.get_ifaceobjs(ifacename) + if not ifaceobjs: self.logger.debug('iface %s' %ifacename + ' not found') return False - # We check classes first if allow_classes: for i in ifaceobjs: @@ -635,13 +625,11 @@ class ifupdownMain(ifupdownBase): if common: return True return False - if auto: for i in ifaceobjs: if i.get_auto(): return True return False - return True def generate_running_env(self, ifaceobj, op): @@ -673,14 +661,14 @@ class ifupdownMain(ifupdownBase): except Exception, e: raise - if ifacenames is not None: + if ifacenames: # If iface list is given by the caller, always check if iface # is present if self.validate_ifaces(ifacenames) != 0: raise Exception('all or some interfaces not found') # if iface list not given by user, assume all from config file - if ifacenames is None: ifacenames = self.ifaceobjdict.keys() + if not ifacenames: ifacenames = self.ifaceobjdict.keys() # filter interfaces based on auto and allow classes filtered_ifacenames = [i for i in ifacenames @@ -705,10 +693,7 @@ class ifupdownMain(ifupdownBase): # Update persistant iface states try: - if self.ALL: - self.statemanager.flush_state(self.ifaceobjdict) - else: - self.statemanager.flush_state() + self.statemanager.save_state() except Exception, e: if self.logger.isEnabledFor(logging.DEBUG): t = sys.exc_info()[2] @@ -717,35 +702,31 @@ class ifupdownMain(ifupdownBase): def down(self, ops, auto=False, allow_classes=None, ifacenames=None, excludepats=None, printdependency=None): - loaded_newconfig = 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.get_ifaceobjdict(): + # Since we are using state manager objects, + # skip the updating of state manager objects + self.UPDATE_STATEMANAGER = False self.read_old_iface_config() else: # If no old state available self.logger.info('old state not available. ' + - 'Loading new iface config file') + 'Loading current iface config file') try: self.read_iface_config() except Exception, e: raise Exception('error reading iface config (%s)' %str(e)) - loaded_newconfig = True - if ifacenames: # If iface list is given by the caller, always check if iface # is present if self.validate_ifaces(ifacenames) != 0: raise Exception('all or some interfaces not found') - # if iface list not given by user, assume all from config file if not ifacenames: ifacenames = self.ifaceobjdict.keys() - # filter interfaces based on auto and allow classes filtered_ifacenames = [i for i in ifacenames if self.iface_whitelisted(auto, allow_classes, @@ -762,26 +743,23 @@ class ifupdownMain(ifupdownBase): self.run_with_dependents(ops, filtered_ifacenames) else: self.run_without_dependents(ops, filtered_ifacenames) - if self.DRYRUN: return - if loaded_newconfig: - # Update persistant iface states - try: - if self.ALL: - self.statemanager.flush_state(self.ifaceobjdict) - else: - self.statemanager.flush_state() - except Exception, e: - if self.logger.isEnabledFor(logging.DEBUG): - t = sys.exc_info()[2] - traceback.print_tb(t) + # Update persistant iface states + try: + self.statemanager.save_state() + except Exception, e: + if self.logger.isEnabledFor(logging.DEBUG): + t = sys.exc_info()[2] + traceback.print_tb(t) self.logger.warning('error saving state (%s)' %str(e)) def query(self, ops, auto=False, allow_classes=None, ifacenames=None, excludepats=None, printdependency=None, format='native'): + + self.UPDATE_STATEMANAGER = False if auto: self.logger.debug('setting flag ALL') self.ALL = True @@ -806,7 +784,7 @@ class ifupdownMain(ifupdownBase): raise Exception('all or some interfaces not found') # if iface list not given by user, assume all from config file - if ifacenames is None: ifacenames = self.ifaceobjdict.keys() + if not ifacenames: ifacenames = self.ifaceobjdict.keys() # filter interfaces based on auto and allow classes if ops[0] == 'query-running': @@ -874,6 +852,7 @@ class ifupdownMain(ifupdownBase): # followed by 'up' aka: reload # old interface config is read into self.ifaceobjdict # + self.UPDATE_STATEMANAGER = False self.read_old_iface_config() op = 'reload' else: @@ -959,10 +938,8 @@ class ifupdownMain(ifupdownBase): self.run_with_dependents(upops, filtered_ifacenames) else: self.run_without_dependents(upops, filtered_ifacenames) - if self.DRYRUN: return - # Update persistant iface states try: if self.ALL: @@ -988,7 +965,7 @@ class ifupdownMain(ifupdownBase): def print_ifaceobjs_raw(self, ifacenames): for i in ifacenames: - for ifaceobj in self.get_iface_objs(i): + for ifaceobj in self.get_ifaceobjs(i): if (self.is_ifaceobj_builtin(ifaceobj) or not ifaceobj.is_config_present()): continue @@ -1001,14 +978,13 @@ class ifupdownMain(ifupdownBase): def print_ifaceobjs_pretty(self, ifacenames, format='native'): for i in ifacenames: - for ifaceobj in self.get_iface_objs(i): + for ifaceobj in self.get_ifaceobjs(i): if (self.is_ifaceobj_noconfig(ifaceobj)): continue if format == 'json': ifaceobj.dump_json() else: ifaceobj.dump_pretty() - if self.WITH_DEPENDS: dlist = ifaceobj.get_lowerifaces() if not dlist: continue @@ -1016,7 +992,7 @@ class ifupdownMain(ifupdownBase): def dump_ifaceobjs(self, ifacenames): for i in ifacenames: - ifaceobjs = self.get_iface_objs(i) + ifaceobjs = self.get_ifaceobjs(i) for i in ifaceobjs: i.dump(self.logger) print '\n' @@ -1055,19 +1031,16 @@ class ifupdownMain(ifupdownBase): def print_ifaceobjsrunning_pretty(self, ifacenames, format='native'): for i in ifacenames: - ifaceobj = self.get_iface_obj_first(i) + ifaceobj = self.get_ifaceobj_first(i) if ifaceobj.get_status() == ifaceStatus.NOTFOUND: print 'iface %s' %ifaceobj.get_name() + ' (not found)\n' continue - - if ifaceobj.is_config_present() == False: + if not ifaceobj.is_config_present(): continue - if format == 'json': ifaceobj.dump_json() else: ifaceobj.dump_pretty() - if self.WITH_DEPENDS: dlist = ifaceobj.get_lowerifaces() if not dlist: continue diff --git a/pkg/scheduler.py b/pkg/scheduler.py index 24e88c6..2f33509 100644 --- a/pkg/scheduler.py +++ b/pkg/scheduler.py @@ -71,15 +71,12 @@ class ifaceScheduler(): err = 1 ifupdownobj.log_error(str(e)) finally: - if err == 1: - ifupdownobj.set_iface_state(ifaceobj, - ifaceState.from_str(op), - ifaceStatus.ERROR) + if err: + ifaceobj.set_state_n_status(ifaceState.from_str(op), + ifaceStatus.ERROR) else: - ifupdownobj.set_iface_state(ifaceobj, - ifaceState.from_str(op), - ifaceStatus.SUCCESS) - + ifaceobj.set_state_n_status(ifaceState.from_str(op), + ifaceStatus.SUCCESS) if ifupdownobj.COMPAT_EXEC_SCRIPTS: # execute /etc/network/ scripts @@ -93,16 +90,16 @@ class ifaceScheduler(): @classmethod def run_iface_ops(cls, ifupdownobj, ifaceobj, ops): - """ Runs all sub operations on an interface """ + """ Runs all operations on an interface """ cenv=None - if ifupdownobj.COMPAT_EXEC_SCRIPTS: # For backward compatibility generate env variables # for attributes cenv = ifupdownobj.generate_running_env(ifaceobj, ops[0]) - - # Each sub operation has a module list map(lambda op: cls.run_iface_op(ifupdownobj, ifaceobj, op, cenv), ops) + posthookfunc = ifupdownobj.sched_hooks.get('posthook') + if posthookfunc: + posthookfunc(ifupdownobj, ifaceobj) @classmethod def run_iface_graph(cls, ifupdownobj, ifacename, ops, parent=None, @@ -117,8 +114,8 @@ class ifaceScheduler(): return # Each ifacename can have a list of iface objects - ifaceobjs = ifupdownobj.get_iface_objs(ifacename) - if ifaceobjs is None: + ifaceobjs = ifupdownobj.get_ifaceobjs(ifacename) + if not ifaceobjs: raise Exception('%s: not found' %ifacename) for ifaceobj in ifaceobjs: @@ -180,8 +177,8 @@ class ifaceScheduler(): pass else: # Dont bring the iface up if children did not come up - ifaceobj.set_state(ifaceState.NEW) - ifaceobj.set_status(ifaceStatus.ERROR) + ifaceobj.set_state_n_sttaus(ifaceState.NEW, + ifacestatus.ERROR) raise if order == ifaceSchedulerFlags.POSTORDER: cls.run_iface_ops(ifupdownobj, ifaceobj, ops) @@ -255,7 +252,7 @@ class ifaceScheduler(): def run_iface(cls, ifupdownobj, ifacename, ops): """ Runs operation on an interface """ - ifaceobjs = ifupdownobj.get_iface_objs(ifacename) + ifaceobjs = ifupdownobj.get_ifaceobjs(ifacename) for i in ifaceobjs: cls.run_iface_ops(ifupdownobj, i, ops) @@ -281,7 +278,7 @@ class ifaceScheduler(): ifacename = iface_run_queue.pop() try: - ifaceobjs = ifupdownobj.get_iface_objs(ifacename) + ifaceobjs = ifupdownobj.get_ifaceobjs(ifacename) for ifaceobj in ifaceobjs: cenv = ifupdownobj.generate_running_env(ifaceobj, op) cls.run_iface_op(ifupdownobj, ifaceobj, op, cenv) @@ -359,7 +356,7 @@ class ifaceScheduler(): cls.accquire_token(iface) # Each iface can have a list of objects - ifaceobjs = ifupdownobj.get_iface_objs(ifacename) + ifaceobjs = ifupdownobj.get_ifaceobjs(ifacename) if ifaceobjs is None: ifupdownobj.logger.warning('%s: ' %ifacename + 'not found') cls.release_token(ifacename) diff --git a/pkg/statemanager.py b/pkg/statemanager.py index 66a389d..24953fe 100644 --- a/pkg/statemanager.py +++ b/pkg/statemanager.py @@ -11,6 +11,7 @@ from collections import OrderedDict import logging import os from iface import * +import copy class pickling(): @@ -68,20 +69,12 @@ class stateManager(): # Read all ifaces from file for ifaceobj in pickling.load(pickle_filename): self.save_ifaceobj(ifaceobj) - #ifaceobj.set_refcnt(0) - #ifaceobj.set_dependents(None) return 0 def get_ifaceobjdict(self): return self.ifaceobjdict - def save_state(self, ifaceobjs, filename=None): - pickle_filename = filename - if not pickle_filename: - pickle_filename = self.state_file - pickling.save(pickle_filename, ifaceobjs) - def compare_iface_state(ifaceobj1, ifaceobj2): ifaceobj1_state = ifaceobj1.get_state() ifaceobj2_state = ifaceobj2.get_state() @@ -93,38 +86,6 @@ class stateManager(): elif ifaceobj1_state == ifaceobj2_state: return 0 - def compare_iface_with_old(self, ifaceobj): - old_ifaceobj = self.ifaceobjdict.get(ifaceobj.get_name()) - if old_ifaceobj == None: - raise ifacenotfound(ifaceobj.get_name()) - - if ifaceobj.get_addr_family() != old_ifaceobj.get_addr_family(): - return -1 - - if ifaceobj.get_method() != old_ifaceobj.get_method(): - return -1 - - # compare config items - unmatched_item = set(ifaceobj.items()) ^ set(old_ifaceobj.items()) - if unmatched_item: - return -1 - - return 0 - - def get_iface_state_old(self, ifaceobj): - old_ifaceobj = self.ifaceobjdict.get(ifaceobj.get_name()) - if old_ifaceobj == None: - raise ifacenotfound(ifaceobj.get_name()) - - return old_ifaceobj.get_state() - - def get_iface_status_old(self, ifaceobj): - old_ifaceobj = self.ifaceobjdict.get(ifaceobj.get_name()) - if old_ifaceobj == None: - raise ifacenotfound(ifaceobj.get_name()) - - return old_ifaceobj.get_status() - def cmp_old_new_state(self, ifacename, operation): """ compares current operation with old state """ @@ -150,7 +111,7 @@ class stateManager(): return 1 - def iface_obj_compare(self, ifaceobj_a, ifaceobj_b): + def ifaceobj_compare(self, ifaceobj_a, ifaceobj_b): if ifaceobj_a.get_name() != ifaceobj_b.get_name(): return False @@ -171,60 +132,28 @@ class stateManager(): return True - - def update_iface_state(self, ifaceobj): - old_ifaceobjs = self.ifaceobjdict.get(ifaceobj.get_name()) - if old_ifaceobjs is None: - self.ifaceobjdict[ifaceobj.get_name()] = [ifaceobj] + def ifaceobj_sync(self, ifaceobj): + ifacename = ifaceobj.get_name() + self.logger.debug('%s: statemanager sync state' %ifacename) + old_ifaceobjs = self.ifaceobjdict.get(ifacename) + if not old_ifaceobjs: + self.ifaceobjdict[ifacename] = [ifaceobj] else: - for oi in old_ifaceobjs: - if self.iface_obj_compare(ifaceobj, oi) == True: - oi.set_state(ifaceobj.get_state()) - oi.set_status(ifaceobj.get_status()) - return - - self.ifaceobjdict[ifaceobj.get_name()].append(ifaceobj) - - def flush_state(self, ifaceobjdict=None): - if ifaceobjdict is None: - ifaceobjdict = self.ifaceobjdict + if old_ifaceobjs[0].flags & iface.PICKLED: + del self.ifaceobjdict[ifacename] + self.ifaceobjdict[ifacename] = [ifaceobj] + else: + self.ifaceobjdict[ifacename].append(ifaceobj) + def save_state(self): try: with open(self.state_file, 'w') as f: - for ifaceobjs in ifaceobjdict.values(): + for ifaceobjs in self.ifaceobjdict.values(): for i in ifaceobjs: pickling.save_obj(f, i) except: raise - - def is_valid_state_transition(self, ifaceobj, tobe_state): - if self.ifaceobjdict is None: - return True - - if tobe_state == 'up': - max_tobe_state = ifaceState.POST_UP - elif tobe_state == 'down': - max_tobe_state = ifaceState.POST_DOWN - else: - return True - - old_ifaceobjs = self.ifaceobjdict.get(ifaceobj.get_name()) - if old_ifaceobjs is not None: - for oi in old_ifaceobjs: - if self.iface_obj_compare(ifaceobj, oi) == True: - if (oi.get_state() == max_tobe_state and - oi.get_status() == ifaceStatus.SUCCESS): - # if old state is greater than or equal to - # tobe_state - return False - else: - return True - - return True - else: - return True - def print_state(self, ifaceobj, prefix, indent): print (indent + '%s' %prefix + '%s' %ifaceobj.get_state_str() + @@ -249,7 +178,7 @@ class stateManager(): print '\n' def dump(self, ifacenames=None): - print 'iface state:' + self.logger.debug('statemanager iface state:') if ifacenames: for i in ifacenames: ifaceobj = self.ifaces.get(i) @@ -258,5 +187,5 @@ class stateManager(): %i + ' not found') ifaceobj.dump(self.logger) else: - for ifacename, ifaceobj in self.ifaceobjdict.items(): - ifaceobj.dump(self.logger) + for ifacename, ifaceobjs in self.ifaceobjdict.items(): + [i.dump(self.logger) for i in ifaceobjs]