Beispiel #1
0
    def test_determine_error(self):
        """Tests that a post-task successfully determines the correct error"""

        scale_errors = [
            ScaleDatabaseError(),
            ScaleIOError(),
            ScaleOperationalError(),
            InvalidResultsManifest(''),
            MissingRequiredOutput('')
        ]

        for scale_error in scale_errors:
            config = ExecutionConfiguration()
            config.create_tasks(['pre'])
            config.set_task_ids(self.job_exe.get_cluster_id())
            task = PostTask('agent_1', self.job_exe, self.job_exe.job_type,
                            config)
            update = job_test_utils.create_task_status_update(
                task.id, task.agent_id, TaskStatusUpdate.RUNNING, now())
            task.update(update)
            update = job_test_utils.create_task_status_update(
                task.id,
                task.agent_id,
                TaskStatusUpdate.FAILED,
                now(),
                exit_code=scale_error.exit_code)
            error = task.determine_error(update)
            self.assertEqual(scale_error.error_name, error.name)
Beispiel #2
0
    def validate(self, output_file_definitions):
        """Validates the results manifest against given output file definitions. This does not validate that the
        parse_data matches the job data inputs.

        :param output_file_definitions: A dictionary with each output param name mapped to a tuple with
            (is_multiple (bool), required(bool))
        :type output_file_definitions: dict of tuples
        """

        self._trim(output_file_definitions)

        file_entry_map = {}
        for manifest_file_entry in self._json_manifest['output_data']:
            entry_name = manifest_file_entry['name']
            if 'files' in manifest_file_entry and not manifest_file_entry['files']:
                # skip empty lists
                continue
            file_entry_map[entry_name] = manifest_file_entry

        for file_name, (is_multiple, is_required) in output_file_definitions.items():
            if file_name not in file_entry_map:
                if is_required:
                    raise MissingRequiredOutput(file_name)
                else:
                    continue

            manifest_file_entry = file_entry_map[file_name]
            if is_multiple and 'files' not in manifest_file_entry:
                msg = 'The output parameter %s must have a files object in the results manifest' % file_name
                raise InvalidResultsManifest(msg)
            if not is_multiple and 'file' not in manifest_file_entry:
                msg = 'The output parameter %s must have a file object in the results manifest' % file_name
                raise InvalidResultsManifest(msg)
Beispiel #3
0
    def validate(self, output_file_definitions):
        """Validates the results manifest against given output file definitions.  Throws a
        :class `job.configuration.results.exceptions.ResultsManifestAndInterfaceDontMatch`: if the
        manifest doesn't match the outputs.  This does not validate that the parse_data matches the job
        data inputs.
        :param output_file_definitions: A dictionary with each output param name mapped to a tuple with
        (is_multiple (bool), required(bool))
        :type output_file_definitions: dict of tuples
        """

        self._trim(output_file_definitions)

        file_entry_map = {}
        for manifest_file_entry in self._json_manifest['files']:
            entry_name = manifest_file_entry['name']
            file_entry_map[entry_name] = manifest_file_entry

        for file_name, (is_multiple,
                        is_required) in output_file_definitions.items():
            if file_name not in file_entry_map:
                if is_required:
                    raise MissingRequiredOutput(file_name)
                else:
                    continue

            manifest_file_entry = file_entry_map[file_name]
            if is_multiple and 'paths' not in manifest_file_entry:
                msg = 'The output parameter %s must have a paths object in the results manifest' % file_name
                raise InvalidResultsManifest(msg)
            if not is_multiple and 'path' not in manifest_file_entry:
                msg = 'The output parameter %s must have a path object in the results manifest' % file_name
                raise InvalidResultsManifest(msg)
Beispiel #4
0
    def ready(self):
        """Registers components related to jobs"""

        # Register job errors
        from error.exceptions import register_error
        from job.configuration.exceptions import MissingMount, MissingSetting
        from job.configuration.results.exceptions import InvalidResultsManifest, MissingRequiredOutput

        register_error(InvalidResultsManifest(''))
        register_error(MissingMount(''))
        register_error(MissingRequiredOutput(''))
        register_error(MissingSetting(''))

        # Register job message types
        from job.messages.blocked_jobs import BlockedJobs
        from job.messages.failed_jobs import FailedJobs
        from job.messages.job_exe_end import CreateJobExecutionEnd
        from job.messages.pending_jobs import PendingJobs
        from job.messages.running_jobs import RunningJobs
        from messaging.messages.factory import add_message_type

        add_message_type(BlockedJobs)
        add_message_type(FailedJobs)
        add_message_type(CreateJobExecutionEnd)
        add_message_type(PendingJobs)
        add_message_type(RunningJobs)
