def main(): """ KBase Convert task manager for converting between KBase objects. Step 1 - Run a converter to pull the source object and save the destination object. Args: workspace_service_url: URL for a KBase Workspace service where KBase objects are stored. ujs_service_url: URL for a User and Job State service to report task progress back to the user. shock_service_url: URL for a KBase SHOCK data store service for storing files and large reference data. handle_service_url: URL for a KBase Handle service that maps permissions from the Workspace to SHOCK for KBase types that specify a Handle reference instead of a SHOCK reference. source_workspace_name: The name of the source workspace. destination_workspace_name: The name of the destination workspace. source_object_name: The source object name. destination_object_name: The destination object name. source_kbase_type: The KBase Workspace type string that indicates the module and type of the object being created. destination_kbase_type: The KBase Workspace type string that indicates the module and type of the object being created. optional_arguments: This is a JSON string containing optional parameters that can be passed in for custom behavior per conversion. ujs_job_id: The job id from the User and Job State service that can be used to report status on task progress back to the user. job_details: This is a JSON string that passes in the script specific command line options for a given conversion type. The service pulls these config settings from a script config created by the developer of the conversion script and passes that into the AWE job that calls this script. working_directory: The working directory on disk where files can be created and will be cleaned when the job ends with success or failure. keep_working_directory: A flag to tell the script not to delete the working directory, which is mainly for debugging purposes. Returns: Literal return value is 0 for success and 1 for failure. Actual data output is one or more Workspace objects saved to a user's workspace. Authors: Matt Henderson, Gavin Price """ logger = script_utils.stderrlogger(__file__, level=logging.DEBUG) logger.info("Executing KBase Convert tasks") script_details = script_utils.parse_docs(main.__doc__) logger.debug(script_details["Args"]) parser = script_utils.ArgumentParser(description=script_details["Description"], epilog=script_details["Authors"]) # provided by service config parser.add_argument('--workspace_service_url', help=script_details["Args"]["workspace_service_url"], action='store', required=True) parser.add_argument('--ujs_service_url', help=script_details["Args"]["ujs_service_url"], action='store', required=True) # optional because not all KBase Workspace types contain a SHOCK or Handle reference parser.add_argument('--shock_service_url', help=script_details["Args"]["shock_service_url"], action='store', default=None) parser.add_argument('--handle_service_url', help=script_details["Args"]["handle_service_url"], action='store', default=None) # workspace info for pulling the data parser.add_argument('--source_workspace_name', help=script_details["Args"]["source_workspace_name"], action='store', required=True) parser.add_argument('--source_object_name', help=script_details["Args"]["source_object_name"], action='store', required=True) # workspace info for saving the data parser.add_argument('--destination_workspace_name', help=script_details["Args"]["destination_workspace_name"], action='store', required=True) parser.add_argument('--destination_object_name', help=script_details["Args"]["destination_object_name"], action='store', required=True) # the types that we are transforming between, currently assumed one to one parser.add_argument('--source_kbase_type', help=script_details["Args"]["source_kbase_type"], action='store', required=True) parser.add_argument('--destination_kbase_type', help=script_details["Args"]["destination_kbase_type"], action='store', required=True) # any user options provided, encoded as a jason string parser.add_argument('--optional_arguments', help=script_details["Args"]["optional_arguments"], action='store', default='{}') # Used if you are restarting a previously executed job? parser.add_argument('--ujs_job_id', help=script_details["Args"]["ujs_job_id"], action='store', default=None, required=False) # config information for running the validate and transform scripts parser.add_argument('--job_details', help=script_details["Args"]["job_details"], action='store', default=None) # the working directory is where all the files for this job will be written, # and normal operation cleans it after the job ends (success or fail) parser.add_argument('--working_directory', help=script_details["Args"]["working_directory"], action='store', default=None, required=True) parser.add_argument('--keep_working_directory', help=script_details["Args"]["keep_working_directory"], action='store_true') # ignore any extra arguments args, unknown = parser.parse_known_args() kb_token = os.environ.get('KB_AUTH_TOKEN') ujs = UserAndJobState(url=args.ujs_service_url, token=kb_token) est = datetime.datetime.utcnow() + datetime.timedelta(minutes=3) if args.ujs_job_id is not None: ujs.update_job_progress(args.ujs_job_id, kb_token, "KBase Data Convert started", 1, est.strftime('%Y-%m-%dT%H:%M:%S+0000')) # parse all the json strings from the argument list into dicts # TODO had issues with json.loads and unicode strings, workaround was using simplejson and base64 args.optional_arguments = simplejson.loads(base64.urlsafe_b64decode(args.optional_arguments)) args.job_details = simplejson.loads(base64.urlsafe_b64decode(args.job_details)) if not os.path.exists(args.working_directory): os.mkdir(args.working_directory) if args.ujs_job_id is not None: ujs.update_job_progress(args.ujs_job_id, kb_token, "Converting from {0} to {1}".format(args.source_kbase_type,args.destination_kbase_type), 1, est.strftime('%Y-%m-%dT%H:%M:%S+0000') ) # Step 1 : Convert the objects try: logger.info(args) convert_args = args.job_details["transform"] convert_args["optional_arguments"] = args.optional_arguments convert_args["working_directory"] = args.working_directory convert_args["workspace_service_url"] = args.workspace_service_url convert_args["source_workspace_name"] = args.source_workspace_name convert_args["source_object_name"] = args.source_object_name convert_args["destination_workspace_name"] = args.destination_workspace_name convert_args["destination_object_name"] = args.destination_object_name logger.info(convert_args) task_output = handler_utils.run_task(logger, convert_args) if task_output["stdout"] is not None: logger.debug("STDOUT : " + str(task_output["stdout"])) if task_output["stderr"] is not None: logger.debug("STDERR : " + str(task_output["stderr"])) except Exception, e: handler_utils.report_exception(logger, {"message": 'ERROR : Conversion from {0} to {1}'.format(args.source_kbase_type,args.destination_kbase_type), "exc": e, "ujs": ujs, "ujs_job_id": args.ujs_job_id, "token": kb_token, }, {"keep_working_directory": args.keep_working_directory, "working_directory": args.working_directory}) ujs.complete_job(args.ujs_job_id, kb_token, "Convert to {0} failed.".format( args.destination_workspace_name), str(e), None)
if "custom_options" in job_details["transform"]["handler_options"]: for c in job_details["transform"]["handler_options"]["custom_options"]: transformation_args[c["name"]] = c["value"] if "working_directory" in transformation_args: logger.debug(os.path.abspath(os.getcwd())) transformation_args["working_directory"] = os.path.abspath(os.getcwd()) # check that we are not missing any required arguments for k in job_details["transform"]["handler_options"]["required_fields"]: if transformation_args[k] is None: raise Exception("Missing required field {0}, please provide using optional_arguments.".format(k)) logger.debug(transformation_args) task_output = handler_utils.run_task(logger, transformation_args, debug=debug) if task_output["stdout"] is not None: logger.debug("STDOUT : " + str(task_output["stdout"])) if task_output["stderr"] is not None: logger.debug("STDERR : " + str(task_output["stderr"])) os.chdir(current_directory) except Exception, e: logger.debug("Caught exception during transformation step!") os.chdir(current_directory) if ujs_job_id is not None: error_object["status"] = "ERROR : Transformation from KBase type to External type failed - {0}".format(e.message)[:handler_utils.UJS_STATUS_MAX]
# Step 1 : Convert the objects try: logger.info(args) convert_args = args.job_details["transform"] convert_args["optional_arguments"] = args.optional_arguments convert_args["working_directory"] = args.working_directory convert_args["workspace_service_url"] = args.workspace_service_url convert_args["source_workspace_name"] = args.source_workspace_name convert_args["source_object_name"] = args.source_object_name convert_args["destination_workspace_name"] = args.destination_workspace_name convert_args["destination_object_name"] = args.destination_object_name logger.info(convert_args) task_output = handler_utils.run_task(logger, convert_args) if task_output["stdout"] is not None: logger.debug("STDOUT : " + str(task_output["stdout"])) if task_output["stderr"] is not None: logger.debug("STDERR : " + str(task_output["stderr"])) except Exception, e: if args.ujs_job_id is not None: error_object["status"] = "ERROR : Conversion between KBase Types failed - {0}".format(e.message)[:handler_utils.UJS_STATUS_MAX] error_object["error_message"] = traceback.format_exc() handler_utils.report_exception(logger, error_object, cleanup_details) ujs.complete_job(args.ujs_job_id, kb_token,
logger.info(args) convert_args = args.job_details["transform"] convert_args["optional_arguments"] = args.optional_arguments convert_args["working_directory"] = args.working_directory convert_args["workspace_service_url"] = args.workspace_service_url convert_args["source_workspace_name"] = args.source_workspace_name convert_args["source_object_name"] = args.source_object_name convert_args[ "destination_workspace_name"] = args.destination_workspace_name convert_args[ "destination_object_name"] = args.destination_object_name logger.info(convert_args) task_output = handler_utils.run_task(logger, convert_args) if task_output["stdout"] is not None: logger.debug("STDOUT : " + str(task_output["stdout"])) if task_output["stderr"] is not None: logger.debug("STDERR : " + str(task_output["stderr"])) except Exception, e: if args.ujs_job_id is not None: error_object[ "status"] = "ERROR : Conversion between KBase Types failed - {0}".format( e.message)[:handler_utils.UJS_STATUS_MAX] error_object["error_message"] = traceback.format_exc() handler_utils.report_exception(logger, error_object, cleanup_details)
filename = os.path.split(files[0])[-1] try: if ujs_job_id is not None: # Update on validation steps logger.info( "UJS message : " + "Attempting to validate {0}".format( filename)[:handler_utils.UJS_STATUS_MAX]) ujs.update_job_progress( ujs_job_id, kb_token, "Attempting to validate {0}".format(filename) [:handler_utils.UJS_STATUS_MAX], 1, est.strftime('%Y-%m-%dT%H:%M:%S+0000')) task_output = handler_utils.run_task(logger, validation_args, callback=lambda msg: \ ujs.update_job_progress(ujs_job_id, kb_token, msg[:handler_utils.UJS_STATUS_MAX], 1, est.strftime('%Y-%m-%dT%H:%M:%S+0000'))) else: logger.info( "Attempting to validate {0}".format(filename)) task_output = handler_utils.run_task( logger, validation_args) except Exception, e: logger.debug("Caught exception while validating!") if ujs_job_id is not None: task_output = dict() task_output["stdout"] = e.args[0] task_output["stderr"] = e.args[1] if task_output["stderr"] != None and len( task_output["stderr"].strip()) > 0:
for k in job_details["validate"]["handler_options"]["required_fields"]: if k not in validation_args: raise Exception("Missing required field {0}, please provide using optional_arguments.".format(k)) elif validation_args[k] is None: raise Exception("Missing value for required field {0}, please provide using optional_arguments.".format(k)) filename = os.path.split(files[0])[-1] try: if ujs_job_id is not None: # Update on validation steps logger.info("UJS message : " + "Attempting to validate {0}".format(filename)[:handler_utils.UJS_STATUS_MAX]) ujs.update_job_progress(ujs_job_id, kb_token, "Attempting to validate {0}".format(filename)[:handler_utils.UJS_STATUS_MAX], 1, est.strftime('%Y-%m-%dT%H:%M:%S+0000')) task_output = handler_utils.run_task(logger, validation_args, callback=lambda msg: \ ujs.update_job_progress(ujs_job_id, kb_token, msg[:handler_utils.UJS_STATUS_MAX], 1, est.strftime('%Y-%m-%dT%H:%M:%S+0000'))) else: logger.info("Attempting to validate {0}".format(filename)) task_output = handler_utils.run_task(logger, validation_args) except Exception, e: logger.debug("Caught exception while validating!") if ujs_job_id is not None: task_output = dict() task_output["stdout"] = e.args[0] task_output["stderr"] = e.args[1] if task_output["stderr"] != None and len(task_output["stderr"].strip()) > 0: error_object["status"] = "ERROR : Validation of input data - {0}".format(task_output["stderr"][-handler_utils.UJS_STATUS_MAX:])[:handler_utils.UJS_STATUS_MAX] error_object["error_message"] = task_output["stderr"] elif task_output["stdout"] != None and len(task_output["stdout"].strip()) > 0: