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

Source Code for Module EDPluginExecProcessXIA2CORE

  1  # 
  2  #    Project: The EDNA Kernel 
  3  #             http://www.edna-site.org 
  4  # 
  5  #    Copyright (C) 2010 Diamond Light Source, Chilton, UK 
  6  # 
  7  #    Principal author: Graeme Winter (graeme.winter@diamond.ac.uk) 
  8  # 
  9  #    This program is free software: you can redistribute it and/or modify 
 10  #    it under the terms of the GNU Lesser General Public License as published 
 11  #    by the Free Software Foundation, either version 3 of the License, or 
 12  #    (at your option) any later version. 
 13  # 
 14  #    This program is distributed in the hope that it will be useful, 
 15  #    but WITHOUT ANY WARRANTY; without even the implied warranty of 
 16  #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 17  #    GNU Lesser General Public License for more details. 
 18  # 
 19  #    You should have received a copy of the GNU General Public License 
 20  #    and the GNU Lesser General Public License  along with this program.   
 21  #    If not, see <http://www.gnu.org/licenses/>. 
 22  # 
 23   
 24  __authors__ = [ "Graeme Winter" ] 
 25  __contact__ = "graeme.winter@diamond.ac.uk" 
 26  __license__ = "LGPLv3+" 
 27  __copyright__ = "Diamond Light Source, Chilton, UK" 
 28   
 29  # I got this far... here's the plan: 
 30  #  
 31  # This will encapsulate a Driver from the DriverFactory, so will be a  
 32  # static class. The interface from the current ScriptPlugin will be  
 33  # maintained. 
 34   
 35  """ 
 36  The purpose of this plugin execute class is to be subclassed for 
 37  creating plugins that execute external programs through the xia2core. 
 38  """ 
 39   
 40  # standard Python imports 
 41  import os 
 42  import shlex 
 43   
 44  # EDNA imports 
 45  from EDFactoryPluginStatic import EDFactoryPluginStatic 
 46  from EDVerbose import EDVerbose 
 47  from EDUtilsFile import EDUtilsFile 
 48  from EDPluginExec import EDPluginExec 
 49  from EDActionExecuteSystemCommand import EDActionExecuteSystemCommand 
 50  from EDConfiguration import EDConfiguration 
 51   
 52  from XSDataCommon import XSPluginItem 
 53   
 54  # import the DriverFactory - either from edna's xia2core or a separate 
 55  # one configured in the environment as XIA2CORE_ROOT. 
 56   
 57  if "XIA2CORE_ROOT" in os.environ and os.environ['XIA2CORE_ROOT'] != '': 
 58      pathxia2core = os.path.join(os.environ['XIA2CORE_ROOT'], 'Python') 
 59  else: 
 60      pathxia2core = EDFactoryPluginStatic.getModuleLocation('XIA2CoreVersion') 
 61      os.environ["XIA2CORE_ROOT"] = os.path.dirname(pathxia2core) 
 62   
 63  EDVerbose.DEBUG('Found xia2core in %s' % pathxia2core) 
 64   
 65  EDFactoryPluginStatic.preImport("Driver", pathxia2core) 
 66   
 67  from Driver.DriverFactory import DriverFactory 
 68   
