Subversion Repositories HomeAutomation

Rev

Rev 750 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. #!/bin/env python
  2.  
  3. import os
  4. import sys
  5. import logging as log
  6. import getopt
  7. import atexit
  8. import time
  9.  
  10. from NodeIfBase import NodeIfBase
  11. from NodeIfCanStim import NodeIfCanStim
  12. from NodeIfSerial import NodeIfSerial
  13. from NodeIfTCP import NodeIfTCP
  14.  
  15. from DaemonConfig import DaemonConfig
  16.  
  17. daemonApp = None
  18.  
  19. class CanDaemon():
  20.    
  21.     cfg = None
  22.     ifNotifier = None
  23.     terminated = False
  24.    
  25.     command_list = []
  26.     command_map = {}
  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]'
  43.     help_command_map = {}
  44.    
  45.     logOptions = {}
  46.     ifOptions = {}
  47.     bridgeOptions = {}
  48.     tcpdOptions = {}
  49.     tlsdOptions = {}
  50.     canctldOptions = {}
  51.     simOptions = {}
  52.  
  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.  
  68.     def __init__ (self):
  69.        
  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'],
  85.                        ['stats', self.statsCmd, '', 'show statistics'],
  86.                        ['nodelist', self.nodesCmd, '', 'list can nodes\n'],
  87.                        ['sim', self.simCmd, '<cmd>', 'simulator commands: \"help sim\"']]
  88.        
  89.         index = 0
  90.         for cmd in self.command_list:
  91.             self.command_map[cmd[0]] = index
  92.             index += 1
  93.  
  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}
  103.  
  104.         self.cfg = DaemonConfig()
  105.    
  106.     class IfNotifier():
  107.         """ Used by if threads to send messages to the main program thread """
  108.        
  109.         parent = None
  110.         UNDEFINED = 0
  111.         TERMINATE = 1
  112.        
  113.         def __init__(self, parent):
  114.             self.parent = parent
  115.    
  116.         def notify(self, msg):
  117.             if msg == self.TERMINATE:
  118.                 print 'Main terminate notify'
  119.             else:
  120.                 print 'UNDEFINED NOTIFY'
  121.        
  122.    
  123.     def __rightAdjust(self, refstr, str):
  124.         spcstr = ''
  125.         endpos = 25-len(refstr)
  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):
  134.         try:
  135.             args = args[0]
  136.         except:
  137.             args = []
  138.         if len(args) < 1:
  139.             quitStr = 'quit, exit'
  140.             print quitStr, self.__rightAdjust(quitStr, 'shutdown pyCanDaemon')
  141.             for cmd in self.command_list:
  142.                 cmdstr = cmd[self.CMDLIST_NAME] + ' ' + cmd[self.CMDLIST_PARAMINFO]
  143.                 print cmdstr, \
  144.                       self.__rightAdjust(cmdstr, cmd[self.CMDLIST_HELP])
  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.  
  154.     def filterCmd(self, *args):
  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
  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
  172.             raise 'Not implemented'
  173.    
  174.     def stateCmd(self, *args):
  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
  183.         cmd = args[0]
  184.         spaceName = args[1]
  185.         # FIXME: verify
  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
  192.             raise 'Not implemented'
  193.    
  194.     def ifAddCmd(self, *args):
  195.         raise 'not implemented'
  196.    
  197.     def ifRemCmd(self, *args):
  198.         raise 'not implemented'
  199.  
  200.     def ifUpCmd(self, *args):
  201.         raise 'not implemented'
  202.  
  203.     def ifDownCmd(self, *args):
  204.         raise 'not implemented'
  205.    
  206.     def addBridgeCmd(self, *args):
  207.         raise 'not implemented'
  208.  
  209.     def remBridgeCmd(self, *args):
  210.         raise 'not implemented'
  211.    
  212.     def tcpdCmd(self, *args):
  213.         raise 'not implemented'
  214.    
  215.     def tlsdCmd(self, *args):
  216.         raise 'not implemented'
  217.    
  218.     def canCtldCmd(self, *args):
  219.         raise 'not implemented'
  220.    
  221.     def statusCmd(self, *args):
  222.         raise 'not implemented'
  223.    
  224.     def statsCmd(self, *args):
  225.         raise 'not implemented'
  226.    
  227.     def nodesCmd(self, *args):
  228.         raise 'not implemented'
  229.    
  230.     def simCmd(self, *args):
  231.         raise 'not implemented'
  232.    
  233.     def logCmd(self, *args):
  234.         raise 'not implemented'
  235.  
  236.     def execCmd(self, *args):
  237.         raise 'not implemented'
  238.    
  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.    
  252.     def exitHelper(self):
  253.         pass
  254. #        if self.nodeIf is not None and self.nodeIf.running():
  255. #            self.nodeIf.stop()
  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.  
  264.  
  265.     def run(self):
  266.         try:
  267.             myPath = os.path.dirname(__file__)
  268.             os.chdir(myPath)
  269.         except:
  270.             return
  271.        
  272.         print 'INIT: Start logging'
  273.         log.basicConfig(level=log.DEBUG)
  274.        
  275.         """command parameters only dictate verbosity and use of config file"""
  276.         print 'INIT: Get config options from command line / config file'
  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
  295.  
  296.         """load config defaults, or last config if exists"""
  297.         """run startup.cfg"""
  298.         print 'INIT: Loading daemon configuration'
  299.         self.cfg = DaemonConfig()
  300.         self.cfg.load()
  301.        
  302.         # create interface for debugging purpose
  303.         self.cfg.addInterface('tcp', None)
  304.         # create daemon
  305.         self.cfg.addServerDaemon('tcpd', None)
  306.  
  307.         self.ifNotifier = self.IfNotifier(self)        
  308.         for nodeIf in self.cfg.nodeInterfaces:
  309.             nodeIf.setIfNotifier(self.ifNotifier)
  310.            
  311.         atexit.register(self.exitHelper)
  312.         sys.excepthook = self.exceptHelper
  313.  
  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'
  324.         for serverd in self.cfg.serverDaemons:
  325.             if not serverd.start():
  326.                 print 'FATAL: Failed to initialize server daemon.'
  327.                 system.exit(-1)
  328.        
  329.         print 'CanDaemon v1 ready'
  330.         print 'Enter command or type \"help\" for a list of commands'
  331.         while not self.terminated:
  332.             input = raw_input('> ')
  333.             self.parseCommand(input)
  334.        
  335.         print 'Shutdown'
  336.         self.cfg.save()
  337.        
  338.         for nodeIf in self.cfg.nodeInterfaces:
  339.             if nodeIf.running():
  340.                 print 'Stopping If thread'
  341.                 nodeIf.stop()
  342.        
  343.         print 'Waiting 0.1..'
  344.         time.sleep(0.1) # wait for threads
  345.         print 'Terminating'
  346.         sys.exit(0) # will except if there are threads remaining
  347.  
  348. #---------------------------------------------------------------------------
  349.  
  350. def main():
  351.     daemonApp = CanDaemon()
  352. #    install_thread_excepthook()
  353.     daemonApp.run()
  354.  
  355. #---------------------------------------------------------------------------
  356.  
  357. if __name__ == '__main__':
  358.     __name__ = 'Main'
  359.     main()
  360.