Subversion Repositories HomeAutomation

Rev

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

  1. ###########################################################
  2. #
  3. # Daemon configuration
  4. #
  5. ###########################################################
  6. import logging as log
  7. import pickle
  8. import hashlib
  9. import os
  10. import imp
  11. import re
  12. from ConfigParser import ConfigParser
  13. import filters
  14. import statespaces
  15.  
  16.  
  17. class DynamicModuleCfg:
  18.     """Dynamic module manager"""
  19.  
  20.     modSubDir = None
  21.     CHECKSUM_FILE = 'checksums'
  22.     CHECKSUM_SECTION = 'SHA-1_CHECKSUMS'
  23.    
  24.     def __init__(self, modSubDir):
  25.         self.modSubDir = modSubDir
  26.         self.checkSumFile = modSubDir + '/' + self.CHECKSUM_FILE
  27.         if not os.path.exists(self.checkSumFile):
  28.             self.__createCsumsFile()
  29.    
  30.     def loadModule(self, className):
  31.         pFileName = os.getcwd() + '/' + self.modSubDir + '/' + className + '.p'
  32.         log.debug('Reading from ' + pFileName)
  33.         fp = open(pFileName, 'r')
  34.         p = pickle.Unpickler(fp)
  35.         loadedMod = p.load()
  36.         fp.close()
  37.         if not self.__verifyCheckSum(className, pFileName):
  38.             print 'Invalid checksum'
  39.             return None
  40.         else:
  41.             return loadedMod
  42.        
  43.        
  44.     def loadModules(self, config = None):
  45.         subDirFiles = os.listdir(os.getcwd() + '/' + self.modSubDir)
  46.         p = re.compile('.p$', re.IGNORECASE)
  47.         modFiles = [elem for elem in subDirFiles if p.search(elem) is not None]
  48.         modNames = []
  49.         for mfName in modFiles:
  50.             modNames.append(mfName.split('.')[0])
  51.         log.debug('Found modules: ' + str(modNames))
  52.         myMods = {}
  53.         for mName in modNames:
  54.             classObj = self.loadModule(mName)
  55.             if classObj is not None:
  56.                 myMods[mName] = classObj
  57.         return myMods
  58.  
  59.    
  60.     def saveModule(self, className, classObj):
  61.         pFileName = os.getcwd() + '/' + self.modSubDir + '/' + className + '.p'
  62.         log.debug('Writing to ' + pFileName)
  63.         fp = open(pFileName, 'w')
  64.         p = pickle.Pickler(fp)
  65.         p.dump(classObj)
  66.         fp.close()
  67.         self.__writeCheckSum(className, pFileName)
  68.    
  69.    
  70.     def __doCheckSum(self, filename):
  71.         f = open(filename, 'r')
  72.         data = f.read()
  73.         f.close()
  74.         hasher = hashlib.sha1()
  75.         hasher.update(data)
  76.         digest = hasher.hexdigest()
  77.         return digest
  78.    
  79.    
  80.     def __createCsumsFile(self):
  81.          csumsfile = open(self.checkSumFile, 'w')
  82.          csumsfile.write('[' + self.CHECKSUM_SECTION + ']\n')
  83.          csumsfile.close()
  84.    
  85.    
  86.     def __writeCheckSum(self, entryname, filename):
  87.         csumsfile = open(self.checkSumFile, 'r+')
  88.         csumcfg = ConfigParser()
  89.         csumcfg.readfp(csumsfile)
  90.         digest = self.__doCheckSum(filename)
  91.         csumcfg.set(self.CHECKSUM_SECTION, entryname, digest)
  92.         csumsfile.seek(0)
  93.         csumcfg.write(csumsfile)
  94.        
  95.        
  96.     def __verifyCheckSum(self, entryname, filename):
  97.         csumsfile = open(self.checkSumFile, 'r')
  98.         csumcfg = ConfigParser()
  99.         csumcfg.readfp(csumsfile)
  100.         digest = csumcfg.get(self.CHECKSUM_SECTION, entryname)
  101.         cur_digest = self.__doCheckSum(filename)
  102.         log.debug('Old checksum ' + digest + '\nNew checksum: ' + cur_digest)
  103.         if cur_digest == digest:
  104.             return True
  105.         return False
  106.    
  107.    
  108.     def importModule(self, className, requiredAttributes):
  109.         """Imports a given class from the module with the same name """
  110.  
  111.         codeFile = os.getcwd() + '/' + self.modSubDir + '/' + className + '.py'
  112.         mod = imp.load_source(self.modSubDir + '.' + className, codeFile)
  113.         newClass = eval('mod.' + className)()
  114.        
  115.         for ra in requiredAttributes:
  116.             if not hasattr(newClass, ra):
  117.                 print className, ': missing required symbol \"' + ra + '\"'
  118.                 return None
  119.        
  120.         self.saveModule(className, newClass)
  121.         return newClass
  122.  
  123.  
  124. class FilterCfg:
  125.     """Filter resource manager"""
  126.    
  127.     REQUIRED_ATTRIBUTES = ['ASSOCIATED_SPACES', 'DESCRIPTIVE_NAME',
  128.                            'attach', 'detach', 'filter']
  129.    
  130.     dynamicModuleCfg = None
  131.     FILTER_SUBDIR = 'filters'
  132.     filterModules = {}
  133.    
  134.     def __init__(self):
  135.         self.dynamicModuleCfg = DynamicModuleCfg(self.FILTER_SUBDIR)
  136.    
  137.     def loadFilter(self, name):
  138.         newFilt = self.dynamicModuleCfg.loadModule(name)
  139.         if newFilt is not None:
  140.             filterModules[name] = newFilt
  141.             return True
  142.         else:
  143.             return False
  144.  
  145.     def loadFilters(self, config = None):
  146.         self.filterModules = self.dynamicModuleCfg.loadModules()
  147.         for fM in self.filterModules:
  148.             log.debug(fM)
  149.  
  150.     def __saveFilter(self, className, classObj):
  151.         self.dynamicModuleCfg.saveModule(className, classObj)
  152.  
  153.     def saveFilters(self):
  154.         for className in self.filterModules:
  155.             self.__saveFilter(className, self.filterModules[className])
  156.        
  157.     def importFilter(self, className):
  158.         """Imports a given filter definition """
  159.         classObj = self.dynamicModuleCfg.importModule(className, self.REQUIRED_ATTRIBUTES)
  160.         if classObj is not None:
  161.             print 'Imported: ' + classObj.DESCRIPTIVE_NAME
  162.             return True
  163.         else:
  164.             return False
  165.        
  166.  
  167. class StateSpaceCfg:
  168.     """State space resource manager"""
  169.    
  170.     REQUIRED_ATTRIBUTES = ['DESCRIPTIVE_NAME',
  171.                            'load', 'reset', 'run', 'unload']
  172.    
  173.     dynamicModuleCfg = None
  174.     FILTER_SUBDIR = 'statespaces'
  175.     spaceModules = {}
  176.    
  177.     def __init__(self):
  178.         self.dynamicModuleCfg = DynamicModuleCfg(self.FILTER_SUBDIR)
  179.    
  180.     def loadSpace(self, name):
  181.         newSpace = self.dynamicModuleCfg.loadModule(name)
  182.         if newSpace is not None:
  183.             spaceModules[name] = newFilt
  184.             return True
  185.         else:
  186.             return False
  187.  
  188.     def loadSpaces(self, config = None):
  189.         self.spaceModules = self.dynamicModuleCfg.loadModules()
  190.         for sM in self.spaceModules:
  191.             log.debug(sM)
  192.  
  193.     def __saveSpace(self, className, classObj):
  194.         self.dynamicModuleCfg.saveModule(className, classObj)
  195.  
  196.     def saveSpaces(self):
  197.         for className in self.spaceModules:
  198.             self.__saveSpace(className, self.spaceModules[className])
  199.    
  200.     def importSpace(self, name):
  201.         """Imports a given state space definition file """
  202.         classObj = self.dynamicModuleCfg.importModule(name, self.REQUIRED_ATTRIBUTES)
  203.         if classObj is not None:
  204.             print 'Imported: ' + classObj.DESCRIPTIVE_NAME
  205.             return True
  206.         else:
  207.             return False
  208.  
  209. class DaemonConfig:
  210.    
  211.     stateSpaceCfg = None
  212.     filterCfg = None
  213.     filterChain = []
  214.    
  215.     def __init__ (self):
  216.         self.filterCfg = FilterCfg()
  217.         self.stateSpaceCfg = StateSpaceCfg()
  218.        
  219.     def setupFilterChain(self):
  220.         self.filterChain = ['DefaultFilter']
  221.    
  222.     def setupFilterBindings(self):
  223.         for f in self.filterCfg.filterModules.values():
  224.             assocSpaces = []
  225.             for s in f.ASSOCIATED_SPACES:
  226.                 if self.stateSpaceCfg.spaceModules.has_key(s):
  227.                     assocSpaces.append(self.stateSpaceCfg.spaceModules[s])
  228.                 else:
  229.                     print 'WARNING: Reference to undefined state space: ' + s
  230.             setattr(f, '__ASSOCIATED_SPACES__', assocSpaces)
  231.    
  232.