Exemplo n.º 1
0
    def invoke(self):
        workflow_invocation = self.workflow_invocation
        remaining_steps = self.progress.remaining_steps()
        delayed_steps = False
        for step in remaining_steps:
            jobs = None
            try:
                self.__check_implicitly_dependent_steps(step)

                jobs = self._invoke_step(step)
                for job in (util.listify(jobs) or [None]):
                    # Record invocation
                    workflow_invocation_step = model.WorkflowInvocationStep()
                    workflow_invocation_step.workflow_invocation = workflow_invocation
                    workflow_invocation_step.workflow_step = step
                    workflow_invocation_step.job = job
            except modules.DelayedWorkflowEvaluation:
                delayed_steps = True
                self.progress.mark_step_outputs_delayed(step)

        if delayed_steps:
            state = model.WorkflowInvocation.states.READY
        else:
            state = model.WorkflowInvocation.states.SCHEDULED
        workflow_invocation.state = state

        # All jobs ran successfully, so we can save now
        self.trans.sa_session.add(workflow_invocation)

        # Not flushing in here, because web controller may create multiple
        # invocations.
        return self.progress.outputs
Exemplo n.º 2
0
    def test_subworkflow_progress(self):
        self._setup_workflow(TEST_SUBWORKFLOW_YAML)
        hda = model.HistoryDatasetAssociation()
        self._set_previous_progress([
            (100, {
                "output": hda
            }),
            (101, UNSCHEDULED_STEP),
        ])
        subworkflow_invocation = self.invocation.create_subworkflow_invocation_for_step(
            self.invocation.workflow.step_by_index(1))
        progress = self._new_workflow_progress()
        remaining_steps = progress.remaining_steps()
        (subworkflow_step, subworkflow_invocation_step) = remaining_steps[0]
        subworkflow_progress = progress.subworkflow_progress(
            subworkflow_invocation, subworkflow_step, {})
        subworkflow = subworkflow_step.subworkflow
        assert subworkflow_progress.workflow_invocation == subworkflow_invocation
        assert subworkflow_progress.workflow_invocation.workflow == subworkflow

        subworkflow_input_step = subworkflow.step_by_index(0)
        subworkflow_invocation_step = model.WorkflowInvocationStep()
        subworkflow_invocation_step.workflow_step_id = subworkflow_input_step.id
        subworkflow_invocation_step.state = 'new'
        subworkflow_invocation_step.workflow_step = subworkflow_input_step

        subworkflow_progress.set_outputs_for_input(subworkflow_invocation_step)

        subworkflow_cat_step = subworkflow.step_by_index(1)

        assert hda is subworkflow_progress.replacement_for_tool_input(
            subworkflow_cat_step,
            MockInput(),
            "input1",
        )
Exemplo n.º 3
0
 def _invocation_step(self, index):
     if index < len(self.invocation.steps):
         return self.invocation.steps[index]
     else:
         workflow_invocation_step = model.WorkflowInvocationStep()
         workflow_invocation_step.workflow_step = self._step(index)
         return workflow_invocation_step
Exemplo n.º 4
0
    def invoke(self):
        workflow_invocation = model.WorkflowInvocation()
        workflow_invocation.workflow = self.workflow

        # Web controller will populate state on each step before calling
        # invoke but not API controller. More work should be done to further
        # harmonize these methods going forward if possible - if possible
        # moving more web controller logic here.
        state_populated = not self.workflow.steps or hasattr(
            self.workflow.steps[0], "state")
        if not state_populated:
            self._populate_state()

        for step in self.workflow.steps:
            jobs = self._invoke_step(step)
            for job in util.listify(jobs):
                # Record invocation
                workflow_invocation_step = model.WorkflowInvocationStep()
                workflow_invocation_step.workflow_invocation = workflow_invocation
                workflow_invocation_step.workflow_step = step
                workflow_invocation_step.job = job

        # All jobs ran successfully, so we can save now
        self.trans.sa_session.add(workflow_invocation)

        # Not flushing in here, because web controller may create multiple
        # invokations.
        return self.outputs
