diff --git a/apps/ops/migrations/0033_auto_20221118_1431.py b/apps/ops/migrations/0033_auto_20221118_1431.py new file mode 100644 index 000000000..70518eee6 --- /dev/null +++ b/apps/ops/migrations/0033_auto_20221118_1431.py @@ -0,0 +1,28 @@ +# Generated by Django 3.2.14 on 2022-11-18 06:31 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ops', '0032_auto_20221117_1848'), + ] + + operations = [ + migrations.AddField( + model_name='job', + name='crontab', + field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Regularly perform'), + ), + migrations.AddField( + model_name='job', + name='interval', + field=models.IntegerField(blank=True, default=24, null=True, verbose_name='Cycle perform'), + ), + migrations.AddField( + model_name='job', + name='is_periodic', + field=models.BooleanField(default=False), + ), + ] diff --git a/apps/ops/models/job.py b/apps/ops/models/job.py index 8897d6107..d5542970d 100644 --- a/apps/ops/models/job.py +++ b/apps/ops/models/job.py @@ -9,14 +9,16 @@ from django.utils.translation import gettext_lazy as _ from django.utils import timezone from celery import current_task +from common.const.choices import Trigger from common.db.models import BaseCreateUpdateModel __all__ = ["Job", "JobExecution"] from ops.ansible import JMSInventory, AdHocRunner, PlaybookRunner +from ops.mixin import PeriodTaskModelMixin -class Job(BaseCreateUpdateModel): +class Job(BaseCreateUpdateModel, PeriodTaskModelMixin): class Types(models.TextChoices): adhoc = 'adhoc', _('Adhoc') playbook = 'playbook', _('Playbook') @@ -48,6 +50,42 @@ class Job(BaseCreateUpdateModel): parameters_define = models.JSONField(default=dict, verbose_name=_('Parameters define')) comment = models.CharField(max_length=1024, default='', verbose_name=_('Comment'), null=True, blank=True) + @property + def last_execution(self): + return self.executions.last() + + @property + def date_last_run(self): + return self.last_execution.date_created if self.last_execution else None + + @property + def summary(self): + summary = { + "total": 0, + "success": 0, + } + for execution in self.executions.all(): + summary["total"] += 1 + if execution.is_success: + summary["success"] += 1 + return summary + + @property + def average_time_cost(self): + total_cost = 0 + finished_count = self.executions.filter(status__in=['success', 'failed']).count() + for execution in self.executions.filter(status__in=['success', 'failed']).all(): + total_cost += execution.time_cost + return total_cost / finished_count if finished_count else 0 + + def get_register_task(self): + from ..tasks import run_ops_job + name = "run_ops_job_period_{}".format(str(self.id)[:8]) + task = run_ops_job.name + args = (str(self.id),) + kwargs = {} + return name, task, args, kwargs + @property def inventory(self): return JMSInventory(self.assets.all(), self.runas_policy, self.runas) @@ -72,7 +110,10 @@ class JobExecution(BaseCreateUpdateModel): def get_runner(self): inv = self.job.inventory inv.write_to_file(self.inventory_path) - extra_vars = json.loads(self.parameters) + if isinstance(self.parameters, str): + extra_vars = json.loads(self.parameters) + else: + extra_vars = {} if self.job.type == 'adhoc': runner = AdHocRunner( diff --git a/apps/ops/serializers/job.py b/apps/ops/serializers/job.py index 2771e2a7f..389b92ce2 100644 --- a/apps/ops/serializers/job.py +++ b/apps/ops/serializers/job.py @@ -2,24 +2,26 @@ from django.db import transaction from rest_framework import serializers from common.drf.fields import ReadableHiddenField +from ops.mixin import PeriodTaskSerializerMixin from ops.models import Job, JobExecution _all_ = [] -class JobSerializer(serializers.ModelSerializer): +class JobSerializer(serializers.ModelSerializer, PeriodTaskSerializerMixin): owner = ReadableHiddenField(default=serializers.CurrentUserDefault()) class Meta: model = Job - fields = [ - "id", "name", "instant", "type", "module", "args", "playbook", "assets", "runas_policy", "runas", "owner", + read_only_fields = ["id", "date_last_run", "date_created", "date_updated", "average_time_cost"] + fields = read_only_fields + [ + "name", "instant", "type", "module", "args", "playbook", "assets", "runas_policy", "runas", "owner", "parameters_define", "timeout", "chdir", "comment", - "date_created", - "date_updated" + "summary", + "is_periodic", "interval", "crontab" ] diff --git a/apps/ops/tasks.py b/apps/ops/tasks.py index c350cdb6b..841f759ff 100644 --- a/apps/ops/tasks.py +++ b/apps/ops/tasks.py @@ -25,7 +25,7 @@ logger = get_logger(__file__) @shared_task(soft_time_limit=60, queue="ansible", verbose_name=_("Run ansible task")) -def run_ops_job(job_id, **kwargs): +def run_ops_job(job_id): job = get_object_or_none(Job, id=job_id) execution = job.create_execution() try: