Subversion Repositories HomeAutomation

Rev

Rev 748 | Go to most recent revision | Blame | Last modification | View Log | SVN | RSS feed

###########################################################
#
# Daemon configuration
#
###########################################################
import logging as log
import pickle
import hashlib
import os
import imp
import re
from ConfigParser import ConfigParser
import filters
import statespaces
from CanPktHandlerBase import CanPktHandlerBase
from CanPktHandler1 import CanPktHandler1

class DynamicModuleCfg:
    """Dynamic module manager"""

    modSubDir = None
    CHECKSUM_FILE = 'checksums'
    CHECKSUM_SECTION = 'SHA-1_CHECKSUMS'
    
    def __init__(self, modSubDir):
        self.modSubDir = modSubDir
        self.checkSumFile = modSubDir + '/' + self.CHECKSUM_FILE
        if not os.path.exists(self.checkSumFile):
            self.__createCsumsFile()
    
    def loadModule(self, className):
        pFileName = os.getcwd() + '/' + self.modSubDir + '/' + className + '.p'
        log.debug('Reading from ' + pFileName)
        fp = open(pFileName, 'r')
        p = pickle.Unpickler(fp)
        loadedMod = p.load()
        fp.close()
        if not self.__verifyCheckSum(className, pFileName):
            print 'Invalid checksum'
            return None
        else:
            return loadedMod
        
        
    def loadModules(self, config = None):
        subDirFiles = os.listdir(os.getcwd() + '/' + self.modSubDir)
        p = re.compile('.p$', re.IGNORECASE)
        modFiles = [elem for elem in subDirFiles if p.search(elem) is not None]
        modNames = []
        for mfName in modFiles:
            modNames.append(mfName.split('.')[0])
        log.debug('Found modules: ' + str(modNames))
        myMods = {}
        for mName in modNames:
            classObj = self.loadModule(mName)
            if classObj is not None:
                myMods[mName] = classObj
        return myMods
  
    
    def saveModule(self, className, classObj):
        pFileName = os.getcwd() + '/' + self.modSubDir + '/' + className + '.p'
        log.debug('Writing to ' + pFileName)
        fp = open(pFileName, 'w')
        p = pickle.Pickler(fp)
        p.dump(classObj)
        fp.close()
        self.__writeCheckSum(className, pFileName)
    
    
    def __doCheckSum(self, filename):
        f = open(filename, 'r')
        data = f.read()
        f.close()
        hasher = hashlib.sha1()
        hasher.update(data)
        digest = hasher.hexdigest()
        return digest
    
    
    def __createCsumsFile(self):
         csumsfile = open(self.checkSumFile, 'w')
         csumsfile.write('[' + self.CHECKSUM_SECTION + ']\n')
         csumsfile.close()
    
    
    def __writeCheckSum(self, entryname, filename):
        csumsfile = open(self.checkSumFile, 'r+')
        csumcfg = ConfigParser()
        csumcfg.readfp(csumsfile)
        digest = self.__doCheckSum(filename)
        csumcfg.set(self.CHECKSUM_SECTION, entryname, digest)
        csumsfile.seek(0)
        csumcfg.write(csumsfile)
        
        
    def __verifyCheckSum(self, entryname, filename):
        csumsfile = open(self.checkSumFile, 'r')
        csumcfg = ConfigParser()
        csumcfg.readfp(csumsfile)
        digest = csumcfg.get(self.CHECKSUM_SECTION, entryname)
        cur_digest = self.__doCheckSum(filename)
        log.debug('Old checksum ' + digest + '\nNew checksum: ' + cur_digest)
        if cur_digest == digest:
            return True
        return False
    
    
    def importModule(self, className, requiredAttributes):
        """Imports a given class from the module with the same name """

        codeFile = os.getcwd() + '/' + self.modSubDir + '/' + className + '.py'
        mod = imp.load_source(self.modSubDir + '.' + className, codeFile)
        newClass = eval('mod.' + className)()
        
        for ra in requiredAttributes:
            if not hasattr(newClass, ra):
                print className, ': missing required symbol \"' + ra + '\"'
                return None 
        
        self.saveModule(className, newClass)
        return newClass


