submit_tm5 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. #! /usr/bin/env python3
  2. #
  3. # job chain:
  4. #
  5. # myrun_001_init.jb
  6. # build/bin/submit_tm5_step_init rcfile
  7. # myrun_001_run.jb
  8. # build/bin/submit_tm5_step_run './tm5.x rcfile'
  9. # myrun_001_done.jb
  10. # build/bin/submit_tm5_step_done rcfile
  11. #
  12. # myrun_002_init.jb
  13. # ...
  14. #
  15. # or for a loadleveler job:
  16. #
  17. # myrun_001.jb
  18. # build/bin/submit_tm5_step_init rcfile
  19. # build/bin/submit_tm5_step_run './tm5.x rcfile'
  20. # build/bin/submit_tm5_step_done rcfile
  21. #
  22. # myrun_002.jb
  23. # ...
  24. #
  25. # -----------------------------------------------
  26. # external
  27. # -----------------------------------------------
  28. # standard modules:
  29. import sys
  30. import os
  31. import optparse
  32. import logging
  33. import datetime
  34. # -----------------------------------------------
  35. # defaults
  36. # -----------------------------------------------
  37. # display info messages ?
  38. verbose_default = False
  39. # where to search for additional scripts ?
  40. # NOTE: this line will be (has been?) replaced by 'pycasso.py/Main'
  41. # with the actual path to the build directory:
  42. pypath_default = os.path.join( os.pardir, 'build', 'bin' )
  43. # -----------------------------------------------
  44. # arguments (1)
  45. # -----------------------------------------------
  46. # extract arguments from sys.argv array:
  47. # 0 = name of calling script, 1: = actual arguments
  48. script = sys.argv[0]
  49. args = sys.argv[1:]
  50. # set text for 'usage' help line:
  51. usage = "%prog [options] [-e|--exec=]<executable>] [-r|--rcfile=]<rcfile> ..."
  52. # extra help text
  53. epilog = """
  54. Arguments that are no flags are supposed to be file names
  55. and clasified according to their extension as either
  56. an executable (.x) or rc file (.rc) .
  57. """
  58. # initialise the option parser:
  59. #parser = optparse.OptionParser(usage=usage,epilog=epilog)
  60. parser = optparse.OptionParser(usage=usage) # not all python version accept epilog yet ...
  61. # define verbose option:
  62. parser.add_option( "-v", "--verbose",
  63. help="print extra logging messages to standard output (%s)" % str(verbose_default),
  64. dest="verbose", action="store_true", default=verbose_default )
  65. parser.add_option( "-p", "--py-path",
  66. help="path to additional submit scripts (%s)" % pypath_default,
  67. dest="pypath", action="store", default=pypath_default )
  68. parser.add_option( "-b", "--background",
  69. help="""Run executable in background. Standard output and error are redirected.""",
  70. dest="submit_to", action="store_const", const='background' )
  71. parser.add_option( "-q", "--queue",
  72. help="submit executable to a queue system",
  73. dest="submit_to", action="store_const", const='queue' )
  74. parser.add_option( "-s", "--submit-option",
  75. help="""Extra submit option(s) passed to queue scheduler.
  76. Example for BSUB:
  77. -K : (keep) wait for end of run before return.""",
  78. dest="submit_options", action="store" )
  79. parser.add_option( "-d", "--debugger",
  80. help="run executable in debuger",
  81. dest="submit_debugger", action="store_true" )
  82. parser.add_option( "-e", "--exec",
  83. help="name of executable",
  84. dest="exe", type="string" )
  85. parser.add_option( "-r", "--rcfile",
  86. help="""Rc file with runtime settings.
  87. Multiple rcfiles could be specified, in which case
  88. a job is submitted for each rcfile.""",
  89. dest="rcfiles", action="append", default=[] )
  90. # now parse the actual arguments;
  91. # return an object 'opts' with fields 'verbose' etc,
  92. # and the unnamed arguments in the list 'args' :
  93. opts,args = parser.parse_args( args=args )
  94. # -----------------------------------------------
  95. # logging
  96. # -----------------------------------------------
  97. # setup messages:
  98. logging.basicConfig( format='%(lineno)-4s:%(filename)-30s [%(levelname)-8s] %(message)s', level=logging.INFO, stream=sys.stdout )
  99. # info ...
  100. logging.info( '' )
  101. tnow = datetime.datetime.now().isoformat(' ').split('.',1)[0]
  102. logging.info( 'Started script at %s ...' % tnow )
  103. logging.info( '' )
  104. # info ...
  105. logging.info( ' parsed options : %s' % opts )
  106. logging.info( ' parsed argument : %s' % args )
  107. # debug messages to standard output ?
  108. if opts.verbose :
  109. logging.info( ' verbose mode for standard output; print all messages ...' )
  110. stdout_handler.setLevel(logging.DEBUG)
  111. else :
  112. logging.info( ' quiet mode for standard output; print info messages only ...' )
  113. #endif
  114. # -----------------------------------------------
  115. # arguments (2)
  116. # -----------------------------------------------
  117. # info ...
  118. logging.info( 'store arguments ...' )
  119. # copy from options into less cryptic variables:
  120. rcfiles = opts.rcfiles
  121. exe = opts.exe
  122. # arguments are either rcfiles or an executable;
  123. # copy from arguments into new variables;
  124. # loop over arguments:
  125. for arg in args :
  126. # executable ?
  127. if arg.endswith('.x') :
  128. # already specified ?
  129. if exe != None :
  130. logging.error( 'found argument "%s", while already executable defined : %s' % (arg,exe) )
  131. raise Exception
  132. #endif
  133. # info ...
  134. logging.info( ' found executable : %s' % arg )
  135. # store:
  136. exe = arg
  137. # next argument:
  138. continue
  139. #endif
  140. # ends with '.rc' ? then add to list with rcfiles:
  141. if arg.endswith('.rc') :
  142. # info ...
  143. logging.info( ' found rcfile : %s' % arg )
  144. # add extra rcfile:
  145. rcfiles.append(arg)
  146. # next argument:
  147. continue
  148. #endif
  149. # unknown ...
  150. logging.error( 'argument is not an executable or rcfile : %s' % arg )
  151. raise Exception
  152. #endfor
  153. # -----------------------------------------------
  154. # toolboxes
  155. # -----------------------------------------------
  156. # prepend location of python modules to search path;
  157. # either passed via arguments or the default defined above:
  158. sys.path.insert( 0, opts.pypath )
  159. # local modules:
  160. import rc
  161. import submit_tm5_tools
  162. # -----------------------------------------------
  163. # begin
  164. # -----------------------------------------------
  165. # executable should have been specified:
  166. if exe == None :
  167. logging.error( 'no executable specified ...' )
  168. sys.exit(1)
  169. #endif
  170. # executable exist ?
  171. if not os.path.exists(exe) :
  172. logging.error( 'executable not found : %s' % exe )
  173. sys.exit(1)
  174. #endif
  175. # info ...
  176. logging.info( 'executable : %s' % exe )
  177. # rcfile(s) should have been specified:
  178. if len(rcfiles) == 0 :
  179. logging.error( 'no rcfile specified ...' )
  180. sys.exit(1)
  181. #endif
  182. # check if rcfiles exists ...
  183. for rcfile in rcfiles :
  184. if not os.path.exists(rcfile) :
  185. logging.error( 'rcfile not found : %s' % rcfile )
  186. sys.exit(1)
  187. #endif
  188. #endfor
  189. # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  190. # loop over rcfiles
  191. # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  192. # loop over rcfiles:
  193. for rcfile in rcfiles :
  194. # info ...
  195. logging.info( 'master rcfile : %s' % rcfile )
  196. # read settings:
  197. rcf = rc.RcFile( rcfile )
  198. # replace rc keys given options passed to the script:
  199. if opts.submit_to != None : rcf.replace( 'submit.to' , opts.submit_to )
  200. if opts.submit_options != None : rcf.replace( 'submit.options' , opts.submit_options )
  201. if opts.submit_debugger != None : rcf.replace( 'submit.debugger', opts.submit_debugger )
  202. ## save sources if requested:
  203. #submit_tm5_tools.Archive_Sources( rcf )
  204. # create first rcfile and job file(s) for the chain,
  205. # submit the result:
  206. try :
  207. submit_tm5_tools.WriteAndSubmitNewJob( rcf, opts.pypath )
  208. except :
  209. logging.error( sys.exc_info()[1] )
  210. logging.error( 'exception from WriteAndSubmitNewJob( rcf )' )
  211. sys.exit(1)
  212. #endtry
  213. #endfor # rcfiles
  214. # -----------------------------------------------
  215. # end
  216. # -----------------------------------------------
  217. logging.info( '' )
  218. tnow = datetime.datetime.now().isoformat(' ').split('.',1)[0]
  219. logging.info( 'End script at %s ...' % tnow )
  220. logging.info( '' )