* Replace plugins list with an overall system status view * Enable export of system status data
This commit is contained in:
parent
a9b311b100
commit
8e1c2ecd92
|
@ -35,5 +35,5 @@ class PluginTable(BaseTable):
|
|||
'name', 'version', 'package', 'author', 'author_email', 'description',
|
||||
)
|
||||
default_columns = (
|
||||
'name', 'version', 'package', 'author', 'author_email', 'description',
|
||||
'name', 'version', 'package', 'description',
|
||||
)
|
||||
|
|
|
@ -43,9 +43,6 @@ urlpatterns = (
|
|||
path('config-revisions/<int:pk>/restore/', views.ConfigRevisionRestoreView.as_view(), name='configrevision_restore'),
|
||||
path('config-revisions/<int:pk>/', include(get_model_urls('core', 'configrevision'))),
|
||||
|
||||
# Configuration
|
||||
path('config/', views.ConfigView.as_view(), name='config'),
|
||||
|
||||
# Plugins
|
||||
path('plugins/', views.PluginListView.as_view(), name='plugin_list'),
|
||||
# System
|
||||
path('system/', views.SystemView.as_view(), name='system'),
|
||||
)
|
||||
|
|
|
@ -1,14 +1,19 @@
|
|||
import json
|
||||
import platform
|
||||
|
||||
from django import __version__ as DJANGO_VERSION
|
||||
from django.apps import apps
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.mixins import UserPassesTestMixin
|
||||
from django.core.cache import cache
|
||||
from django.http import HttpResponseForbidden, Http404
|
||||
from django.db import connection, ProgrammingError
|
||||
from django.http import HttpResponse, HttpResponseForbidden, Http404
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.generic import View
|
||||
from django_rq.queues import get_queue_by_index, get_redis_connection
|
||||
from django_rq.queues import get_connection, get_queue_by_index, get_redis_connection
|
||||
from django_rq.settings import QUEUES_MAP, QUEUES_LIST
|
||||
from django_rq.utils import get_jobs, get_statistics, stop_jobs
|
||||
from rq import requeue_job
|
||||
|
@ -175,20 +180,6 @@ class JobBulkDeleteView(generic.BulkDeleteView):
|
|||
# Config Revisions
|
||||
#
|
||||
|
||||
class ConfigView(generic.ObjectView):
|
||||
queryset = ConfigRevision.objects.all()
|
||||
|
||||
def get_object(self, **kwargs):
|
||||
revision_id = cache.get('config_version')
|
||||
try:
|
||||
return ConfigRevision.objects.get(pk=revision_id)
|
||||
except ConfigRevision.DoesNotExist:
|
||||
# Fall back to using the active config data if no record is found
|
||||
return ConfigRevision(
|
||||
data=get_config().defaults
|
||||
)
|
||||
|
||||
|
||||
class ConfigRevisionListView(generic.ObjectListView):
|
||||
queryset = ConfigRevision.objects.all()
|
||||
filterset = filtersets.ConfigRevisionFilterSet
|
||||
|
@ -527,21 +518,69 @@ class WorkerView(BaseRQView):
|
|||
# Plugins
|
||||
#
|
||||
|
||||
class PluginListView(UserPassesTestMixin, View):
|
||||
class SystemView(UserPassesTestMixin, View):
|
||||
|
||||
def test_func(self):
|
||||
return self.request.user.is_staff
|
||||
|
||||
def get(self, request):
|
||||
|
||||
# System stats
|
||||
psql_version = db_name = db_size = None
|
||||
try:
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute("SELECT version()")
|
||||
psql_version = cursor.fetchone()[0]
|
||||
psql_version = psql_version.split('(')[0].strip()
|
||||
cursor.execute("SELECT current_database()")
|
||||
db_name = cursor.fetchone()[0]
|
||||
cursor.execute(f"SELECT pg_size_pretty(pg_database_size('{db_name}'))")
|
||||
db_size = cursor.fetchone()[0]
|
||||
except (ProgrammingError, IndexError):
|
||||
pass
|
||||
stats = {
|
||||
'netbox_version': settings.VERSION,
|
||||
'django_version': DJANGO_VERSION,
|
||||
'python_version': platform.python_version(),
|
||||
'postgresql_version': psql_version,
|
||||
'database_name': db_name,
|
||||
'database_size': db_size,
|
||||
'rq_worker_count': Worker.count(get_connection('default')),
|
||||
}
|
||||
|
||||
# Plugins
|
||||
plugins = [
|
||||
# Look up app config by package name
|
||||
apps.get_app_config(plugin.rsplit('.', 1)[-1]) for plugin in settings.PLUGINS
|
||||
]
|
||||
table = tables.PluginTable(plugins, user=request.user)
|
||||
table.configure(request)
|
||||
|
||||
return render(request, 'core/plugin_list.html', {
|
||||
'plugins': plugins,
|
||||
'active_tab': 'api-tokens',
|
||||
'table': table,
|
||||
# Configuration
|
||||
try:
|
||||
config = ConfigRevision.objects.get(pk=cache.get('config_version'))
|
||||
except ConfigRevision.DoesNotExist:
|
||||
# Fall back to using the active config data if no record is found
|
||||
config = ConfigRevision(data=get_config().defaults)
|
||||
|
||||
# Raw data export
|
||||
if 'export' in request.GET:
|
||||
data = {
|
||||
**stats,
|
||||
'plugins': {
|
||||
plugin.name: plugin.version for plugin in plugins
|
||||
},
|
||||
'config': {
|
||||
k: config.data[k] for k in sorted(config.data)
|
||||
},
|
||||
}
|
||||
response = HttpResponse(json.dumps(data, indent=4), content_type='text/json')
|
||||
response['Content-Disposition'] = 'attachment; filename="netbox.json"'
|
||||
return response
|
||||
|
||||
plugins_table = tables.PluginTable(plugins, orderable=False)
|
||||
plugins_table.configure(request)
|
||||
|
||||
return render(request, 'core/system.html', {
|
||||
'stats': stats,
|
||||
'plugins_table': plugins_table,
|
||||
'config': config,
|
||||
})
|
||||
|
|
|
@ -420,27 +420,17 @@ ADMIN_MENU = Menu(
|
|||
),
|
||||
),
|
||||
),
|
||||
MenuGroup(
|
||||
label=_('Configuration'),
|
||||
items=(
|
||||
MenuItem(
|
||||
link='core:config',
|
||||
link_text=_('Current Config'),
|
||||
permissions=['core.view_configrevision']
|
||||
),
|
||||
MenuItem(
|
||||
link='core:configrevision_list',
|
||||
link_text=_('Config Revisions'),
|
||||
permissions=['core.view_configrevision']
|
||||
),
|
||||
),
|
||||
),
|
||||
MenuGroup(
|
||||
label=_('System'),
|
||||
items=(
|
||||
MenuItem(
|
||||
link='core:plugin_list',
|
||||
link_text=_('Plugins')
|
||||
link='core:system',
|
||||
link_text=_('System')
|
||||
),
|
||||
MenuItem(
|
||||
link='core:configrevision_list',
|
||||
link_text=_('Configuration History'),
|
||||
permissions=['core.view_configrevision']
|
||||
),
|
||||
MenuItem(
|
||||
link='core:background_queue_list',
|
||||
|
|
|
@ -32,163 +32,8 @@
|
|||
<div class="row">
|
||||
<div class="col col-md-12">
|
||||
<div class="card">
|
||||
<h5 class="card-header">{% trans "Rack Elevations" %}</h5>
|
||||
<table class="table table-hover attr-table">
|
||||
<tr>
|
||||
<th scope="row">{% trans "Default unit height" %}</th>
|
||||
<td>{{ object.data.RACK_ELEVATION_DEFAULT_UNIT_HEIGHT }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "Default unit width" %}</th>
|
||||
<td>{{ object.data.RACK_ELEVATION_DEFAULT_UNIT_WIDTH }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h5 class="card-header">{% trans "Power Feeds" %}</h5>
|
||||
<table class="table table-hover attr-table">
|
||||
<tr>
|
||||
<th scope="row">{% trans "Default voltage" %}</th>
|
||||
<td>{{ object.data.POWERFEED_DEFAULT_VOLTAGE }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "Default amperage" %}</th>
|
||||
<td>{{ object.data.POWERFEED_DEFAULT_AMPERAGE }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "Default max utilization" %}</th>
|
||||
<td>{{ object.data.POWERFEED_DEFAULT_MAX_UTILIZATION }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h5 class="card-header">{% trans "IPAM" %}</h5>
|
||||
<table class="table table-hover attr-table">
|
||||
<tr>
|
||||
<th scope="row">{% trans "Enforce global unique" %}</th>
|
||||
<td>{{ object.data.ENFORCE_GLOBAL_UNIQUE }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "Prefer IPv4" %}</th>
|
||||
<td>{{ object.data.PREFER_IPV4 }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h5 class="card-header">{% trans "Security" %}</h5>
|
||||
<table class="table table-hover attr-table">
|
||||
<tr>
|
||||
<th scope="row">{% trans "Allowed URL schemes" %}</th>
|
||||
<td>{{ object.data.ALLOWED_URL_SCHEMES|join:", "|placeholder }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h5 class="card-header">{% trans "Banners" %}</h5>
|
||||
<table class="table table-hover attr-table">
|
||||
<tr>
|
||||
<th scope="row">{% trans "Login banner" %}</th>
|
||||
<td>{{ object.data.BANNER_LOGIN }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "Maintenance banner" %}</th>
|
||||
<td>{{ object.data.BANNER_MAINTENANCE }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "Top banner" %}</th>
|
||||
<td>{{ object.data.BANNER_TOP }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "Bottom banner" %}</th>
|
||||
<td>{{ object.data.BANNER_BOTTOM }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h5 class="card-header">{% trans "Pagination" %}</h5>
|
||||
<table class="table table-hover attr-table">
|
||||
<tr>
|
||||
<th scope="row">{% trans "Paginate count" %}</th>
|
||||
<td>{{ object.data.PAGINATE_COUNT }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "Max page size" %}</th>
|
||||
<td>{{ object.data.MAX_PAGE_SIZE }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h5 class="card-header">{% trans "Validation" %}</h5>
|
||||
<table class="table table-hover attr-table">
|
||||
<tr>
|
||||
<th scope="row">{% trans "Custom validators" %}</th>
|
||||
{% if object.data.CUSTOM_VALIDATORS %}
|
||||
<td class="font-monospace">
|
||||
<pre>{{ object.data.CUSTOM_VALIDATORS|json }}</pre>
|
||||
</td>
|
||||
{% else %}
|
||||
<td>{{ ''|placeholder }}</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "Protection rules" %}</th>
|
||||
{% if object.data.PROTECTION_RULES %}
|
||||
<td>
|
||||
<pre>{{ object.data.PROTECTION_RULES|json }}</pre>
|
||||
</td>
|
||||
{% else %}
|
||||
<td>{{ ''|placeholder }}</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h5 class="card-header">{% trans "User Preferences" %}</h5>
|
||||
<table class="table table-hover attr-table">
|
||||
<tr>
|
||||
<th scope="row">{% trans "Default user preferences" %}</th>
|
||||
{% if object.data.DEFAULT_USER_PREFERENCES %}
|
||||
<td>
|
||||
<pre>{{ object.data.DEFAULT_USER_PREFERENCES|json }}</pre>
|
||||
</td>
|
||||
{% else %}
|
||||
<td>{{ ''|placeholder }}</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h5 class="card-header">{% trans "Miscellaneous" %}</h5>
|
||||
<table class="table table-hover attr-table">
|
||||
<tr>
|
||||
<th scope="row">{% trans "Maintenance mode" %}</th>
|
||||
<td>{{ object.data.MAINTENANCE_MODE }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "GraphQL enabled" %}</th>
|
||||
<td>{{ object.data.GRAPHQL_ENABLED }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "Changelog retention" %}</th>
|
||||
<td>{{ object.data.CHANGELOG_RETENTION }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "Job retention" %}</th>
|
||||
<td>{{ object.data.JOB_RETENTION }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "Maps URL" %}</th>
|
||||
<td>{{ object.data.MAPS_URL }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h5 class="card-header">{% trans "Configuration Data" %}</h5>
|
||||
{% include 'core/inc/config_data.html' with config=config.data %}
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
{% load i18n %}
|
||||
|
||||
<table class="table table-hover attr-table">
|
||||
|
||||
{# Rack elevations #}
|
||||
<tr>
|
||||
<td colspan="2" class="bg-secondary-subtle fs-5 fw-bold border-0 py-1">{% trans "Rack elevations" %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" class="ps-3">{% trans "Default unit height" %}</th>
|
||||
<td>{{ config.RACK_ELEVATION_DEFAULT_UNIT_HEIGHT }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" class="border-0 ps-3">{% trans "Default unit width" %}</th>
|
||||
<td class="border-0">{{ config.RACK_ELEVATION_DEFAULT_UNIT_WIDTH }}</td>
|
||||
</tr>
|
||||
|
||||
{# Power feeds #}
|
||||
<tr>
|
||||
<td colspan="2" class="bg-secondary-subtle fs-5 fw-bold border-0 py-1">{% trans "Power feeds" %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" class="ps-3">{% trans "Default voltage" %}</th>
|
||||
<td>{{ config.POWERFEED_DEFAULT_VOLTAGE }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" class="ps-3">{% trans "Default amperage" %}</th>
|
||||
<td>{{ config.POWERFEED_DEFAULT_AMPERAGE }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" class="border-0 ps-3">{% trans "Default max utilization" %}</th>
|
||||
<td class="border-0">{{ config.POWERFEED_DEFAULT_MAX_UTILIZATION }}</td>
|
||||
</tr>
|
||||
|
||||
{# IPAM #}
|
||||
<tr>
|
||||
<td colspan="2" class="bg-secondary-subtle fs-5 fw-bold border-0 py-1">{% trans "IPAM" %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" class="ps-3">{% trans "Enforce global unique" %}</th>
|
||||
<td>{% checkmark config.ENFORCE_GLOBAL_UNIQUE %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" class="border-0 ps-3">{% trans "Prefer IPv4" %}</th>
|
||||
<td class="border-0">{% checkmark config.PREFER_IPV4 %}</td>
|
||||
</tr>
|
||||
|
||||
{# Security #}
|
||||
<tr>
|
||||
<td colspan="2" class="bg-secondary-subtle fs-5 fw-bold border-0 py-1">{% trans "Security" %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" class="border-0 ps-3">{% trans "Allowed URL schemes" %}</th>
|
||||
<td class="border-0">{{ config.ALLOWED_URL_SCHEMES|join:", "|placeholder }}</td>
|
||||
</tr>
|
||||
|
||||
{# Banners #}
|
||||
<tr>
|
||||
<td colspan="2" class="bg-secondary-subtle fs-5 fw-bold border-0 py-1">{% trans "Banners" %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" class="ps-3">{% trans "Login banner" %}</th>
|
||||
<td>{{ config.BANNER_LOGIN|placeholder }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" class="ps-3">{% trans "Maintenance banner" %}</th>
|
||||
<td>{{ config.BANNER_MAINTENANCE|placeholder }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" class="ps-3">{% trans "Top banner" %}</th>
|
||||
<td>{{ config.BANNER_TOP|placeholder }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" class="border-0 ps-3">{% trans "Bottom banner" %}</th>
|
||||
<td class="border-0">{{ config.BANNER_BOTTOM|placeholder }}</td>
|
||||
</tr>
|
||||
|
||||
{# Pagination #}
|
||||
<tr>
|
||||
<td colspan="2" class="bg-secondary-subtle fs-5 fw-bold border-0 py-1">{% trans "Pagination" %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" class="ps-3">{% trans "Paginate count" %}</th>
|
||||
<td>{{ config.PAGINATE_COUNT }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" class="border-0 ps-3">{% trans "Max page size" %}</th>
|
||||
<td class="border-0">{{ config.MAX_PAGE_SIZE }}</td>
|
||||
</tr>
|
||||
|
||||
{# Validation #}
|
||||
<tr>
|
||||
<td colspan="2" class="bg-secondary-subtle fs-5 fw-bold border-0 py-1">{% trans "Validation" %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" class="ps-3">{% trans "Custom validators" %}</th>
|
||||
{% if config.CUSTOM_VALIDATORS %}
|
||||
<td><pre>{{ config.CUSTOM_VALIDATORS|json }}</pre></td>
|
||||
{% else %}
|
||||
<td>{{ ''|placeholder }}</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" class="border-0 ps-3">{% trans "Protection rules" %}</th>
|
||||
{% if config.PROTECTION_RULES %}
|
||||
<td class="border-0"><pre>{{ config.PROTECTION_RULES|json }}</pre></td>
|
||||
{% else %}
|
||||
<td class="border-0">{{ ''|placeholder }}</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
|
||||
{# User Preferences #}
|
||||
<tr>
|
||||
<td colspan="2" class="bg-secondary-subtle fs-5 fw-bold border-0 py-1">{% trans "User preferences" %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" class="border-0 ps-3">{% trans "Default preferences" %}</th>
|
||||
{% if config.DEFAULT_USER_PREFERENCES %}
|
||||
<td class="border-0"><pre>{{ config.DEFAULT_USER_PREFERENCES|json }}</pre></td>
|
||||
{% else %}
|
||||
<td class="border-0">{{ ''|placeholder }}</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
|
||||
{# Miscellaneous #}
|
||||
<tr>
|
||||
<td colspan="2" class="bg-secondary-subtle fs-5 fw-bold border-0 py-1">{% trans "Miscellaneous" %}</td>
|
||||
<tr>
|
||||
<th scope="row" class="ps-3">{% trans "Maintenance mode" %}</th>
|
||||
<td>{% checkmark config.MAINTENANCE_MODE %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" class="ps-3">{% trans "GraphQL enabled" %}</th>
|
||||
<td>{% checkmark config.GRAPHQL_ENABLED %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" class="ps-3">{% trans "Changelog retention" %}</th>
|
||||
<td>{{ config.CHANGELOG_RETENTION }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" class="ps-3">{% trans "Job retention" %}</th>
|
||||
<td>{{ config.JOB_RETENTION }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row" class="border-0 ps-3">{% trans "Maps URL" %}</th>
|
||||
<td class="border-0">{{ config.MAPS_URL }}</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
|
@ -1,36 +0,0 @@
|
|||
{% extends 'generic/_base.html' %}
|
||||
{% load buttons %}
|
||||
{% load helpers %}
|
||||
{% load i18n %}
|
||||
{% load render_table from django_tables2 %}
|
||||
|
||||
{% block title %}{% trans "Plugins" %}{% endblock %}
|
||||
|
||||
{% block tabs %}
|
||||
<ul class="nav nav-tabs px-3">
|
||||
<li class="nav-item" role="presentation">
|
||||
<a class="nav-link active" role="tab">{% trans "Plugins" %}</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endblock tabs %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row mb-3">
|
||||
<div class="col-auto ms-auto d-print-none">
|
||||
{# Table configuration button #}
|
||||
<div class="table-configure input-group">
|
||||
<button type="button" data-bs-toggle="modal" title="{% trans "Configure Table" %}" data-bs-target="#ObjectTable_config" class="btn">
|
||||
<i class="mdi mdi-cog"></i> {% trans "Configure Table" %}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
{% render_table table %}
|
||||
</div>
|
||||
{% endblock content %}
|
||||
|
||||
{% block modals %}
|
||||
{% table_config_form table table_name="ObjectTable" %}
|
||||
{% endblock modals %}
|
|
@ -0,0 +1,92 @@
|
|||
{% extends 'generic/_base.html' %}
|
||||
{% load buttons %}
|
||||
{% load helpers %}
|
||||
{% load i18n %}
|
||||
{% load render_table from django_tables2 %}
|
||||
|
||||
{% block title %}{% trans "System" %}{% endblock %}
|
||||
|
||||
{% block controls %}
|
||||
<a href="?export=true" class="btn btn-purple">
|
||||
<i class="mdi mdi-download"></i> {% trans "Export" %}
|
||||
</a>
|
||||
{% endblock controls %}
|
||||
|
||||
{% block tabs %}
|
||||
<ul class="nav nav-tabs px-3">
|
||||
<li class="nav-item" role="presentation">
|
||||
<a class="nav-link active" role="tab">{% trans "Status" %}</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endblock tabs %}
|
||||
|
||||
{% block content %}
|
||||
{# System status #}
|
||||
<div class="row mb-3">
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<h5 class="card-header">{% trans "System Status" %}</h5>
|
||||
<table class="table table-hover attr-table">
|
||||
<tr>
|
||||
<th scope="row">{% trans "NetBox version" %}</th>
|
||||
<td>{{ stats.netbox_version }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "Django version" %}</th>
|
||||
<td>{{ stats.django_version }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "PotsgreSQL version" %}</th>
|
||||
<td>{{ stats.postgresql_version }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "Database name" %}</th>
|
||||
<td>{{ stats.database_name }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "Database size" %}</th>
|
||||
<td>
|
||||
{% if stats.database_size %}
|
||||
{{ stats.database_size }}
|
||||
{% else %}
|
||||
<span class="text-muted">{% trans "Unavailable" %}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "RQ workers" %}</th>
|
||||
<td>
|
||||
<a href="{% url 'core:background_queue_list' %}">{{ stats.rq_worker_count }}</a>
|
||||
({% trans "default queue" %})
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "System time" %}</th>
|
||||
<td>{% now 'Y-m-d H:i:s T' %}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Plugins #}
|
||||
<div class="row mb-3">
|
||||
<div class="col col-md-12">
|
||||
<div class="card">
|
||||
<h5 class="card-header">{% trans "Plugins" %}</h5>
|
||||
{% render_table plugins_table %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Configuration #}
|
||||
<div class="row mb-3">
|
||||
<div class="col col-md-12">
|
||||
<div class="card">
|
||||
<h5 class="card-header">{% trans "Current Configuration" %}</h5>
|
||||
{% include 'core/inc/config_data.html' with config=config.data %}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
Loading…
Reference in New Issue