mirror of https://github.com/BOINC/boinc.git
120 lines
4.3 KiB
Python
Executable File
120 lines
4.3 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
import boinc_path_config
|
|
from assimilator import *
|
|
import os, sys, shutil
|
|
|
|
class PymwAssimilator(Assimilator):
|
|
"""
|
|
PyMW Assimilator. Copies workunit results to a predefined output directory.
|
|
"""
|
|
|
|
def __init__(self):
|
|
Assimilator.__init__(self)
|
|
self.pymwDir = None
|
|
|
|
def _copy_to_output(self, result, error_mask=0):
|
|
# validate that the destination path still exists
|
|
if not os.path.exists(self.pymwDir):
|
|
self.logCritical("PyMW path does not exist or is inaccessible: %s\n", \
|
|
self.pymwDir)
|
|
return
|
|
|
|
resultFullPath = self.get_file_path(result)
|
|
resultName = re.search('<open_name>(.*)</open_name>',result.xml_doc_in).group(1)
|
|
|
|
# validate that the source path is accessible
|
|
if not error_mask and not os.path.exists(resultFullPath):
|
|
self.logCritical("Result path does not exist or is inaccessible: %s\n", \
|
|
resultFullPath)
|
|
return
|
|
|
|
# copy the file to the output directory where it
|
|
# will be processed by PyMW
|
|
try:
|
|
dest = os.path.join(self.pymwDir, resultName)
|
|
if error_mask:
|
|
dest += ".error"
|
|
f = open(dest, "w")
|
|
try:
|
|
f.writelines("BOINC error: " + str(error_mask) + "\n")
|
|
if result.stderr_out:
|
|
f.writelines("STD ERR: " + result.stderr_out + "\n")
|
|
f.writelines("For additional information, check: " +
|
|
"$project/log_$machine/pymw_assimilator.py.log\n")
|
|
finally: f.close()
|
|
self.logNormal("Error flag created [%s]\n", resultName)
|
|
else:
|
|
shutil.copy2(resultFullPath, dest)
|
|
self.logNormal("Result copied [%s]\n", resultName)
|
|
except (Exception, msg):
|
|
self.logCritical("Error copying output\n" + \
|
|
" - Source: %s\n" + \
|
|
" - Dest: %s\n" +
|
|
" - Error: %s",
|
|
resultFullPath, dest, msg)
|
|
|
|
def assimilate_handler(self, wu, results, canonical_result):
|
|
"""
|
|
Assimilates a canonical result by copying the result file
|
|
to the PyMW pickup directory, self.pymwDir
|
|
"""
|
|
|
|
# check for valid wu.canonical_result
|
|
if wu.canonical_result:
|
|
self.logNormal("[%s] Found canonical result\n", wu.name)
|
|
self._copy_to_output(canonical_result, wu.error_mask)
|
|
elif wu.error_mask != 0:
|
|
# this is an error
|
|
self.logNormal("[%s] Workunit failed, sending arbitrary result\n", wu.name)
|
|
self._copy_to_output(results[0], wu.error_mask)
|
|
self.logNormal("[%s] No canonical result\n", wu.name)
|
|
else:
|
|
self.logNormal("[%s] No canonical result\n", wu.name)
|
|
|
|
# report errors with the workunit
|
|
if self.report_errors(wu):
|
|
pass
|
|
|
|
|
|
def parse_args(self, args):
|
|
"""
|
|
This overridden version adds support for a PyMW destination directory.
|
|
"""
|
|
|
|
# scan the args for the -pymw_dir switch
|
|
# remove it when found so the base class doesn't complain
|
|
# then call the base parse_args method
|
|
|
|
newArgs = []
|
|
args.reverse()
|
|
found = False
|
|
|
|
while len(args):
|
|
arg = args.pop()
|
|
if arg.strip() == '-pymw_dir':
|
|
if len(args) == 0:
|
|
self.logCritical("Error, path switch found, but no path specified\n")
|
|
sys.exit(1)
|
|
|
|
self.pymwDir = args.pop()
|
|
if not os.path.exists(self.pymwDir):
|
|
self.logNormal("Warning, path does not exist or is inaccessible: %s\n", \
|
|
self.pymwDir)
|
|
found = True
|
|
else:
|
|
found = True
|
|
else:
|
|
newArgs.append(arg)
|
|
|
|
if not found:
|
|
self.logCritical("Error, path argument expected: -pymw_dir <PATH>\n")
|
|
sys.exit(1)
|
|
|
|
Assimilator.parse_args(self, newArgs)
|
|
|
|
# allow the module to be executed as an application
|
|
if __name__ == '__main__':
|
|
asm = PymwAssimilator()
|
|
asm.run()
|