def test_json_forced_nodes(self):
        """Tests coverting a ProcessRecipeInput message to and from JSON with forced nodes provided"""

        data_dict = convert_data_to_v6_json(Data()).get_dict()
        recipe = recipe_test_utils.create_recipe(input=data_dict)
        forced_nodes = ForcedNodes()
        forced_nodes.set_all_nodes()
        forced_nodes_dict = convert_forced_nodes_to_v6(forced_nodes).get_dict()

        # Create message
        message = create_process_recipe_input_messages(
            [recipe.id], forced_nodes=forced_nodes)[0]

        # Convert message to JSON and back, and then execute
        message_json_dict = message.to_json()
        new_message = ProcessRecipeInput.from_json(message_json_dict)
        result = new_message.execute()

        self.assertTrue(result)
        recipe = Recipe.objects.get(id=recipe.id)
        self.assertEqual(len(new_message.new_messages), 1)
        msg = new_message.new_messages[0]
        self.assertEqual(msg.type, 'update_recipe')
        self.assertEqual(msg.root_recipe_id, recipe.id)
        self.assertDictEqual(
            convert_forced_nodes_to_v6(msg.forced_nodes).get_dict(),
            forced_nodes_dict)
        # Recipe should have input_file_size set to 0 (no input files)
        self.assertEqual(recipe.input_file_size, 0.0)
Beispiel #2
0
def convert_definition_to_v6(definition):
    """Returns the v6 definition JSON for the given batch definition

    :param definition: The batch definition
    :type definition: :class:`batch.definition.definition.BatchDefinition`
    :returns: The v6 definition JSON
    :rtype: :class:`batch.definition.json.definition_v6.BatchDefinitionV6`
    """

    json_dict = {'version': SCHEMA_VERSION}
    if definition.root_batch_id is not None:
        prev_batch_dict = {'root_batch_id': definition.root_batch_id}
        if definition.forced_nodes:
            prev_batch_dict['forced_nodes'] = convert_forced_nodes_to_v6(
                definition.forced_nodes).get_dict()
        json_dict['previous_batch'] = prev_batch_dict

    if definition.dataset:
        json_dict['dataset'] = definition.dataset
    if definition.supersedes is not None:
        json_dict['supersedes'] = definition.supersedes
    if definition.forced_nodes:
        json_dict['forced_nodes'] = convert_forced_nodes_to_v6(
            definition.forced_nodes).get_dict()
    return BatchDefinitionV6(definition=json_dict, do_validate=False)
Beispiel #3
0
    def to_json(self):
        """See :meth:`messaging.messages.message.CommandMessage.to_json`
        """

        json_dict = {'recipe_id': self.recipe_id}

        if self.forced_nodes:
            json_dict['forced_nodes'] = convert_forced_nodes_to_v6(self.forced_nodes).get_dict()

        return json_dict
Beispiel #4
0
    def test_json_forced_nodes(self):
        """Tests converting an UpdateRecipe message to and from JSON when forced nodes are provided"""

        data_dict = convert_data_to_v6_json(Data()).get_dict()
        job_completed = job_test_utils.create_job(status='COMPLETED', input=data_dict, output=data_dict)
        sub_recipe_type = recipe_test_utils.create_recipe_type_v6()
        definition = RecipeDefinition(Interface())
        definition.add_job_node('job_completed', job_completed.job_type.name, job_completed.job_type.version,
                                job_completed.job_type_rev.revision_num)
        definition.add_recipe_node('the_sub_recipe', sub_recipe_type.name, sub_recipe_type.revision_num)
        definition.add_dependency('job_completed', 'the_sub_recipe')
        definition_dict = convert_recipe_definition_to_v6_json(definition).get_dict()
        recipe_type = recipe_test_utils.create_recipe_type_v6(definition=definition_dict)
        recipe = recipe_test_utils.create_recipe(recipe_type=recipe_type, input=data_dict)
        recipe_test_utils.create_recipe_job(recipe=recipe, job_name='job_completed', job=job_completed)
        forced_nodes = ForcedNodes()
        sub_forced_nodes = ForcedNodes()
        sub_forced_nodes.set_all_nodes()
        forced_nodes.add_subrecipe('the_sub_recipe', sub_forced_nodes)

        # Create message
        message = create_update_recipe_message(recipe.id, forced_nodes=forced_nodes)

        # Convert message to JSON and back, and then execute
        message_json_dict = message.to_json()
        new_message = UpdateRecipe.from_json(message_json_dict)
        result = new_message.execute()
        self.assertTrue(result)

        # Check for message to create sub-recipe
        self.assertEqual(len(new_message.new_messages), 1)
        msg = new_message.new_messages[0]
        self.assertEqual(msg.type, 'create_recipes')
        self.assertEqual(msg.event_id, recipe.event_id)
        msg_forced_nodes_dict = convert_forced_nodes_to_v6(msg.forced_nodes).get_dict()
        expected_forced_nodes_dict = convert_forced_nodes_to_v6(forced_nodes).get_dict()
        self.assertDictEqual(msg_forced_nodes_dict, expected_forced_nodes_dict)
        self.assertEqual(msg.create_recipes_type, SUB_RECIPE_TYPE)
        self.assertEqual(msg.recipe_id, recipe.id)
        self.assertEqual(msg.root_recipe_id, recipe.root_superseded_recipe_id)
        self.assertIsNone(msg.superseded_recipe_id)
        sub = SubRecipe(sub_recipe_type.name, sub_recipe_type.revision_num, 'the_sub_recipe', True)
        self.assertListEqual(msg.sub_recipes, [sub])
