Ejemplo n.º 1
0
    def stage_files(self):
        cwl_job = self.cwl_job()

        def stageFunc(resolved_path, target_path):
            log.info("resolving %s to %s" % (resolved_path, target_path))
            try:
                os.symlink(resolved_path, target_path)
            except OSError:
                pass

        if hasattr(cwl_job, "pathmapper"):
            process.stageFiles(cwl_job.pathmapper,
                               stageFunc,
                               ignoreWritable=True,
                               symLink=False)

        if hasattr(cwl_job, "generatefiles"):
            outdir = os.path.join(self._job_directory, "working")
            # TODO: Why doesn't cwl_job.generatemapper work?
            generate_mapper = pathmapper.PathMapper(
                cwl_job.generatefiles["listing"],
                outdir,
                outdir,
                separateDirs=False)
            # TODO: figure out what inplace_update should be.
            inplace_update = getattr(cwl_job, "inplace_update")
            process.stageFiles(generate_mapper,
                               stageFunc,
                               ignoreWritable=inplace_update,
                               symLink=False)
            from cwltool import job
            job.relink_initialworkdir(generate_mapper,
                                      outdir,
                                      outdir,
                                      inplace_update=inplace_update)
Ejemplo n.º 2
0
    def run(self,
            runtimeContext,     # type: RuntimeContext
            tmpdir_lock=None,   # type: Optional[ThreadLock]
            ):                  # type: (...) -> None

        make_dirs(self.tmpdir, exist_ok=True)
        env = self.environment
        vars_to_preserve = runtimeContext.preserve_environment
        if runtimeContext.preserve_entire_environment:
            vars_to_preserve = os.environ
        if vars_to_preserve is not None:
            for key, value in os.environ.items():
                if key in vars_to_preserve and key not in env:
                    # On Windows, subprocess env can't handle unicode.
                    env[key] = str(value) if onWindows() else value
        env["HOME"] = str(self.outdir) if onWindows() else self.outdir
        env["TMPDIR"] = str(self.tmpdir) if onWindows() else self.tmpdir
        if "PATH" not in env:
            env["PATH"] = str(os.environ["PATH"]) if onWindows() else os.environ["PATH"]
        if "SYSTEMROOT" not in env and "SYSTEMROOT" in os.environ:
            env["SYSTEMROOT"] = str(os.environ["SYSTEMROOT"]) if onWindows() else os.environ["SYSTEMROOT"]

        # stageFiles(self.pathmapper, ignoreWritable=True, symLink=True, secret_store=runtimeContext.secret_store)
        if self.generatemapper:
            # FIXME: see if this is needed... func doesn't exist anymore in cwltool 2.x
            # stageFiles(self.generatemapper, ignoreWritable=self.inplace_update,
            #            symLink=True, secret_store=runtimeContext.secret_store)
            relink_initialworkdir(self.generatemapper, self.outdir,
                                  self.builder.outdir, inplace_update=self.inplace_update)

        self.execute([], env, runtimeContext)
Ejemplo n.º 3
0
    def stage_files(self):
        cwl_job = self.cwl_job()

        def stageFunc(resolved_path, target_path):
            log.info("resolving %s to %s" % (resolved_path, target_path))
            try:
                os.symlink(resolved_path, target_path)
            except OSError:
                pass

        if hasattr(cwl_job, "pathmapper"):
            process.stageFiles(cwl_job.pathmapper, stageFunc, ignoreWritable=True, symLink=False)

        if hasattr(cwl_job, "generatefiles"):
            outdir = os.path.join(self._job_directory, "working")
            # TODO: Why doesn't cwl_job.generatemapper work?
            generate_mapper = pathmapper.PathMapper(cwl_job.generatefiles["listing"],
                                                    outdir, outdir, separateDirs=False)
            # TODO: figure out what inplace_update should be.
            inplace_update = getattr(cwl_job, "inplace_update")
            process.stageFiles(generate_mapper, stageFunc, ignoreWritable=inplace_update, symLink=False)
            from cwltool import job
            job.relink_initialworkdir(generate_mapper, outdir, outdir, inplace_update=inplace_update)
