hod
上传用户:quxuerui
上传日期:2018-01-08
资源大小:41811k
文件大小:23k
源码类别:

网格计算

开发平台:

Java

  1. #!/bin/sh
  2. # Licensed to the Apache Software Foundation (ASF) under one or more
  3. # contributor license agreements.  See the NOTICE file distributed with
  4. # this work for additional information regarding copyright ownership.
  5. # The ASF licenses this file to You under the Apache License, Version 2.0
  6. # (the "License"); you may not use this file except in compliance with
  7. # the License.  You may obtain a copy of the License at
  8. #
  9. #     http://www.apache.org/licenses/LICENSE-2.0
  10. #
  11. # Unless required by applicable law or agreed to in writing, software
  12. # distributed under the License is distributed on an "AS IS" BASIS,
  13. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. # See the License for the specific language governing permissions and
  15. # limitations under the License.
  16. """:"
  17. work_dir=$(dirname $0)
  18. base_name=$(basename $0)
  19. original_dir=$PWD
  20. cd $work_dir
  21. if [ $HOD_PYTHON_HOME ]; then
  22.     exec $HOD_PYTHON_HOME -u -OO $base_name ${1+"$@"} --hod.original-dir $original_dir
  23. elif [ -e /usr/bin/python ]; then
  24.     exec /usr/bin/python -u -OO $base_name ${1+"$@"} --hod.original-dir $original_dir
  25. elif [ -e /usr/local/bin/python ]; then
  26.     exec /usr/local/bin/python -u -OO $base_name ${1+"$@"} --hod.original-dir $original_dir
  27. else
  28.     exec python -u -OO $base_name ${1+"$@"} --hod.original-dir $work_dir
  29. fi
  30. ":"""
  31. """The executable to be used by the user"""
  32. import sys, os, re, pwd, threading, sys
  33. myName          = os.path.basename(sys.argv[0])
  34. myName          = re.sub(".*/", "", myName)
  35. binDirectory    = os.path.realpath(sys.argv[0])
  36. rootDirectory   = re.sub("/bin/.*", "", binDirectory)
  37. libDirectory    = rootDirectory
  38. sys.path.append(libDirectory)
  39. from hodlib.Hod.hod import hodRunner
  40. from hodlib.Common.setup import *
  41. from hodlib.Common.descGenerator import *
  42. from hodlib.Common.util import local_fqdn, need_to_allocate, filter_warnings,
  43.     get_exception_error_string, hodInterrupt, 
  44.     HOD_INTERRUPTED_MESG, HOD_INTERRUPTED_CODE,
  45.     TORQUE_USER_LIMITS_COMMENT_FIELD
  46. from hodlib.Common.tcp import tcpError, tcpSocket
  47. from hodlib.Hod.hod import hodHelp
  48. filter_warnings()
  49. reVersion = re.compile(".*(d+_d+).*")
  50. VERSION = None
  51. if os.path.exists("./VERSION"):
  52.   vFile = open("./VERSION", 'r')
  53.   VERSION = vFile.readline()
  54.   vFile.close()
  55. # Always look for hodrc file here unless otherwise specified with -c:   
  56. DEFAULT_LOC = os.path.join(rootDirectory, 'conf')
  57. DEFAULT_HOD_DIR = os.path.join(os.environ['HOME'], ".hod")
  58. if not os.path.isdir(DEFAULT_HOD_DIR):
  59.   os.mkdir(DEFAULT_HOD_DIR, 0777)
  60. DEFAULT_CONFIG = os.path.join(DEFAULT_HOD_DIR, 'hodrc')
  61. if not os.path.exists(DEFAULT_CONFIG):
  62.   if os.environ.has_key('HOD_CONF_DIR') and os.environ['HOD_CONF_DIR'] is not None:
  63.     DEFAULT_CONFIG = os.path.join(os.environ['HOD_CONF_DIR'], 'hodrc')
  64. # Definition tuple is of the form:
  65. #  (name, type, description, help?, default value, required?, validate?, 
  66. #   short option)
  67. #
  68. defList = { 'hod' : (      
  69.              ('original-dir', 'directory', 'hod original start directory',
  70.               False, None, True, True, 'r'),
  71.              ('clusterdir', 'directory', 
  72.              'Directory where cluster state information and hadoop-site.xml' +
  73.              ' will be stored.',
  74.               True, None, False, False, 'd'),
  75.              ('syslog-address', 'address', 'Syslog address.',
  76.               False, None, False, True, 'y'),
  77.               
  78.              ('java-home', 'directory', 'Java home directory.',
  79.               True, None, True, True, 'j'),
  80.             
  81.              ('debug', 'pos_int', 'Debugging level, 0-4.',
  82.               True, 3, True, True, 'b'),
  83.             
  84.              ('stream', 'bool', 'Output to stderr.',
  85.               False, True, False, True),
  86.              ('nodecount', 'pos_int', 
  87.               'Number of nodes to allocate at startup. ',
  88.               True, None, False, True, 'n'),
  89.              ('script', 'file', 'Hadoop script to execute.',
  90.               True, None, False, False, 's'), 
  91.              ('userid', 'user_account', 
  92.               'User ID the hod shell is running under.',
  93.               False, pwd.getpwuid(os.getuid())[0], False, True, 'u'),
  94.              
  95.              ('allocate-wait-time', 'pos_int', 
  96.               'Time to wait for cluster allocation.',
  97.               False, 300, True, True, 'e'),         
  98.               
  99.              ('operation', 'string',
  100.               'Initiate a hod operation. (help, allocate, deallocate ...)',
  101.               False, None, False, True, 'o'),
  102.              
  103.              ('cluster-factor', 'pos_float',
  104.               'The number of grid slots per machines', False, 1.9, False, True,
  105.               'x'),
  106.              
  107.              ('cluster', 'string', 'Name of cluster being used.',
  108.               False, None, True, True, 'w'),
  109.              ('proxy-xrs-address', 'address', 
  110.               'Address to Allocation Manager XML RPC proxy.',
  111.               False, None, False, True, 'p'),
  112.               
  113.              ('xrs-port-range', 'range', 'XML-RPC port range n-m.',
  114.               False, None, True, True),
  115.              ('client-params', 'keyval', 'Hadoop client xml key/value list',
  116.               True, None, False, True, 'C'), 
  117.              ('hadoop-ui-log-dir', 'directory', 'Directory to store Web UI Logs of Hadoop',
  118.               True, None, False, True),
  119.              ('temp-dir', 'directory', 'HOD temporary directories.',
  120.               False, None, True, False),
  121.              ('update-worker-info', 'bool', 'Specifies whether to update Worker Info after allocation',
  122.               False, False, False, True),
  123.              ('job-feasibility-attr', 'string', 'Specifies whether to check job feasibility - resource manager and/or scheduler limits, also gives the attribute value',
  124.               False, None, False, True),
  125.              ('title', 'string', 'Title for the current HOD allocation.',
  126.                True, "HOD", False, True, 'N'),
  127.              ('walltime', 'pos_int', 'Walltime in seconds for the current HOD allocation',
  128.               True, None, False, True, 'l'),
  129.              ('script-wait-time', 'pos_int', 'Specifies the time to wait before running the script. Used with the hod.script option.',
  130.               True, 10, False, True, 'W'),
  131.              ('log-rollover-count', 'pos_int', 'Specifies the number of rolled-over log files of HOD client. A zero value disables rollover.',
  132.               True, 5, False, True, 'L'),
  133.              ('job-status-query-interval', 'pos_int', 'Specifies the time between checking for job status', 
  134.               False, 30, False, True),
  135.              ('job-command-failure-interval', 'pos_int', 'Specifies the time between checking for failed job status or submission commands', 
  136.               False, 10, False, True),
  137.              ('job-status-query-failure-retries', 'pos_int', 'Specifies the number of times job status failure queries are retried', 
  138.               False, 3, False, True),
  139.              ('job-submission-failure-retries', 'pos_int', 'Specifies the number of times job submission failure queries are retried',
  140.               False, 3, False, True)),
  141.             'resource_manager' : (
  142.              ('id', 'string', 'Batch scheduler ID: torque|condor.',
  143.               False, None, True, True),
  144.              
  145.              ('pbs-user', 'user_account', 'User ID jobs are submitted under.',
  146.               False, None, False, True),
  147.               
  148.              ('pbs-account', 'string', 'User Account jobs are submitted under.',
  149.               True, None, False, False, 'A'),
  150.               
  151.              ('queue', 'string', 'Queue of the batch scheduler to query.',
  152.               True, 'batch', False, True, 'Q'),
  153.              
  154.              ('batch-home', 'directory', 'Scheduler installation directory.',
  155.               False, None, True, True),
  156.              
  157.              ('options', 'keyval', 'Options to pass to the scheduler.',
  158.               False, None, False, True),
  159.              ('env-vars', 'keyval', 'Environment variables to pass to the submitted jobs.',
  160.               False, None, False, True)),
  161.                             
  162.             'ringmaster' : (
  163.              ('work-dirs', 'list', 'hod work directories',
  164.               False, None, True, False),
  165.              ('temp-dir', 'directory', 'Ringmaster temporary directory.',
  166.               False, None, True, False),
  167.               
  168.              ('log-dir', 'directory', 'hod logging directory.', 
  169.               False, os.path.join(rootDirectory, 'logs'), False, False),
  170.              ('syslog-address', 'address', 'Syslog address.',
  171.               False, None, False, True),
  172.              ('xrs-port-range', 'range', 'XML-RPC port range n-m.',
  173.               False, None, True, True),
  174.               
  175.              ('http-port-range', 'range', 'HTTP port range n-m.',
  176.               False, None, True, True),
  177.               
  178.              ('debug', 'pos_int', 'Debugging level, 0-4.',
  179.               False, 4, True,   True),
  180.                
  181.              ('register', 'bool', 'Register with service registry?',
  182.               False, True, True, True),
  183.                
  184.              ('stream', 'bool', 'Output to stderr.',
  185.               False, False, False, True),
  186.               
  187.              ('userid', 'user_account', 
  188.               'User ID the hod shell is running under.',
  189.               False, pwd.getpwuid(os.getuid())[0], False, True),
  190.                
  191.              ('svcrgy-addr', 'address', 'Download HTTP address.',
  192.               False, None, False, False),             
  193.              
  194.              ('hadoop-tar-ball', 'uri', 'hadoop program tar ball.',
  195.               True, None, False, False, 't'),
  196.              ('max-connect','pos_int','max connections allowed for a single tarball server',
  197.              False, 30, False, True),
  198.              ('jt-poll-interval', 'pos_int', 'How often to poll the Job tracker for idleness',
  199.              False, 120, False, True),
  200.              ('idleness-limit', 'pos_int', 'Limit after which to deallocate the cluster',
  201.              False, 3600, False, True),
  202.              ('max-master-failures', 'pos_int', 
  203.               'Defines how many times a master can fail before' 
  204.               ' failing cluster allocation', False, 5, True, True),
  205.              ('workers_per_ring', 'pos_int', 'Defines number of workers per service per hodring',
  206.              False, 1, False, True)),
  207.             'gridservice-mapred' : (
  208.              ('external', 'bool', "Connect to an already running MapRed?",
  209.               False, False, True, True),
  210.               
  211.              ('host', 'hostname', 'Mapred hostname.', 
  212.               False, 'localhost', False, False),
  213.              ('info_port', 'pos_int', 'Mapred info port.',
  214.               False, None, False, False),
  215.              
  216.              ('tracker_port', 'pos_int', 'Mapred job tracker port.',
  217.               False, None, False, False),
  218.                         
  219.              ('cmdline-params', 'keyval', 'Hadoop cmdline key/value list.',
  220.               False, None, False, False),
  221.              ('server-params', 'keyval', 'Hadoop xml key/value list',
  222.               True, None, False, True, 'M'),
  223.                
  224.              ('envs', 'keyval', 'environment to run this package in',
  225.               False, None, False, True),
  226.              ('final-server-params', 'keyval', 'Hadoop final xml key/val list',
  227.               False, None, False, True, 'F'),
  228.              ('pkgs', 'directory', "directory where the package is installed",
  229.               False, None, False, False)), 
  230.                
  231.                
  232.             'gridservice-hdfs' : (
  233.              ('external', 'bool', "Connect to an already running HDFS?",
  234.               False, False, True, True),
  235.              
  236.              ('host', 'hostname', 'HDFS hostname.', 
  237.               False, 'localhost', False, False),
  238.              
  239.              ('fs_port', 'pos_int', 'HDFS port.',
  240.               False, None, False, False),
  241.               
  242.              ('info_port', 'pos_int', 'HDFS info port.',
  243.               False, None, False, False), 
  244.              
  245.              ('cmdline-params', 'keyval', 'Hadoop cmdline key/value list.',
  246.               False, None, False, False),
  247.              ('server-params', 'keyval', 'Hadoop xml key/value list',
  248.               False, None, False, True, 'H'),
  249.              ('final-server-params', 'keyval', 'Hadoop final xml key/value list',
  250.               False, None, False, True, 'S'),
  251.            
  252.              ('envs', 'keyval', 'Environment in which to run this package.',
  253.               False, None, False, True),
  254.              ('pkgs', 'directory', "directory where the package is installed",
  255.               False, None, False, False)),           
  256.              
  257.              
  258.             'hodring' : (
  259.              ('temp-dir', 'list', 'hodring temporary directory.',
  260.               False, None, True, False),
  261.               
  262.              ('log-dir', 'directory', 'hod logging directory.', 
  263.               False, os.path.join(rootDirectory, 'logs'), False, False), 
  264.               
  265.              ('log-destination-uri', 'string', 
  266.               'URI to store logs to, local://some_path or '
  267.               + 'hdfs://host:port/some_path', 
  268.               False, None, False, True),
  269.              ('pkgs', 'directory', 'Path to Hadoop to use in case of uploading to HDFS',
  270.               False, None, False, False),
  271.               
  272.              ('syslog-address', 'address', 'Syslog address.',
  273.               False, None, False, True),
  274.           
  275.              ('java-home', 'directory', 'Java home directory.',
  276.               False, None, True, False),
  277.               
  278.              ('debug', 'pos_int', 'Debugging level, 0-4.',
  279.               False, 3, True, True),
  280.                
  281.              ('register', 'bool', 'Register with service registry?',
  282.               False, True, True, True),
  283.                
  284.              ('stream', 'bool', 'Output to stderr.',
  285.               False, False, False, True),
  286.              ('userid', 'user_account', 
  287.               'User ID the hod shell is running under.',
  288.               False, pwd.getpwuid(os.getuid())[0], False, True),
  289.                
  290.              ('command', 'string', 'Command for hodring to run.',
  291.               False, None, False, True),
  292.              ('xrs-port-range', 'range', 'XML-RPC port range n-m.',
  293.               False, None, True, True),
  294.                
  295.              ('http-port-range', 'range', 'HTTP port range n-m.',
  296.               False, None, True, True),
  297.               
  298.              ('service-id', 'string', 'Service ID.',
  299.               False, None, False, True),
  300.               
  301.              ('download-addr', 'string', 'Download HTTP address.',
  302.               False, None, False, True),
  303.                
  304.              ('svcrgy-addr', 'address', 'Download HTTP address.',
  305.               False, None, False, True), 
  306.     
  307.              ('ringmaster-xrs-addr', 'address', 'Ringmaster XML-RPC address.',
  308.               False, None, False, True),
  309.              ('tarball-retry-initial-time', 'pos_float','Initial Retry time for tarball download',
  310.               False, 1, False, True),
  311.               
  312.              ('tarball-retry-interval', 'pos_float','interval to spread retries for tarball download',
  313.               False, 3, False, True),
  314.               
  315.              ('cmd-retry-initial-time', 'pos_float','Initial retry time for getting commands',
  316.               False, 2, False, True),
  317.              
  318.              ('cmd-retry-interval', 'pos_float','interval to spread retries for getting commands',
  319.               False, 2, False, True),
  320.              ('mapred-system-dir-root', 'string', 'Root under which mapreduce system directory names are generated by HOD.',
  321.               False, '/mapredsystem', False, False))
  322.               }   
  323. defOrder = [ 'hod', 'ringmaster', 'hodring', 'resource_manager', 
  324.              'gridservice-mapred', 'gridservice-hdfs' ]
  325. def printErrors(msgs):
  326.   for msg in msgs:
  327.     print msg
  328. def op_requires_pkgs(config):
  329.   if config['hod'].has_key('operation'):
  330.     return config['hod']['operation'].startswith('allocate')
  331.   else:
  332.     return config['hod'].has_key('script')
  333. if __name__ == '__main__':  
  334.   try:
  335.     confDef = definition()
  336.     confDef.add_defs(defList, defOrder)
  337.     hodhelp = hodHelp()
  338.     usage = hodhelp.help()
  339.             
  340.     hodOptions = options(confDef, usage,
  341.                       VERSION, withConfig=True, defaultConfig=DEFAULT_CONFIG,
  342.                       name=myName )
  343.     # hodConfig is a dict like object, hodConfig[section][name]
  344.     try:
  345.       hodConfig = config(hodOptions['config'], configDef=confDef, 
  346.                        originalDir=hodOptions['hod']['original-dir'],
  347.                        options=hodOptions) 
  348.     except IOError, e:
  349.       print >>sys.stderr,"error: %s not found. Specify the path to the HOD configuration file, or define the environment variable %s under which a file named hodrc can be found." % (hodOptions['config'], 'HOD_CONF_DIR')
  350.       sys.exit(1)
  351.   
  352.     # Conditional validation
  353.     statusMsgs = []
  354.     if hodConfig.normalizeValue('gridservice-hdfs', 'external'):
  355.       # For external HDFS
  356.       statusMsgs.extend(hodConfig.validateValue('gridservice-hdfs',
  357.                                                 'fs_port'))
  358.       statusMsgs.extend(hodConfig.validateValue('gridservice-hdfs',
  359.                                                 'info_port'))
  360.       statusMsgs.extend(hodConfig.validateValue('gridservice-hdfs',
  361.                                                 'host'))
  362.     else:
  363.       hodConfig['gridservice-hdfs']['fs_port'] = 0 # Dummy
  364.       hodConfig['gridservice-hdfs']['info_port'] = 0 # Not used at all
  365.     if hodConfig.normalizeValue('gridservice-mapred', 'external'):
  366.       statusMsgs.extend(hodConfig.validateValue('gridservice-mapred',
  367.                                                 'tracker_port'))
  368.       statusMsgs.extend(hodConfig.validateValue('gridservice-mapred',
  369.                                                 'info_port'))
  370.       statusMsgs.extend(hodConfig.validateValue('gridservice-mapred',
  371.                                                 'host'))
  372.     else:
  373.       hodConfig['gridservice-mapred']['tracker_port'] = 0 # Dummy
  374.       hodConfig['gridservice-mapred']['info_port'] = 0 # Not used at all
  375.     if len(statusMsgs) != 0:
  376.       for msg in statusMsgs:
  377.         print >>sys.stderr, msg
  378.       sys.exit(1)
  379.     # End of conditional validation
  380.     status = True
  381.     statusMsgs = []
  382.   
  383.     (status,statusMsgs) = hodConfig.verify()
  384.     if not status:
  385.       print >>sys.stderr,"error: bin/hod failed to start."
  386.       for msg in statusMsgs:
  387.         print >>sys.stderr,"%s" % (msg)
  388.       sys.exit(1)
  389.   
  390.     ## TODO : should move the dependency verification to hodConfig.verify
  391.     if hodConfig['hod'].has_key('operation') and 
  392.       hodConfig['hod'].has_key('script'):
  393.       print "Script operation is mutually exclusive with other HOD operations"
  394.       hodOptions.print_help(sys.stderr)
  395.       sys.exit(1)
  396.     
  397.     if 'operation' not in hodConfig['hod'] and 'script' not in hodConfig['hod']:
  398.       print "HOD requires at least a script or operation be specified."
  399.       hodOptions.print_help(sys.stderr)
  400.       sys.exit(1)    
  401.     
  402.     if hodConfig['gridservice-hdfs']['external']:
  403.       hdfsAddress = "%s:%s" % (hodConfig['gridservice-hdfs']['host'], 
  404.                                hodConfig['gridservice-hdfs']['fs_port'])
  405.   
  406.       hdfsSocket = tcpSocket(hdfsAddress)
  407.         
  408.       try:
  409.         hdfsSocket.open()
  410.         hdfsSocket.close()
  411.       except tcpError:
  412.         printErrors(hodConfig.var_error('hod', 'gridservice-hdfs', 
  413.           "Failed to open a connection to external hdfs address: %s." % 
  414.           hdfsAddress))
  415.         sys.exit(1)
  416.     else:
  417.       hodConfig['gridservice-hdfs']['host'] = 'localhost'
  418.   
  419.     if hodConfig['gridservice-mapred']['external']:
  420.       mapredAddress = "%s:%s" % (hodConfig['gridservice-mapred']['host'], 
  421.                                  hodConfig['gridservice-mapred']['tracker_port'])
  422.   
  423.       mapredSocket = tcpSocket(mapredAddress)
  424.         
  425.       try:
  426.         mapredSocket.open()
  427.         mapredSocket.close()
  428.       except tcpError:
  429.         printErrors(hodConfig.var_error('hod', 'gridservice-mapred', 
  430.           "Failed to open a connection to external mapred address: %s." % 
  431.           mapredAddress))
  432.         sys.exit(1)
  433.     else:
  434.       hodConfig['gridservice-mapred']['host'] = 'localhost'
  435.   
  436.     if not hodConfig['ringmaster'].has_key('hadoop-tar-ball') and 
  437.       not hodConfig['gridservice-hdfs'].has_key('pkgs') and 
  438.       op_requires_pkgs(hodConfig):
  439.       printErrors(hodConfig.var_error('gridservice-hdfs', 'pkgs', 
  440.         "gridservice-hdfs.pkgs must be defined if ringmaster.hadoop-tar-ball "
  441.         + "is not defined."))
  442.       sys.exit(1)
  443.   
  444.     if not hodConfig['ringmaster'].has_key('hadoop-tar-ball') and 
  445.       not hodConfig['gridservice-mapred'].has_key('pkgs') and 
  446.       op_requires_pkgs(hodConfig):
  447.       printErrors(hodConfig.var_error('gridservice-mapred', 'pkgs', 
  448.         "gridservice-mapred.pkgs must be defined if ringmaster.hadoop-tar-ball "
  449.         + "is not defined."))
  450.       sys.exit(1)
  451.   
  452.     if hodConfig['hodring'].has_key('log-destination-uri'):
  453.       if hodConfig['hodring']['log-destination-uri'].startswith('file://'):
  454.         pass
  455.       elif hodConfig['hodring']['log-destination-uri'].startswith('hdfs://'):
  456.         hostPort = hodConfig['hodring']['log-destination-uri'][7:].split("/")
  457.         hostPort = hostPort[0]
  458.         socket = tcpSocket(hostPort)
  459.         try:
  460.           socket.open()
  461.           socket.close()
  462.         except:
  463.           printErrors(hodConfig.var_error('hodring', 'log-destination-uri', 
  464.           "Unable to contact host/port specified in log destination uri: %s" % 
  465.           hodConfig['hodring']['log-destination-uri']))
  466.           sys.exit(1)
  467.       else:
  468.         printErrors(hodConfig.var_error('hodring', 'log-destination-uri', 
  469.           "The log destiniation uri must be of type local:// or hdfs://."))
  470.         sys.exit(1)
  471.   
  472.     if hodConfig['ringmaster']['workers_per_ring'] < 1:
  473.       printErrors(hodConfig.var_error('ringmaster', 'workers_per_ring',
  474.                 "ringmaster.workers_per_ring must be a positive integer " +
  475.                 "greater than or equal to 1"))
  476.       sys.exit(1)
  477.                         
  478.     ## TODO : end of should move the dependency verification to hodConfig.verif
  479.       
  480.     hodConfig['hod']['base-dir'] = rootDirectory
  481.     hodConfig['hod']['user_state'] = DEFAULT_HOD_DIR
  482.   
  483.     dGen = DescGenerator(hodConfig)
  484.     hodConfig = dGen.initializeDesc()
  485.     
  486.     os.environ['JAVA_HOME'] = hodConfig['hod']['java-home']
  487.     
  488.     if hodConfig['hod']['debug'] == 4:
  489.       print ""
  490.       print "Using Python: %s" % sys.version
  491.       print ""
  492.    
  493.     hod = hodRunner(hodConfig)
  494.   
  495.     # Initiate signal handling
  496.     hodInterrupt.set_log(hod.get_logger())
  497.     hodInterrupt.init_signals()
  498.     # Interrupts set up. Now on we handle signals only when we wish to.
  499.   except KeyboardInterrupt:
  500.     print HOD_INTERRUPTED_MESG
  501.     sys.exit(HOD_INTERRUPTED_CODE)
  502.   
  503.   opCode = 0
  504.   try:
  505.     if hodConfig['hod'].has_key('script'):
  506.       opCode = hod.script()
  507.     else:  
  508.       opCode = hod.operation()
  509.   except Exception, e:
  510.     print "Uncaught Exception : %s" % e
  511.   finally:
  512.     sys.exit(opCode)