Subversion Repositories HomeAutomation

Rev

Rev 749 | Rev 751 | Go to most recent revision | Blame | Compare with Previous | 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. from CanPktHandlerBase import CanPktHandlerBase
  16. from CanPktHandler1 import CanPktHandler1
  17.  
  18. from NodeIfSerial import NodeIfSerial
  19. from NodeIfTCP import NodeIfTCP
  20. from NodeIfUDP import NodeIfUDP
  21. from NodeIfTCPTLS import NodeIfTCPTLS
  22. from NodeIfCanStim import NodeIfCanStim
  23.  
  24. class DynamicModuleCfg:
  25.     """Dynamic module manager"""
  26.  
  27.     modSubDir = None
  28.     CHECKSUM_FILE = 'checksums'
  29.     CHECKSUM_SECTION = 'SHA-1_CHECKSUMS'
  30.    
  31.     def __init__(self, modSubDir):
  32.         self.modSubDir = modSubDir
  33.         self.checkSumFile = modSubDir + '/' + self.CHECKSUM_FILE
  34.         if not os.path.exists(self.checkSumFile):
  35.             self.__createCsumsFile()
  36.    
  37.     def loadModule(self, className):
  38.         pFileName = os.getcwd() + '/' + self.modSubDir + '/' + className + '.p'
  39.         log.debug('Reading from ' + pFileName)
  40.         fp = open(pFileName, 'r')
  41.         p = pickle.Unpickler(fp)
  42.         loadedMod = p.load()
  43.         fp.close()
  44.         if not self.__verifyCheckSum(className, pFileName):
  45.             print 'Invalid checksum'
  46.             return None
  47.         else:
  48.             return loadedMod
  49.        
  50.        
  51.     def loadModules(self, config = None):
  52.         subDirFiles = os.listdir(os.getcwd() + '/' + self.modSubDir)
  53.         p = re.compile('.p$', re.IGNORECASE)
  54.         modFiles = [elem for elem in subDirFiles if p.search(elem) is not None]
  55.         modNames = []
  56.         for mfName in modFiles:
  57.             modNames.append(mfName.split('.')[0])
  58.         log.debug('Found modules: ' + str(modNames))
  59.         myMods = {}
  60.         for mName in modNames:
  61.             classObj = self.loadModule(mName)
  62.             if classObj is not None:
  63.                 myMods[mName] = classObj
  64.         return myMods
  65.  
  66.    
  67.     def saveModule(self, className, classObj):
  68.         pFileName = os.getcwd() + '/' + self.modSubDir + '/' + className + '.p'
  69.         log.debug('Writing to ' + pFileName)
  70.         fp = open(pFileName, 'w')
  71.         p = pickle.Pickler(fp)
  72.         p.dump(classObj)
  73.         fp.close()
  74.         self.__writeCheckSum(className, pFileName)
  75.    
  76.    
  77.     def __doCheckSum(self, filename):
  78.         f = open(filename, 'r')
  79.         data = f.read()
  80.         f.close()
  81.         hasher = hashlib.sha1()
  82.         hasher.update(data)
  83.         digest = hasher.hexdigest()
  84.         return digest
  85.    
  86.    
  87.     def __createCsumsFile(self):
  88.          csumsfile = open(self.checkSumFile, 'w')
  89.          csumsfile.write('[' + self.CHECKSUM_SECTION + ']\n')
  90.          csumsfile.close()
  91.    
  92.    
  93.     def __writeCheckSum(self, entryname, filename):
  94.         csumsfile = open(self.checkSumFile, 'r+')
  95.         csumcfg = ConfigParser()
  96.         csumcfg.readfp(csumsfile)
  97.         digest = self.__doCheckSum(filename)
  98.         csumcfg.set(self.CHECKSUM_SECTION, entryname, digest)
  99.         csumsfile.seek(0)
  100.         csumcfg.write(csumsfile)
  101.        
  102.        
  103.     def __verifyCheckSum(self, entryname, filename):
  104.         csumsfile = open(self.checkSumFile, 'r')
  105.         csumcfg = ConfigParser()
  106.         csumcfg.readfp(csumsfile)
  107.         digest = csumcfg.get(self.CHECKSUM_SECTION, entryname)
  108.         cur_digest = self.__doCheckSum(filename)
  109.         log.debug('Old checksum ' + digest + '\nNew checksum: ' + cur_digest)
  110.         if cur_digest == digest:
  111.             return True
  112.         return False
  113.    
  114.    
  115.     def importModule(self, className, requiredAttributes):
  116.         """Imports a given class from the module with the same name """
  117.  
  118.         codeFile = os.getcwd() + '/' + self.modSubDir + '/' + className + '.py'
  119.         mod = imp.load_source(self.modSubDir + '.' + className, codeFile)
  120.         newClass = eval('mod.' + className)()
  121.        
  122.         for ra in requiredAttributes:
  123.             if not hasattr(newClass, ra):
  124.                 print className, ': missing required symbol \"' + ra + '\"'
  125.                 return None
  126.        
  127.         self.saveModule(className, newClass)
  128.         return newClass
  129.  
  130.  
  131. class FilterCfg:
  132.     """Filter resource manager"""
  133.    
  134.     REQUIRED_ATTRIBUTES = ['ASSOCIATED_SPACES', 'DESCRIPTIVE_NAME',
  135.                            'attach', 'detach', 'filter']
  136.    
  137.     dynamicModuleCfg = None
  138.     FILTER_SUBDIR = 'filters'
  139.     filterModules = {}
  140.    
  141.     def __init__(self):
  142.         self.dynamicModuleCfg = DynamicModuleCfg(self.FILTER_SUBDIR)
  143.    
  144.     def loadFilter(self, name):
  145.         newFilt = self.dynamicModuleCfg.loadModule(name)
  146.         if newFilt is not None:
  147.             self.filterModules[name] = newFilt
  148.             return True
  149.         else:
  150.             return False
  151.  
  152.     def loadFilters(self, config = None):
  153.         self.filterModules = self.dynamicModuleCfg.loadModules()
  154.         for fM in self.filterModules:
  155.             log.debug(fM)
  156.  
  157.     def __saveFilter(self, className, classObj):
  158.         self.dynamicModuleCfg.saveModule(className, classObj)
  159.  
  160.     def saveFilters(self):
  161.         for className in self.filterModules:
  162.             self.__saveFilter(className, self.filterModules[className])
  163.        
  164.     def importFilter(self, className):
  165.         """Imports a given filter definition """
  166.         classObj = self.dynamicModuleCfg.importModule(className, self.REQUIRED_ATTRIBUTES)
  167.         if classObj is not None:
  168.             print 'Imported: ' + classObj.DESCRIPTIVE_NAME
  169.             return True
  170.         else:
  171.             return False
  172.        
  173.  
  174. class StateSpaceCfg:
  175.     """State space resource manager"""
  176.    
  177.     REQUIRED_ATTRIBUTES = ['DESCRIPTIVE_NAME', 'RELATED_SPACES'
  178.                            'load', 'reset', 'run', 'unload']
  179.    
  180.     dynamicModuleCfg = None
  181.     FILTER_SUBDIR = 'statespaces'
  182.     spaceModules = {}
  183.    
  184.     def __init__(self):
  185.         self.dynamicModuleCfg = DynamicModuleCfg(self.FILTER_SUBDIR)
  186.    
  187.     def loadSpace(self, name):
  188.         newSpace = self.dynamicModuleCfg.loadModule(name)
  189.         if newSpace is not None:
  190.             self.spaceModules[name] = newFilt
  191.             return True
  192.         else:
  193.             return False
  194.  
  195.     def loadSpaces(self, config = None):
  196.         self.spaceModules = self.dynamicModuleCfg.loadModules()
  197.         for sM in self.spaceModules:
  198.             log.debug(sM)
  199.  
  200.     def __saveSpace(self, className, classObj):
  201.         self.dynamicModuleCfg.saveModule(className, classObj)
  202.  
  203.     def saveSpaces(self):
  204.         for className in self.spaceModules:
  205.             self.__saveSpace(className, self.spaceModules[className])
  206.    
  207.     def importSpace(self, name):
  208.         """Imports a given state space definition file """
  209.         classObj = self.dynamicModuleCfg.importModule(name, self.REQUIRED_ATTRIBUTES)
  210.         if classObj is not None:
  211.             print 'Imported: ' + classObj.DESCRIPTIVE_NAME
  212.             return True
  213.         else:
  214.             return False
  215.  
  216. class DaemonConfig:
  217.    
  218.     stateSpaceCfg = None
  219.     filterCfg = None
  220.     pktHandler = None
  221.    
  222.     filterChain = []
  223.     nodeInterfaces = []
  224.     nodeInterfaceMap = {}
  225.    
  226.     INTERFACE_TYPES = {'serial' : NodeIfSerial, 'tcp' : NodeIfTCP,
  227.                        'udp' : NodeIfUDP, 'sim' : NodeIfCanStim,
  228.                        'tcptls' : NodeIfTCPTLS}
  229.  
  230.     def __init__ (self):
  231.         self.filterCfg = FilterCfg()
  232.         self.stateSpaceCfg = StateSpaceCfg()
  233.         self.pktHandler = CanPktHandler1(self)
  234.        
  235.     def load(self):
  236.         self.stateSpaceCfg.loadSpaces()
  237.         self.filterCfg.loadFilters()
  238.         self.__setupFilterBindings()
  239.         self.__setupStateSpaceRelations()
  240.         self.__setupFilterChain()
  241.  
  242.     def save(self):
  243.         self.stateSpaceCfg.saveSpaces()
  244.         self.filterCfg.saveFilters()
  245.        
  246.     def addInterface(self, type, cfg = None):
  247.         """ addInterface
  248.        type - a valid interface type name
  249.        cfg - interface configuration
  250.        returns: True on success, False otherwise """
  251.        
  252.         if not self.INTERFACE_TYPES.has_key(type):
  253.             log.debug('addInterface called with invalid interface type')
  254.             return False
  255.        
  256.         cfg = self.INTERFACE_TYPES[type].DEFAULT_CONFIG
  257.         print cfg
  258.         nodeIf = self.INTERFACE_TYPES[type](self.pktHandler, cfg)
  259.         print nodeIf
  260.         self.nodeInterfaces.append(nodeIf)
  261.    
  262.     def remInterface(self, name):
  263.         pass
  264.        
  265.     def __setupFilterChain(self):
  266.         self.filterChain = ['DefaultFilter']
  267.    
  268.     def __setupFilterBindings(self):
  269.         for f in self.filterCfg.filterModules.values():
  270.             assocSpaces = []
  271.             for s in f.ASSOCIATED_SPACES:
  272.                 if self.stateSpaceCfg.spaceModules.has_key(s):
  273.                     assocSpaces.append(self.stateSpaceCfg.spaceModules[s])
  274.                 else:
  275.                     print 'WARNING: Reference to undefined state space: ' + s
  276.             setattr(f, '__ASSOCIATED_SPACES__', assocSpaces)
  277.  
  278.     def __setupStateSpaceRelations(self):
  279.         for sm in self.stateSpaceCfg.spaceModules:
  280.             relatedSpaceNames = self.stateSpaceCfg.spaceModules[sm].RELATED_SPACES
  281.             relatedSpaces = {}
  282.             for rsname in relatedSpaceNames:
  283.                 relatedSpaces[rsname] = self.stateSpaceCfg.spaceModules[rsname]
  284.             setattr(self.stateSpaceCfg.spaceModules[sm], '__RELATED_SPACES__', relatedSpaces)
  285.  
  286.