#!/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('(.*)',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: " + error_mask)
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:
self.logCritical("Error copying output\n" + \
" - Source: %s\n" + \
" - Dest: %s\n" +
" - Error: %s",
resultFullPath, dest, Exception)
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.logCritical("Path does not exist or is inaccessible: %s\n", \
self.pymwDir)
sys.exit(1)
else:
found = True
else:
newArgs.append(arg)
if not found:
self.logCritical("Error, path argument expected: -pymw_dir \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()