Ejemplo n.º 4
0
    def execute(self, runtime, env, runtime_context):  # noqa: E811
        # type: (List[Text], MutableMapping[Text, Text], RuntimeContext) -> None

        self.results = self.wps_process.execute(self.builder.job, self.outdir,
                                                self.expected_outputs)

        if self.joborder and runtime_context.research_obj:
            job_order = self.joborder
            assert runtime_context.prov_obj
            assert runtime_context.process_run_id
            runtime_context.prov_obj.used_artefacts(
                job_order, runtime_context.process_run_id, str(self.name))
        outputs = {}  # type: Dict[Text, Text]
        try:
            rcode = 0

            if self.successCodes:
                process_status = "success"
            elif self.temporaryFailCodes:
                process_status = "temporaryFail"
            elif self.permanentFailCodes:
                process_status = "permanentFail"
            elif rcode == 0:
                process_status = "success"
            else:
                process_status = "permanentFail"

            if self.generatefiles["listing"]:
                assert self.generatemapper is not None
                relink_initialworkdir(self.generatemapper,
                                      self.outdir,
                                      self.builder.outdir,
                                      inplace_update=self.inplace_update)

            outputs = self.collect_outputs(self.outdir)
            outputs = bytes2str_in_dicts(outputs)  # type: ignore
        except OSError as exc:
            if exc.errno == 2:
                if runtime:
                    LOGGER.exception(u"'%s' not found", runtime[0])
                else:
                    LOGGER.exception(u"'%s' not found", self.command_line[0])
            else:
                LOGGER.exception("Exception while running job")
            process_status = "permanentFail"
        except WorkflowException as err:
            LOGGER.exception(u"[job %s] Job error:\n%s", self.name, err)
            process_status = "permanentFail"
        except Exception:  # noqa: W0703 # nosec: B110
            LOGGER.exception("Exception while running job")
            process_status = "permanentFail"
        if runtime_context.research_obj and self.prov_obj and \
                runtime_context.process_run_id:
            # creating entities for the outputs produced by each step (in the provenance document)
            self.prov_obj.generate_output_prov(outputs,
                                               runtime_context.process_run_id,
                                               str(self.name))
            self.prov_obj.document.wasEndedBy(runtime_context.process_run_id,
                                              None,
                                              self.prov_obj.workflow_run_uri,
                                              now())
        if process_status != "success":
            LOGGER.warning(u"[job %s] completed %s", self.name, process_status)
        else:
            LOGGER.info(u"[job %s] completed %s", self.name, process_status)

        if LOGGER.isEnabledFor(logging.DEBUG):
            LOGGER.debug(u"[job %s] %s", self.name,
                         json.dumps(outputs, indent=4))

        if self.generatemapper and runtime_context.secret_store:
            # Delete any runtime-generated files containing secrets.
            for _, path_item in self.generatemapper.items():
                if path_item.type == "CreateFile":
                    if runtime_context.secret_store.has_secret(
                            path_item.resolved):
                        host_outdir = self.outdir
                        container_outdir = self.builder.outdir
                        host_outdir_tgt = path_item.target
                        if path_item.target.startswith(container_outdir + "/"):
                            host_outdir_tgt = os.path.join(
                                host_outdir,
                                path_item.target[len(container_outdir) + 1:])
                        os.remove(host_outdir_tgt)

        if runtime_context.workflow_eval_lock is None:
            raise WorkflowException(
                "runtime_context.workflow_eval_lock must not be None")

        with runtime_context.workflow_eval_lock:
            self.output_callback(outputs, process_status)

        if self.stagedir and os.path.exists(self.stagedir):
            LOGGER.debug(u"[job %s] Removing input staging directory %s",
                         self.name, self.stagedir)
            shutil.rmtree(self.stagedir, True)

        if runtime_context.rm_tmpdir:
            LOGGER.debug(u"[job %s] Removing temporary directory %s",
                         self.name, self.tmpdir)
            shutil.rmtree(self.tmpdir, True)
