mirror of
https://github.com/eduardogsilva/routerfleet.git
synced 2025-08-02 17:24:29 +02:00
Router availability display and history
This commit is contained in:
parent
23c4090ec1
commit
1f5bbf1608
8 changed files with 116 additions and 4 deletions
|
@ -1,3 +1,11 @@
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
from .models import RouterDownTime
|
||||||
|
|
||||||
# Register your models here.
|
|
||||||
|
class RouterDownTimeAdmin(admin.ModelAdmin):
|
||||||
|
list_display = ('router', 'start_time', 'end_time', 'total_down_time', 'updated', 'created', 'uuid')
|
||||||
|
search_fields = ('router', 'start_time', 'end_time', 'total_down_time', 'updated', 'created', 'uuid')
|
||||||
|
readonly_fields = ('updated', 'created', 'uuid')
|
||||||
|
|
||||||
|
|
||||||
|
admin.site.register(RouterDownTime, RouterDownTimeAdmin)
|
||||||
|
|
|
@ -7,8 +7,13 @@ class RouterDownTime(models.Model):
|
||||||
router = models.ForeignKey(Router, on_delete=models.CASCADE)
|
router = models.ForeignKey(Router, on_delete=models.CASCADE)
|
||||||
start_time = models.DateTimeField(blank=True, null=True)
|
start_time = models.DateTimeField(blank=True, null=True)
|
||||||
end_time = models.DateTimeField(blank=True, null=True)
|
end_time = models.DateTimeField(blank=True, null=True)
|
||||||
total_down_time = models.IntegerField(default=0) # minutes
|
total_down_time = models.IntegerField(default=0) # seconds
|
||||||
|
|
||||||
updated = models.DateTimeField(auto_now=True)
|
updated = models.DateTimeField(auto_now=True)
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
uuid = models.UUIDField(unique=True, editable=False, default=uuid.uuid4)
|
uuid = models.UUIDField(unique=True, editable=False, default=uuid.uuid4)
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
if self.end_time:
|
||||||
|
self.total_down_time = int((self.end_time - self.start_time).total_seconds())
|
||||||
|
super().save(*args, **kwargs)
|
|
@ -1,4 +1,6 @@
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
|
|
||||||
|
from monitoring.models import RouterDownTime
|
||||||
from router_manager.models import Router
|
from router_manager.models import Router
|
||||||
from django.http import JsonResponse
|
from django.http import JsonResponse
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
@ -40,6 +42,10 @@ def view_export_router_list(request):
|
||||||
def view_update_router_status(request):
|
def view_update_router_status(request):
|
||||||
router = Router.objects.get(uuid=request.GET.get('uuid'))
|
router = Router.objects.get(uuid=request.GET.get('uuid'))
|
||||||
new_status = request.GET.get('status')
|
new_status = request.GET.get('status')
|
||||||
|
if router.routerstatus.status_online:
|
||||||
|
current_status = 'online'
|
||||||
|
else:
|
||||||
|
current_status = 'offline'
|
||||||
if new_status not in ['online', 'offline']:
|
if new_status not in ['online', 'offline']:
|
||||||
return JsonResponse({'status': 'error', 'error_message': 'Invalid status'}, status=400)
|
return JsonResponse({'status': 'error', 'error_message': 'Invalid status'}, status=400)
|
||||||
if new_status == 'online':
|
if new_status == 'online':
|
||||||
|
@ -47,6 +53,23 @@ def view_update_router_status(request):
|
||||||
else:
|
else:
|
||||||
router.routerstatus.status_online = False
|
router.routerstatus.status_online = False
|
||||||
router.routerstatus.save()
|
router.routerstatus.save()
|
||||||
|
|
||||||
|
if current_status != new_status:
|
||||||
|
|
||||||
|
if new_status == 'online':
|
||||||
|
router.routerstatus.status_online = True
|
||||||
|
downtime = RouterDownTime.objects.filter(router=router, end_time=None).first()
|
||||||
|
if downtime:
|
||||||
|
downtime.end_time = timezone.now()
|
||||||
|
downtime.save()
|
||||||
|
else:
|
||||||
|
router.routerstatus.status_online = False
|
||||||
|
downtime = RouterDownTime.objects.create(router=router, start_time=timezone.now())
|
||||||
|
router.routerstatus.last_status_change = timezone.now()
|
||||||
|
router.routerstatus.save()
|
||||||
|
if downtime:
|
||||||
|
RouterDownTime.objects.filter(router=router, end_time=None).exclude(uuid=downtime.uuid).delete()
|
||||||
|
|
||||||
webadmin_settings, _ = WebadminSettings.objects.get_or_create(name='webadmin_settings')
|
webadmin_settings, _ = WebadminSettings.objects.get_or_create(name='webadmin_settings')
|
||||||
webadmin_settings.monitoring_last_run = timezone.now()
|
webadmin_settings.monitoring_last_run = timezone.now()
|
||||||
webadmin_settings.save()
|
webadmin_settings.save()
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
|
from django.db.models import Sum
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.shortcuts import render, get_object_or_404, redirect
|
from django.shortcuts import render, get_object_or_404, redirect
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
|
|
||||||
from backup.models import BackupProfile
|
from backup.models import BackupProfile
|
||||||
from backup_data.models import RouterBackup
|
from backup_data.models import RouterBackup
|
||||||
|
from monitoring.models import RouterDownTime
|
||||||
from routerfleet_tools.models import WebadminSettings
|
from routerfleet_tools.models import WebadminSettings
|
||||||
from .models import Router, RouterGroup, RouterStatus, SSHKey, BackupSchedule
|
from .models import Router, RouterGroup, RouterStatus, SSHKey, BackupSchedule
|
||||||
from .forms import RouterForm, RouterGroupForm, SSHKeyForm
|
from .forms import RouterForm, RouterGroupForm, SSHKeyForm
|
||||||
|
@ -34,11 +36,29 @@ def view_router_list(request):
|
||||||
return render(request, 'router_manager/router_list.html', context=context)
|
return render(request, 'router_manager/router_list.html', context=context)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required()
|
||||||
|
def view_router_availability(request):
|
||||||
|
router = get_object_or_404(Router, uuid=request.GET.get('uuid'))
|
||||||
|
data = {
|
||||||
|
'router': router,
|
||||||
|
'downtime_list': router.routerdowntime_set.all().order_by('-start_time'),
|
||||||
|
}
|
||||||
|
return render(request, 'router_manager/router_availability.html', context=data)
|
||||||
|
|
||||||
|
|
||||||
@login_required()
|
@login_required()
|
||||||
def view_router_details(request):
|
def view_router_details(request):
|
||||||
router = get_object_or_404(Router, uuid=request.GET.get('uuid'))
|
router = get_object_or_404(Router, uuid=request.GET.get('uuid'))
|
||||||
router_status, _ = RouterStatus.objects.get_or_create(router=router)
|
router_status, _ = RouterStatus.objects.get_or_create(router=router)
|
||||||
router_backup_list = router.routerbackup_set.all().order_by('-created')
|
router_backup_list = router.routerbackup_set.all().order_by('-created')
|
||||||
|
downtime_last_week = router.routerdowntime_set.filter(start_time__gte=timezone.now() - timezone.timedelta(days=7)).aggregate(total=Sum('total_down_time'))['total']
|
||||||
|
if downtime_last_week is None:
|
||||||
|
downtime_last_week = 0
|
||||||
|
total_last_week = 7 * 24 * 60 * 60 # total seconds in a week
|
||||||
|
last_week_availability = round((total_last_week - downtime_last_week) / total_last_week * 100, 3)
|
||||||
|
if downtime_last_week > 0 and last_week_availability == 100:
|
||||||
|
last_week_availability = 99.999
|
||||||
|
|
||||||
if router_status.backup_lock:
|
if router_status.backup_lock:
|
||||||
if not router_backup_list.filter(success=False, error=False).exists():
|
if not router_backup_list.filter(success=False, error=False).exists():
|
||||||
router_status.backup_lock = None
|
router_status.backup_lock = None
|
||||||
|
@ -50,6 +70,9 @@ def view_router_details(request):
|
||||||
'router_status': router_status,
|
'router_status': router_status,
|
||||||
'router_backup_list': router_backup_list,
|
'router_backup_list': router_backup_list,
|
||||||
'page_title': 'Router Details',
|
'page_title': 'Router Details',
|
||||||
|
'offline_time_last_week': downtime_last_week,
|
||||||
|
'last_week_availability': last_week_availability,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -140,6 +140,6 @@ STATICFILES_DIRS = [
|
||||||
|
|
||||||
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||||
MEDIA_ROOT = '/var/lib/routerfleet/'
|
MEDIA_ROOT = '/var/lib/routerfleet/'
|
||||||
ROUTERFLEET_VERSION = 7007
|
ROUTERFLEET_VERSION = 7008
|
||||||
|
|
||||||
from routerfleet.production_settings import *
|
from routerfleet.production_settings import *
|
||||||
|
|
|
@ -4,7 +4,7 @@ from dashboard.views import view_dashboard, view_status
|
||||||
from integration_manager.views import view_wireguard_webadmin_launcher, view_manage_wireguard_integration, view_launch_wireguard_webadmin
|
from integration_manager.views import view_wireguard_webadmin_launcher, view_manage_wireguard_integration, view_launch_wireguard_webadmin
|
||||||
from user_manager.views import view_manage_user, view_user_list
|
from user_manager.views import view_manage_user, view_user_list
|
||||||
from accounts.views import view_login, view_logout, view_create_first_user
|
from accounts.views import view_login, view_logout, view_create_first_user
|
||||||
from router_manager.views import view_router_list, view_manage_router, view_router_group_list, view_ssh_key_list, view_manage_router_group, view_manage_sshkey, view_router_details, view_create_instant_backup_task
|
from router_manager.views import view_router_list, view_manage_router, view_router_group_list, view_ssh_key_list, view_manage_router_group, view_manage_sshkey, view_router_details, view_create_instant_backup_task, view_router_availability
|
||||||
from backup.views import view_backup_profile_list, view_manage_backup_profile, view_backup_list, view_backup_details, view_debug_run_backups, view_compare_backups, view_backup_download, view_backup_delete
|
from backup.views import view_backup_profile_list, view_manage_backup_profile, view_backup_list, view_backup_details, view_debug_run_backups, view_compare_backups, view_backup_download, view_backup_delete
|
||||||
from monitoring.views import view_export_router_list, view_update_router_status, view_router_config_timestamp
|
from monitoring.views import view_export_router_list, view_update_router_status, view_router_config_timestamp
|
||||||
from backup_data.views import view_generate_backup_schedule, view_create_backup_tasks, view_perform_backup_tasks, view_housekeeping
|
from backup_data.views import view_generate_backup_schedule, view_create_backup_tasks, view_perform_backup_tasks, view_housekeeping
|
||||||
|
@ -24,6 +24,7 @@ urlpatterns = [
|
||||||
path('router/list/', view_router_list, name='router_list'),
|
path('router/list/', view_router_list, name='router_list'),
|
||||||
path('router/manage/', view_manage_router, name='manage_router'),
|
path('router/manage/', view_manage_router, name='manage_router'),
|
||||||
path('router/details/', view_router_details, name='router_details'),
|
path('router/details/', view_router_details, name='router_details'),
|
||||||
|
path('router/availability/', view_router_availability, name='router_availability'),
|
||||||
path('router/group_list/', view_router_group_list, name='router_group_list'),
|
path('router/group_list/', view_router_group_list, name='router_group_list'),
|
||||||
path('router/ssh_keys/', view_ssh_key_list, name='ssh_keys_list'),
|
path('router/ssh_keys/', view_ssh_key_list, name='ssh_keys_list'),
|
||||||
path('router/manage_group/', view_manage_router_group, name='manage_router_group'),
|
path('router/manage_group/', view_manage_router_group, name='manage_router_group'),
|
||||||
|
|
42
templates/router_manager/router_availability.html
Normal file
42
templates/router_manager/router_availability.html
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class='row'>
|
||||||
|
<div class='col-xl-6'>
|
||||||
|
<div class="card card-primary card-outline">
|
||||||
|
<div class="card-header">
|
||||||
|
<h3 class="card-title">
|
||||||
|
Availabiliy for
|
||||||
|
<a href="/router/details/?uuid={{ router.uuid }}" >
|
||||||
|
{{ router.name }}
|
||||||
|
</a>
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<div class="card-body row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Start Time</th>
|
||||||
|
<th>End Time</th>
|
||||||
|
<th>Duration</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for downtime in downtime_list %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ downtime.start_time }}</td>
|
||||||
|
<td>{{ downtime.end_time }}</td>
|
||||||
|
<td>{{ downtime.total_down_time }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
|
@ -60,6 +60,16 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
|
{% if router.monitoring %}
|
||||||
|
<li class="list-group-item">
|
||||||
|
<b>Availability (last 7 days)</b>
|
||||||
|
<span class="float-right">
|
||||||
|
<a href="/router/availability/?uuid={{ router.uuid }}">
|
||||||
|
{{ last_week_availability }}%
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<b>Router Type</b>
|
<b>Router Type</b>
|
||||||
<span class="float-right">{{ router.get_router_type_display }}</span>
|
<span class="float-right">{{ router.get_router_type_display }}</span>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue