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