Exemplo n.º 5
0
    def invoke( self ):
        workflow_invocation = self.workflow_invocation
        maximum_duration = getattr( self.trans.app.config, "maximum_workflow_invocation_duration", -1 )
        if maximum_duration > 0 and workflow_invocation.seconds_since_created > maximum_duration:
            log.debug("Workflow invocation [%s] exceeded maximum number of seconds allowed for scheduling [%s], failing." % (workflow_invocation.id, maximum_duration))
            workflow_invocation.state = model.WorkflowInvocation.states.FAILED
            # All jobs ran successfully, so we can save now
            self.trans.sa_session.add( workflow_invocation )

            # Not flushing in here, because web controller may create multiple
            # invocations.
            return self.progress.outputs

        remaining_steps = self.progress.remaining_steps()
        delayed_steps = False
        for step in remaining_steps:
            step_delayed = False
            step_timer = ExecutionTimer()
            jobs = None
            try:
                self.__check_implicitly_dependent_steps(step)

                # TODO: step may fail to invoke, do something about that.
                jobs = self._invoke_step( step )
                for job in (util.listify( jobs ) or [None]):
                    # Record invocation
                    workflow_invocation_step = model.WorkflowInvocationStep()
                    workflow_invocation_step.workflow_invocation = workflow_invocation
                    workflow_invocation_step.workflow_step = step
                    # Job may not be generated in this thread if bursting is enabled
                    # https://github.com/galaxyproject/galaxy/issues/2259
                    if job:
                        workflow_invocation_step.job_id = job.id
            except modules.DelayedWorkflowEvaluation:
                step_delayed = delayed_steps = True
                self.progress.mark_step_outputs_delayed( step )
            except Exception:
                log.exception(
                    "Failed to schedule %s, problem occurred on %s.",
                    self.workflow_invocation.workflow.log_str(),
                    step.log_str(),
                )
                raise

            step_verb = "invoked" if not step_delayed else "delayed"
            log.debug("Workflow step %s of invocation %s %s %s" % (step.id, workflow_invocation.id, step_verb, step_timer))

        if delayed_steps:
            state = model.WorkflowInvocation.states.READY
        else:
            state = model.WorkflowInvocation.states.SCHEDULED
        workflow_invocation.state = state

        # All jobs ran successfully, so we can save now
        self.trans.sa_session.add( workflow_invocation )

        # Not flushing in here, because web controller may create multiple
        # invocations.
        return self.progress.outputs
Exemplo n.º 6
0
    def _set_previous_progress(self, outputs_dict):
        for step_id, step_value in outputs_dict.items():
            if step_value is not UNSCHEDULED_STEP:
                self.progress[step_id] = step_value

                workflow_invocation_step = model.WorkflowInvocationStep()
                workflow_invocation_step.workflow_step_id = step_id
                self.invocation.steps.append(workflow_invocation_step)

            workflow_invocation_step_state = model.WorkflowRequestStepState()
            workflow_invocation_step_state.workflow_step_id = step_id
            workflow_invocation_step_state.value = True
            self.invocation.step_states.append(workflow_invocation_step_state)
Exemplo n.º 7
0
    def _set_previous_progress(self, outputs):
        for i, (step_id, step_value) in enumerate(outputs):
            if step_value is not UNSCHEDULED_STEP:
                self.progress[step_id] = step_value

                workflow_invocation_step = model.WorkflowInvocationStep()
                workflow_invocation_step.workflow_step_id = step_id
                workflow_invocation_step.state = 'scheduled'
                workflow_invocation_step.workflow_step = self._step(i)
                self.assertEqual(step_id, self._step(i).id)
                # workflow_invocation_step.workflow_invocation = self.invocation
                self.invocation.steps.append(workflow_invocation_step)

            workflow_invocation_step_state = model.WorkflowRequestStepState()
            workflow_invocation_step_state.workflow_step_id = step_id
            workflow_invocation_step_state.value = True
            self.invocation.step_states.append(workflow_invocation_step_state)
