Subversion Repositories HomeAutomation

Rev

Details | Last modification | View Log | SVN | RSS feed

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