Subversion Repositories HomeAutomation

Rev

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

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