Module EDPluginExecProcessScript
[hide private]
[frames] | no frames]

Source Code for Module EDPluginExecProcessScript

  1  # coding: utf8 
  2  # 
  3  #    Project: The EDNA Kernel 
  4  #             http://www.edna-site.org 
  5  # 
  6  #    File: "$Id$" 
  7  # 
  8  #    Copyright (C) 2008-2012 European Synchrotron Radiation Facility 
  9  #                            Grenoble, France 
 10  # 
 11  #    Principal authors: Marie-Francoise Incardona (incardon@esrf.fr) 
 12  #                       Olof Svensson (svensson@esrf.fr)  
 13  #                       Jérôme Kieffer (jerome.kieffer@esrf.eu) 
 14  # 
 15  #    This program is free software: you can redistribute it and/or modify 
 16  #    it under the terms of the GNU Lesser General Public License as published 
 17  #    by the Free Software Foundation, either version 3 of the License, or 
 18  #    (at your option) any later version. 
 19  # 
 20  #    This program is distributed in the hope that it will be useful, 
 21  #    but WITHOUT ANY WARRANTY; without even the implied warranty of 
 22  #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 23  #    GNU Lesser General Public License for more details. 
 24  # 
 25  #    You should have received a copy of the GNU General Public License 
 26  #    and the GNU Lesser General Public License  along with this program.   
 27  #    If not, see <http://www.gnu.org/licenses/>. 
 28  # 
 29   
 30  from __future__ import with_statement 
 31   
 32  __authors__ = [ "Marie-Francoise Incardona", "Olof Svensson", "Jérôme Kieffer" ] 
 33  __contact__ = "svensson@esrf.fr" 
 34  __license__ = "LGPLv3+" 
 35  __copyright__ = "European Synchrotron Radiation Facility, Grenoble, France" 
 36  __doc__ = """ 
 37  The purpose of this plugin execute class is to be subclassed for 
 38  creating plugins that execute external programs through scripts. 
 39  """ 
 40  import os, shlex, sys 
 41  from EDVerbose              import EDVerbose 
 42  from EDUtilsFile            import EDUtilsFile 
 43  from EDUtilsPath            import EDUtilsPath 
 44  from EDPluginExecProcess    import EDPluginExecProcess 
 45  from EDConfiguration        import EDConfiguration 
 46  from EDUtilsPlatform        import EDUtilsPlatform 
 47  from XSDataCommon           import XSPluginItem 
 48   
 49   
