X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/ec0d70da440802b2859d3199e559f27cf74c035d..8afc85aabb9563da4de17b0b5f7d4fe574e9ad8d:/sdk/cwl/arvados_cwl/__init__.py diff --git a/sdk/cwl/arvados_cwl/__init__.py b/sdk/cwl/arvados_cwl/__init__.py index be093d7450..d509f400f1 100644 --- a/sdk/cwl/arvados_cwl/__init__.py +++ b/sdk/cwl/arvados_cwl/__init__.py @@ -19,6 +19,8 @@ from functools import partial import pkg_resources # part of setuptools import Queue import time +import signal +import thread from cwltool.errors import WorkflowException import cwltool.main @@ -31,6 +33,7 @@ import arvados import arvados.config from arvados.keep import KeepClient from arvados.errors import ApiError +import arvados.commands._util as arv_cmd from .arvcontainer import ArvadosContainer, RunnerContainer from .arvjob import ArvadosJob, RunnerJob, RunnerTemplate @@ -96,6 +99,11 @@ class ArvCwlRunner(object): self.collection_cache = CollectionCache(self.api, self.keep_client, self.num_retries) + self.fetcher_constructor = partial(CollectionFetcher, + api_client=self.api, + fs_access=CollectionFsAccess("", collection_cache=self.collection_cache), + num_retries=self.num_retries) + self.work_api = None expected_api = ["jobs", "containers"] for api in expected_api: @@ -116,10 +124,7 @@ class ArvCwlRunner(object): def arv_make_tool(self, toolpath_object, **kwargs): kwargs["work_api"] = self.work_api - kwargs["fetcher_constructor"] = partial(CollectionFetcher, - api_client=self.api, - fs_access=CollectionFsAccess("", collection_cache=self.collection_cache), - num_retries=self.num_retries) + kwargs["fetcher_constructor"] = self.fetcher_constructor kwargs["resolver"] = partial(collectionResolver, self.api, num_retries=self.num_retries) if "class" in toolpath_object and toolpath_object["class"] == "CommandLineTool": return ArvadosCommandTool(self, toolpath_object, **kwargs) @@ -152,10 +157,12 @@ class ArvCwlRunner(object): with self.workflow_eval_lock: self.processes[container.uuid] = container - def process_done(self, uuid): + def process_done(self, uuid, record): with self.workflow_eval_lock: - if uuid in self.processes: - del self.processes[uuid] + j = self.processes[uuid] + logger.info("%s %s is %s", self.label(j), uuid, record["state"]) + self.task_queue.add(partial(j.done, record)) + del self.processes[uuid] def wrapped_callback(self, cb, obj, st): with self.workflow_eval_lock: @@ -176,10 +183,7 @@ class ArvCwlRunner(object): j.update_pipeline_component(event["properties"]["new_attributes"]) logger.info("%s %s is Running", self.label(j), uuid) elif event["properties"]["new_attributes"]["state"] in ("Complete", "Failed", "Cancelled", "Final"): - with self.workflow_eval_lock: - j = self.processes[uuid] - self.task_queue.add(partial(j.done, event["properties"]["new_attributes"])) - logger.info("%s %s is %s", self.label(j), uuid, event["properties"]["new_attributes"]["state"]) + self.process_done(uuid, event["properties"]["new_attributes"]) def label(self, obj): return "[%s %s]" % (self.work_api[0:-1], obj.name) @@ -251,7 +255,7 @@ class ArvCwlRunner(object): self.api.collections().delete(uuid=i).execute(num_retries=self.num_retries) except: logger.warn("Failed to delete intermediate output: %s", sys.exc_info()[1], exc_info=(sys.exc_info()[1] if self.debug else False)) - if sys.exc_info()[0] is KeyboardInterrupt: + if sys.exc_info()[0] is KeyboardInterrupt or sys.exc_info()[0] is SystemExit: break def check_features(self, obj): @@ -565,8 +569,8 @@ class ArvCwlRunner(object): except UnsupportedRequirement: raise except: - if sys.exc_info()[0] is KeyboardInterrupt: - logger.error("Interrupted, marking pipeline as failed") + if sys.exc_info()[0] is KeyboardInterrupt or sys.exc_info()[0] is SystemExit: + logger.error("Interrupted, workflow will be cancelled") else: logger.error("Execution failed: %s", sys.exc_info()[1], exc_info=(sys.exc_info()[1] if self.debug else False)) if self.pipeline: @@ -763,12 +767,20 @@ def add_arv_hints(): "http://arvados.org/cwl#ReuseRequirement" ]) -def main(args, stdout, stderr, api_client=None, keep_client=None): +def exit_signal_handler(sigcode, frame): + logger.error("Caught signal {}, exiting.".format(sigcode)) + sys.exit(-sigcode) + +def main(args, stdout, stderr, api_client=None, keep_client=None, + install_sig_handlers=True): parser = arg_parser() job_order_object = None arvargs = parser.parse_args(args) + if install_sig_handlers: + arv_cmd.install_signal_handlers() + if arvargs.update_workflow: if arvargs.update_workflow.find('-7fd4e-') == 5: want_api = 'containers'