Subversion Repositories HomeAutomation

Rev

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

Rev Author Line No. Line
736 olof 1
#!/bin/env python
2
 
3
import os
4
import sys
5
import logging as log
6
import getopt
7
import atexit
738 olof 8
import time
736 olof 9
 
10
from NodeIfBase import NodeIfBase
11
from NodeIfCanStim import NodeIfCanStim
12
from NodeIfSerial import NodeIfSerial
746 olof 13
from NodeIfTCP import NodeIfTCP
736 olof 14
 
15
from DaemonConfig import DaemonConfig
16
 
17
daemonApp = None
18
 
19
class CanDaemon():
20
 
740 olof 21
    cfg = None
738 olof 22
    ifNotifier = None
23
    terminated = False
741 olof 24
 
739 olof 25
    command_list = []
740 olof 26
    command_map = {}
741 olof 27
    CMDLIST_NAME = 0
28
    CMDLIST_HANDLER = 1
29
    CMDLIST_PARAMINFO = 2
30
    CMDLIST_HELP = 3
31
 
32
    logHelp = 'usage:\t log [options]\n\n' \
33
              '\t options:\n' \
34
              '\t level <num>, where: 0 < num < 3\n'
35
    stateHelp = 'usage: state [name/add/rem]'
36
    filterHelp = 'usage: filter [name/add/rem]'
37
    addifHelp = 'usage: addif [name] [options]'
38
    addbridgeHelp = 'usage: addbridge [interface names]'
39
    tcpdHelp = 'usage: tcpd [start/stop/configure] [options]'
40
    tlsdHelp = 'usage: tlsd [start/stop/configure] [options]'
41
    canctldHelp = 'usage: canctld [start/stop/configure] [options]'
42
    simHelp = 'usage: sim [record/play/add/rem/save/load] [options]'
740 olof 43
    help_command_map = {}
741 olof 44
 
45
    logOptions = {}
46
    ifOptions = {}
47
    bridgeOptions = {}
48
    tcpdOptions = {}
49
    tlsdOptions = {}
50
    canctldOptions = {}
51
    simOptions = {}
739 olof 52
 
741 olof 53
    logValidOptions = {'level' : ['range', 0, 3]}
54
    ifValidOptions = {'type' : ['alt', 'serial','udp']}
55
 
56
    ifSerialOptions = {'' : []}
57
    ifCanStimOptions = {'' : []}
58
    ifTelnetOptions = {'' : []}
59
    ifTcpTlsOptions = {'' : []}
60
    ifUDPOptions = {'' : []}
61
 
62
    bridgeValidOptions = {'' : ['']}
63
    tcpdValidOptions = {'' : []}
64
    tlsdValidOptions = {'' : []}
65
    canctldValidOptions = {'' : []}
66
    simValidOptions = {'' : []}
67
 
739 olof 68
    def __init__ (self):
740 olof 69
 
741 olof 70
        self.command_list = [['help', self.helpCmd, '', 'display help'],
71
                       ['log', self.logCmd, '<options>', 'log control: \"help log\"'],
72
                       ['exec', self.execCmd, '<filename>', 'run command listing\n'],
73
                       ['filter', self.filterCmd, '<cmd>', 'filter commands: \"help filter\"'],
74
                       ['state', self.stateCmd, '<cmd>', 'state commands: \"help state\"\n'],
75
                       ['addif', self.ifAddCmd, '<options>', 'add interface: \"help addif\"'],
76
                       ['remif', self.ifRemCmd, '<name>', 'remove interface'],
77
                       ['ifup', self.ifUpCmd, '<name>', 'bring up interface'],
78
                       ['ifdown', self.ifDownCmd, '<name>', 'bring down interface\n'],
79
                       ['addbrigde', self.addBridgeCmd, '<options>', 'add bridge: \"help addbridge\"'],
80
                       ['rembridge', self.remBridgeCmd, '<id>', 'remove bridge\n'],
81
                       ['tcpd', self.tcpdCmd, '<cmd>', 'tcpd server control: \"help tcpd\"'],
82
                       ['tlsd', self.tlsdCmd, '<cmd>', 'tlsd server control: \"help tlsd\"'],
83
                       ['canctld', self.canCtldCmd, '<cmd>', 'canctld server control: \"help canctld\"\n'],
84
                       ['status', self.statusCmd, '', 'show daemon status'],
747 olof 85
                       ['stats', self.statsCmd, '', 'show statistics'],
86
                       ['nodelist', self.nodesCmd, '', 'list can nodes\n'],
741 olof 87
                       ['sim', self.simCmd, '<cmd>', 'simulator commands: \"help sim\"']]
88
 
740 olof 89
        index = 0
90
        for cmd in self.command_list:
91
            self.command_map[cmd[0]] = index
92
            index += 1
93
 
741 olof 94
        self.help_command_map = {'log' : self.logHelp,
95
                                'filter' : self.filterHelp,
96
                                'state' : self.stateHelp,
97
                                'addif' : self.addifHelp,
98
                                'addbridge' : self.addbridgeHelp,
99
                                'tcpd' : self.tcpdHelp,
100
                                'tlsd' : self.tlsdHelp,
101
                                'canctld' : self.canctldHelp,
102
                                'sim' : self.simHelp}
