mirror of
https://github.com/ansible/awx.git
synced 2026-02-12 15:14:45 -03:30
Various points (e.g. created, running, processing events), are structured into json format and output to /var/log/tower/job_lifecycle.log As part of this work, the DependencyGraph is reworked to return which job object is doing the blocking, rather than a boolean.
129 lines
4.9 KiB
Python
129 lines
4.9 KiB
Python
from awx.main.models import (
|
|
Job,
|
|
ProjectUpdate,
|
|
InventoryUpdate,
|
|
SystemJob,
|
|
AdHocCommand,
|
|
WorkflowJob,
|
|
)
|
|
|
|
|
|
class DependencyGraph(object):
|
|
PROJECT_UPDATES = 'project_updates'
|
|
INVENTORY_UPDATES = 'inventory_updates'
|
|
|
|
JOB_TEMPLATE_JOBS = 'job_template_jobs'
|
|
|
|
SYSTEM_JOB = 'system_job'
|
|
INVENTORY_SOURCE_UPDATES = 'inventory_source_updates'
|
|
WORKFLOW_JOB_TEMPLATES_JOBS = 'workflow_job_template_jobs'
|
|
|
|
INVENTORY_SOURCES = 'inventory_source_ids'
|
|
|
|
def __init__(self):
|
|
self.data = {}
|
|
self.data[self.PROJECT_UPDATES] = {}
|
|
# The reason for tracking both inventory and inventory sources:
|
|
# Consider InvA, which has two sources, InvSource1, InvSource2.
|
|
# JobB might depend on InvA, which launches two updates, one for each source.
|
|
# To determine if JobB can run, we can just check InvA, which is marked in
|
|
# INVENTORY_UPDATES, instead of having to check for both entries in
|
|
# INVENTORY_SOURCE_UPDATES.
|
|
self.data[self.INVENTORY_UPDATES] = {}
|
|
self.data[self.INVENTORY_SOURCE_UPDATES] = {}
|
|
self.data[self.JOB_TEMPLATE_JOBS] = {}
|
|
self.data[self.SYSTEM_JOB] = {}
|
|
self.data[self.WORKFLOW_JOB_TEMPLATES_JOBS] = {}
|
|
|
|
def mark_if_no_key(self, job_type, id, job):
|
|
# only mark first occurrence of a task. If 10 of JobA are launched
|
|
# (concurrent disabled), the dependency graph should return that jobs
|
|
# 2 through 10 are blocked by job1
|
|
if id not in self.data[job_type]:
|
|
self.data[job_type][id] = job
|
|
|
|
def get_item(self, job_type, id):
|
|
return self.data[job_type].get(id, None)
|
|
|
|
def mark_system_job(self, job):
|
|
# Don't track different types of system jobs, so that only one can run
|
|
# at a time. Therefore id in this case is just 'system_job'.
|
|
self.mark_if_no_key(self.SYSTEM_JOB, 'system_job', job)
|
|
|
|
def mark_project_update(self, job):
|
|
self.mark_if_no_key(self.PROJECT_UPDATES, job.project_id, job)
|
|
|
|
def mark_inventory_update(self, job):
|
|
if type(job) is AdHocCommand:
|
|
self.mark_if_no_key(self.INVENTORY_UPDATES, job.inventory_id, job)
|
|
else:
|
|
self.mark_if_no_key(self.INVENTORY_UPDATES, job.inventory_source.inventory_id, job)
|
|
|
|
def mark_inventory_source_update(self, job):
|
|
self.mark_if_no_key(self.INVENTORY_SOURCE_UPDATES, job.inventory_source_id, job)
|
|
|
|
def mark_job_template_job(self, job):
|
|
self.mark_if_no_key(self.JOB_TEMPLATE_JOBS, job.job_template_id, job)
|
|
|
|
def mark_workflow_job(self, job):
|
|
self.mark_if_no_key(self.WORKFLOW_JOB_TEMPLATES_JOBS, job.workflow_job_template_id, job)
|
|
|
|
def project_update_blocked_by(self, job):
|
|
return self.get_item(self.PROJECT_UPDATES, job.project_id)
|
|
|
|
def inventory_update_blocked_by(self, job):
|
|
return self.get_item(self.INVENTORY_SOURCE_UPDATES, job.inventory_source_id)
|
|
|
|
def job_blocked_by(self, job):
|
|
project_block = self.get_item(self.PROJECT_UPDATES, job.project_id)
|
|
inventory_block = self.get_item(self.INVENTORY_UPDATES, job.inventory_id)
|
|
if job.allow_simultaneous is False:
|
|
job_block = self.get_item(self.JOB_TEMPLATE_JOBS, job.job_template_id)
|
|
else:
|
|
job_block = None
|
|
return project_block or inventory_block or job_block
|
|
|
|
def workflow_job_blocked_by(self, job):
|
|
if job.allow_simultaneous is False:
|
|
return self.get_item(self.WORKFLOW_JOB_TEMPLATES_JOBS, job.workflow_job_template_id)
|
|
return None
|
|
|
|
def system_job_blocked_by(self, job):
|
|
return self.get_item(self.SYSTEM_JOB, 'system_job')
|
|
|
|
def ad_hoc_command_blocked_by(self, job):
|
|
return self.get_item(self.INVENTORY_UPDATES, job.inventory_id)
|
|
|
|
def task_blocked_by(self, job):
|
|
if type(job) is ProjectUpdate:
|
|
return self.project_update_blocked_by(job)
|
|
elif type(job) is InventoryUpdate:
|
|
return self.inventory_update_blocked_by(job)
|
|
elif type(job) is Job:
|
|
return self.job_blocked_by(job)
|
|
elif type(job) is SystemJob:
|
|
return self.system_job_blocked_by(job)
|
|
elif type(job) is AdHocCommand:
|
|
return self.ad_hoc_command_blocked_by(job)
|
|
elif type(job) is WorkflowJob:
|
|
return self.workflow_job_blocked_by(job)
|
|
|
|
def add_job(self, job):
|
|
if type(job) is ProjectUpdate:
|
|
self.mark_project_update(job)
|
|
elif type(job) is InventoryUpdate:
|
|
self.mark_inventory_update(job)
|
|
self.mark_inventory_source_update(job)
|
|
elif type(job) is Job:
|
|
self.mark_job_template_job(job)
|
|
elif type(job) is WorkflowJob:
|
|
self.mark_workflow_job(job)
|
|
elif type(job) is SystemJob:
|
|
self.mark_system_job(job)
|
|
elif type(job) is AdHocCommand:
|
|
self.mark_inventory_update(job)
|
|
|
|
def add_jobs(self, jobs):
|
|
for j in jobs:
|
|
self.add_job(j)
|