Beispiel #5
0
    def to_json(self):
        """See :meth:`messaging.messages.message.CommandMessage.to_json`
        """

        json_dict = {
            'event_id': self.event_id,
            'create_recipes_type': self.create_recipes_type
        }

        if self.batch_id:
            json_dict['batch_id'] = self.batch_id
        if self.forced_nodes:
            json_dict['forced_nodes'] = convert_forced_nodes_to_v6(
                self.forced_nodes).get_dict()

        if self.create_recipes_type == NEW_RECIPE_TYPE:
            if self.ingest_event_id:
                json_dict['ingest_event_id'] = self.ingest_event_id
            json_dict['recipe_input_data'] = self.recipe_input_data
            json_dict['recipe_type_name'] = self.recipe_type_name
            json_dict['recipe_type_rev_num'] = self.recipe_type_rev_num
            json_dict['recipe_configuration'] = self.configuration
            json_dict['new_recipes'] = self.new_recipes
        elif self.create_recipes_type == REPROCESS_TYPE:
            json_dict['recipe_type_name'] = self.recipe_type_name
            json_dict['recipe_type_rev_num'] = self.recipe_type_rev_num
            json_dict['root_recipe_ids'] = self.root_recipe_ids
        elif self.create_recipes_type == SUB_RECIPE_TYPE:
            json_dict['recipe_id'] = self.recipe_id
            if self.root_recipe_id:
                json_dict['root_recipe_id'] = self.root_recipe_id
            if self.superseded_recipe_id:
                json_dict['superseded_recipe_id'] = self.superseded_recipe_id
            sub_recipes = []
            for sub_recipe in self.sub_recipes:
                sub_recipes.append({
                    'recipe_type_name': sub_recipe.recipe_type_name,
                    'recipe_type_rev_num': sub_recipe.recipe_type_rev_num,
                    'node_name': sub_recipe.node_name,
                    'process_input': sub_recipe.process_input
                })
            json_dict['sub_recipes'] = sub_recipes

        return json_dict
Beispiel #6
0
    def test_convert_forced_nodes_to_v6_full(self):
        """Tests calling convert_forced_nodes_to_v6() with a full diff with all types (deleted, new, changed, etc) of nodes"""

        recipe_d_forced_nodes = ForcedNodes()
        recipe_d_forced_nodes.add_node('1')
        recipe_d_forced_nodes.add_node('2')
        top_forced_nodes = ForcedNodes()
        top_forced_nodes.add_node('C')
        top_forced_nodes.add_subrecipe('D', recipe_d_forced_nodes)
        v6 = convert_forced_nodes_to_v6(top_forced_nodes)
        full = {
            'version': '7',
            'all': False,
            'nodes': [u'C', u'D'],
            'sub_recipes': {
                'D': {
                    'version': '7',
                    'all': False,
                    'nodes': ['1', '2']
                }
            }
        }
        self.assertDictEqual(v6.get_dict(), full)
