def testjob_submission(job_definition, user, check_device=None, original_job=None): """ Single submission frontend for JSON or YAML :param job_definition: string of the job submission :param user: user attempting the submission :param check_device: set specified device as the target **and** thereby set job as a health check job. (JSON only) :return: a job or a list of jobs :raises: SubmissionException, Device.DoesNotExist, DeviceType.DoesNotExist, DevicesUnavailableException, JSONDataError, JSONDecodeError, ValueError """ if is_deprecated_json(job_definition): allow_health = False job_json = simplejson.loads(job_definition) target_device = None if 'target' in job_json: target_device = Device.objects.get(hostname=job_json['target']) if check_device: job_json['target'] = check_device.hostname job_json['health-check'] = True job_definition = simplejson.dumps(job_json) allow_health = True try: # returns a single job or a list (not a QuerySet) of job objects. job = TestJob.from_json_and_user(job_definition, user, health_check=allow_health) if isinstance(job, list): # multinode health checks not supported return job job.health_check = allow_health if check_device: job.requested_device = check_device elif target_device: job.requested_device = target_device job.save(update_fields=['health_check', 'requested_device']) except (JSONDataError, ValueError) as exc: if check_device: check_device.put_into_maintenance_mode( user, "Job submission failed for health job for %s: %s" % (check_device, exc)) raise JSONDataError("Health check job submission failed for %s: %s" % (check_device, exc)) else: raise JSONDataError("Job submission failed: %s" % exc) else: validate_job(job_definition) # returns a single job or a list (not a QuerySet) of job objects. job = TestJob.from_yaml_and_user(job_definition, user, original_job=original_job) if check_device and isinstance(check_device, Device) and not isinstance(job, list): # the slave must neither know nor care if this is a health check, # only the master cares and that has the database connection. job.health_check = True job.requested_device = check_device job.save(update_fields=['health_check', 'requested_device']) return job
def initiate_health_check_job(device): logger = logging.getLogger('dispatcher-master') logger.info("Initiating health check") if not device: # logic error logger.error("No device") return None if device.status in [Device.RETIRED]: # logic error logger.error("[%s] has been retired", device) return None job_data = device.get_health_check() user = User.objects.get(username='******') if not job_data: # This should never happen, it's a logic error. logger.error("No health check definition found for %s", device) device.put_into_maintenance_mode( user, "health check job not found in initiate_health_check_job") raise JSONDataError("no health check job found for %r", device.hostname) if is_deprecated_json(job_data): # only JSON supports 'target' and that needs to be set by the health-check not the admin. job_json = simplejson.loads(job_data) if 'target' in job_json: logger.error("[%s] JSON Health check definition must not specify a 'target'.", device.device_type.name) device.put_into_maintenance_mode( user, "target must not be defined in health check definitions.") return None try: job = testjob_submission(job_data, user, check_device=device) except (DevicesUnavailableException, SubmissionException) as exc: logger.error("[%s] failed to submit health check - %s", device.device_type.name, exc) return None return job