1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Job Scheduling WIP

This commit is contained in:
kkthxbye-code
2022-09-23 06:45:40 +02:00
parent c8671ce8e8
commit cbb3378d10
7 changed files with 81 additions and 1 deletions

View File

@ -139,6 +139,7 @@ class LogLevelChoices(ChoiceSet):
class JobResultStatusChoices(ChoiceSet):
STATUS_PENDING = 'pending'
STATUS_SCHEDULED = 'pending'
STATUS_RUNNING = 'running'
STATUS_COMPLETED = 'completed'
STATUS_ERRORED = 'errored'
@ -146,6 +147,7 @@ class JobResultStatusChoices(ChoiceSet):
CHOICES = (
(STATUS_PENDING, 'Pending'),
(STATUS_SCHEDULED, 'Pending'),
(STATUS_RUNNING, 'Running'),
(STATUS_COMPLETED, 'Completed'),
(STATUS_ERRORED, 'Errored'),

View File

@ -16,6 +16,7 @@ __all__ = (
'ConfigContextFilterSet',
'ContentTypeFilterSet',
'CustomFieldFilterSet',
'JobResultFilterSet',
'CustomLinkFilterSet',
'ExportTemplateFilterSet',
'ImageAttachmentFilterSet',
@ -86,6 +87,26 @@ class CustomFieldFilterSet(BaseFilterSet):
Q(description__icontains=value)
)
class JobResultFilterSet(BaseFilterSet):
q = django_filters.CharFilter(
method='search',
label='Search',
)
# TODO: Add filters
class Meta:
model = JobResult
fields = [
'id', 'name', 'obj_type', 'created', 'completed', 'user', 'status'
]
def search(self, queryset, name, value):
if not value.strip():
return queryset
return queryset.filter(
Q(name__icontains=value)
)
class CustomLinkFilterSet(BaseFilterSet):
q = django_filters.CharFilter(

View File

@ -19,6 +19,7 @@ from virtualization.models import Cluster, ClusterGroup, ClusterType
__all__ = (
'ConfigContextFilterForm',
'CustomFieldFilterForm',
'JobResultFilterForm',
'CustomLinkFilterForm',
'ExportTemplateFilterForm',
'JournalEntryFilterForm',
@ -65,6 +66,13 @@ class CustomFieldFilterForm(FilterForm):
)
class JobResultFilterForm(FilterForm):
fieldsets = (
(None, ('q',)),
#('Attributes', ('type', 'content_type_id', 'group_name', 'weight', 'required', 'ui_visibility')),
)
class CustomLinkFilterForm(FilterForm):
fieldsets = (
(None, ('q',)),

View File

@ -509,12 +509,18 @@ class JobResult(models.Model):
unique=True
)
objects = RestrictedQuerySet.as_manager()
class Meta:
ordering = ['obj_type', 'name', '-created']
def __str__(self):
return str(self.job_id)
def get_absolute_url(self):
# TODO: Fix this to point the right place
return reverse('virtualization:clustertype', args=[self.pk])
@property
def duration(self):
if not self.completed:
@ -546,7 +552,7 @@ class JobResult(models.Model):
args: additional args passed to the callable
kwargs: additional kargs passed to the callable
"""
job_result = cls.objects.create(
job_result: JobResult = cls.objects.create(
name=name,
obj_type=obj_type,
user=user,
@ -556,6 +562,9 @@ class JobResult(models.Model):
queue = django_rq.get_queue("default")
if schedule_at := kwargs.pop("schedule_at", None):
job_result.status = JobResultStatusChoices.STATUS_SCHEDULED
job_result.save()
queue.enqueue_at(schedule_at, func, job_id=str(job_result.job_id), job_result=job_result, **kwargs)
else:
queue.enqueue(func, job_id=str(job_result.job_id), job_result=job_result, **kwargs)

View File

@ -8,6 +8,7 @@ from .template_code import *
__all__ = (
'ConfigContextTable',
'CustomFieldTable',
'JobResultTable',
'CustomLinkTable',
'ExportTemplateTable',
'JournalEntryTable',
@ -39,6 +40,30 @@ class CustomFieldTable(NetBoxTable):
default_columns = ('pk', 'name', 'content_types', 'label', 'group_name', 'type', 'required', 'description')
#
# Custom fields
#
class JobResultTable(NetBoxTable):
name = tables.Column(
linkify=True
)
#obj_type = columns.ContentTypesColumn()
required = columns.BooleanColumn()
ui_visibility = columns.ChoiceFieldColumn(verbose_name="UI visibility")
actions = columns.ActionsColumn(
actions=() # TODO: Delete
)
class Meta(NetBoxTable.Meta):
model = JobResult
fields = (
'pk', 'id', 'name', 'obj_type', 'created', 'completed', 'user', 'status', 'job_id',
)
default_columns = ('pk', 'id', 'name', 'obj_type', 'created', 'completed', 'user', 'status', 'job_id')
#
# Custom links
#

View File

@ -103,6 +103,10 @@ urlpatterns = [
path('reports/results/<int:job_result_pk>/', views.ReportResultView.as_view(), name='report_result'),
re_path(r'^reports/(?P<module>.([^.]+)).(?P<name>.(.+))/', views.ReportView.as_view(), name='report'),
# Job results
path('job-results/', views.JobResultListView.as_view(), name='jobresult_view'),
# path('custom-fields/<int:pk>/', views.CustomFieldView.as_view(), name='customfield'),
# Scripts
path('scripts/', views.ScriptListView.as_view(), name='script_list'),
path('scripts/results/<int:job_result_pk>/', views.ScriptResultView.as_view(), name='script_result'),

View File

@ -775,3 +775,14 @@ class ScriptResultView(ContentTypePermissionRequiredMixin, GetScriptMixin, View)
'result': result,
'class_name': script.__class__.__name__
})
#
# Job results
#
class JobResultListView(generic.ObjectListView):
queryset = JobResult.objects.all()
filterset = filtersets.JobResultFilterSet
filterset_form = forms.JobResultFilterForm
table = tables.JobResultTable