Beispiel #7
0
    def test_execute(self):
        """Tests calling CompletedJobs.execute() successfully"""

        from recipe.test import utils as recipe_test_utils
        recipe_1 = recipe_test_utils.create_recipe()

        job_1 = job_test_utils.create_job(num_exes=1, status='QUEUED')
        job_test_utils.create_job_exe(job=job_1)
        job_2 = job_test_utils.create_job(num_exes=1,
                                          status='RUNNING',
                                          recipe=recipe_1)
        job_test_utils.create_job_exe(job=job_2, output=JobResults())
        job_3 = job_test_utils.create_job(num_exes=0, status='PENDING')
        job_ids = [job_1.id, job_2.id, job_3.id]

        recipe_test_utils.create_recipe_job(recipe=recipe_1, job=job_2)

        when_ended = now()

        # Add jobs to message
        message = CompletedJobs()
        message.ended = when_ended
        if message.can_fit_more():
            message.add_completed_job(CompletedJob(job_1.id, job_1.num_exes))
        if message.can_fit_more():
            message.add_completed_job(CompletedJob(job_2.id, job_2.num_exes))
        if message.can_fit_more():
            message.add_completed_job(CompletedJob(job_3.id, job_3.num_exes))

        # Execute message
        result = message.execute()
        self.assertTrue(result)

        from recipe.diff.forced_nodes import ForcedNodes
        from recipe.diff.json.forced_nodes_v6 import convert_forced_nodes_to_v6
        forced_nodes = ForcedNodes()
        forced_nodes.set_all_nodes()
        forced_nodes_dict = convert_forced_nodes_to_v6(forced_nodes).get_dict()

        jobs = Job.objects.filter(id__in=job_ids).order_by('id')
        self.assertEqual(len(message.new_messages), 3)
        update_recipe_metrics_msg = None
        update_recipe_msg = None
        publish_job_msg = None
        for msg in message.new_messages:
            if msg.type == 'update_recipe':
                update_recipe_msg = msg
            elif msg.type == 'publish_job':
                publish_job_msg = msg
            elif msg.type == 'update_recipe_metrics':
                update_recipe_metrics_msg = msg
        self.assertIsNotNone(update_recipe_msg)
        self.assertIsNotNone(publish_job_msg)
        self.assertIsNotNone(update_recipe_metrics_msg)
        self.assertEqual(publish_job_msg.job_id, job_2.id)

        # Job 1 should be completed
        self.assertEqual(jobs[0].status, 'COMPLETED')
        self.assertEqual(jobs[0].num_exes, 1)
        self.assertEqual(jobs[0].ended, when_ended)
        # Job 2 should be completed and has output, so should be in update_recipe message
        self.assertEqual(jobs[1].status, 'COMPLETED')
        self.assertEqual(jobs[1].num_exes, 1)
        self.assertEqual(jobs[1].ended, when_ended)
        self.assertEqual(update_recipe_msg.root_recipe_id, recipe_1.id)
        self.assertDictEqual(
            convert_forced_nodes_to_v6(
                update_recipe_msg.forced_nodes).get_dict(), forced_nodes_dict)
        # Job 3 should ignore update
        self.assertEqual(jobs[2].status, 'PENDING')
        self.assertEqual(jobs[2].num_exes, 0)

        # Test executing message again
        new_ended = when_ended + datetime.timedelta(minutes=5)
        message_json_dict = message.to_json()
        message = CompletedJobs.from_json(message_json_dict)
        message.ended = new_ended
        result = message.execute()
        self.assertTrue(result)

        # Should have the same messages as before
        jobs = Job.objects.filter(id__in=job_ids).order_by('id')
        self.assertEqual(len(message.new_messages), 3)
        update_recipe_metrics_msg = None
        update_recipe_msg = None
        publish_job_msg = None
        for msg in message.new_messages:
            if msg.type == 'update_recipe':
                update_recipe_msg = msg
            elif msg.type == 'publish_job':
                publish_job_msg = msg
            elif msg.type == 'update_recipe_metrics':
                update_recipe_metrics_msg = msg
        self.assertIsNotNone(update_recipe_msg)
        self.assertIsNotNone(publish_job_msg)
        self.assertIsNotNone(update_recipe_metrics_msg)
        self.assertEqual(publish_job_msg.job_id, job_2.id)

        # Job 1 should be completed
        self.assertEqual(jobs[0].status, 'COMPLETED')
        self.assertEqual(jobs[0].num_exes, 1)
        self.assertEqual(jobs[0].ended, when_ended)
        # Job 2 should be completed and has output, so should be in update_recipe message
        self.assertEqual(jobs[1].status, 'COMPLETED')
        self.assertEqual(jobs[1].num_exes, 1)
        self.assertEqual(jobs[1].ended, when_ended)
        self.assertEqual(update_recipe_msg.root_recipe_id, recipe_1.id)
        self.assertDictEqual(
            convert_forced_nodes_to_v6(
                update_recipe_msg.forced_nodes).get_dict(), forced_nodes_dict)
        # Job 3 should ignore update
        self.assertEqual(jobs[2].status, 'PENDING')
        self.assertEqual(jobs[2].num_exes, 0)