Beispiel #5
0
    def ready(self):
        """Registers job errors"""
        from error.exceptions import register_error
        from job.configuration.exceptions import MissingMount, MissingSetting
        from job.configuration.results.exceptions import InvalidResultsManifest, MissingRequiredOutput

        register_error(InvalidResultsManifest(''))
        register_error(MissingMount(''))
        register_error(MissingRequiredOutput(''))
        register_error(MissingSetting(''))
    def test_scale_post_steps_missing_manifest_output_error(
            self, mock_job_exe_manager, mock_sys_exit):
        """Tests executing scale_post_steps when a missing output manifest occurs."""

        # Set up mocks
        mock_job_exe_manager.get_job_exe_with_job_and_job_type.return_value.get_job_interface.return_value.perform_post_steps.side_effect = MissingRequiredOutput(
            '')

        # Call method to test
        cmd = PostCommand()
        cmd.run_from_argv(
            ['manage.py', 'scale_post_steps', '-i',
             str(self.job_exe.id)])

        # Check results
        mock_sys_exit.assert_called_with(MissingRequiredOutput('').exit_code)
Beispiel #7
0
    def ready(self):
        """Registers components related to jobs"""

        # Register job errors
        from error.exceptions import register_error
        from job.configuration.results.exceptions import InvalidResultsManifest, MissingRequiredOutput, UnexpectedMultipleOutputs
        from job.execution.configuration.exceptions import MissingMount, MissingSetting

        register_error(InvalidResultsManifest(''))
        register_error(MissingMount(''))
        register_error(MissingRequiredOutput(''))
        register_error(UnexpectedMultipleOutputs(''))
        register_error(MissingSetting(''))

        # Register job message types
        from job.messages.blocked_jobs import BlockedJobs
        from job.messages.cancel_jobs import CancelJobs
        from job.messages.cancel_jobs_bulk import CancelJobsBulk
        from job.messages.completed_jobs import CompletedJobs
        from job.messages.create_jobs import CreateJobs
        from job.messages.failed_jobs import FailedJobs
        from job.messages.job_exe_end import CreateJobExecutionEnd
        from job.messages.pending_jobs import PendingJobs
        from job.messages.process_job_input import ProcessJobInput
        from job.messages.publish_job import PublishJob
        from job.messages.purge_jobs import PurgeJobs
        from job.messages.running_jobs import RunningJobs
        from job.messages.spawn_delete_files_job import SpawnDeleteFilesJob
        from job.messages.uncancel_jobs import UncancelJobs
        from job.messages.unpublish_jobs import UnpublishJobs
        from messaging.messages.factory import add_message_type

        add_message_type(BlockedJobs)
        add_message_type(CancelJobs)
        add_message_type(CancelJobsBulk)
        add_message_type(CompletedJobs)
        add_message_type(CreateJobs)
        add_message_type(FailedJobs)
        add_message_type(CreateJobExecutionEnd)
        add_message_type(PendingJobs)
        add_message_type(ProcessJobInput)
        add_message_type(PublishJob)
        add_message_type(PurgeJobs)
        add_message_type(RunningJobs)
        add_message_type(SpawnDeleteFilesJob)
        add_message_type(UncancelJobs)
        add_message_type(UnpublishJobs)
Beispiel #8
0
    def test_scale_post_steps_missing_manifest_output_error(
            self, mock_env_vars, mock_job_exe_manager, mock_sys_exit):
        """Tests executing scale_post_steps when a missing output manifest occurs."""

        # Set up mocks
        def get_env_vars(name, *args, **kwargs):
            return str(self.job.id) if name == 'SCALE_JOB_ID' else str(
                self.job_exe.exe_num)

        mock_env_vars.side_effect = get_env_vars
        mock_job_exe_manager.get_job_exe_with_job_and_job_type.return_value.job_type.get_job_interface.return_value.perform_post_steps.side_effect = MissingRequiredOutput(
            '')

        # Call method to test
        cmd = PostCommand()
        cmd.run_from_argv(['manage.py', 'scale_post_steps'])

        # Check results
        mock_sys_exit.assert_called_with(MissingRequiredOutput('').exit_code)
Beispiel #9
0
    def get_files(self):
        """Get a list of absolute paths to files following job execution

        :return: files matched by pattern defined for object
        :rtype: [str]
        :raises: OutputCaptureError
        """
        path_pattern = os.path.join(SCALE_JOB_EXE_OUTPUT_PATH, self.pattern)
        results = glob.glob(path_pattern)

        logger.info(
            'Results found in post-step pattern match for output %s: %s' %
            (self.name, results))

        # Remove any metadata.json and special json files from results
        purged_results = []
        for x in results:
            for file_name in SPECIAL_FILES:
                if file_name in x:
                    break
            else:
                purged_results.append(x)
        results = purged_results

        # Handle required validation
        if self.required and len(results) == 0:
            raise MissingRequiredOutput(
                "No glob match for pattern '%s' defined for required output files"
                " key '%s'." % (self.pattern, self.name))

        # Check against multiple to verify we are matching the files as defined.
        if not self.multiple and len(results) > 1:
            raise UnexpectedMultipleOutputs(
                "Pattern matched %i, which is not consistent with a false value for 'multiple'."
                % (len(results), ))

        return results