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:
@ -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'),
|
||||
|
@ -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(
|
||||
|
@ -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',)),
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
#
|
||||
|
@ -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'),
|
||||
|
@ -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
|
Reference in New Issue
Block a user