Beispiel #8
0
    def test_execute(self):
        """Tests calling CancelJobs.execute() successfully"""

        when = now()
        data = JobData()
        from recipe.test import utils as recipe_test_utils
        recipe = recipe_test_utils.create_recipe()
        job_type = job_test_utils.create_seed_job_type()
        job_1 = job_test_utils.create_job(job_type=job_type,
                                          num_exes=3,
                                          status='FAILED',
                                          input=data.get_dict(),
                                          recipe=recipe)
        job_2 = job_test_utils.create_job(job_type=job_type,
                                          num_exes=3,
                                          status='CANCELED',
                                          input=data.get_dict(),
                                          recipe=recipe)
        job_3 = job_test_utils.create_job(job_type=job_type,
                                          num_exes=1,
                                          status='COMPLETED',
                                          input=data.get_dict(),
                                          recipe=recipe)
        job_4 = job_test_utils.create_job(job_type=job_type,
                                          num_exes=0,
                                          status='PENDING',
                                          recipe=recipe)
        job_ids = [job_1.id, job_2.id, job_3.id, job_4.id]
        recipe_test_utils.create_recipe_job(recipe=recipe,
                                            job_name='job_1',
                                            job=job_1)
        recipe_test_utils.create_recipe_job(recipe=recipe,
                                            job_name='job_2',
                                            job=job_2)
        recipe_test_utils.create_recipe_job(recipe=recipe,
                                            job_name='job_3',
                                            job=job_3)
        recipe_test_utils.create_recipe_job(recipe=recipe,
                                            job_name='job_4',
                                            job=job_4)

        # Add jobs to message
        message = CancelJobs()
        message.when = when
        if message.can_fit_more():
            message.add_job(job_1.id)
        if message.can_fit_more():
            message.add_job(job_2.id)
        if message.can_fit_more():
            message.add_job(job_3.id)
        if message.can_fit_more():
            message.add_job(job_4.id)

        # Execute message
        result = message.execute()
        self.assertTrue(result)

        jobs = Job.objects.filter(id__in=job_ids).order_by('id')
        # Job 1 should have been canceled
        self.assertEqual(jobs[0].status, 'CANCELED')
        self.assertEqual(jobs[0].last_status_change, when)
        # Job 2 was already canceled
        self.assertEqual(jobs[1].status, 'CANCELED')
        self.assertNotEqual(jobs[1].last_status_change, when)
        # Job 3 was already COMPLETED, so can't be canceled
        self.assertEqual(jobs[2].status, 'COMPLETED')
        self.assertNotEqual(jobs[2].last_status_change, when)
        # Job 4 should have been canceled
        self.assertEqual(jobs[3].status, 'CANCELED')
        self.assertEqual(jobs[3].last_status_change, when)
        from recipe.diff.forced_nodes import ForcedNodes
        from recipe.diff.json.forced_nodes_v6 import convert_forced_nodes_to_v6
        forced_nodes = ForcedNodes()
        forced_nodes.set_all_nodes()
        forced_nodes_dict = convert_forced_nodes_to_v6(forced_nodes).get_dict()
        # Should be messages to update recipe and update recipe metrics after canceling jobs
        self.assertEqual(len(message.new_messages), 2)
        update_recipe_msg = None
        update_recipe_metrics_msg = None
        for msg in message.new_messages:
            if msg.type == 'update_recipe':
                update_recipe_msg = msg
            elif msg.type == 'update_recipe_metrics':
                update_recipe_metrics_msg = msg
        self.assertIsNotNone(update_recipe_msg)
        self.assertIsNotNone(update_recipe_metrics_msg)
        self.assertEqual(update_recipe_msg.root_recipe_id, recipe.id)
        self.assertDictEqual(
            convert_forced_nodes_to_v6(
                update_recipe_msg.forced_nodes).get_dict(), forced_nodes_dict)
        self.assertListEqual(update_recipe_metrics_msg._recipe_ids,
                             [recipe.id])

        # Test executing message again
        message.new_messages = []
        result = message.execute()
        self.assertTrue(result)

        # All results should be the same
        jobs = Job.objects.filter(id__in=job_ids).order_by('id')
        # Job 1 should have been canceled
        self.assertEqual(jobs[0].status, 'CANCELED')
        self.assertEqual(jobs[0].last_status_change, when)
        # Job 2 was already canceled
        self.assertEqual(jobs[1].status, 'CANCELED')
        self.assertNotEqual(jobs[1].last_status_change, when)
        # Job 3 was already COMPLETED, so can't be canceled
        self.assertEqual(jobs[2].status, 'COMPLETED')
        self.assertNotEqual(jobs[2].last_status_change, when)
        # Job 4 should have been canceled
        self.assertEqual(jobs[3].status, 'CANCELED')
        self.assertEqual(jobs[3].last_status_change, when)
        # Should be messages to update recipe and update recipe metrics after canceling jobs
        self.assertEqual(len(message.new_messages), 2)
        update_recipe_msg = None
        update_recipe_metrics_msg = None
        for msg in message.new_messages:
            if msg.type == 'update_recipe':
                update_recipe_msg = msg
            elif msg.type == 'update_recipe_metrics':
                update_recipe_metrics_msg = msg
        self.assertIsNotNone(update_recipe_msg)
        self.assertIsNotNone(update_recipe_metrics_msg)
        self.assertEqual(update_recipe_msg.root_recipe_id, recipe.id)
        self.assertDictEqual(
            convert_forced_nodes_to_v6(
                update_recipe_msg.forced_nodes).get_dict(), forced_nodes_dict)
        self.assertListEqual(update_recipe_metrics_msg._recipe_ids,
                             [recipe.id])
    def test_execute_with_top_level_recipe(self):
        """Tests calling UpdateRecipeMetrics.execute() successfully where messages need to be sent to update a top-level
        recipe
        """

        batch = batch_test_utils.create_batch()
        top_recipe = recipe_test_utils.create_recipe(batch=batch)
        recipe = recipe_test_utils.create_recipe(batch=batch)
        recipe.recipe = top_recipe
        recipe.root_recipe = top_recipe
        recipe.save()
        recipe_node_1 = recipe_test_utils.create_recipe_node(recipe=top_recipe,
                                                             sub_recipe=recipe)
        forced_nodes = ForcedNodes()
        forced_nodes.set_all_nodes()
        forced_nodes_dict = convert_forced_nodes_to_v6(forced_nodes).get_dict()

        # Recipe jobs
        job_1 = job_test_utils.create_job(status='FAILED', save=False)
        job_2 = job_test_utils.create_job(status='CANCELED', save=False)
        job_3 = job_test_utils.create_job(status='BLOCKED', save=False)
        job_4 = job_test_utils.create_job(status='BLOCKED', save=False)
        job_5 = job_test_utils.create_job(status='COMPLETED', save=False)
        Job.objects.bulk_create([job_1, job_2, job_3, job_4, job_5])

        # Recipe nodes
        recipe_node_2 = recipe_test_utils.create_recipe_node(recipe=recipe,
                                                             job=job_1)
        recipe_node_3 = recipe_test_utils.create_recipe_node(recipe=recipe,
                                                             job=job_2)
        recipe_node_4 = recipe_test_utils.create_recipe_node(recipe=recipe,
                                                             job=job_3)
        recipe_node_5 = recipe_test_utils.create_recipe_node(recipe=recipe,
                                                             job=job_4)
        recipe_node_6 = recipe_test_utils.create_recipe_node(recipe=recipe,
                                                             job=job_5)
        RecipeNode.objects.bulk_create([
            recipe_node_1, recipe_node_2, recipe_node_3, recipe_node_4,
            recipe_node_5, recipe_node_6
        ])

        # Add recipes to message
        message = UpdateRecipeMetrics()
        if message.can_fit_more():
            message.add_recipe(recipe.id)

        # Execute message
        result = message.execute()
        self.assertTrue(result)

        recipe = Recipe.objects.get(id=recipe.id)
        self.assertEqual(recipe.jobs_total, 5)
        self.assertEqual(recipe.jobs_pending, 0)
        self.assertEqual(recipe.jobs_blocked, 2)
        self.assertEqual(recipe.jobs_queued, 0)
        self.assertEqual(recipe.jobs_running, 0)
        self.assertEqual(recipe.jobs_failed, 1)
        self.assertEqual(recipe.jobs_completed, 1)
        self.assertEqual(recipe.jobs_canceled, 1)
        self.assertEqual(recipe.sub_recipes_total, 0)
        self.assertEqual(recipe.sub_recipes_completed, 0)

        # Make sure message is created to update top-level recipe and recipe metrics
        # There should be no message to update batch metrics since we did not update a top-level recipe
        self.assertEqual(len(message.new_messages), 2)
        update_recipe_metrics_msg = message.new_messages[0]
        update_recipe_msg = message.new_messages[1]
        self.assertEqual(update_recipe_metrics_msg.type,
                         'update_recipe_metrics')
        self.assertListEqual(update_recipe_metrics_msg._recipe_ids,
                             [top_recipe.id])
        self.assertEqual(update_recipe_msg.type, 'update_recipe')
        self.assertEqual(update_recipe_msg.root_recipe_id, top_recipe.id)
        self.assertDictEqual(
            convert_forced_nodes_to_v6(
                update_recipe_msg.forced_nodes).get_dict(), forced_nodes_dict)

        # Test executing message again
        message_json_dict = message.to_json()
        message = UpdateRecipeMetrics.from_json(message_json_dict)
        result = message.execute()
        self.assertTrue(result)

        recipe = Recipe.objects.get(id=recipe.id)
        self.assertEqual(recipe.jobs_total, 5)
        self.assertEqual(recipe.jobs_pending, 0)
        self.assertEqual(recipe.jobs_blocked, 2)
        self.assertEqual(recipe.jobs_queued, 0)
        self.assertEqual(recipe.jobs_running, 0)
        self.assertEqual(recipe.jobs_failed, 1)
        self.assertEqual(recipe.jobs_completed, 1)
        self.assertEqual(recipe.jobs_canceled, 1)
        self.assertEqual(recipe.sub_recipes_total, 0)
        self.assertEqual(recipe.sub_recipes_completed, 0)

        # Make sure message is created to update top-level recipe and recipe metrics
        # There should be no message to update batch metrics since we did not update a top-level recipe
        self.assertEqual(len(message.new_messages), 2)
        update_recipe_metrics_msg = message.new_messages[0]
        update_recipe_msg = message.new_messages[1]
        self.assertEqual(update_recipe_metrics_msg.type,
                         'update_recipe_metrics')
        self.assertListEqual(update_recipe_metrics_msg._recipe_ids,
                             [top_recipe.id])
        self.assertEqual(update_recipe_msg.type, 'update_recipe')
        self.assertEqual(update_recipe_msg.root_recipe_id, top_recipe.id)
        self.assertDictEqual(
            convert_forced_nodes_to_v6(
                update_recipe_msg.forced_nodes).get_dict(), forced_nodes_dict)
