Просмотр исходного кода

Work on job scheduling:
* Added JobResult form filtersets
* Change housekeeping cleanup delete from `_raw_delete` to `delete` to make sure scheduled tasks are cancelled
* Change default sort of JobResult table to -created
* Added `delete` override to `JobResult` to remove scheduled tasks from RQ when a JobResult is deleted
* Updated js/css dist files. Will need to be redone when develop is merged to feature.

kkthxbye-code 3 лет назад
Родитель
Сommit
679a9e839b

+ 2 - 2
netbox/extras/choices.py

@@ -141,7 +141,7 @@ class LogLevelChoices(ChoiceSet):
 class JobResultStatusChoices(ChoiceSet):
 class JobResultStatusChoices(ChoiceSet):
 
 
     STATUS_PENDING = 'pending'
     STATUS_PENDING = 'pending'
-    STATUS_SCHEDULED = 'pending'
+    STATUS_SCHEDULED = 'scheduled'
     STATUS_RUNNING = 'running'
     STATUS_RUNNING = 'running'
     STATUS_COMPLETED = 'completed'
     STATUS_COMPLETED = 'completed'
     STATUS_ERRORED = 'errored'
     STATUS_ERRORED = 'errored'
@@ -149,7 +149,7 @@ class JobResultStatusChoices(ChoiceSet):
 
 
     CHOICES = (
     CHOICES = (
         (STATUS_PENDING, 'Pending'),
         (STATUS_PENDING, 'Pending'),
-        (STATUS_SCHEDULED, 'Pending'),
+        (STATUS_SCHEDULED, 'Scheduled'),
         (STATUS_RUNNING, 'Running'),
         (STATUS_RUNNING, 'Running'),
         (STATUS_COMPLETED, 'Completed'),
         (STATUS_COMPLETED, 'Completed'),
         (STATUS_ERRORED, 'Errored'),
         (STATUS_ERRORED, 'Errored'),

+ 3 - 2
netbox/extras/filtersets.py

@@ -87,6 +87,7 @@ class CustomFieldFilterSet(BaseFilterSet):
             Q(description__icontains=value)
             Q(description__icontains=value)
         )
         )
 
 
+
 class CustomLinkFilterSet(BaseFilterSet):
 class CustomLinkFilterSet(BaseFilterSet):
     q = django_filters.CharFilter(
     q = django_filters.CharFilter(
         method='search',
         method='search',
@@ -434,8 +435,8 @@ class JobResultFilterSet(BaseFilterSet):
         method='search',
         method='search',
         label='Search',
         label='Search',
     )
     )
-    created = django_filters.DateTimeFilter()
-    completed = django_filters.DateTimeFilter()
+    created = django_filters.DateTimeFromToRangeFilter()
+    completed = django_filters.DateTimeFromToRangeFilter()
     status = django_filters.MultipleChoiceFilter(
     status = django_filters.MultipleChoiceFilter(
         choices=JobResultStatusChoices,
         choices=JobResultStatusChoices,
         null_value=None
         null_value=None

+ 37 - 1
netbox/extras/forms/filtersets.py

@@ -69,7 +69,43 @@ class CustomFieldFilterForm(FilterForm):
 class JobResultFilterForm(FilterForm):
 class JobResultFilterForm(FilterForm):
     fieldsets = (
     fieldsets = (
         (None, ('q',)),
         (None, ('q',)),
-        #('Attributes', ('type', 'content_type_id', 'group_name', 'weight', 'required', 'ui_visibility')),
+        ('Attributes', ('obj_type', 'status')),
+        ('Creation', ('created_before', 'created_after', 'completed_before', 'completed_after', 'user')),
+    )
+
+    obj_type = ContentTypeChoiceField(
+        label=_('Object Type'),
+        queryset=ContentType.objects.all(),
+        limit_choices_to=FeatureQuery('job_results'),  # TODO: This doesn't actually work
+        required=False,
+    )
+    status = MultipleChoiceField(
+        choices=JobResultStatusChoices,
+        required=False
+    )
+    created_after = forms.DateTimeField(
+        required=False,
+        widget=DateTimePicker()
+    )
+    created_before = forms.DateTimeField(
+        required=False,
+        widget=DateTimePicker()
+    )
+    completed_after = forms.DateTimeField(
+        required=False,
+        widget=DateTimePicker()
+    )
+    completed_before = forms.DateTimeField(
+        required=False,
+        widget=DateTimePicker()
+    )
+    user = DynamicModelMultipleChoiceField(
+        queryset=User.objects.all(),
+        required=False,
+        label=_('User'),
+        widget=APISelectMultiple(
+            api_url='/api/users/users/',
+        )
     )
     )
 
 
 
 

+ 1 - 1
netbox/extras/forms/reports.py

@@ -13,4 +13,4 @@ class ReportForm(BootstrapMixin, forms.Form):
         widget=DateTimePicker(),
         widget=DateTimePicker(),
         label="Schedule at",
         label="Schedule at",
         help_text="Schedule execution of report to a set time",
         help_text="Schedule execution of report to a set time",
-    )
+    )

+ 1 - 1
netbox/extras/management/commands/housekeeping.py

@@ -81,7 +81,7 @@ class Command(BaseCommand):
                         ending=""
                         ending=""
                     )
                     )
                     self.stdout.flush()
                     self.stdout.flush()
-                JobResult.objects.filter(created__lt=cutoff)._raw_delete(using=DEFAULT_DB_ALIAS)
+                JobResult.objects.filter(created__lt=cutoff).delete(using=DEFAULT_DB_ALIAS)
                 if options['verbosity']:
                 if options['verbosity']:
                     self.stdout.write("Done.", self.style.SUCCESS)
                     self.stdout.write("Done.", self.style.SUCCESS)
             elif options['verbosity']:
             elif options['verbosity']:

+ 17 - 0
netbox/extras/migrations/0079_change_jobresult_order.py

@@ -0,0 +1,17 @@
+# Generated by Django 4.1.1 on 2022-10-09 18:37
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('extras', '0078_unique_constraints'),
+    ]
+
+    operations = [
+        migrations.AlterModelOptions(
+            name='jobresult',
+            options={'ordering': ['-created']},
+        ),
+    ]

+ 12 - 3
netbox/extras/models/models.py

@@ -528,13 +528,22 @@ class JobResult(models.Model):
     objects = RestrictedQuerySet.as_manager()
     objects = RestrictedQuerySet.as_manager()
 
 
     class Meta:
     class Meta:
-        ordering = ['obj_type', 'name', '-created']
+        ordering = ['-created']
 
 
     def __str__(self):
     def __str__(self):
         return str(self.job_id)
         return str(self.job_id)
 
 
+    def delete(self, *args, **kwargs):
+        queue = django_rq.get_queue("default")
+        job = queue.fetch_job(str(self.job_id))
+
+        if job:
+            job.cancel()
+
+        return super().delete(*args, **kwargs)
+
     def get_absolute_url(self):
     def get_absolute_url(self):
-        return reverse('extras:jobresult', args=[self.pk])
+        return reverse(f'extras:{self.obj_type.name}_result', args=[self.pk])
 
 
     @property
     @property
     def duration(self):
     def duration(self):
@@ -579,7 +588,7 @@ class JobResult(models.Model):
         if schedule_at := kwargs.pop("schedule_at", None):
         if schedule_at := kwargs.pop("schedule_at", None):
             job_result.status = JobResultStatusChoices.STATUS_SCHEDULED
             job_result.status = JobResultStatusChoices.STATUS_SCHEDULED
             job_result.save()
             job_result.save()
-            
+
             queue.enqueue_at(schedule_at, func, job_id=str(job_result.job_id), job_result=job_result, **kwargs)
             queue.enqueue_at(schedule_at, func, job_id=str(job_result.job_id), job_result=job_result, **kwargs)
         else:
         else:
             queue.enqueue(func, job_id=str(job_result.job_id), job_result=job_result, **kwargs)
             queue.enqueue(func, job_id=str(job_result.job_id), job_result=job_result, **kwargs)

+ 2 - 2
netbox/extras/tables/tables.py

@@ -56,9 +56,9 @@ class JobResultTable(NetBoxTable):
     class Meta(NetBoxTable.Meta):
     class Meta(NetBoxTable.Meta):
         model = JobResult
         model = JobResult
         fields = (
         fields = (
-            'pk', 'id', 'name', 'obj_type', 'created', 'completed', 'user', 'status', 'job_id',
+            'pk', 'id', 'name', 'obj_type', 'job_id', 'created', 'completed', 'user', 'status',
         )
         )
-        default_columns = ('pk', 'id', 'name', 'obj_type', 'created', 'completed', 'user', 'status', 'job_id')
+        default_columns = ('pk', 'id', 'name', 'obj_type', 'status', 'created', 'completed', 'user',)
 
 
 
 
 #
 #

+ 0 - 1
netbox/extras/urls.py

@@ -76,7 +76,6 @@ urlpatterns = [
 
 
     # Job results
     # Job results
     path('job-results/', views.JobResultListView.as_view(), name='jobresult_list'),
     path('job-results/', views.JobResultListView.as_view(), name='jobresult_list'),
-    path('job-results/<int:pk>/', views.JobResultView.as_view(), name='jobresult'),
     path('job-results/delete/', views.JobResultBulkDeleteView.as_view(), name='jobresult_bulk_delete'),
     path('job-results/delete/', views.JobResultBulkDeleteView.as_view(), name='jobresult_bulk_delete'),
     path('job-results/<int:pk>/delete/', views.JobResultDeleteView.as_view(), name='jobresult_delete'),
     path('job-results/<int:pk>/delete/', views.JobResultDeleteView.as_view(), name='jobresult_delete'),
 
 

+ 2 - 1
netbox/extras/views.py

@@ -815,6 +815,7 @@ class JobResultListView(generic.ObjectListView):
     table = tables.JobResultTable
     table = tables.JobResultTable
     actions = ('delete', 'bulk_delete', )
     actions = ('delete', 'bulk_delete', )
 
 
+
 class JobResultDeleteView(generic.ObjectDeleteView):
 class JobResultDeleteView(generic.ObjectDeleteView):
     queryset = JobResult.objects.all()
     queryset = JobResult.objects.all()
 
 
@@ -822,4 +823,4 @@ class JobResultDeleteView(generic.ObjectDeleteView):
 class JobResultBulkDeleteView(generic.BulkDeleteView):
 class JobResultBulkDeleteView(generic.BulkDeleteView):
     queryset = JobResult.objects.all()
     queryset = JobResult.objects.all()
     filterset = filtersets.JobResultFilterSet
     filterset = filtersets.JobResultFilterSet
-    table = tables.JobResultTable
+    table = tables.JobResultTable

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
netbox/project-static/dist/netbox-external.css


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
netbox/project-static/dist/netbox.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
netbox/project-static/dist/netbox.js.map


+ 0 - 60
netbox/templates/extras/jobresult.html

@@ -1,60 +0,0 @@
-{% extends 'generic/object.html' %}
-{% load helpers %}
-{% load plugins %}
-
-{% block title %}{{ object.name }} ({{object.job_id}}){% endblock %}
-
-{# JobResult does not support add/edit controls #}
-{% block controls %}{% endblock %}
-{% block subtitle %}{% endblock %}
-
-{% block content %}
-  <div class="row">
-    <div class="col col-md-6">
-      <div class="card">
-        <h5 class="card-header">
-          Tag
-        </h5>
-        <div class="card-body">
-          <table class="table table-hover panel-body attr-table">
-            <tr>
-              <th scope="row">Name</th>
-              <td>
-                {{ object.name }}
-              </td>
-            </tr>
-            <tr>
-              <th scope="row">Created</th>
-              <td>
-                  {{ object.created|annotated_date }}
-              </td>
-            </tr>
-            <tr>
-              <th scope="row">Completed</th>
-              <td>
-                  {{ object.completed|annotated_date }}
-              </td>
-            </tr>
-          </table>
-        </div>
-      </div>
-    </div>
-    <div class="col col-md-6">
-      <div class="card">
-        <h5 class="card-header">
-          TODO
-        </h5>
-        <div class="card-body">
-          <table class="table table-hover panel-body attr-table">
-            TODO
-          </table>
-        </div>
-      </div>
-    </div>
-  </div>
-  <div class="row">
-    <div class="col col-md-12">
-      {% plugin_full_width_page object %}
-    </div>
-  </div>
-{% endblock %}

Некоторые файлы не были показаны из-за большого количества измененных файлов