Subversion Repositories HomeAutomation

Rev

Rev 751 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | SVN | RSS feed

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