Beispiel #10
0
    def test_execute(self):
        """Tests calling UncancelJobs.execute() successfully"""

        old_when = now()
        when = old_when + datetime.timedelta(minutes=60)
        recipe = recipe_test_utils.create_recipe()

        job_1 = job_test_utils.create_job(num_exes=0,
                                          status='PENDING',
                                          last_status_change=old_when)
        job_2 = job_test_utils.create_job(num_exes=0,
                                          status='CANCELED',
                                          last_status_change=old_when,
                                          recipe=recipe)
        job_3 = job_test_utils.create_job(num_exes=1,
                                          status='CANCELED',
                                          last_status_change=old_when)
        job_4 = job_test_utils.create_job(num_exes=1,
                                          status='FAILED',
                                          last_status_change=old_when)
        job_ids = [job_1.id, job_2.id, job_3.id, job_4.id]

        recipe_test_utils.create_recipe_job(recipe=recipe, job=job_2)

        # Add jobs to message
        message = UncancelJobs()
        message.when = when
        if message.can_fit_more():
            message.add_job(job_1.id)
        if message.can_fit_more():
            message.add_job(job_2.id)
        if message.can_fit_more():
            message.add_job(job_3.id)
        if message.can_fit_more():
            message.add_job(job_4.id)

        # Execute message
        result = message.execute()
        self.assertTrue(result)

        from recipe.diff.forced_nodes import ForcedNodes
        from recipe.diff.json.forced_nodes_v6 import convert_forced_nodes_to_v6
        forced_nodes = ForcedNodes()
        forced_nodes.set_all_nodes()
        forced_nodes_dict = convert_forced_nodes_to_v6(forced_nodes).get_dict()

        jobs = Job.objects.filter(id__in=job_ids).order_by('id')
        # Job 1 should not be updated because it was not CANCELED
        self.assertEqual(jobs[0].status, 'PENDING')
        self.assertEqual(jobs[0].last_status_change, old_when)
        # Job 2 should be uncanceled
        self.assertEqual(jobs[1].status, 'PENDING')
        self.assertEqual(jobs[1].last_status_change, when)
        # Job 3 should not be updated since it has already been queued
        self.assertEqual(jobs[2].status, 'CANCELED')
        self.assertEqual(jobs[2].last_status_change, old_when)
        # Job 4 should not be updated because it was not CANCELED
        self.assertEqual(jobs[3].status, 'FAILED')
        self.assertEqual(jobs[3].last_status_change, old_when)

        # Make sure update_recipe and update_recipe_metrics messages were created
        self.assertEqual(len(message.new_messages), 2)
        update_recipe_msg = None
        update_recipe_metrics_msg = None
        for msg in message.new_messages:
            if msg.type == 'update_recipe':
                update_recipe_msg = msg
            elif msg.type == 'update_recipe_metrics':
                update_recipe_metrics_msg = msg
        self.assertIsNotNone(update_recipe_msg)
        self.assertIsNotNone(update_recipe_metrics_msg)
        self.assertEqual(update_recipe_msg.root_recipe_id, recipe.id)
        self.assertDictEqual(
            convert_forced_nodes_to_v6(
                update_recipe_msg.forced_nodes).get_dict(), forced_nodes_dict)
        self.assertListEqual(update_recipe_metrics_msg._recipe_ids,
                             [recipe.id])

        # Test executing message again
        newer_when = when + datetime.timedelta(minutes=60)
        message_json_dict = message.to_json()
        message = UncancelJobs.from_json(message_json_dict)
        message.when = newer_when
        result = message.execute()
        self.assertTrue(result)

        jobs = Job.objects.filter(id__in=job_ids).order_by('id')
        # Job 1 should not be updated because it was not CANCELED
        self.assertEqual(jobs[0].status, 'PENDING')
        self.assertEqual(jobs[0].last_status_change, old_when)
        # Job 2 should not be updated since it already was last mexxage execution
        self.assertEqual(jobs[1].status, 'PENDING')
        self.assertEqual(jobs[1].last_status_change, when)
        # Job 3 should not be updated since it has already been queued
        self.assertEqual(jobs[2].status, 'CANCELED')
        self.assertEqual(jobs[2].last_status_change, old_when)
        # Job 4 should not be updated because it was not CANCELED
        self.assertEqual(jobs[3].status, 'FAILED')
        self.assertEqual(jobs[3].last_status_change, old_when)

        # Make sure update_recipe and update_recipe_metrics messages were created
        self.assertEqual(len(message.new_messages), 2)
        update_recipe_msg = None
        update_recipe_metrics_msg = None
        for msg in message.new_messages:
            if msg.type == 'update_recipe':
                update_recipe_msg = msg
            elif msg.type == 'update_recipe_metrics':
                update_recipe_metrics_msg = msg
        self.assertIsNotNone(update_recipe_msg)
        self.assertIsNotNone(update_recipe_metrics_msg)
        self.assertEqual(update_recipe_msg.root_recipe_id, recipe.id)
        self.assertDictEqual(
            convert_forced_nodes_to_v6(
                update_recipe_msg.forced_nodes).get_dict(), forced_nodes_dict)
        self.assertListEqual(update_recipe_metrics_msg._recipe_ids,
                             [recipe.id])
