Ejemplo n.º 1
0
    def test_workflow_fast_kill(self):
        from aiida.cmdline.commands.workflow import Workflow as WfCmd
        from aiida.orm.backend import construct_backend

        backend = construct_backend()

        params = dict()
        params['nmachine'] = 2

        # Create a workflow with 2 subworkflows and start it
        head_wf = WFTestSimpleWithSubWF()
        head_wf.start()

        # Get the user
        user = backend.users.find(email=self.user_email)[0]
        wfl = get_workflow_list(user=user)
        running_no = 0
        for w in get_workflow_list(user=user, all_states=True):
            if w.get_aiida_class().get_state() == wf_states.RUNNING:
                running_no += 1
        self.assertEquals(running_no, 3)

        # Killing the head workflow
        wf_cmd = WfCmd()
        wf_cmd.workflow_kill(*[str(head_wf.pk), '-f', '-q'])

        # At this point no running workflow should be found
        running_no = 0
        for w in get_workflow_list(user=user, all_states=True):
            if w.get_aiida_class().get_state() == wf_states.RUNNING:
                running_no += 1
        self.assertEquals(running_no, 0,
                          "No running workflows should be found")

        self.assertNotEquals(get_all_running_steps(), 0,
                             "At this point there will be running steps.")

        # Making the daemon to advance. This will automatically set
        # to FINISHED all the running steps that are (directly) under
        # a finished workflow
        legacy_workflow_stepper()

        self.assertEquals(len(list(get_all_running_steps())), 0,
                          "At this point there should be no running steps.")
        running_no = 0
        for w in get_workflow_list(user=user, all_states=True):
            if w.get_aiida_class().get_state() == wf_states.RUNNING:
                running_no += 1
        self.assertEquals(
            running_no, 0, "At this point there should be "
            "no running workflows.")

        # Make the daemon to advance a bit more and make sure that no
        # workflows resurrect.
        for _ in range(5):
            legacy_workflow_stepper()

        self.assertEquals(len(list(get_all_running_steps())), 0,
                          "At this point there should be no running steps.")
        running_no = 0
        for w in get_workflow_list(user=user, all_states=True):
            if w.get_aiida_class().get_state() == wf_states.RUNNING:
                running_no += 1
        self.assertEquals(
            running_no, 0, "At this point there should be "
            "no running workflows.")
Ejemplo n.º 2
0
def execute_steps():
    """
    This method loops on the RUNNING workflows and handled the execution of the
    steps until each workflow reaches an end (or gets stopped for errors).

    In the loop for each RUNNING workflow the method loops also in each of its 
    RUNNING steps, testing if all the calculation and subworkflows attached to 
    the step are FINISHED. In this case the step is set as FINISHED and the 
    workflow is advanced to the step's next method present in the db with 
    ``advance_workflow``, otherwise if any step's JobCalculation is found in 
    NEW state the method will submit. If none of the previous conditions apply 
    the step is flagged as ERROR and cannot proceed anymore, blocking the future
    execution of the step and, connected, the workflow.

    Finally, for each workflow the method tests if there are INITIALIZED steps 
    to be launched, and in case reloads the workflow and execute the specific 
    those steps. In case or error the step is flagged in ERROR state and the 
    stack is reported in the workflow report.
    """

    from aiida.orm import JobCalculation
    from aiida.orm.implementation import get_all_running_steps

    logger.info("Querying the worflow DB")

    running_steps = get_all_running_steps()

    for s in running_steps:
        if s.parent.state == wf_states.FINISHED:
            s.set_state(wf_states.FINISHED)
            continue

        w = s.parent.get_aiida_class()

        logger.info("[{0}] Found active step: {1}".format(w.pk, s.name))

        s_calcs_new = [c.pk for c in s.get_calculations() if c._is_new()]
        s_calcs_finished = [
            c.pk for c in s.get_calculations() if c.has_finished_ok()
        ]
        s_calcs_failed = [c.pk for c in s.get_calculations() if c.has_failed()]
        s_calcs_num = len(s.get_calculations())

        s_sub_wf_finished = [
            sw.pk for sw in s.get_sub_workflows() if sw.has_finished_ok()
        ]
        s_sub_wf_failed = [
            sw.pk for sw in s.get_sub_workflows() if sw.has_failed()
        ]
        s_sub_wf_num = len(s.get_sub_workflows())

        if (s_calcs_num == (len(s_calcs_finished) + len(s_calcs_failed))
                and s_sub_wf_num
                == (len(s_sub_wf_finished) + len(s_sub_wf_failed))):

            logger.info("[{0}] Step: {1} ready to move".format(w.pk, s.name))

            s.set_state(wf_states.FINISHED)

            advance_workflow(w, s)

        elif len(s_calcs_new) > 0:

            for pk in s_calcs_new:

                obj_calc = JobCalculation.get_subclass_from_pk(pk=pk)
                try:
                    obj_calc.submit()
                    logger.info(
                        "[{0}] Step: {1} launched calculation {2}".format(
                            w.pk, s.name, pk))
                except:
                    logger.error(
                        "[{0}] Step: {1} cannot launch calculation {2}".format(
                            w.pk, s.name, pk))