def from_json(json_dict): """See :meth:`messaging.messages.message.CommandMessage.from_json` """ message = CreateJobExecutionEnd() for job_exe_end_dict in json_dict['job_exe_end_models']: job_exe_end = JobExecutionEnd() task_results = TaskResults(job_exe_end_dict['task_results'], do_validate=False) job_exe_end.job_exe_id = job_exe_end_dict['id'] job_exe_end.job_id = job_exe_end_dict['job_id'] job_exe_end.job_type_id = job_exe_end_dict['job_type_id'] job_exe_end.exe_num = job_exe_end_dict['exe_num'] job_exe_end.task_results = job_exe_end_dict['task_results'] job_exe_end.status = job_exe_end_dict['status'] job_exe_end.queued = parse_datetime(job_exe_end_dict['queued']) job_exe_end.seed_started = task_results.get_task_started('main') job_exe_end.seed_ended = task_results.get_task_ended('main') job_exe_end.ended = parse_datetime(job_exe_end_dict['ended']) if 'error_id' in job_exe_end_dict: job_exe_end.error_id = job_exe_end_dict['error_id'] if 'node_id' in job_exe_end_dict: job_exe_end.node_id = job_exe_end_dict['node_id'] if 'started' in job_exe_end_dict: job_exe_end.started = job_exe_end_dict['started'] message.add_job_exe_end(job_exe_end) return message
def create_job_exe_end_model(self): """Creates and returns a job execution end model for this job execution. Caller must ensure that this job execution is finished before calling. :returns: The job execution end model :rtype: :class:`job.models.JobExecutionEnd` """ task_results = TaskResults(do_validate=False) task_results.add_task_results(self._all_tasks) job_exe_end = JobExecutionEnd() job_exe_end.job_exe_id = self.id job_exe_end.job_id = self.job_id job_exe_end.job_type_id = self.job_type_id job_exe_end.exe_num = self.exe_num job_exe_end.task_results = task_results.get_dict() job_exe_end.status = self._status if self._error: job_exe_end.error_id = self._error.id job_exe_end.node_id = self.node_id job_exe_end.queued = self.queued job_exe_end.started = self.started job_exe_end.ended = self._finished return job_exe_end
def create_job_exe(job_type=None, job=None, exe_num=None, node=None, timeout=None, input_file_size=10.0, queued=None, started=None, status='RUNNING', error=None, ended=None, output=None, task_results=None): """Creates a job_exe model for unit testing, may also create job_exe_end and job_exe_output models depending on status :returns: The job_exe model :rtype: :class:`job.execution.job_exe.RunningJobExecution` """ when = timezone.now() if not job: job = create_job(job_type=job_type, status=status, input_file_size=input_file_size) job_type = job.job_type job_exe = JobExecution() job_exe.job = job job_exe.job_type = job_type if not exe_num: exe_num = job.num_exes job_exe.exe_num = exe_num job_exe.set_cluster_id('1234', job.id, job_exe.exe_num) if not node: node = node_utils.create_node() job_exe.node = node if not timeout: timeout = job.timeout job_exe.timeout = timeout job_exe.input_file_size = input_file_size job_exe.resources = job.get_resources().get_json().get_dict() job_exe.configuration = ExecutionConfiguration().get_dict() if not queued: queued = when job_exe.queued = queued if not started: started = when + datetime.timedelta(seconds=1) job_exe.started = started job_exe.save() if status in ['COMPLETED', 'FAILED', 'CANCELED']: job_exe_end = JobExecutionEnd() job_exe_end.job_exe_id = job_exe.id job_exe_end.job = job_exe.job job_exe_end.job_type = job_exe.job_type job_exe_end.exe_num = job_exe.exe_num if not task_results: task_results = TaskResults() job_exe_end.task_results = task_results.get_dict() job_exe_end.status = status if status == 'FAILED' and not error: error = error_test_utils.create_error() job_exe_end.error = error job_exe_end.node = node job_exe_end.queued = queued job_exe_end.started = started job_exe_end.seed_started = task_results.get_task_started('main') job_exe_end.seed_ended = task_results.get_task_ended('main') if not ended: ended = started + datetime.timedelta(seconds=1) job_exe_end.ended = ended job_exe_end.save() if status == 'COMPLETED' or output: job_exe_output = JobExecutionOutput() job_exe_output.job_exe_id = job_exe.id job_exe_output.job = job_exe.job job_exe_output.job_type = job_exe.job_type job_exe_output.exe_num = job_exe.exe_num if not output: output = JobResults() job_exe_output.output = output.get_dict() job_exe_output.save() return job_exe
def _perform_update_iteration(self): """Performs a single iteration of the database update """ # Retrieve 500 job executions that need to be updated and get job IDs job_ids = set() for job_exe in JobExecution.objects.filter(status__isnull=False).only('id', 'job_id')[:500]: job_ids.add(job_exe.job_id) # Retrieve all job executions for those jobs in sorted order job_exe_count = 0 current_job_id = None current_exe_num = 1 exe_num_dict = {} # {exe_num: [job_exe.id]} job_exe_end_models = [] job_exe_output_models = [] job_exe_qry = JobExecution.objects.select_related('job').filter(job_id__in=job_ids) for job_exe in job_exe_qry.defer('resources', 'configuration', 'stdout', 'stderr').order_by('job_id', 'id'): job_exe_count += 1 if job_exe.job_id == current_job_id: current_exe_num += 1 else: current_job_id = job_exe.job_id current_exe_num = 1 # This job_exe model needs to be updated with its exe_num if current_exe_num in exe_num_dict: exe_num_dict[current_exe_num].append(job_exe.id) else: exe_num_dict[current_exe_num] = [job_exe.id] if job_exe.status in ['COMPLETED', 'FAILED', 'CANCELED']: # Create corresponding job_exe_end model job_exe_end = JobExecutionEnd() job_exe_end.job_exe_id = job_exe.id job_exe_end.job_id = job_exe.job_id job_exe_end.job_type_id = job_exe.job.job_type_id job_exe_end.exe_num = current_exe_num # Create task results from job_exe task fields task_list = [] if job_exe.pre_started: pre_task_dict = {'task_id': '%s_%s' % (job_exe.get_cluster_id(), 'pre'), 'type': 'pre', 'was_launched': True, 'was_started': True, 'started': datetime_to_string(job_exe.pre_started)} if job_exe.pre_completed: pre_task_dict['ended'] = datetime_to_string(job_exe.pre_completed) if job_exe.pre_exit_code is not None: pre_task_dict['exit_code'] = job_exe.pre_exit_code task_list.append(pre_task_dict) if job_exe.job_started: job_task_dict = {'task_id': '%s_%s' % (job_exe.get_cluster_id(), 'job'), 'type': 'main', 'was_launched': True, 'was_started': True, 'started': datetime_to_string(job_exe.job_started)} if job_exe.job_completed: job_task_dict['ended'] = datetime_to_string(job_exe.job_completed) if job_exe.job_exit_code is not None: job_task_dict['exit_code'] = job_exe.job_exit_code task_list.append(job_task_dict) if job_exe.post_started: post_task_dict = {'task_id': '%s_%s' % (job_exe.get_cluster_id(), 'post'), 'type': 'post', 'was_launched': True, 'was_started': True, 'started': datetime_to_string(job_exe.post_started)} if job_exe.post_completed: post_task_dict['ended'] = datetime_to_string(job_exe.post_completed) if job_exe.post_exit_code is not None: post_task_dict['exit_code'] = job_exe.post_exit_code task_list.append(post_task_dict) task_results = TaskResults({'tasks': task_list}) job_exe_end.task_results = task_results.get_dict() job_exe_end.status = job_exe.status job_exe_end.error_id = job_exe.error_id job_exe_end.node_id = job_exe.node_id job_exe_end.queued = job_exe.queued job_exe_end.started = job_exe.started job_exe_end.seed_started = task_results.get_task_started('main') job_exe_end.seed_ended = task_results.get_task_ended('main') job_exe_end.ended = job_exe.ended job_exe_end_models.append(job_exe_end) if job_exe.status == 'COMPLETED': # Create corresponding job_exe_output model job_exe_output = JobExecutionOutput() job_exe_output.job_exe_id = job_exe.id job_exe_output.job_id = job_exe.job_id job_exe_output.job_type_id = job_exe.job.job_type_id job_exe_output.exe_num = current_exe_num job_exe_output.output = job_exe.results job_exe_output_models.append(job_exe_output) # Update/create models in an atomic transaction with transaction.atomic(): for exe_num, job_exe_ids in exe_num_dict.items(): JobExecution.objects.filter(id__in=job_exe_ids).update(exe_num=exe_num, status=None, error_id=None, command_arguments=None, environment=None, cpus_scheduled=None, mem_scheduled=None, disk_out_scheduled=None, disk_total_scheduled=None, pre_started=None, pre_completed=None, pre_exit_code=None, job_started=None, job_completed=None, job_exit_code=None, job_metrics=None, post_started=None, post_completed=None, post_exit_code=None, stdout=None, stderr=None, results_manifest=None, results=None, ended=None, last_modified=None) JobExecutionEnd.objects.bulk_create(job_exe_end_models) JobExecutionOutput.objects.bulk_create(job_exe_output_models) logger.info('Updated %d job executions', job_exe_count) self._updated_job_exe += job_exe_count percent = (float(self._updated_job_exe) / float(self._total_job_exe)) * 100.00 print 'Completed %s of %s job executions (%.1f%%)' % (self._updated_job_exe, self._total_job_exe, percent)