Beispiel #11
0
    def test_convert_forced_nodes_to_v6_empty(self):
        """Tests calling convert_forced_nodes_to_v6() with an empty forced nodes object"""

        empty = ForcedNodes()
        v6 = convert_forced_nodes_to_v6(empty)
        self.assertDictEqual(v6.get_dict(), {'version': '7', 'all': False})
Beispiel #12
0
    def test_execute(self):
        """Tests calling UpdateRecipe.execute() successfully"""

        data_dict = convert_data_to_v6_json(Data()).get_dict()
        job_a = job_test_utils.create_job(status='COMPLETED', input=data_dict, output=data_dict)
        recipe_b = recipe_test_utils.create_recipe()
        job_c = job_test_utils.create_job(status='PENDING')
        job_d = job_test_utils.create_job(status='BLOCKED')
        recipe_type_e = recipe_test_utils.create_recipe_type_v6()
        job_type_f = job_test_utils.create_seed_job_type()
        job_type_k = job_test_utils.create_seed_job_type()
        job_g = job_test_utils.create_job(status='FAILED', input=data_dict)
        job_h = job_test_utils.create_job(status='PENDING')
        condition_i = recipe_test_utils.create_recipe_condition(save=True)
        definition = RecipeDefinition(Interface())
        definition.add_job_node('node_a', job_a.job_type.name, job_a.job_type.version, job_a.job_type_rev.revision_num)
        definition.add_recipe_node('node_b', recipe_b.recipe_type.name, recipe_b.recipe_type.revision_num)
        definition.add_job_node('node_c', job_c.job_type.name, job_c.job_type.version, job_c.job_type_rev.revision_num)
        definition.add_job_node('node_d', job_d.job_type.name, job_d.job_type.version, job_d.job_type_rev.revision_num)
        definition.add_recipe_node('node_e', recipe_type_e.name, recipe_type_e.revision_num)
        definition.add_job_node('node_f', job_type_f.name, job_type_f.version, job_type_f.revision_num)
        definition.add_job_node('node_g', job_g.job_type.name, job_g.job_type.version, job_g.job_type_rev.revision_num)
        definition.add_job_node('node_h', job_h.job_type.name, job_h.job_type.version, job_h.job_type_rev.revision_num)
        definition.add_condition_node('node_i', Interface(), DataFilter()) #True
        definition.add_condition_node('node_j', Interface(), DataFilter()) #True
        definition.add_job_node('node_k', job_type_k.name, job_type_k.version, job_type_k.revision_num)
        definition.add_dependency('node_a', 'node_c')
        definition.add_dependency('node_a', 'node_e')
        definition.add_dependency('node_a', 'node_g')
        definition.add_dependency('node_c', 'node_d')
        definition.add_dependency('node_e', 'node_f')
        definition.add_dependency('node_g', 'node_h')
        definition.add_dependency('node_a', 'node_i')
        definition.add_dependency('node_a', 'node_j')
        definition.add_dependency('node_i', 'node_k')
        definition.add_dependency('node_j', 'node_k')
        definition_dict = convert_recipe_definition_to_v6_json(definition).get_dict()
        recipe_type = recipe_test_utils.create_recipe_type_v6(definition=definition_dict)
        recipe = recipe_test_utils.create_recipe(recipe_type=recipe_type, input=data_dict)
        node_a = recipe_test_utils.create_recipe_node(recipe=recipe, node_name='node_a', job=job_a, save=False)
        node_b = recipe_test_utils.create_recipe_node(recipe=recipe, node_name='node_b', sub_recipe=recipe_b,
                                                      save=False)
        node_c = recipe_test_utils.create_recipe_node(recipe=recipe, node_name='node_c', job=job_c, save=False)
        node_d = recipe_test_utils.create_recipe_node(recipe=recipe, node_name='node_d', job=job_d, save=False)
        node_g = recipe_test_utils.create_recipe_node(recipe=recipe, node_name='node_g', job=job_g, save=False)
        node_h = recipe_test_utils.create_recipe_node(recipe=recipe, node_name='node_h', job=job_h, save=False)
        node_i = recipe_test_utils.create_recipe_node(recipe=recipe, node_name='node_i', condition=condition_i,
                                                      save=False)
        RecipeNode.objects.bulk_create([node_a, node_b, node_c, node_d, node_g, node_h, node_i])
        forced_nodes = ForcedNodes()
        forced_nodes_e = ForcedNodes()
        forced_nodes_e.set_all_nodes()
        forced_nodes.add_subrecipe('node_e', forced_nodes_e)

        # Create and execute message
        message = create_update_recipe_message(recipe.id, forced_nodes=forced_nodes)
        result = message.execute()
        self.assertTrue(result)

        self.assertEqual(len(message.new_messages), 8)
        # Check messages
        blocked_jobs_msg = None
        pending_jobs_msg = None
        create_cond_msg = None
        create_jobs_msg = None
        create_recipes_msg = None
        process_condition_msg = None
        process_job_input_msg = None
        process_recipe_input_msg = None
        for msg in message.new_messages:
            if msg.type == 'blocked_jobs':
                blocked_jobs_msg = msg
            elif msg.type == 'pending_jobs':
                pending_jobs_msg = msg
            elif msg.type == 'create_conditions':
                create_cond_msg = msg
            elif msg.type == 'create_jobs':
                create_jobs_msg = msg
            elif msg.type == 'create_recipes':
                create_recipes_msg = msg
            elif msg.type == 'process_condition':
                process_condition_msg = msg
            elif msg.type == 'process_job_input':
                process_job_input_msg = msg
            elif msg.type == 'process_recipe_input':
                process_recipe_input_msg = msg
        self.assertIsNotNone(blocked_jobs_msg)
        self.assertIsNotNone(pending_jobs_msg)
        self.assertIsNotNone(create_cond_msg)
        self.assertIsNotNone(create_jobs_msg)
        self.assertIsNotNone(create_recipes_msg)
        self.assertIsNotNone(process_condition_msg)
        self.assertIsNotNone(process_job_input_msg)
        self.assertIsNotNone(process_recipe_input_msg)
        # Check message to change jobs to BLOCKED
        self.assertListEqual(blocked_jobs_msg._blocked_job_ids, [job_h.id])
        # Check message to change jobs to PENDING
        self.assertListEqual(pending_jobs_msg._pending_job_ids, [job_d.id])
        # Check message to create conditions
        self.assertEqual(create_cond_msg.recipe_id, recipe.id)
        self.assertEqual(create_cond_msg.root_recipe_id, recipe.root_superseded_recipe_id)
        condition = Condition('node_j', True)
        self.assertListEqual(create_cond_msg.conditions, [condition])
        # Check message to create jobs
        self.assertEqual(create_jobs_msg.event_id, recipe.event_id)
        self.assertEqual(create_jobs_msg.create_jobs_type, RECIPE_TYPE)
        self.assertEqual(create_jobs_msg.recipe_id, recipe.id)
        self.assertEqual(create_jobs_msg.root_recipe_id, recipe.root_superseded_recipe_id)
        self.assertIsNone(create_jobs_msg.superseded_recipe_id)
        recipe_job = RecipeJob(job_type_f.name, job_type_f.version, job_type_f.revision_num, 'node_f', False)
        self.assertListEqual(create_jobs_msg.recipe_jobs, [recipe_job])
        # Check message to create sub-recipes
        self.assertEqual(create_recipes_msg.event_id, recipe.event_id)
        msg_forced_nodes_dict = convert_forced_nodes_to_v6(create_recipes_msg.forced_nodes).get_dict()
        expected_forced_nodes_dict = convert_forced_nodes_to_v6(forced_nodes).get_dict()
        self.assertDictEqual(msg_forced_nodes_dict, expected_forced_nodes_dict)
        self.assertEqual(create_recipes_msg.create_recipes_type, SUB_RECIPE_TYPE)
        self.assertEqual(create_recipes_msg.recipe_id, recipe.id)
        self.assertEqual(create_recipes_msg.root_recipe_id, recipe.root_superseded_recipe_id)
        self.assertIsNone(create_recipes_msg.superseded_recipe_id)
        sub = SubRecipe(recipe_type_e.name, recipe_type_e.revision_num, 'node_e', True)
        self.assertListEqual(create_recipes_msg.sub_recipes, [sub])
        # Check message to process condition
        self.assertEqual(process_condition_msg.condition_id, condition_i.id)
        # Check message to process job input
        self.assertEqual(process_job_input_msg.job_id, job_c.id)
        # Check message to process recipe input
        self.assertEqual(process_recipe_input_msg.recipe_id, recipe_b.id)

        # Test executing message again
        message_json_dict = message.to_json()
        message = UpdateRecipe.from_json(message_json_dict)
        result = message.execute()
        self.assertTrue(result)

        # Make sure the same messages are returned
        self.assertEqual(len(message.new_messages), 8)
        blocked_jobs_msg = None
        pending_jobs_msg = None
        create_cond_msg = None
        create_jobs_msg = None
        create_recipes_msg = None
        process_condition_msg = None
        process_job_input_msg = None
        process_recipe_input_msg = None
        for msg in message.new_messages:
            if msg.type == 'blocked_jobs':
                blocked_jobs_msg = msg
            elif msg.type == 'pending_jobs':
                pending_jobs_msg = msg
            elif msg.type == 'create_conditions':
                create_cond_msg = msg
            elif msg.type == 'create_jobs':
                create_jobs_msg = msg
            elif msg.type == 'create_recipes':
                create_recipes_msg = msg
            elif msg.type == 'process_condition':
                process_condition_msg = msg
            elif msg.type == 'process_job_input':
                process_job_input_msg = msg
            elif msg.type == 'process_recipe_input':
                process_recipe_input_msg = msg
        self.assertIsNotNone(blocked_jobs_msg)
        self.assertIsNotNone(pending_jobs_msg)
        self.assertIsNotNone(create_cond_msg)
        self.assertIsNotNone(create_jobs_msg)
        self.assertIsNotNone(create_recipes_msg)
        self.assertIsNotNone(process_condition_msg)
        self.assertIsNotNone(process_job_input_msg)
        self.assertIsNotNone(process_recipe_input_msg)
        # Check message to change jobs to BLOCKED
        self.assertListEqual(blocked_jobs_msg._blocked_job_ids, [job_h.id])
        # Check message to change jobs to PENDING
        self.assertListEqual(pending_jobs_msg._pending_job_ids, [job_d.id])
        # Check message to create conditions
        self.assertEqual(create_cond_msg.recipe_id, recipe.id)
        self.assertEqual(create_cond_msg.root_recipe_id, recipe.root_superseded_recipe_id)
        condition = Condition('node_j', True)
        self.assertListEqual(create_cond_msg.conditions, [condition])
        # Check message to create jobs
        self.assertEqual(create_jobs_msg.event_id, recipe.event_id)
        self.assertEqual(create_jobs_msg.create_jobs_type, RECIPE_TYPE)
        self.assertEqual(create_jobs_msg.recipe_id, recipe.id)
        self.assertEqual(create_jobs_msg.root_recipe_id, recipe.root_superseded_recipe_id)
        self.assertIsNone(create_jobs_msg.superseded_recipe_id)
        recipe_job = RecipeJob(job_type_f.name, job_type_f.version, job_type_f.revision_num, 'node_f', False)
        self.assertListEqual(create_jobs_msg.recipe_jobs, [recipe_job])
        # Check message to create sub-recipes
        self.assertEqual(create_recipes_msg.event_id, recipe.event_id)
        msg_forced_nodes_dict = convert_forced_nodes_to_v6(create_recipes_msg.forced_nodes).get_dict()
        expected_forced_nodes_dict = convert_forced_nodes_to_v6(forced_nodes).get_dict()
        self.assertDictEqual(msg_forced_nodes_dict, expected_forced_nodes_dict)
        self.assertEqual(create_recipes_msg.create_recipes_type, SUB_RECIPE_TYPE)
        self.assertEqual(create_recipes_msg.recipe_id, recipe.id)
        self.assertEqual(create_recipes_msg.root_recipe_id, recipe.root_superseded_recipe_id)
        self.assertIsNone(create_recipes_msg.superseded_recipe_id)
        sub = SubRecipe(recipe_type_e.name, recipe_type_e.revision_num, 'node_e', True)
        self.assertListEqual(create_recipes_msg.sub_recipes, [sub])
        # Check message to process condition
        self.assertEqual(process_condition_msg.condition_id, condition_i.id)
        # Check message to process job input
        self.assertEqual(process_job_input_msg.job_id, job_c.id)
        # Check message to process recipe input
        self.assertEqual(process_recipe_input_msg.recipe_id, recipe_b.id)