Ejemplo n.º 5
0
    def run(self, runtimeContext):  # noqa: C901
        """Run a job."""
        self._setup(runtimeContext)

        env = self.environment
        if not os.path.exists(self.tmpdir):
            os.makedirs(self.tmpdir)
        vars_to_preserve = runtimeContext.preserve_environment
        if runtimeContext.preserve_entire_environment:
            vars_to_preserve = os.environ
        if vars_to_preserve is not None:
            for key, value in os.environ.items():
                if key in vars_to_preserve and key not in env:
                    env[key] = value
        env["HOME"] = self.builder.outdir
        env["TMPDIR"] = self.tmpdir
        if "PATH" not in env:
            env["PATH"] = os.environ["PATH"]
        if "SYSTEMROOT" not in env and "SYSTEMROOT" in os.environ:
            env["SYSTEMROOT"] = os.environ["SYSTEMROOT"]

        try:
            stage_files(self.pathmapper, ignore_writable=True, symlink=False)
            if getattr(self, "generatemapper", ""):
                stage_files(
                    self.generatemapper,
                    ignore_writable=self.inplace_update,
                    symlink=False,
                )
                relink_initialworkdir(
                    self.generatemapper,
                    self.outdir,
                    self.builder.outdir,
                    inplace_update=self.inplace_update,
                )
        except OSError:
            # cwltool/process.py, line 239, in stage_files
            # shutil.copytree(p.resolved, p.target)
            pass
        self.add_volumes(self.pathmapper)
        if getattr(self, "generatemapper", ""):
            self.add_volumes(self.generatemapper)

        # useful for debugging
        log.debug(f"[job {self.name}] self.__dict__ in run() ---------------")
        log.debug(pformat(self.__dict__))

        task = self.create_task_msg(
            runtimeContext.working_dir, runtimeContext.workflow_uuid
        )

        log.info(f"[job {self.name}] CREATED TASK MSG----------------------")
        log.info(pformat(task))

        try:
            # task_id = job_id received from job-controller
            task_id = runtimeContext.pipeline.service.submit(**task)
            task_id = str(task_id["job_id"])
            running_jobs = {"total": 1, "job_ids": [task_id]}
            runtimeContext.publisher.publish_workflow_status(
                runtimeContext.workflow_uuid,
                1,
                message={"progress": {"running": running_jobs,}},
            )
            log.info(f"[job {self.name}] SUBMITTED TASK --------------------")
            log.info(f"[job {self.name}] task id: {task_id} ")
            self.task_name_map[self.name] = task_id
            operation = runtimeContext.pipeline.service.check_status(task_id)
        except Exception as e:
            log.error(
                f"[job {self.name}] " f"Failed to submit task to job controller:\n{e}"
            )
            raise WorkflowException(e)

        def callback(rcode):
            try:
                outputs = self.collect_outputs(self.outdir, rcode=rcode)
                cleaned_outputs = {}
                for k, v in outputs.items():
                    if isinstance(k, bytes):
                        k = k.decode("utf8")
                    if isinstance(v, bytes):
                        v = v.decode("utf8")
                    cleaned_outputs[k] = v
                self.outputs = cleaned_outputs
                self.output_callback(self.outputs, "success")
            except WorkflowException as e:
                log.error(f"[job {self.name}] workflow job error:\n{e}")
                self.output_callback({}, "permanentFail")
            except Exception as e:
                log.error(f"[job {self.name}] job error:\n{e}")
                self.output_callback({}, "permanentFail")
            finally:
                if self.outputs is not None:
                    log.info(f"[job {self.name}] OUTPUTS ------------------")
                    log.info(pformat(self.outputs))
                self.cleanup(runtimeContext.rm_tmpdir)

        poll = ReanaPipelinePoll(
            workflow_uuid=runtimeContext.workflow_uuid,
            task_id=self.task_name_map.get(self.name),
            jobname=self.name,
            service=runtimeContext.pipeline.service,
            operation=operation,
            callback=callback,
            publisher=runtimeContext.publisher,
        )

        runtimeContext.pipeline.add_thread(poll)
        poll.start()