Exemplo n.º 8
0
    def invoke(self):
        workflow_invocation = self.workflow_invocation
        remaining_steps = self.progress.remaining_steps()
        delayed_steps = False
        for step in remaining_steps:
            step_delayed = False
            step_timer = ExecutionTimer()
            jobs = None
            try:
                self.__check_implicitly_dependent_steps(step)

                # TODO: step may fail to invoke, do something about that.
                jobs = self._invoke_step(step)
                for job in (util.listify(jobs) or [None]):
                    # Record invocation
                    workflow_invocation_step = model.WorkflowInvocationStep()
                    workflow_invocation_step.workflow_invocation = workflow_invocation
                    workflow_invocation_step.workflow_step = step
                    workflow_invocation_step.job = job
            except modules.DelayedWorkflowEvaluation:
                step_delayed = delayed_steps = True
                self.progress.mark_step_outputs_delayed(step)
            except Exception:
                log.exception(
                    "Failed to schedule %s, problem occurred on %s.",
                    self.workflow_invocation.workflow.log_str(),
                    step.log_str(),
                )
                raise

            step_verb = "invoked" if not step_delayed else "delayed"
            log.debug("Workflow step %s of invocation %s %s %s" %
                      (step.id, workflow_invocation.id, step_verb, step_timer))

        if delayed_steps:
            state = model.WorkflowInvocation.states.READY
        else:
            state = model.WorkflowInvocation.states.SCHEDULED
        workflow_invocation.state = state

        # All jobs ran successfully, so we can save now
        self.trans.sa_session.add(workflow_invocation)

        # Not flushing in here, because web controller may create multiple
        # invocations.
        return self.progress.outputs
Exemplo n.º 9
0
    def invoke( self ):
        workflow_invocation = self.workflow_invocation
        remaining_steps = self.progress.remaining_steps()
        for step in remaining_steps:
            jobs = self._invoke_step( step )
            for job in util.listify( jobs ):
                # Record invocation
                workflow_invocation_step = model.WorkflowInvocationStep()
                workflow_invocation_step.workflow_invocation = workflow_invocation
                workflow_invocation_step.workflow_step = step
                workflow_invocation_step.job = job

        # All jobs ran successfully, so we can save now
        self.trans.sa_session.add( workflow_invocation )

        # Not flushing in here, because web controller may create multiple
        # invocations.
        return self.progress.outputs
Exemplo n.º 10
0
    def test_workflows(self):
        model = self.model
        user = model.User(
            email="*****@*****.**",
            password="******"
        )

        def workflow_from_steps(steps):
            stored_workflow = model.StoredWorkflow()
            stored_workflow.user = user
            workflow = model.Workflow()
            workflow.steps = steps
            workflow.stored_workflow = stored_workflow
            return workflow

        child_workflow = workflow_from_steps([])
        self.persist(child_workflow)

        workflow_step_1 = model.WorkflowStep()
        workflow_step_1.order_index = 0
        workflow_step_1.type = "data_input"
        workflow_step_2 = model.WorkflowStep()
        workflow_step_2.order_index = 1
        workflow_step_2.type = "subworkflow"
        workflow_step_2.subworkflow = child_workflow

        workflow_step_1.get_or_add_input("moo1")
        workflow_step_1.get_or_add_input("moo2")
        workflow_step_2.get_or_add_input("moo")
        workflow_step_1.add_connection("foo", "cow", workflow_step_2)

        workflow = workflow_from_steps([workflow_step_1, workflow_step_2])
        self.persist(workflow)
        workflow_id = workflow.id

        annotation = model.WorkflowStepAnnotationAssociation()
        annotation.annotation = "Test Step Annotation"
        annotation.user = user
        annotation.workflow_step = workflow_step_1
        self.persist(annotation)

        assert workflow_step_1.id is not None
        h1 = model.History(name="WorkflowHistory1", user=user)

        invocation_uuid = uuid.uuid1()

        workflow_invocation = model.WorkflowInvocation()
        workflow_invocation.uuid = invocation_uuid
        workflow_invocation.history = h1

        workflow_invocation_step1 = model.WorkflowInvocationStep()
        workflow_invocation_step1.workflow_invocation = workflow_invocation
        workflow_invocation_step1.workflow_step = workflow_step_1

        subworkflow_invocation = model.WorkflowInvocation()
        workflow_invocation.attach_subworkflow_invocation_for_step(workflow_step_2, subworkflow_invocation)

        workflow_invocation_step2 = model.WorkflowInvocationStep()
        workflow_invocation_step2.workflow_invocation = workflow_invocation
        workflow_invocation_step2.workflow_step = workflow_step_2

        workflow_invocation.workflow = workflow

        d1 = self.new_hda(h1, name="1")
        workflow_request_dataset = model.WorkflowRequestToInputDatasetAssociation()
        workflow_request_dataset.workflow_invocation = workflow_invocation
        workflow_request_dataset.workflow_step = workflow_step_1
        workflow_request_dataset.dataset = d1
        self.persist(workflow_invocation)
        assert workflow_request_dataset is not None
        assert workflow_invocation.id is not None

        history_id = h1.id
        self.expunge()

        loaded_invocation = self.query(model.WorkflowInvocation).get(workflow_invocation.id)
        assert loaded_invocation.uuid == invocation_uuid, "%s != %s" % (loaded_invocation.uuid, invocation_uuid)
        assert loaded_invocation
        assert loaded_invocation.history.id == history_id

        step_1, step_2 = loaded_invocation.workflow.steps

        assert not step_1.subworkflow
        assert step_2.subworkflow
        assert len(loaded_invocation.steps) == 2

        subworkflow_invocation_assoc = loaded_invocation.get_subworkflow_invocation_association_for_step(step_2)
        assert subworkflow_invocation_assoc is not None
        assert isinstance(subworkflow_invocation_assoc.subworkflow_invocation, model.WorkflowInvocation)
        assert isinstance(subworkflow_invocation_assoc.parent_workflow_invocation, model.WorkflowInvocation)

        assert subworkflow_invocation_assoc.subworkflow_invocation.history.id == history_id

        loaded_workflow = self.query(model.Workflow).get(workflow_id)
        assert len(loaded_workflow.steps[0].annotations) == 1
        copied_workflow = loaded_workflow.copy(user=user)
        annotations = copied_workflow.steps[0].annotations
        assert len(annotations) == 1