class FilterCfg:
    """Filter resource manager"""
    
    REQUIRED_ATTRIBUTES = ['ASSOCIATED_SPACES', 'DESCRIPTIVE_NAME',
                           'attach', 'detach', 'filter']
    
    dynamicModuleCfg = None
    FILTER_SUBDIR = 'filters'
    filterModules = {}
    
    def __init__(self):
        self.dynamicModuleCfg = DynamicModuleCfg(self.FILTER_SUBDIR)
    
    def loadFilter(self, name):
        newFilt = self.dynamicModuleCfg.loadModule(name)
        if newFilt is not None:
            self.filterModules[name] = newFilt
            return True
        else:
            return False

    def loadFilters(self, config = None):
        self.filterModules = self.dynamicModuleCfg.loadModules()
        for fM in self.filterModules:
            log.debug(fM)

    def __saveFilter(self, className, classObj):
        self.dynamicModuleCfg.saveModule(className, classObj)

    def saveFilters(self):
        for className in self.filterModules:
            self.__saveFilter(className, self.filterModules[className])
        
    def importFilter(self, className):
        """Imports a given filter definition """
        classObj = self.dynamicModuleCfg.importModule(className, self.REQUIRED_ATTRIBUTES)
        if classObj is not None:
            print 'Imported: ' + classObj.DESCRIPTIVE_NAME
            return True
        else:
            return False
        

class StateSpaceCfg:
    """State space resource manager"""
    
    REQUIRED_ATTRIBUTES = ['DESCRIPTIVE_NAME', 'RELATED_SPACES'
                           'load', 'reset', 'run', 'unload']
    
    dynamicModuleCfg = None
    FILTER_SUBDIR = 'statespaces'
    spaceModules = {}
    
    def __init__(self):
        self.dynamicModuleCfg = DynamicModuleCfg(self.FILTER_SUBDIR)
    
    def loadSpace(self, name):
        newSpace = self.dynamicModuleCfg.loadModule(name)
        if newSpace is not None:
            self.spaceModules[name] = newFilt
            return True
        else:
            return False

    def loadSpaces(self, config = None):
        self.spaceModules = self.dynamicModuleCfg.loadModules()
        for sM in self.spaceModules:
            log.debug(sM)

    def __saveSpace(self, className, classObj):
        self.dynamicModuleCfg.saveModule(className, classObj)

    def saveSpaces(self):
        for className in self.spaceModules:
            self.__saveSpace(className, self.spaceModules[className])
    
    def importSpace(self, name):
        """Imports a given state space definition file """
        classObj = self.dynamicModuleCfg.importModule(name, self.REQUIRED_ATTRIBUTES)
        if classObj is not None:
            print 'Imported: ' + classObj.DESCRIPTIVE_NAME
            return True
        else:
            return False

class DaemonConfig:
    
    stateSpaceCfg = None
    filterCfg = None
    pktHandler = None
    
    filterChain = []
    nodeInterfaces = []
    nodeInterfaceMap = {}
    
    def __init__ (self):
        self.filterCfg = FilterCfg()
        self.stateSpaceCfg = StateSpaceCfg()
        self.pktHandler = CanPktHandler1()
        
    def load(self):
        self.stateSpaceCfg.loadSpaces()
        self.stateSpaceCfg.loadFilters()
        __setupFilterBindings()
        __setupFilterChain()
    
    def save(self):
        self.stateSpaceCfg.saveSpaces()
        self.filterCfg.saveFilters()
        
    def __setupFilterChain(self):
        self.filterChain = ['DefaultFilter']
    
    def __setupFilterBindings(self):
        for f in self.filterCfg.filterModules.values():
            assocSpaces = []
            for s in f.ASSOCIATED_SPACES:
                if self.stateSpaceCfg.spaceModules.has_key(s):
                    assocSpaces.append(self.stateSpaceCfg.spaceModules[s])
                else:
                    print 'WARNING: Reference to undefined state space: ' + s
            setattr(f, '__ASSOCIATED_SPACES__', assocSpaces)
    

    def setupStateSpaceRelations(self):
        for sm in self.stateSpaceCfg.spaceModules:
            relatedSpaceNames = self.stateSpaceCfg.spaceModules[sm].RELATED_SPACES
            relatedSpaces = {}
            for rsname in relatedSpaceNames:
                relatedSpaces[rsname] = self.stateSpaceCfg.spaceModules[rsname]
            setattr(sm, '__RELATED_SPACES__', relatedSpaces)