#!/usr/bin/env python import boinc_path_config from Boinc.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()