Exemplo n.º 11
0
    def invoke(self):
        workflow_invocation = self.workflow_invocation
        config = self.trans.app.config
        maximum_duration = getattr(config,
                                   "maximum_workflow_invocation_duration", -1)
        if maximum_duration > 0 and workflow_invocation.seconds_since_created > maximum_duration:
            log.debug(
                "Workflow invocation [%s] exceeded maximum number of seconds allowed for scheduling [%s], failing."
                % (workflow_invocation.id, maximum_duration))
            workflow_invocation.state = model.WorkflowInvocation.states.FAILED
            # All jobs ran successfully, so we can save now
            self.trans.sa_session.add(workflow_invocation)

            # Not flushing in here, because web controller may create multiple
            # invocations.
            return self.progress.outputs

        if workflow_invocation.history.deleted:
            log.info("Cancelled workflow evaluation due to deleted history")
            raise modules.CancelWorkflowEvaluation()

        remaining_steps = self.progress.remaining_steps()
        delayed_steps = False
        for (step, workflow_invocation_step) in remaining_steps:
            step_delayed = False
            step_timer = ExecutionTimer()
            try:
                self.__check_implicitly_dependent_steps(step)

                if not workflow_invocation_step:
                    workflow_invocation_step = model.WorkflowInvocationStep()
                    workflow_invocation_step.workflow_invocation = workflow_invocation
                    workflow_invocation_step.workflow_step = step
                    workflow_invocation_step.state = 'new'

                    workflow_invocation.steps.append(workflow_invocation_step)

                incomplete_or_none = self._invoke_step(
                    workflow_invocation_step)
                if incomplete_or_none is False:
                    step_delayed = delayed_steps = True
                    workflow_invocation_step.state = 'ready'
                    self.progress.mark_step_outputs_delayed(
                        step, why="Not all jobs scheduled for state.")
                else:
                    workflow_invocation_step.state = 'scheduled'
            except modules.DelayedWorkflowEvaluation as de:
                step_delayed = delayed_steps = True
                self.progress.mark_step_outputs_delayed(step, why=de.why)
            except Exception:
                log.exception(
                    "Failed to schedule %s, problem occurred on %s.",
                    self.workflow_invocation.workflow.log_str(),
                    step.log_str(),
                )
                raise

            if not step_delayed:
                log.debug("Workflow step %s of invocation %s invoked %s" %
                          (step.id, workflow_invocation.id, step_timer))

        if delayed_steps:
            state = model.WorkflowInvocation.states.READY
        else:
            state = model.WorkflowInvocation.states.SCHEDULED
        workflow_invocation.state = state

        # All jobs ran successfully, so we can save now
        self.trans.sa_session.add(workflow_invocation)

        # Not flushing in here, because web controller may create multiple
        # invocations.
        return self.progress.outputs