69 -class EDPluginExecProcessXIA2CORE(EDPluginExec):
70 71 # static class variables 72 73 CONF_EXEC_PROCESS_EXECUTABLE = "execProcessExecutable" 74 CONF_EXEC_PROCESS_XIA2CORE_TYPE = "execProcessXIA2COREType" 75 CONF_EXEC_PROCESS_VERSION_STRING = "execProcessXIA2COREVersionString" 76
77 - def __init__ (self):
78 """ 79 Initializes process related attributes described above 80 """ 81 EDPluginExec.__init__(self) 82 self.__strExecutable = None 83 self.__strVersion = None 84 self.__listCompatibleVersions = [] 85 self.__strCommandline = "" 86 self.__listCommandPreExecution = [] 87 self.__listCommandExecution = [] 88 self.__listCommandPostExecution = [] 89 self.__strLogFileName = None 90 self.__strErrorLogFileName = None 91 self.__listStandardOutput = [] 92 self.__listStandardError = [] 93 self.__strConfigXIA2COREType = None 94 95 return
96
97 - def preProcess(self, _edObject=None):
98 """ 99 Calls the parent preProcess method 100 Generates the script 101 """ 102 EDPluginExec.preProcess(self) 103 EDVerbose.DEBUG("EDPluginExecProcessXIA2CORE.preProcess") 104 105 return
106
107 - def generateXIA2CORE(self, _edObject=None, executable=None):
108 """Factory method to create and configure a xia2core Driver 109 instance.""" 110 111 if executable is None: 112 executable = self.getExecutable() 113 114 if executable is None: 115 raise RuntimeError, 'no executable set in factory' 116 117 EDVerbose.DEBUG("Driver created for executable %s" % executable) 118 119 driver = DriverFactory.Driver(self.__strConfigXIA2COREType) 120 driver.set_executable(executable) 121 driver.set_working_directory(self.getWorkingDirectory()) 122 123 return driver
124
125 - def process(self, _edObject=None):
126 """ 127 This method starts the execution of the EDNA script using 128 EDActionExecuteSystemCommand. In case of failure, an error 129 message is added to the list and the plugin fails. 130 """ 131 EDVerbose.DEBUG("EDPluginExecProcessXIA2CORE.process starting") 132 self.synchronizeOn() 133 134 # FIXME from here will need to do some real programming 135 136 self.launchProcessWithXIA2CORE() 137 138 EDVerbose.DEBUG("EDPluginExecProcessXIA2CORE.process finished ") 139 self.synchronizeOff()
140 141
142 - def postProcess(self, _edObject=None):
143 """ 144 Calls the parent preProcess method 145 Checks that the installed 3rd party software is in the list of 146 compatible versions 147 """ 148 EDPluginExec.postProcess(self) 149 EDVerbose.DEBUG("EDPluginExecProcessXIA2CORE.postProcess") 150 151 # Tests the compatibles executable versions 152 listCompatibleVersions = self.getListOfCompatibleVersions() 153 154 if(len(listCompatibleVersions) != 0): 155 156 bFound = False 157 for compatibleVersion in listCompatibleVersions: 158 bFound = self.findStringInLog(compatibleVersion) 159 if(bFound == True): 160 break 161 162 if(bFound == False): 163 strErrorMessage = "Plugin not compatible with %s, compatible versions are: %s" % \ 164 (self.getStringVersion(), 165 self.getCompatibleVersionsStringLine()) 166 EDVerbose.warning(strErrorMessage) 167 self.addWarningMessage(strErrorMessage)
168 #self.setFailure() 169 #if (EDVerbose.isVerboseDebug()): 170 # raise RuntimeError, strErrorMessage 171 172 173 # why is this configuration not a separate thing? surely it would make 174 # more sense to have a class which you pass a dictionary of wanted keys 175 # which could do all of the setattr stuff and configuration reading 176 # all in one place? 177
178 - def configure(self):
179 """ 180 Configures the plugin from the configuration file with the following 181 parameters 182 - The shell that will execute the script 183 - Script executor 184 - Script executable to be invoked 185 - Path to CCP4 setup file if required 186 - The 3rd party executable installed version 187 """ 188 EDPluginExec.configure(self) 189 EDVerbose.DEBUG("EDPluginExecProcessXIA2CORE.configure") 190 xsPluginItem = self.getConfiguration() 191 if (xsPluginItem == None): 192 EDVerbose.warning( 193 "EDPluginExecProcessXIA2CORE.configure: No plugin item defined.") 194 xsPluginItem = XSPluginItem() 195 196 if (self.getExecutable() is None): 197 strExecutable = EDConfiguration.getStringParamValue( 198 xsPluginItem, 199 EDPluginExecProcessXIA2CORE.CONF_EXEC_PROCESS_EXECUTABLE) 200 if(strExecutable == None): 201 strErrorMessage = "Configuration parameter missing: " + \ 202 EDPluginExecProcessXIA2CORE.CONF_EXEC_PROCESS_EXECUTABLE 203 EDVerbose.error(strErrorMessage) 204 self.addErrorMessage(strErrorMessage) 205 self.setFailure() 206 if (EDVerbose.isVerboseDebug()): 207 raise RuntimeError, strErrorMessage 208 else: 209 # Check that the executable file exists 210 if (os.path.exists(strExecutable) == False): 211 strErrorMessage = "Cannot find configured " + EDPluginExecProcessXIA2CORE.CONF_EXEC_PROCESS_EXECUTABLE + " : " + strExecutable 212 EDVerbose.error(strErrorMessage) 213 self.addErrorMessage(strErrorMessage) 214 self.setFailure() 215 if (EDVerbose.isVerboseDebug()): 216 raise RuntimeError, strErrorMessage 217 else: 218 self.setExecutable(strExecutable) 219 220 if (self.getConfigXIA2COREType() is None): 221 strXIA2COREType = EDConfiguration.getStringParamValue( 222 xsPluginItem, 223 EDPluginExecProcessXIA2CORE.CONF_EXEC_PROCESS_XIA2CORE_TYPE) 224 if(strXIA2COREType == None): 225 strErrorMessage = "Configuration parameter not set: " + \ 226 EDPluginExecProcessXIA2CORE.CONF_EXEC_PROCESS_XIA2CORE_TYPE 227 EDVerbose.DEBUG(strErrorMessage) 228 else: 229 # FIXME test that this is a legal name 230 self.__strConfigXIA2COREType = strXIA2COREType 231 232 strVersion = EDConfiguration.getStringParamValue(xsPluginItem, EDPluginExecProcessXIA2CORE.CONF_EXEC_PROCESS_VERSION_STRING) 233 if(strVersion == None): 234 EDVerbose.DEBUG("EDPluginExecProcessXIA2CORE.configure: No configuration parameter found for: " + \ 235 EDPluginExecProcessXIA2CORE.CONF_EXEC_PROCESS_VERSION_STRING + ", NO default value!") 236 else: 237 self.setStringVersion(strVersion) 238 if (self.__strLogFileName == None): 239 self.setLogFileName(self.getBaseName() + ".log") 240 if (self.__strErrorLogFileName == None): 241 self.setErrorLogFileName(self.getBaseName() + ".err") 242 243 if self.__strExecutable is None: 244 EDVerbose.ERROR("Executable not defined in configuration file") 245 # shall we raise an exception? 246 247 self.__strPathToHostNamePidFile = os.path.join(self.getWorkingDirectory(), os.path.basename(self.__strExecutable) + "_hostNamePid.txt") 248 249 return
250
252 """ 253 Launch a process using the xia2 core. 254 """ 255 EDVerbose.DEBUG("EDPluginExecProcessXIA2CORE.launchProcessWithXIA2CORE") 256 257 # launch the preexecution steps 258 for strCommandPreExecution in self.__listCommandPreExecution: 259 split_command_line = shlex.split(str(strCommandPreExecution)) 260 executable = split_command_line[0] 261 arguments = split_command_line[1:] 262 driver = self.generateXIA2CORE(executable) 263 for token in arguments: 264 driver.add_command_line(token) 265 driver.start() 266 driver.close_wait() 267 268 driver = self.generateXIA2CORE() 269 for token in shlex.split(str(self.__strCommandline)): 270 driver.add_command_line(token) 271 driver.start() 272 for record in self.__listCommandExecution: 273 driver.input(record) 274 if self.__strLogFileName: 275 EDVerbose.DEBUG("Logging to %s in %s" % (self.__strLogFileName, self.getWorkingDirectory())) 276 driver.write_log_file(os.path.join(self.getWorkingDirectory(), self.__strLogFileName)) 277 driver.close_wait() 278 279 self.__listStandardOutput = driver.get_all_output() 280 281 for strCommandPostExecution in self.__listCommandPostExecution: 282 split_command_line = shlex.split(str(strCommandPreExecution)) 283 executable = split_command_line[0] 284 arguments = split_command_line[1:] 285 driver = self.generateXIA2CORE(executable) 286 for token in arguments: 287 driver.add_command_line(token) 288 driver.start() 289 driver.close_wait() 290 291 # FIXME in here I need to check for errors 292 293 return
294 295
297 """ 298 Returns the list of compatible executable versions the plugin supports 299 """ 300 return self.__listCompatibleVersions
301 302
303 - def addCompatibleVersion(self, _strCompatibleVersion):
304 """ 305 Adds a compatible executable version to the list 306 """ 307 self.__listCompatibleVersions.append(_strCompatibleVersion)
308 309
311 """ 312 This Method constructs a string line by concatening the compatible versions this plugin supports 313 This is for Log message purpose only. 314 """ 315 strCompatibleVersionsStringLine = "" 316 for compatibleVersion in self.getListOfCompatibleVersions(): 317 strCompatibleVersionsStringLine = strCompatibleVersionsStringLine + compatibleVersion + " ; " 318 319 return strCompatibleVersionsStringLine
320 321 # why are the following not defined in a super class which is standard 322 # across the different exec plugins? 323 324
325 - def setListCommandExecution(self, _listCommandExecution):
326 """ 327 Sets the list of execution commands 328 """ 329 self.synchronizeOn() 330 if (_listCommandExecution is not None): 331 self.__listCommandExecution = list(_listCommandExecution) 332 self.synchronizeOff()
333 334
335 - def addListCommandExecution(self, _strCommandExecution):
336 """ 337 Adds an execution command to the list 338 """ 339 self.synchronizeOn() 340 if (_strCommandExecution is not None): 341 self.__listCommandExecution.append(_strCommandExecution) 342 self.synchronizeOff()
343 344
345 - def getListCommandExecution(self):
346 """ 347 Returns the list of execution commands 348 """ 349 self.synchronizeOn() 350 edObject = None 351 if (self.__listCommandExecution is not None): 352 edObject = list(self.__listCommandExecution) 353 self.synchronizeOff() 354 return edObject
355 356
357 - def setListCommandPreExecution(self, _listCommandPreExecution):
358 """ 359 Sets the list of pre execution commands 360 """ 361 self.synchronizeOn() 362 if (_listCommandPreExecution is not None): 363 self.__listCommandPreExecution = list(_listCommandPreExecution) 364 self.synchronizeOff()
365 366
367 - def addListCommandPreExecution(self, _strCommandPreExecution):
368 """ 369 Adds a pre execution command to the list 370 """ 371 self.synchronizeOn() 372 if (_strCommandPreExecution is not None): 373 self.__listCommandPreExecution.append(_strCommandPreExecution) 374 self.synchronizeOff()
375 376
378 """ 379 Returns the list of pre execution commands 380 """ 381 self.synchronizeOn() 382 edObject = None 383 if (self.__listCommandPreExecution != None): 384 edObject = list(self.__listCommandPreExecution) 385 self.synchronizeOff() 386 return edObject
387 388
389 - def setListCommandPostExecution(self, _listCommandPostExecution):
390 """ 391 Sets the list of post execution commands 392 """ 393 self.synchronizeOn() 394 if (_listCommandPostExecution is not None): 395 self.__listCommandPostExecution = list(_listCommandPostExecution) 396 self.synchronizeOff()
397 398
399 - def addListCommandPostExecution(self, _strCommandPostExecution):
400 """ 401 Adds a post execution command to the list 402 """ 403 self.synchronizeOn() 404 if (_strCommandPostExecution is not None): 405 self.__listCommandPostExecution.append(_strCommandPostExecution) 406 self.synchronizeOff()
407 408
410 """ 411 Returns the list of post execution commands 412 """ 413 self.synchronizeOn() 414 edObject = None 415 if (self.__listCommandPostExecution != None): 416 edObject = list(self.__listCommandPostExecution) 417 self.synchronizeOff() 418 return edObject
419 420
421 - def setConfigXIA2COREType(self, _strXIA2COREType):
422 """ 423 Sets the script shell 424 """ 425 self.synchronizeOn() 426 self.__strConfigXIA2COREType = _strXIA2COREType 427 self.synchronizeOff()
428 429
430 - def getConfigXIA2COREType(self):
431 """ 432 Returns the script shell 433 """ 434 return self.__strConfigXIA2COREType
435 436
437 - def setLogFileName(self, _strLogFileName):
438 """ 439 Sets the standard output log file name 440 """ 441 self.synchronizeOn() 442 self.__strLogFileName = _strLogFileName 443 self.synchronizeOff()
444 445
446 - def setErrorLogFileName(self, _strErrorLogFileName):
447 """ 448 Sets the error output log file name 449 """ 450 self.synchronizeOn() 451 self.__strErrorLogFileName = _strErrorLogFileName 452 self.synchronizeOff()
453 454
455 - def getLogFileName(self):
456 """ 457 Returns the standard output log file name 458 """ 459 return self.__strLogFileName
460 461
462 - def getErrorLogFileName(self):
463 """ 464 Returns the error output log file name 465 """ 466 return self.__strErrorLogFileName
467
468 - def setExecutable(self, _strExecutable):
469 """ 470 Sets the executable path 471 """ 472 self.synchronizeOn() 473 self.__strExecutable = _strExecutable 474 self.synchronizeOff()
475 476
477 - def getExecutable(self):
478 """ 479 Returns the executable path 480 """ 481 returnValue = self.__strExecutable 482 if (returnValue is not None): 483 returnValue = self.__strExecutable 484 return returnValue
485
486 - def setCommandline(self, _strCommandline):
487 """ 488 Sets the script command line (parameters to executable) 489 """ 490 self.synchronizeOn() 491 self.__strCommandline = _strCommandline 492 self.synchronizeOff()
493 494
495 - def getCommandline(self):
496 """ 497 Returns the script command line (parameters to executable) 498 """ 499 return self.__strCommandline
500 501
502 - def setStringVersion(self, _strVersion):
503 """ 504 Sets the executable version 505 """ 506 self.synchronizeOn() 507 self.__strVersion = _strVersion 508 self.synchronizeOff()
509 510
511 - def getStringVersion(self):
512 """ 513 Returns the executable version 514 """ 515 returnValue = None 516 if (self.__strVersion is not None): 517 returnValue = self.__strVersion 518 return returnValue
519 520
521 - def setPathToHostNamePidFile(self, _strPathToHostNamePidFile):
522 """ 523 Sets the executable version 524 """ 525 self.__strPathToHostNamePidFile = _strPathToHostNamePidFile
526 527
528 - def getPathToHostNamePidFile(self):
529 """ 530 Returns the executable version 531 """ 532 return self.__strPathToHostNamePidFile
533
534 - def findStringInLog(self, _strInput):
535 """ 536 Returns True if a string exists in the log file 537 """ 538 EDVerbose.DEBUG("EDPluginExecProcessXIA2CORE.findStringInLog") 539 for record in self.__listStandardOutput: 540 if _strInput in record: 541 return True 542 return False
543
544 - def writeProcessFile(self, _strFileName, _strContent):
545 """ 546 Main method to write a file in the plugin working directory 547 Such a file is called process file 548 """ 549 EDVerbose.DEBUG("EDPluginExecProcessXIA2CORE.writeProcessFile") 550 strFilePath = os.path.join(self.getWorkingDirectory(), _strFileName) 551 EDUtilsFile.writeFile(strFilePath, _strContent)
552 553
554 - def readProcessFile(self, _strFileName):
555 """ 556 Returns the file content of a process file 557 """ 558 EDVerbose.DEBUG("EDPluginExecProcessXIA2CORE.readProcessFile") 559 strFilePath = os.path.join(self.getWorkingDirectory(), _strFileName) 560 strFileContent = None 561 if os.path.exists(strFilePath): 562 strFileContent = EDUtilsFile.readFile(strFilePath) 563 return strFileContent
564 565
566 - def readProcessLogFile(self):
567 """ 568 Returns the content of the process standard output log file 569 """ 570 EDVerbose.DEBUG("EDPluginExecProcessXIA2CORE.readProcessLogFile") 571 return ''.join(self.__listStandardOutput)
572
573 - def readProcessErrorLogFile(self):
574 """ 575 Returns the content of the process error output log file 576 """ 577 EDVerbose.DEBUG("EDPluginExecProcessXIA2CORE.readProcessErrorLogFile") 578 return ''.join(self.__listStandardError)
579
580 - def getScriptBaseName(self):
581 return self.getBaseName()
582