740 olof 103
 
104
        self.cfg = DaemonConfig()
736 olof 105
 
738 olof 106
    class IfNotifier():
739 olof 107
        """ Used by if threads to send messages to the main program thread """
742 olof 108
 
109
        parent = None
738 olof 110
        UNDEFINED = 0
111
        TERMINATE = 1
742 olof 112
 
113
        def __init__(self, parent):
114
            self.parent = parent
738 olof 115
 
116
        def notify(self, msg):
117
            if msg == self.TERMINATE:
118
                print 'Main terminate notify'
119
            else:
120
                print 'UNDEFINED NOTIFY'
121
 
739 olof 122
 
123
    def __rightAdjust(self, refstr, str):
124
        spcstr = ''
741 olof 125
        endpos = 25-len(refstr)
739 olof 126
        for i in range(1,endpos):
127
            if i == endpos-5:
128
                spcstr += ':'
129
            else:
130
                spcstr += ' '
131
        return (spcstr+str)
132
 
133
    def helpCmd(self, *args):
741 olof 134
        try:
135
            args = args[0]
136
        except:
137
            args = []
740 olof 138
        if len(args) < 1:
139
            quitStr = 'quit, exit'
140
            print quitStr, self.__rightAdjust(quitStr, 'shutdown pyCanDaemon')
141
            for cmd in self.command_list:
741 olof 142
                cmdstr = cmd[self.CMDLIST_NAME] + ' ' + cmd[self.CMDLIST_PARAMINFO]
143
                print cmdstr, \
144
                      self.__rightAdjust(cmdstr, cmd[self.CMDLIST_HELP])
740 olof 145
        elif len(args) < 2:
146
            subCmd = args[0]
147
            if self.help_command_map.has_key(subCmd):
148
                print self.help_command_map[subCmd]
149
            else:
150
                print 'no help for ' + subCmd
151
        else:
152
            print 'usage: help [topic]'
153
 
739 olof 154
    def filterCmd(self, *args):
741 olof 155
        try:
156
            args = args[0]
157
        except:
158
            args = []
159
        log.debug('filterCmd ' + str(args))
160
        if len(args) < 2:
161
            print 'Invalid arguments\n' + self.filterHelp
162
            return
740 olof 163
        cmd = args[0]
164
        filterName = args[1]
165
        # FIXME: verify 
166
        if cmd == 'add':
167
            print 'Importing filter: ' + filterName
168
            self.cfg.filterCfg.importFilter(filterName)
169
        elif cmd == 'rem' or cmd == 'remove':
170
            print 'Deleting filter: ' + filterName
171
            # FIXME: actually delete
741 olof 172
            raise 'Not implemented'
736 olof 173
 
739 olof 174
    def stateCmd(self, *args):
741 olof 175
        try:
176
            args = args[0]
177
        except:
178
            args = []
179
        log.debug('stateCmd ' + str(args))
180
        if len(args) < 2:
181
            print 'Invalid arguments\n' + self.stateHelp
182
            return
740 olof 183
        cmd = args[0]
184
        spaceName = args[1]
741 olof 185
        # FIXME: verify 
740 olof 186
        if cmd == 'add':
187
            print 'Importing state space: ' + spaceName
188
            self.cfg.stateSpaceCfg.importSpace(spaceName)
189
        elif cmd == 'rem' or cmd == 'remove':
190
            print 'Deleting state space: ' + spaceName
191
            # FIXME: actually delete statespace
741 olof 192
            raise 'Not implemented'
736 olof 193
 
739 olof 194
    def ifAddCmd(self, *args):
741 olof 195
        raise 'not implemented'
736 olof 196
 
739 olof 197
    def ifRemCmd(self, *args):
741 olof 198
        raise 'not implemented'
740 olof 199
 
739 olof 200
    def ifUpCmd(self, *args):
741 olof 201
        raise 'not implemented'
740 olof 202
 
739 olof 203
    def ifDownCmd(self, *args):
741 olof 204
        raise 'not implemented'
736 olof 205
 
739 olof 206
    def addBridgeCmd(self, *args):
741 olof 207
        raise 'not implemented'
740 olof 208
 
739 olof 209
    def remBridgeCmd(self, *args):
741 olof 210
        raise 'not implemented'
739 olof 211
 
212
    def tcpdCmd(self, *args):
741 olof 213
        raise 'not implemented'
739 olof 214
 
215
    def tlsdCmd(self, *args):
741 olof 216
        raise 'not implemented'
739 olof 217
 
218
    def canCtldCmd(self, *args):
741 olof 219
        raise 'not implemented'
739 olof 220
 
221
    def statusCmd(self, *args):
741 olof 222
        raise 'not implemented'
739 olof 223
 
224
    def statsCmd(self, *args):
741 olof 225
        raise 'not implemented'
739 olof 226
 
227
    def nodesCmd(self, *args):
741 olof 228
        raise 'not implemented'
739 olof 229
 
230
    def simCmd(self, *args):
741 olof 231
        raise 'not implemented'
