diff --git a/app/models.py b/app/models.py index 1a3eb981e54fe4cc6f7d527d9171f99a4c434a87..2a83e8a758f8d17d2c52b44354d2d53ae0d58529 100644 --- a/app/models.py +++ b/app/models.py @@ -961,9 +961,11 @@ class Task(db.Model): # Use job id generated by RQ id = db.Column(postgresql.UUID, primary_key=True) created_at = db.Column(db.DateTime, default=utcnow()) + ended_at = db.Column(db.DateTime) name = db.Column(db.Text, nullable=False, index=True) command = db.Column(db.Text) status = db.Column(db.Enum(JobStatus, name='job_status')) + awx_job_id = db.Column(db.Integer) user_id = db.Column(db.Integer, db.ForeignKey('user_account.id'), nullable=False, default=utils.fetch_current_user_id) @@ -973,10 +975,12 @@ class Task(db.Model): def to_dict(self): return { 'id': self.id, - 'created_at': utils.format_field(self.created_at), 'name': self.name, + 'created_at': utils.format_field(self.created_at), + 'ended_at': utils.format_field(self.ended_at), + 'status': self.status.name, + 'awx_job_id': self.awx_job_id, 'command': self.command, - 'status': self.status, 'user': str(self.user), } diff --git a/app/task/views.py b/app/task/views.py index ad3f42758d05763277cf0626b1ecae45d0eb9f69..19508230cdde91b276b9b8a2324ac8916a85d5f2 100644 --- a/app/task/views.py +++ b/app/task/views.py @@ -11,7 +11,7 @@ This module implements the task blueprint. """ from flask import Blueprint, render_template, jsonify from flask_login import login_required, current_user -from .. import utils, models +from .. import models bp = Blueprint('task', __name__) @@ -32,11 +32,5 @@ def view_task(id_): @bp.route('/_retrieve_tasks') @login_required def retrieve_tasks(): - data = [(task.id, - task.name, - utils.format_field(task.created_at), - task.status.name, - task.command, - str(task.user)) - for task in current_user.get_tasks()] + data = [list(task.to_dict().values()) for task in current_user.get_tasks()] return jsonify(data=data) diff --git a/app/tasks.py b/app/tasks.py index d54680671ee64f5750ee40f4bec99753c027abe4..c558b83016ee529b4d8e34256cffef1fe2da7b69 100644 --- a/app/tasks.py +++ b/app/tasks.py @@ -12,7 +12,7 @@ This module implements tasks to run. import time import tower_cli from flask import current_app -from rq import Worker +from rq import Worker, get_current_job from .extensions import db from . import utils, models @@ -23,7 +23,7 @@ class TaskWorker(Worker): the task status in the CSEntry database """ - def update_task_status(self, job, status): + def update_task_attribute(self, job, name, value): # The task is created after enqueueing the job. # If the job is processed very quickly, the task might # not be found in the database. We wait up to 3 seconds. @@ -35,21 +35,23 @@ class TaskWorker(Worker): self.log.warning('task not found...') time.sleep(1) else: - self.log.error(f'Task {job.id} not found! Task status not updated!') + self.log.error(f'Task {job.id} not found! Task attribute not updated!') return - task.status = status + setattr(task, name, value) db.session.commit() def move_to_failed_queue(self, job, *exc_info): - self.update_task_status(job, status=models.JobStatus.FAILED) + self.update_task_attribute(job, 'ended_at', job.ended_at) + self.update_task_attribute(job, 'status', models.JobStatus.FAILED) super().move_to_failed_queue(job, *exc_info) def handle_job_success(self, job, queue, started_job_registry): - self.update_task_status(job, status=models.JobStatus.FINISHED) + self.update_task_attribute(job, 'ended_at', job.ended_at) + self.update_task_attribute(job, 'status', models.JobStatus.FINISHED) super().handle_job_success(job, queue, started_job_registry) def prepare_job_execution(self, job): - self.update_task_status(job, status=models.JobStatus.STARTED) + self.update_task_attribute(job, 'status', models.JobStatus.STARTED) super().prepare_job_execution(job) @@ -118,7 +120,8 @@ def trigger_core_services_update(): return task -def launch_job_template(job_template, monitor=True, **kwargs): +def launch_job_template(job_template, **kwargs): + rq_job = get_current_job() if (job_template in (current_app.config['AWX_CREATE_VIOC'], current_app.config['AWX_CREATE_VM']) and not current_app.config.get('AWX_VM_CREATION_ENABLED', False)): current_app.logger.info('AWX VM creation is disabled. Not sending any request.') @@ -126,6 +129,13 @@ def launch_job_template(job_template, monitor=True, **kwargs): if not current_app.config.get('AWX_JOB_ENABLED', False): current_app.logger.info('AWX job is disabled. Not sending any request.') return 'AWX job not triggered' + # Launch the AWX job resource = tower_cli.get_resource('job') - result = resource.launch(job_template=job_template, monitor=monitor, **kwargs) + result = resource.launch(job_template=job_template, **kwargs) + # Save the AWX job id in the task + task = models.Task.query.get(rq_job.id) + task.awx_job_id = result['id'] + db.session.commit() + # Monitor the job until done + result = resource.monitor(pk=result['id']) return result diff --git a/app/templates/task/tasks.html b/app/templates/task/tasks.html index d6a4159c8572cdebaf67818b83517b031a99a505..799be141fd245ad35e531d0cb3413feb017e1cb2 100644 --- a/app/templates/task/tasks.html +++ b/app/templates/task/tasks.html @@ -21,7 +21,9 @@ <th>Id</th> <th>Name</th> <th>Created at</th> + <th>Ended at</th> <th>Status</th> + <th>AWX job</th> <th>Command</th> <th>User</th> </tr> diff --git a/app/templates/task/view_task.html b/app/templates/task/view_task.html index ff1bee2abfcbbd64ff1538f52b88d639d4bf0449..7823a366f4c8115d38d328ec005c4796ea71e254 100644 --- a/app/templates/task/view_task.html +++ b/app/templates/task/view_task.html @@ -18,8 +18,12 @@ <dd class="col-sm-9">{{ task.name }}</dd> <dt class="col-sm-3">Created at</dt> <dd class="col-sm-9">{{ task.created_at }}</dd> + <dt class="col-sm-3">Ended at</dt> + <dd class="col-sm-9">{{ task.ended_at }}</dd> <dt class="col-sm-3">Status</dt> <dd class="col-sm-9">{{ task.status.name }}</dd> + <dt class="col-sm-3">AWX job</dt> + <dd class="col-sm-9">{{ task.awx_job_id }}</dd> <dt class="col-sm-3">Command</dt> <dd class="col-sm-9">{{ task.command }}</dd> <dt class="col-sm-3">User</dt> diff --git a/migrations/versions/c0b8036078e7_add_fields_to_task_table.py b/migrations/versions/c0b8036078e7_add_fields_to_task_table.py new file mode 100644 index 0000000000000000000000000000000000000000..1ac53cb33bd916f1a8aab7dd65b11b8810d82888 --- /dev/null +++ b/migrations/versions/c0b8036078e7_add_fields_to_task_table.py @@ -0,0 +1,26 @@ +"""add fields to task table + +Revision ID: c0b8036078e7 +Revises: 7d0d580cdb1a +Create Date: 2018-07-02 11:45:28.255006 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'c0b8036078e7' +down_revision = '7d0d580cdb1a' +branch_labels = None +depends_on = None + + +def upgrade(): + op.add_column('task', sa.Column('awx_job_id', sa.Integer(), nullable=True)) + op.add_column('task', sa.Column('ended_at', sa.DateTime(), nullable=True)) + + +def downgrade(): + op.drop_column('task', 'ended_at') + op.drop_column('task', 'awx_job_id')