diff --git a/netbox/core/tables/tasks.py b/netbox/core/tables/tasks.py index 58713392a..4dc7d56ae 100644 --- a/netbox/core/tables/tasks.py +++ b/netbox/core/tables/tasks.py @@ -1,4 +1,5 @@ import django_tables2 as tables +from django_tables2.utils import A # alias for Accessor from django.utils.translation import gettext_lazy as _ from netbox.tables import NetBoxTable, columns @@ -6,21 +7,45 @@ from ..models import Job class BackgroundTasksTable(tables.Table): - name = tables.Column() - jobs = tables.Column(verbose_name=_("Queued Jobs")) + name = tables.LinkColumn("core:background_tasks_queues", args=[A("index")], verbose_name=_("Name")) + jobs = tables.LinkColumn("core:background_tasks_queues", args=[A("index")], verbose_name=_("Queued Jobs")) oldest_job_timestamp = tables.Column(verbose_name=_("Oldest Queued Job")) started_jobs = tables.Column(verbose_name=_("Active Jobs")) - deferred_jobs = tables.Column() - finished_jobs = tables.Column() - failed_jobs = tables.Column() - scheduled_jobs = tables.Column() - workers = tables.Column() - host = tables.Column(accessor="connection_kwargs__host") - port = tables.Column(accessor="connection_kwargs__port") - db = tables.Column(accessor="connection_kwargs__db") + deferred_jobs = tables.Column(verbose_name=_("Deferred Jobs")) + finished_jobs = tables.Column(verbose_name=_("Finished Jobs")) + failed_jobs = tables.Column(verbose_name=_("Failed Jobs")) + scheduled_jobs = tables.Column(verbose_name=_("Scheduled Jobs")) + workers = tables.Column(verbose_name=_("Workers")) + host = tables.Column(accessor="connection_kwargs__host", verbose_name=_("Host")) + port = tables.Column(accessor="connection_kwargs__port", verbose_name=_("Port")) + db = tables.Column(accessor="connection_kwargs__db", verbose_name=_("DB")) pid = tables.Column(accessor="scheduler__pid", verbose_name=_("Scheduler PID")) class Meta: attrs = { 'class': 'table table-hover object-list', } + + +class BackgroundTasksQueueTable(tables.Table): + # id = tables.LinkColumn("core:background_tasks_queues", args=[A("index")], verbose_name=_("ID")) + id = tables.Column(verbose_name=_("ID")) + created_at = tables.Column(verbose_name=_("Created")) + enqueued_at = tables.Column(verbose_name=_("Enqueued")) + ended_at = tables.Column(verbose_name=_("Ended")) + status = tables.Column(empty_values=(), verbose_name=_("Status")) + callable = tables.Column(empty_values=(), verbose_name=_("Callable")) + + class Meta: + attrs = { + 'class': 'table table-hover object-list', + } + + def render_status(self, value, record): + return record.get_status + + def render_callable(self, value, record): + try: + return record.func_name + except Exception as e: + return repr(e) diff --git a/netbox/core/urls.py b/netbox/core/urls.py index 2347a732b..00df16f05 100644 --- a/netbox/core/urls.py +++ b/netbox/core/urls.py @@ -26,7 +26,8 @@ urlpatterns = ( path('jobs//delete/', views.JobDeleteView.as_view(), name='job_delete'), # Background Tasks - path('tasks/', views.BackgroundTasksView.as_view(), name='background_tasks'), + path('background-tasks/', views.BackgroundTasksListView.as_view(), name='background_tasks_list'), + path('background-tasks/queues//', views.BackgroundTasksQueueListView.as_view(), name='background_tasks_queues'), # Config revisions path('config-revisions/', views.ConfigRevisionListView.as_view(), name='configrevision_list'), diff --git a/netbox/core/views.py b/netbox/core/views.py index f70fbfb3a..9a692a23f 100644 --- a/netbox/core/views.py +++ b/netbox/core/views.py @@ -2,6 +2,7 @@ from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin from django.core.cache import cache from django.http import HttpResponseForbidden +from django_rq.queues import get_queue_by_index from django_rq.utils import get_scheduler_statistics, get_statistics from django.shortcuts import get_object_or_404, redirect, render @@ -241,11 +242,28 @@ class ConfigRevisionRestoreView(ContentTypePermissionRequiredMixin, View): # -class BackgroundTasksView(LoginRequiredMixin, View): +class BackgroundTasksListView(LoginRequiredMixin, View): def get(self, request): table = tables.BackgroundTasksTable(get_statistics(run_maintenance_tasks=True)["queues"]) return render(request, 'core/background_tasks.html', { - 'active_tab': 'api-tokens', 'table': table, }) + + +class BackgroundTasksQueueListView(LoginRequiredMixin, View): + + def get(self, request, queue_index): + queue_index = int(queue_index) + queue = get_queue_by_index(queue_index) + + if queue.count > 0: + jobs = queue.get_jobs() + else: + jobs = [] + + table = tables.BackgroundTasksQueueTable(jobs) + return render(request, 'core/background_tasks_queue.html', { + 'table': table, + 'queue': queue, + }) diff --git a/netbox/netbox/navigation/menu.py b/netbox/netbox/navigation/menu.py index 3de1b68f9..b2a3017b1 100644 --- a/netbox/netbox/navigation/menu.py +++ b/netbox/netbox/navigation/menu.py @@ -357,7 +357,7 @@ OPERATIONS_MENU = Menu( permissions=['core.view_job'], ), MenuItem( - link='core:background_tasks', + link='core:background_tasks_list', link_text=_('Background Tasks'), permissions=['core.view_job'], ), diff --git a/netbox/templates/core/background_tasks.html b/netbox/templates/core/background_tasks.html index 6bef90cee..d2ad030bb 100644 --- a/netbox/templates/core/background_tasks.html +++ b/netbox/templates/core/background_tasks.html @@ -4,7 +4,7 @@ {% load i18n %} {% load render_table from django_tables2 %} -{% block title %}{% trans "Plugins" %}{% endblock %} +{% block title %}{% trans "Background Tasks" %}{% endblock %} {% block controls %}