739 olof 232
 
233
    def logCmd(self, *args):
741 olof 234
        raise 'not implemented'
740 olof 235
 
739 olof 236
    def execCmd(self, *args):
741 olof 237
        raise 'not implemented'
739 olof 238
 
741 olof 239
    def parseCommand(self, cmdstr):
240
        incmd = cmdstr.strip()
241
        cmd = incmd.split(' ')
242
        if len(cmd[0]) < 2:
243
            return
244
        cmd[0] = cmd[0].lower()
245
        if cmd[0] == 'quit' or cmd[0] == 'exit':
246
            self.terminated = True
247
        elif self.command_map.has_key(cmd[0]):
248
            self.command_list[self.command_map[cmd[0]]][self.CMDLIST_HANDLER](cmd[1:])
249
        else:
250
            print 'unknown command: ' + cmd[0]
251
 
736 olof 252
    def exitHelper(self):
749 olof 253
        pass
254
#        if self.nodeIf is not None and self.nodeIf.running():
255
#            self.nodeIf.stop()
739 olof 256
 
257
    def exceptHelper(self, type, value, tb):
258
        import traceback
259
        traceback.print_exception(type, value, tb)
260
        print '\nException in main program, shutting down threads'
261
        self.terminated = True
262
        self.exitHelper()
263
 
749 olof 264
 
736 olof 265
    def run(self):
266
        try:
741 olof 267
            myPath = os.path.dirname(__file__)
268
            os.chdir(myPath)
736 olof 269
        except:
270
            return
271
 
737 olof 272
        print 'INIT: Start logging'
736 olof 273
        log.basicConfig(level=log.DEBUG)
274
 
741 olof 275
        """command parameters only dictate verbosity and use of config file"""
737 olof 276
        print 'INIT: Get config options from command line / config file'
736 olof 277
        try:
278
            opts, args = getopt.getopt(sys.argv[1:], "ho:v", ["help", "output="])
279
        except getopt.GetoptError:
280
            print 'Invalid usage'
281
            usage()
282
            sys.exit(2)
283
     #   output = None
284
     #   verbose = False
285
        for o, a in opts:
286
            if o == "-v":
287
                pass
288
     #           verbose = True
289
            if o in ("-h", "--help"):
290
                usage()
291
                sys.exit()
292
            if o in ("-o", "--output"):
293
                pass
294
    #            output = a
740 olof 295
 
741 olof 296
        """load config defaults, or last config if exists"""
297
        """run startup.cfg"""
749 olof 298
        print 'INIT: Loading daemon configuration'
299
        self.cfg = DaemonConfig()
300
        self.cfg.load()
750 olof 301
 
302
        # create interface for debugging purpose
303
        self.cfg.addInterface('tcp', None)
751 olof 304
        # create daemon
305
        self.cfg.addServerDaemon('tcpd', None)
740 olof 306
 
749 olof 307
        self.ifNotifier = self.IfNotifier(self)        
308
        for nodeIf in self.cfg.nodeInterfaces:
309
            nodeIf.setIfNotifier(self.ifNotifier)
310
 
746 olof 311
        atexit.register(self.exitHelper)
312
        sys.excepthook = self.exceptHelper
736 olof 313
 
749 olof 314
        print 'INIT: Starting configured node interfaces'
315
        for nodeIf in self.cfg.nodeInterfaces:
316
            if not nodeIf.start():
317
                print 'FATAL: Failed to initialize node interface.'
318
                print 'This may indicate that the interface is unavailable, ' \
319
                      'or that you do not have permission to access it.'
320
                sys.exit(-1)
321
 
322
        print 'INIT: Initialize/gather info on connected can nodes and load associated state'
323
        print 'INIT: Starting configured servers'
751 olof 324
        for serverd in self.cfg.serverDaemons:
325
            if not serverd.start():
326
                print 'FATAL: Failed to initialize server daemon.'
327
                system.exit(-1)
736 olof 328
 
329
        print 'CanDaemon v1 ready'
330
        print 'Enter command or type \"help\" for a list of commands'
738 olof 331
        while not self.terminated:
741 olof 332
            input = raw_input('> ')
333
            self.parseCommand(input)
750 olof 334
 
736 olof 335
        print 'Shutdown'
749 olof 336
        self.cfg.save()
738 olof 337
 
749 olof 338
        for nodeIf in self.cfg.nodeInterfaces:
750 olof 339
            if nodeIf.running():
749 olof 340
                print 'Stopping If thread'
750 olof 341
                nodeIf.stop()
749 olof 342
 
739 olof 343
        print 'Waiting 0.1..'
738 olof 344
        time.sleep(0.1) # wait for threads
739 olof 345
        print 'Terminating'
738 olof 346
        sys.exit(0) # will except if there are threads remaining
736 olof 347
 
348
#---------------------------------------------------------------------------
349
 
350
def main():
351
    daemonApp = CanDaemon()
737 olof 352
#    install_thread_excepthook()
736 olof 353
    daemonApp.run()
354
 
355
#---------------------------------------------------------------------------
356
 
357
if __name__ == '__main__':
358
    __name__ = 'Main'
359
    main()