50 -class EDPluginExecProcessScript(EDPluginExecProcess):
51 """ 52 The super class for all EDNA plugins that execute a task using a script. 53 This class manages the process script to be executed: 54 - Configuration options: 55 - execProcessScriptShell : The shell that will execute the script, written into the top line of the script, for example : #!/bin/bash 56 - execProcessScriptExecutor : If defined, this command is used for launching the shell. 57 It can be used for example to launch the shell using a grid engine. (Note that the example to launch the shell using a grid engine. 58 (Note that the execProcessScriptExecutor will be replaced by execProcessExecutable) 59 - execProcessScriptExecutable : The path to the third-party executable that will be launched in the script. 60 - execProcessScriptSetupCCP4 : Path to CCP4 setup file (if required) 61 - execProcessScriptVersionString : A string which describes the version of the execProcessScriptExecutable, 62 which should match the version string written into the program log, for example: "Version 7.0.1 for Image plate and CCD data 20th August 2007" 63 (Note that this configuration option will be moved to EDPluginExecProcess) 64 - The list of compatible 3rd party executable version the plugin should support (should be move up to EDPluginExecProcess) 65 - The list of pre-execution commands 66 - The script command line that invokes the executable, which is written into the script 67 (the EDPluginExecProcess command line is not used, but will be in the future: It will consist of the 68 execProcessExecutable and the path to the script file.) 69 - The list of execution commands for the execProcessScriptExecutable 70 - The list of post-execution commands 71 - The script base name (<date>-<random number>-<base name>) 72 - The script file name 73 - The script file path 74 - The standard output log file name 75 - The error output file log file name 76 - The poll sleep time for checking if the process has finished (set to 1 s). 77 """ 78 79 CONF_EXEC_PROCESS_SCRIPT_SHELL = "execProcessScriptShell" 80 CONF_EXEC_PROCESS_SCRIPT_EXECUTOR = "execProcessScriptExecutor" 81 CONF_EXEC_PROCESS_SCRIPT_EXECUTABLE = "execProcessScriptExecutable" 82 CONF_EXEC_PROCESS_SCRIPT_SETUP_CCP4 = "execProcessScriptSetupCCP4" 83 CONF_EXEC_PROCESS_SCRIPT_VERSION_STRING = "execProcessScriptVersionString" 84 START_OF_ENVIRONMENT = "EDNA_START_OF_ENVIRONMENT" 85
86 - def __init__ (self):
87 """ 88 Initializes process related attributes described above 89 """ 90 EDPluginExecProcess.__init__(self) 91 self.__strConfigShell = "/bin/bash" 92 self.__strScriptExecutor = None 93 self.__strScriptExecutable = None 94 self.__strConfigSetupCCP4 = None 95 self.__strVersion = None 96 self.__listCompatibleVersions = [] 97 self.__strScriptCommandline = "" 98 self.__strScriptBaseName = None 99 self.__strScriptLogFileName = None 100 self.__strScriptErrorLogFileName = None 101 self.__strScriptFileName = None 102 self.__bRequireCCP4 = False 103 self.__listCommandPreExecution = [] 104 self.__listCommandExecution = [] 105 self.__listCommandPostExecution = [] 106 self.__iPollScriptProcessTime = 1 # [s] 107 self.__strPathToHostNamePidFile = None 108 self.__iNumberOfLastLinesFromLogFileIfError = 15
109 110
111 - def preProcess(self, _edObject=None):
112 """ 113 Calls the parent preProcess method 114 Generates the script 115 """ 116 EDPluginExecProcess.preProcess(self) 117 self.DEBUG("EDPluginExecProcessScript.preProcess") 118 # The generateScript method will be called at the end of the preProcess method 119 self.connectPreProcess(self.generateScript)
120 121
122 - def generateScript(self, _edObject=None):
123 """ 124 This method prepares the script and writes it to disk. 125 """ 126 strScript = self.prepareScript() 127 self.writeExecutableScript(strScript)
128 129
130 - def process(self, _edObject=None):
131 """ 132 This method starts the execution of the EDNA script using EDActionExecuteSystemCommand 133 In case of failure, an error message is added to the list and the plugin fails. 134 """ 135 EDPluginExecProcess.process(self) 136 self.DEBUG("EDPluginExecProcessScript.process starting") 137 self.synchronizeOn() 138 if "TIMEOUT" in EDUtilsFile.readFile(self.__strPathToHostNamePidFile): 139 self.error("Timeout message found in %s" % self.__strPathToHostNamePidFile) 140 self.hasTimedOut(True) 141 142 bTimeOut = self.isTimeOut() 143 if bTimeOut == True: 144 self.DEBUG("EDPluginExecProcessScript.process ========================================= ERROR! ================") 145 strErrorMessage = "%s execution timed out ( > %.1f s)!" % (self.__strScriptExecutable, float(self.getTimeOut())) 146 self.error(strErrorMessage) 147 self.addErrorMessage(strErrorMessage) 148 self.setFailure() 149 strExecutionStatus = "timeout" 150 if self.isVerboseDebug(): 151 raise RuntimeError(strErrorMessage) 152 else: 153 strExecutionStatus = self.getExecutionStatus() 154 # Report an error if the result is not "0" and the result is not an empty string 155 if not strExecutionStatus == "0" and not strExecutionStatus == "": 156 self.DEBUG("EDPluginExecProcessScript.process ========================================= ERROR! ================") 157 # Add any messages in the error log file (.err) to the list of error messages 158 strErrorLog = self.readProcessErrorLogFile() 159 if strErrorLog is None: 160 strErrorMessage = "%s execution error - status : %s" % (self.getClassName(), strExecutionStatus) 161 self.error(strErrorMessage) 162 self.addErrorMessage(strErrorMessage) 163 self.setFailure() 164 if self.isVerboseDebug(): 165 raise RuntimeError(strErrorMessage) 166 else: 167 strErrorMessage = "%s execution error : %s" % (self.getClassName(), strErrorLog) 168 self.error(strErrorMessage) 169 self.addErrorMessage(strErrorMessage) 170 self.setFailure() 171 if self.isVerboseDebug(): 172 raise RuntimeError(strErrorMessage) 173 # Add any messages in the log file (.log) to the list of error messages 174 strLog = self.readProcessLogFile() 175 if strLog is not None: 176 # Cut down the log file to the last part if it's long 177 listLogLines = strLog.split("\n") 178 if len(listLogLines) > self.__iNumberOfLastLinesFromLogFileIfError: 179 strErrorMessage = "Last part of the %s log file:" % self.__strScriptExecutable 180 self.ERROR(strErrorMessage) 181 self.addErrorMessage(strErrorMessage) 182 listLogLastLines = listLogLines[-self.__iNumberOfLastLinesFromLogFileIfError:] 183 strLogLastLines = "" 184 for strLine in listLogLastLines: 185 strLogLastLines += strLine + "\n" 186 self.ERROR(strLogLastLines) 187 self.addErrorMessage(strLogLastLines) 188 strMessage = "Please inspect log file: %s" % os.path.join(self.getWorkingDirectory(), self.getScriptLogFileName()) 189 self.ERROR(strMessage) 190 self.addErrorMessage(strMessage) 191 else: 192 strMessage = "%s log file: \n%s" % (self.__strScriptExecutable, strLog) 193 self.ERROR(strMessage) 194 self.addErrorMessage(strMessage) 195 # Save the return code of the external program in the PID file 196 open(self.__strPathToHostNamePidFile, "a").write(strExecutionStatus + os.linesep) 197 198 self.DEBUG("EDPluginExecProcessScript.process finished ") 199 self.synchronizeOff()
200 201
202 - def postProcess(self, _edObject=None):
203 """ 204 Calls the parent preProcess method 205 Checks that the installed 3rd party software is in the list of compatible versions 206 """ 207 EDPluginExecProcess.postProcess(self) 208 self.DEBUG("EDPluginExecProcessScript.postProcess") 209 210 # Tests the compatibles executable versions 211 listCompatibleVersions = self.getListOfCompatibleVersions() 212 213 if(len(listCompatibleVersions) != 0): 214 215 bFound = False 216 for compatibleVersion in listCompatibleVersions: 217 bFound = self.findStringInLog(compatibleVersion) 218 if(bFound == True): 219 break 220 221 if(bFound == False): 222 strErrorMessage = "Plugin not compatible with %s, compatible versions are: %s" % (self.getStringVersion(), self.getCompatibleVersionsStringLine()) 223 self.error(strErrorMessage) 224 self.addErrorMessage(strErrorMessage) 225 self.setFailure() 226 if self.isVerboseDebug(): 227 raise RuntimeError, strErrorMessage
228 229 230
231 - def configure(self):
232 """ 233 Configures the plugin from the configuration file with the following parameters 234 - The shell that will execute the script 235 - Script executor 236 - Script executable to be invoked 237 - Path to CCP4 setup file if required 238 - The 3rd party executable installed version 239 """ 240 EDPluginExecProcess.configure(self) 241 self.DEBUG("EDPluginExecProcessScript.configure") 242 strShell = self.config.get(self.CONF_EXEC_PROCESS_SCRIPT_SHELL) 243 if strShell is None: 244 self.DEBUG("EDPluginExecProcessScript.configure: No configuration parameter found for: " + \ 245 self.CONF_EXEC_PROCESS_SCRIPT_SHELL + ", using default value: " + self.getScriptShell()) 246 else: 247 self.setScriptShell(strShell) 248 strScriptExecutor = self.config.get(self.CONF_EXEC_PROCESS_SCRIPT_EXECUTOR) 249 if strScriptExecutor is None: 250 self.setScriptExecutor(self.getScriptShell()) 251 self.DEBUG("EDPluginExecProcessScript.configure: No configuration parameter found for: " + \ 252 self.CONF_EXEC_PROCESS_SCRIPT_EXECUTOR + ", using script shell: " + self.getScriptShell()) 253 else: 254 self.setScriptExecutor(strScriptExecutor) 255 if self.__strScriptExecutable is None: 256 strScriptExecutable = self.config.get(self.CONF_EXEC_PROCESS_SCRIPT_EXECUTABLE) 257 if strScriptExecutable is None: 258 strErrorMessage = "Configuration parameter %s missing for plugin %s with EDNA_SITE=%s" % \ 259 (self.CONF_EXEC_PROCESS_SCRIPT_EXECUTABLE, \ 260 self.getPluginName(), EDUtilsPath.EDNA_SITE) 261 self.error(strErrorMessage) 262 self.addErrorMessage(strErrorMessage) 263 self.setFailure() 264 if self.isVerboseDebug(): 265 raise RuntimeError, strErrorMessage 266 else: 267 # Check that the executable file exists 268 if not os.path.exists(strScriptExecutable): 269 strErrorMessage = "Cannot find configured executable %s: %s for plugin %s with EDNA_SITE=%s" % \ 270 (self.CONF_EXEC_PROCESS_SCRIPT_EXECUTABLE, strScriptExecutable, \ 271 self.getPluginName(), EDUtilsPath.EDNA_SITE) 272 self.error(strErrorMessage) 273 self.addErrorMessage(strErrorMessage) 274 self.setFailure() 275 if self.isVerboseDebug(): 276 raise RuntimeError, strErrorMessage 277 else: 278 self.setScriptExecutable(strScriptExecutable) 279 if not self.__strScriptExecutable: 280 self.error("No executable found for plugin %s with EDNA_SITE=%s" % (self.getClassName(), EDUtilsPath.EDNA_SITE)) 281 282 strConfigSetupCCP4 = self.config.get(self.CONF_EXEC_PROCESS_SCRIPT_SETUP_CCP4) 283 if strConfigSetupCCP4 is None: 284 self.DEBUG("EDPluginExecProcessScript.configure: No configuration parameter found for: " + \ 285 self.CONF_EXEC_PROCESS_SCRIPT_SETUP_CCP4 + ", NO default value!") 286 else: 287 self.setSetupCCP4(strConfigSetupCCP4) 288 strVersion = self.config.get(self.CONF_EXEC_PROCESS_SCRIPT_VERSION_STRING) 289 if strVersion is None: 290 self.DEBUG("EDPluginExecProcessScript.configure: No configuration parameter found for: " + \ 291 self.CONF_EXEC_PROCESS_SCRIPT_VERSION_STRING + ", NO default value!") 292 else: 293 self.setStringVersion(strVersion) 294 295 if self.__strScriptBaseName is None: 296 self.setScriptBaseName(self.getBaseName()) 297 if self.__strScriptFileName is None: 298 self.setScriptFileName(self.__strScriptBaseName + ".sh") 299 if self.__strScriptLogFileName is None: 300 self.setScriptLogFileName(self.__strScriptBaseName + ".log") 301 if self.__strScriptErrorLogFileName is None: 302 self.setScriptErrorLogFileName(self.__strScriptBaseName + ".err") 303 if self.__strScriptExecutable is not None: 304 self.__strPathToHostNamePidFile = os.path.join(self.getWorkingDirectory(), os.path.basename(self.__strScriptExecutable) + "_hostNamePid.txt")
305 306
307 - def prepareScript(self):
308 """ 309 Returns a string containing the script. 310 """ 311 strScript = None 312 self.DEBUG("EDPluginExecProcessScript.prepareScript") 313 if "sh" in self.getScriptShell(): 314 strScript = self.prepareShellScript() 315 elif "python" in self.getScriptShell(): 316 if self.__strScriptFileName.endswith(".sh"): 317 self.setScriptFileName(self.__strScriptFileName[:-3] + ".py") 318 strScript = self.preparePythonScript() 319 elif "cmd" in self.getScriptShell(): 320 if self.__strScriptFileName.endswith(".sh"): 321 self.setScriptFileName(self.__strScriptFileName[:-3] + ".bat") 322 strScript = self.prepareBatchScript() 323 return strScript
324
325 - def prepareShellScript(self):
326 """ 327 Returns a string containing the Shell script. 328 """ 329 self.DEBUG("EDPluginExecProcessScript.prepareShellScript") 330 listScript = ["#!%s" % self.getScriptShell(), 331 "cd " + self.getWorkingDirectory()] 332 if self.__bRequireCCP4: 333 if self.__strConfigSetupCCP4 == None or self.__strConfigSetupCCP4 == "": 334 self.DEBUG("EDPluginExecProcessScript.prepareShellScript : CCP4 setup script not defined.") 335 else: 336 listScript.append(". " + self.__strConfigSetupCCP4) 337 # Add pre-execution commands - if any 338 for strCommandPreExecution in self.__listCommandPreExecution: 339 listScript.append(strCommandPreExecution) 340 # Execution 341 strScript = self.__strScriptExecutable + " " + self.__strScriptCommandline + " > " + self.__strScriptLogFileName + " 2> " + self.__strScriptErrorLogFileName 342 # Add execution commands - if any 343 if self.__listCommandExecution == []: 344 strScript += " &" 345 listScript.append(strScript) 346 else: 347 strScript += " << EOF-EDPluginExecProcessScript &" 348 listScript.append(strScript) 349 for strCommandExecution in self.__listCommandExecution: 350 listScript.append(strCommandExecution) 351 listScript.append("EOF-EDPluginExecProcessScript") 352 353 listScript.append("ednaJobPid=$!") 354 listScript.append("ednaJobHostName=$(hostname)") 355 listScript.append('echo "$ednaJobHostName $ednaJobPid" > %s' % self.__strPathToHostNamePidFile) 356 listScript.append("wait $ednaJobPid") 357 # Add post-execution commands - if any 358 for strCommandPostExecution in self.__listCommandPostExecution: 359 listScript.append(strCommandPostExecution) 360 listScript.append("") 361 return os.linesep.join(listScript)
362 363
364 - def preparePythonScript(self):
365 """ 366 Returns a string containing the Python script. 367 """ 368 self.DEBUG("EDPluginExecProcessScript.preparePythonScript") 369 370 #when running python script allow 1s+1% gracetime to let the python scripting mechanism to finish 371 iScriptTimeOut = max(1, self.getTimeOut()) 372 self.setTimeOut(1 + 1.05 * iScriptTimeOut) 373 self.DEBUG("Original Timeout is %s setting to %s" % (iScriptTimeOut, self.getTimeOut())) 374 375 listScript = ["#!%s" % sys.executable, ""] 376 377 listScript += ["import os, sys, subprocess, threading, socket, signal", "", 378 "os.chdir('%s')" % EDUtilsPlatform.escape(self.getWorkingDirectory()), "", 379 "def writeStdOutErr(std,filename):", 380 " open(filename,'wb').write(std.read())", 381 "", 382 "def kill(pid):", 383 " sys.stderr.write('TIMEOUT of %s pid: '+str(pid)+os.linesep)" % 384 EDUtilsPlatform.escape(self.__strScriptExecutable), 385 " open('%s','a').write('TIMEOUT after %ss %s')" % 386 (EDUtilsPlatform.escape(self.__strPathToHostNamePidFile), 387 iScriptTimeOut, EDUtilsPlatform.escapedLinesep), 388 ] 389 if EDUtilsPlatform.name == "nt": 390 listScript += [" os.kill(pid,signal.SIGTERM)", 391 " sys.exit(-signal.SIGTERM)", ""] 392 else: 393 listScript += [" os.kill(pid,signal.SIGKILL)", 394 " sys.exit(-signal.SIGKILL)", ""] 395 396 # Add pre-execution commands - if any 397 cmdline = "" 398 if self.__bRequireCCP4: 399 if self.__strConfigSetupCCP4 == None or self.__strConfigSetupCCP4 == "": 400 self.DEBUG("EDPluginExecProcessScript.preparePythonScript : CCP4 setup script not defined.") 401 else: 402 cmdline += ". %s %s" % (self.__strConfigSetupCCP4, EDUtilsPlatform.cmdSep) 403 404 for strCommandPreExecution in self.__listCommandPreExecution: 405 if strCommandPreExecution.strip().endswith("&"): 406 cmdline += strCommandPreExecution 407 else: 408 cmdline += strCommandPreExecution + EDUtilsPlatform.cmdSep 409 if len(cmdline) > 2: 410 listScript += ["def getEnvironment(filename):", 411 " dictEnv=None", 412 " for oneFullLine in open(filename,'rb').readlines():", 413 " oneLine=oneFullLine.strip()", 414 " if ('=' in oneLine) and (isinstance(dictEnv,dict)):", 415 " key,value = oneLine.split('=',1)", 416 " dictEnv[key]=value", 417 " elif oneLine == '%s':" % EDPluginExecProcessScript.START_OF_ENVIRONMENT, 418 " dictEnv={}", 419 " return dictEnv", 420 "" 421 ] 422 423 cmdline += "echo %secho %s%s%s" % (EDUtilsPlatform.cmdSep, 424 EDPluginExecProcessScript.START_OF_ENVIRONMENT, 425 EDUtilsPlatform.cmdSep, 426 EDUtilsPlatform.cmdEnv) 427 listScript += ['subPre = subprocess.Popen("""%s""",shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)' % cmdline, 428 'threadStdErr = threading.Thread(target=writeStdOutErr, name="PreExecuteWriteStdErr", args=(subPre.stderr,"preExecute.err"))', 429 'threadStdOut = threading.Thread(target=writeStdOutErr, name="PreExecuteWriteStdOut", args=(subPre.stdout,"preExecute.log"))', 430 'threadStdErr.start()', 431 'threadStdOut.start()', 432 'threadStdErr.join()', 433 'threadStdOut.join()', 434 'subPre.wait()', 435 'dictEnv=getEnvironment("preExecute.log")'] 436 else: 437 listScript.append('dictEnv=os.environ') 438 439 # # Execution 440 listScript.append("") 441 442 strcmd = "%s %s" % ( 443 EDUtilsPlatform.escape(self.__strScriptExecutable), 444 EDUtilsPlatform.escape(self.__strScriptCommandline)) 445 446 listCommandLine = shlex.split(str(strcmd)) 447 if self.__listCommandExecution == []: 448 listScript.append('subP = subprocess.Popen(%s,stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=dictEnv)' % listCommandLine) 449 else: 450 listScript.append('subP = subprocess.Popen(%s, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=dictEnv)' % listCommandLine) 451 for strCommandExecution in self.__listCommandExecution: 452 listScript.append('subP.stdin.write("%s%s")' % (strCommandExecution, 453 EDUtilsPlatform.escapedLinesep)) 454 listScript.append('subP.stdin.close()') 455 listScript += ['timer = threading.Timer(%s,kill,args=(subP.pid,))' % (iScriptTimeOut), 456 'timer.start()', 457 'open("%s","wb").write("%%s %%s %%s"%%(subP.pid,socket.gethostname(),os.linesep)) ' % 458 EDUtilsPlatform.escape(self.__strPathToHostNamePidFile), 459 'threadStdErr = threading.Thread(target=writeStdOutErr, name="WriteStdErr", args=(subP.stderr,"%s"))' % 460 EDUtilsPlatform.escape(self.__strScriptErrorLogFileName), 461 'threadStdOut = threading.Thread(target=writeStdOutErr, name="WriteStdOut", args=(subP.stdout,"%s"))' % 462 EDUtilsPlatform.escape(self.__strScriptLogFileName), 463 'threadStdErr.start()', 464 'threadStdOut.start()', 465 'threadStdErr.join()', 466 'threadStdOut.join()', 467 'subP.wait()', 468 'timer.cancel()' 469 ''] 470 # Add post-execution commands - if any 471 cmdline = "" 472 for strCommandPostExecution in self.__listCommandPostExecution: 473 if strCommandPostExecution.strip().endswith(" & "): 474 cmdline += strCommandPostExecution 475 else: 476 cmdline += strCommandPostExecution + EDUtilsPlatform.cmdSep 477 478 listScript.append('subPost = subprocess.Popen("""%s""", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=dictEnv)' % cmdline) 479 listScript.append('threadStdErr = threading.Thread(target=writeStdOutErr, name="PreExecuteWriteStdErr", args=(subPost.stderr,"postExecute.log"))') 480 listScript.append('threadStdOut = threading.Thread(target=writeStdOutErr, name="PreExecuteWriteStdOut", args=(subPost.stdout,"postExecute.err"))') 481 listScript.append('threadStdErr.start()') 482 listScript.append('threadStdOut.start()') 483 listScript.append('threadStdErr.join()') 484 listScript.append('threadStdOut.join()') 485 listScript.append('subPost.wait()') 486 487 488 listScript.append("sys.exit(subP.returncode)") 489 listScript.append("") 490 strPythonScript = os.linesep.join(listScript) 491 return strPythonScript
492 493 494
495 - def prepareBatchScript(self):
496 """ 497 Returns a string containing the windows batch script. 498 """ 499 500 self.DEBUG("EDPluginExecProcessScript.prepareBatchScript") 501 listScript = ["@ECHO OFF", 502 "cd " + self.getWorkingDirectory()] 503 504 # Add pre-execution commands - if any 505 for strCommandPreExecution in self.__listCommandPreExecution: 506 listScript.append(strCommandPreExecution) 507 # Execution 508 # Add execution commands - if any 509 if self.__strScriptExecutable.endswith(".bat") or self.__strScriptExecutable.endswith(".cmd") : 510 strExecutable = "@CALL " + self.__strScriptExecutable 511 else: 512 strExecutable = self.__strScriptExecutable 513 if self.__listCommandExecution == []: 514 listScript.append("'%s' '%s' > '%s' 2> '%s' &" % (strExecutable , self.__strScriptCommandline , self.__strScriptLogFileName, self.__strScriptErrorLogFileName)) 515 else: 516 for strCommandExecution in self.__listCommandExecution: 517 listScript.append("echo %s >>EDNA_StdInput.txt" % strCommandExecution) 518 519 listScript.append("'%s' '%s' < EDNA_StdInput.txt > '%s' 2> '%s' &" % (self.__strScriptExecutable , self.__strScriptCommandline , self.__strScriptLogFileName, self.__strScriptErrorLogFileName)) 520 521 listScript.append('for /F "token=2" %I in (\' TASKLIST /NH /FI "IMAGENAME eq %s " \')DO SET PID=%I' % os.path.basename(self.__strScriptExecutable)) 522 listScript.append('hostname> %s' % self.__strPathToHostNamePidFile) 523 listScript.append('echo %PID% > %s' % self.__strPathToHostNamePidFile) 524 # listScript.append("wait $ednaJobPid") 525 # Add post-execution commands - if any 526 for strCommandPostExecution in self.__listCommandPostExecution: 527 listScript.append(strCommandPostExecution) 528 listScript.append("") 529 return os.linesep.join(listScript)
530 531
533 """ 534 Returns the list of compatible executable versions the plugin supports 535 """ 536 return self.__listCompatibleVersions
537
538 - def addCompatibleVersion(self, _strCompatibleVersion):
539 """ 540 Adds a compatible executable version to the list 541 """ 542 self.__listCompatibleVersions.append(_strCompatibleVersion)
543 544
546 """ 547 This Method constructs a string line by concatening the compatible versions this plugin supports 548 This is for Log message purpose only. 549 """ 550 strCompatibleVersionsStringLine = "" 551 for compatibleVersion in self.getListOfCompatibleVersions(): 552 strCompatibleVersionsStringLine = strCompatibleVersionsStringLine + compatibleVersion + " ; " 553 554 return strCompatibleVersionsStringLine
555 556
557 - def setRequireCCP4(self, _bReqireCCP4):
558 """ 559 Sets a requirement on CCP4 560 """ 561 self.synchronizeOn() 562 self.__bRequireCCP4 = _bReqireCCP4 563 self.synchronizeOff()
564 565
566 - def getRequireCCP4(self):
567 """ 568 Returns True if the executable requires CCP4 569 """ 570 return self.__bRequireCCP4
571 572
573 - def setListCommandExecution(self, _listCommandExecution):
574 """ 575 Sets the list of execution commands 576 """ 577 self.synchronizeOn() 578 if _listCommandExecution is not None: 579 self.__listCommandExecution = list(_listCommandExecution) 580 self.synchronizeOff()
581 582
583 - def addListCommandExecution(self, _strCommandExecution):
584 """ 585 Adds an execution command to the list 586 """ 587 self.synchronizeOn() 588 if _strCommandExecution is not None: 589 self.__listCommandExecution.append(_strCommandExecution) 590 self.synchronizeOff()
591 592
593 - def getListCommandExecution(self):
594 """ 595 Returns the list of execution commands 596 """ 597 self.synchronizeOn() 598 edObject = None 599 if self.__listCommandExecution is not None: 600 edObject = list(self.__listCommandExecution) 601 self.synchronizeOff() 602 return edObject
603 604
605 - def setListCommandPreExecution(self, _listCommandPreExecution):
606 """ 607 Sets the list of pre execution commands 608 """ 609 self.synchronizeOn() 610 if _listCommandPreExecution is not None: 611 self.__listCommandPreExecution = list(_listCommandPreExecution) 612 self.synchronizeOff()
613 614
615 - def addListCommandPreExecution(self, _strCommandPreExecution):
616 """ 617 Adds a pre execution command to the list 618 """ 619 self.synchronizeOn() 620 if _strCommandPreExecution is not None: 621 self.__listCommandPreExecution.append(_strCommandPreExecution) 622 self.synchronizeOff()
623 624
626 """ 627 Returns the list of pre execution commands 628 """ 629 self.synchronizeOn() 630 edObject = None 631 if self.__listCommandPreExecution != None: 632 edObject = list(self.__listCommandPreExecution) 633 self.synchronizeOff() 634 return edObject
635 636
637 - def setListCommandPostExecution(self, _listCommandPostExecution):
638 """ 639 Sets the list of post execution commands 640 """ 641 self.synchronizeOn() 642 if _listCommandPostExecution is not None: 643 self.__listCommandPostExecution = list(_listCommandPostExecution) 644 self.synchronizeOff()
645 646
647 - def addListCommandPostExecution(self, _strCommandPostExecution):
648 """ 649 Adds a post execution command to the list 650 """ 651 self.synchronizeOn() 652 if _strCommandPostExecution is not None: 653 self.__listCommandPostExecution.append(_strCommandPostExecution) 654 self.synchronizeOff()
655 656
658 """ 659 Returns the list of post execution commands 660 """ 661 self.synchronizeOn() 662 edObject = None 663 if self.__listCommandPostExecution != None: 664 edObject = list(self.__listCommandPostExecution) 665 self.synchronizeOff() 666 return edObject
667 668
669 - def setScriptShell(self, _strScriptShell):
670 """ 671 Sets the script shell 672 """ 673 self.synchronizeOn() 674 self.__strConfigShell = _strScriptShell 675 self.synchronizeOff()
676 677
678 - def getScriptShell(self):
679 """ 680 Returns the script shell 681 """ 682 return self.__strConfigShell
683 684
685 - def setScriptExecutor(self, _strScriptExecutor):
686 """ 687 Sets the script executor 688 """ 689 self.synchronizeOn() 690 self.__strScriptExecutor = _strScriptExecutor 691 self.synchronizeOff()
692 693
694 - def getScriptExecutor(self):
695 """ 696 Returns the script executor 697 """ 698 return self.__strScriptExecutor
699 700
701 - def setSetupCCP4(self, _strSetupCCP4):
702 """ 703 Sets the path to CCP4 setup file 704 """ 705 self.synchronizeOn() 706 self.__strConfigSetupCCP4 = _strSetupCCP4 707 self.synchronizeOff()
708 709
710 - def getSetupCCP4(self):
711 """ 712 Returns the path to CCP4 setup file 713 """ 714 return self.__strConfigSetupCCP4
715 716
717 - def setScriptBaseName(self, _strScriptBaseName):
718 """ 719 Sets the script name 720 """ 721 self.synchronizeOn() 722 self.__strScriptBaseName = _strScriptBaseName 723 self.synchronizeOff()
724 725
726 - def getScriptBaseName(self):
727 """ 728 Returns the script name 729 if None, create it: <date>-<random number>-<base name> 730 """ 731 if self.__strScriptBaseName is None: 732 self.__strScriptBaseName = self.createBaseName() 733 return self.__strScriptBaseName
734 735
736 - def setScriptLogFileName(self, _strScriptLogFileName):
737 """ 738 Sets the standard output log file name 739 """ 740 self.synchronizeOn() 741 self.__strScriptLogFileName = _strScriptLogFileName 742 self.synchronizeOff()
743 744
745 - def setScriptErrorLogFileName(self, _strScriptErrorLogFileName):
746 """ 747 Sets the error output log file name 748 """ 749 self.synchronizeOn() 750 self.__strScriptErrorLogFileName = _strScriptErrorLogFileName 751 self.synchronizeOff()
752 753
754 - def getScriptLogFileName(self):
755 """ 756 Returns the standard output log file name 757 """ 758 return self.__strScriptLogFileName
759 760
762 """ 763 Returns the error output log file name 764 """ 765 return self.__strScriptErrorLogFileName
766 767
768 - def setScriptFileName(self, _strScriptFileName):
769 """ 770 Sets the script file name 771 """ 772 self.synchronizeOn() 773 self.__strScriptFileName = _strScriptFileName 774 self.synchronizeOff()
775 776
777 - def getScriptFileName(self):
778 """ 779 Returns the script file name 780 """ 781 return self.__strScriptFileName
782 783
784 - def getScriptFilePath(self):
785 """ 786 Returns the script file path 787 """ 788 return os.path.join(self.getWorkingDirectory(), self.__strScriptFileName)
789 790
791 - def setScriptExecutable(self, _strScriptExecutable):
792 """ 793 Sets the executable path 794 """ 795 with self.locked(): 796 self.__strScriptExecutable = _strScriptExecutable
797
798 - def getScriptExecutable(self):
799 """ 800 Returns the executable path 801 """ 802 return self.__strScriptExecutable
803 scriptExecutable = property(getScriptExecutable, setScriptExecutable) 804
805 - def setScriptCommandline(self, _strScriptCommandline):
806 """ 807 Sets the script command line (parameters to executable) 808 """ 809 self.synchronizeOn() 810 self.__strScriptCommandline = _strScriptCommandline 811 self.synchronizeOff()
812 813
814 - def getScriptCommandline(self):
815 """ 816 Returns the script command line (parameters to executable) 817 """ 818 return self.__strScriptCommandline
819 820
821 - def setStringVersion(self, _strVersion):
822 """ 823 Sets the executable version 824 """ 825 self.synchronizeOn() 826 self.__strVersion = _strVersion 827 self.synchronizeOff()
828 829
830 - def getStringVersion(self):
831 """ 832 Returns the executable version 833 """ 834 returnValue = None 835 if self.__strVersion is not None: 836 returnValue = self.__strVersion 837 return returnValue
838 839
840 - def setPathToHostNamePidFile(self, _strPathToHostNamePidFile):
841 """ 842 Sets the executable version 843 """ 844 self.__strPathToHostNamePidFile = _strPathToHostNamePidFile
845 846
847 - def getPathToHostNamePidFile(self):
848 """ 849 Returns the executable version 850 """ 851 return self.__strPathToHostNamePidFile
852 853 854 855
856 - def writeExecutableScript(self, _strScript):
857 """ 858 Writes the script to the script file. 859 """ 860 self.DEBUG("EDPluginExecProcessScript.writeScriptToFile") 861 EDUtilsFile.writeFile(self.getScriptFilePath(), _strScript) 862 self.setExecutable(self.getScriptExecutor()) 863 self.setCommandline(self.getScriptFilePath())
864 865
866 - def findStringInLog(self, _strInput):
867 """ 868 Returns True if a string exists in the log file 869 """ 870 self.DEBUG("EDPluginExecProcessScript.findStringInLog") 871 bTestSuccess = False 872 strLogFileContent = self.readProcessLogFile() 873 if strLogFileContent.find(_strInput) != -1: 874 bTestSuccess = True 875 return bTestSuccess
876 877
878 - def testVersion(self):
879 """ 880 Deprecated not used 881 See postProcess for version checking 882 """ 883 self.DEBUG("EDPluginExecProcessScript.testVersion") 884 bCorrectVersion = False 885 if self.findStringInLog(self.__strVersion) != None: 886 bCorrectVersion = True 887 return bCorrectVersion
888 889
890 - def writeProcessFile(self, _strFileName, _strContent):
891 """ 892 Main method to write a file in the plugin working directory 893 Such a file is called process file 894 """ 895 self.DEBUG("EDPluginExecProcessScript.writeProcessFile") 896 strFilePath = os.path.join(self.getWorkingDirectory(), _strFileName) 897 EDUtilsFile.writeFile(strFilePath, _strContent)
898 899
900 - def readProcessFile(self, _strFileName):
901 """ 902 Returns the file content of a process file 903 """ 904 self.DEBUG("EDPluginExecProcessScript.readProcessFile") 905 strFilePath = os.path.join(self.getWorkingDirectory(), _strFileName) 906 strFileContent = None 907 if os.path.exists(strFilePath): 908 strFileContent = EDUtilsFile.readFile(strFilePath) 909 return strFileContent
910 911
912 - def readProcessLogFile(self):
913 """ 914 Returns the content of the process standard output log file 915 """ 916 self.DEBUG("EDPluginExecProcessScript.readProcessLogFile") 917 strLogFileContent = None 918 if self.getScriptLogFileName() is not None: 919 strLogFileContent = self.readProcessFile(self.getScriptLogFileName()) 920 return strLogFileContent
921 922
923 - def readProcessErrorLogFile(self):
924 """ 925 Returns the content of the process error output log file 926 """ 927 self.DEBUG("EDPluginExecProcessScript.readProcessErrorLogFile") 928 strErrorLogFileContent = self.readProcessFile(self.getScriptErrorLogFileName()) 929 return strErrorLogFileContent
930