mirror of
https://github.com/eduardogsilva/routerfleet.git
synced 2025-07-16 05:04:25 +02:00
Manage backup profiles
This commit is contained in:
parent
e507987530
commit
cc54ba0f73
12 changed files with 392 additions and 18 deletions
131
backup/forms.py
Normal file
131
backup/forms.py
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
from django import forms
|
||||||
|
from crispy_forms.helper import FormHelper
|
||||||
|
from crispy_forms.layout import Layout, Submit, Row, Column, HTML, Field, Div
|
||||||
|
from .models import BackupProfile
|
||||||
|
|
||||||
|
|
||||||
|
class BackupProfileForm(forms.ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = BackupProfile
|
||||||
|
fields = [
|
||||||
|
'name', 'daily_backup', 'weekly_backup', 'monthly_backup',
|
||||||
|
'daily_retenion', 'weekly_retention', 'monthly_retenion',
|
||||||
|
'retain_backups_on_error', 'daily_day_monday', 'daily_day_tuesday',
|
||||||
|
'daily_day_wednesday', 'daily_day_thursday', 'daily_day_friday',
|
||||||
|
'daily_day_saturday', 'daily_day_sunday', 'weekly_day',
|
||||||
|
'monthly_day', 'daily_hour', 'weekly_hour', 'monthly_hour',
|
||||||
|
'max_retry', 'retry_interval', 'backup_interval'
|
||||||
|
]
|
||||||
|
# widgets = {
|
||||||
|
# 'weekly_day': forms.Select(),
|
||||||
|
# 'monthly_day': forms.Select(),
|
||||||
|
# 'daily_hour': forms.Select(choices=HOUR_CHOICES),
|
||||||
|
# 'weekly_hour': forms.Select(choices=HOUR_CHOICES),
|
||||||
|
# 'monthly_hour': forms.Select(choices=HOUR_CHOICES),
|
||||||
|
# 'max_retry': forms.Select(),
|
||||||
|
# 'retry_interval': forms.Select(),
|
||||||
|
# 'backup_interval': forms.Select(),
|
||||||
|
# }
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(BackupProfileForm, self).__init__(*args, **kwargs)
|
||||||
|
self.helper = FormHelper()
|
||||||
|
self.helper.form_method = 'post'
|
||||||
|
if self.instance.pk:
|
||||||
|
delete_html = "<a href='javascript:void(0)' class='btn btn-outline-danger' data-command='delete' onclick='openCommandDialog(this)'>Delete</a>"
|
||||||
|
else:
|
||||||
|
delete_html = ''
|
||||||
|
|
||||||
|
self.fields['daily_day_monday'].label = 'Monday'
|
||||||
|
self.fields['daily_day_tuesday'].label = 'Tuesday'
|
||||||
|
self.fields['daily_day_wednesday'].label = 'Wednesday'
|
||||||
|
self.fields['daily_day_thursday'].label = 'Thursday'
|
||||||
|
self.fields['daily_day_friday'].label = 'Friday'
|
||||||
|
self.fields['daily_day_saturday'].label = 'Saturday'
|
||||||
|
self.fields['daily_day_sunday'].label = 'Sunday'
|
||||||
|
self.fields['daily_backup'].label = 'Daily'
|
||||||
|
self.fields['weekly_backup'].label = 'Weekly'
|
||||||
|
self.fields['monthly_backup'].label = 'Monthly'
|
||||||
|
self.fields['daily_retenion'].label = 'Retention (days)'
|
||||||
|
self.fields['weekly_retention'].label = 'Retention (days)'
|
||||||
|
self.fields['monthly_retenion'].label = 'Retention (days)'
|
||||||
|
|
||||||
|
self.helper.layout = Layout(
|
||||||
|
Div(Div('name', css_class='col-md-12'), css_class='row'),
|
||||||
|
Div(
|
||||||
|
Div('daily_backup', css_class='col-md-4'),
|
||||||
|
Div('weekly_backup', css_class='col-md-4'),
|
||||||
|
Div('monthly_backup', css_class='col-md-4'),
|
||||||
|
css_class='row'),
|
||||||
|
|
||||||
|
Div(
|
||||||
|
Div(HTML('<hr><h4>Daily Backups</h4>'), css_class='col-md-12'),
|
||||||
|
Div('daily_hour', css_class='col-md-4'),
|
||||||
|
Div('daily_retenion', css_class='col-md-4'),
|
||||||
|
Div(css_class='col-md-4'),
|
||||||
|
Div('daily_day_monday', css_class='col-md-4'),
|
||||||
|
Div('daily_day_tuesday', css_class='col-md-4'),
|
||||||
|
Div('daily_day_wednesday', css_class='col-md-4'),
|
||||||
|
Div('daily_day_thursday',css_class='col-md-4'),
|
||||||
|
Div('daily_day_friday', css_class='col-md-4'),
|
||||||
|
Div('daily_day_saturday', css_class='col-md-4'),
|
||||||
|
Div('daily_day_sunday', css_class='col-md-4'),
|
||||||
|
css_id='daily_settings', css_class='row'
|
||||||
|
),
|
||||||
|
|
||||||
|
Div(
|
||||||
|
Div(HTML('<hr><h4>Weekly Backups</h4>'), css_class='col-md-12'),
|
||||||
|
Div('weekly_hour', css_class='col-md-4'),
|
||||||
|
Div('weekly_retention', css_class='col-md-4'),
|
||||||
|
Div('weekly_day', css_class='col-md-4'),
|
||||||
|
css_id='weekly_settings', css_class='row'
|
||||||
|
),
|
||||||
|
|
||||||
|
Div(
|
||||||
|
Div(HTML('<hr><h4>Monthly Backups</h4>'), css_class='col-md-12'),
|
||||||
|
Div('monthly_hour', css_class='col-md-4'),
|
||||||
|
Div('monthly_retenion', css_class='col-md-4'),
|
||||||
|
Div('monthly_day', css_class='col-md-4'),
|
||||||
|
css_id='monthly_settings', css_class='row'
|
||||||
|
),
|
||||||
|
|
||||||
|
Div(
|
||||||
|
Div(HTML('<hr><h4>Backup Settings</h4>'), css_class='col-md-12'),
|
||||||
|
Div('max_retry', css_class='col-md-4'),
|
||||||
|
Div('retry_interval', css_class='col-md-4'),
|
||||||
|
Div('backup_interval', css_class='col-md-4'),
|
||||||
|
Div('retain_backups_on_error', css_class='col-md-12'),
|
||||||
|
css_id='misc_settings', css_class='row'
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
Column(
|
||||||
|
Submit('submit', 'Salvar', css_class='btn btn-success'),
|
||||||
|
HTML(' <a class="btn btn-secondary" href="/backup/profile_list/">Back</a> '),
|
||||||
|
HTML(delete_html),
|
||||||
|
css_class='col-md-12'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
cleaned_data = super().clean()
|
||||||
|
daily_backup = cleaned_data.get('daily_backup')
|
||||||
|
weekly_backup = cleaned_data.get('weekly_backup')
|
||||||
|
monthly_backup = cleaned_data.get('monthly_backup')
|
||||||
|
|
||||||
|
daily_day_monday = cleaned_data.get('daily_day_monday')
|
||||||
|
daily_day_tuesday = cleaned_data.get('daily_day_tuesday')
|
||||||
|
daily_day_wednesday = cleaned_data.get('daily_day_wednesday')
|
||||||
|
daily_day_thursday = cleaned_data.get('daily_day_thursday')
|
||||||
|
daily_day_friday = cleaned_data.get('daily_day_friday')
|
||||||
|
daily_day_saturday = cleaned_data.get('daily_day_saturday')
|
||||||
|
daily_day_sunday = cleaned_data.get('daily_day_sunday')
|
||||||
|
|
||||||
|
if daily_backup:
|
||||||
|
if not daily_day_monday and not daily_day_tuesday and not daily_day_wednesday and not daily_day_thursday and not daily_day_friday and not daily_day_saturday and not daily_day_sunday:
|
||||||
|
raise forms.ValidationError('You must select at least one day for daily backups')
|
||||||
|
|
||||||
|
if not daily_backup and not weekly_backup and not monthly_backup:
|
||||||
|
raise forms.ValidationError('You must select at least one backup type')
|
||||||
|
|
||||||
|
return cleaned_data
|
18
backup/migrations/0002_alter_backupprofile_weekly_day.py
Normal file
18
backup/migrations/0002_alter_backupprofile_weekly_day.py
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 5.0.3 on 2024-03-17 14:43
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('backup', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='backupprofile',
|
||||||
|
name='weekly_day',
|
||||||
|
field=models.CharField(choices=[('monday', 'Monday'), ('tuesday', 'Tuesday'), ('wednesday', 'Wednesday'), ('thursday', 'Thursday'), ('friday', 'Friday'), ('saturday', 'Saturday'), ('sunday', 'Sunday')], default='sunday', max_length=10),
|
||||||
|
),
|
||||||
|
]
|
18
backup/migrations/0003_alter_backupprofile_retry_interval.py
Normal file
18
backup/migrations/0003_alter_backupprofile_retry_interval.py
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 5.0.3 on 2024-03-17 19:37
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('backup', '0002_alter_backupprofile_weekly_day'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='backupprofile',
|
||||||
|
name='retry_interval',
|
||||||
|
field=models.IntegerField(choices=[(1, '1 Minute'), (15, '15 Minutes'), (30, '30 Minutes'), (60, '1 Hour')], default=30),
|
||||||
|
),
|
||||||
|
]
|
|
@ -29,7 +29,7 @@ class BackupProfile(models.Model):
|
||||||
daily_day_saturday = models.BooleanField(default=True)
|
daily_day_saturday = models.BooleanField(default=True)
|
||||||
daily_day_sunday = models.BooleanField(default=True)
|
daily_day_sunday = models.BooleanField(default=True)
|
||||||
|
|
||||||
weekly_day = models.CharField(max_length=10, choices=(('monday', 'Monday'), ('tuesday', 'Tuesday'), ('wednesday', 'Wednesday'), ('thursday', 'Thursday'), ('friday', 'Friday'), ('saturday', 'Saturday'), ('sunday', 'Sunday')))
|
weekly_day = models.CharField(max_length=10, default='sunday', choices=(('monday', 'Monday'), ('tuesday', 'Tuesday'), ('wednesday', 'Wednesday'), ('thursday', 'Thursday'), ('friday', 'Friday'), ('saturday', 'Saturday'), ('sunday', 'Sunday')))
|
||||||
monthly_day = models.IntegerField(default=1, choices=((1, '1st'), (7, '7th'), (14, '14th'), (21, '21st'), (28, '28th')))
|
monthly_day = models.IntegerField(default=1, choices=((1, '1st'), (7, '7th'), (14, '14th'), (21, '21st'), (28, '28th')))
|
||||||
|
|
||||||
daily_hour = models.IntegerField(default=3, choices=HOUR_CHOICES)
|
daily_hour = models.IntegerField(default=3, choices=HOUR_CHOICES)
|
||||||
|
@ -37,7 +37,7 @@ class BackupProfile(models.Model):
|
||||||
monthly_hour = models.IntegerField(default=0, choices=HOUR_CHOICES)
|
monthly_hour = models.IntegerField(default=0, choices=HOUR_CHOICES)
|
||||||
|
|
||||||
max_retry = models.IntegerField(default=3, choices=((1, '1'), (2, '2'), (3, '3'), (4, '4'), (5, '5')))
|
max_retry = models.IntegerField(default=3, choices=((1, '1'), (2, '2'), (3, '3'), (4, '4'), (5, '5')))
|
||||||
retry_interval = models.IntegerField(default=30, choices=(('1', '1 Minute'), ('15', '15 Minutes'), ('30', '30 Minutes'), ('60', '1 Hour')))
|
retry_interval = models.IntegerField(default=30, choices=((1, '1 Minute'), (15, '15 Minutes'), (30, '30 Minutes'), (60, '1 Hour')))
|
||||||
backup_interval = models.IntegerField(default=60, choices=((0, 'No interval'), (5, '5 seconds'), (60, '1 minute')))
|
backup_interval = models.IntegerField(default=60, choices=((0, 'No interval'), (5, '5 seconds'), (60, '1 minute')))
|
||||||
|
|
||||||
updated = models.DateTimeField(auto_now=True)
|
updated = models.DateTimeField(auto_now=True)
|
||||||
|
|
|
@ -1,3 +1,48 @@
|
||||||
from django.shortcuts import render
|
from django.contrib.auth.decorators import login_required
|
||||||
|
from django.shortcuts import render, get_object_or_404, redirect
|
||||||
|
from django.contrib import messages
|
||||||
|
from .models import BackupProfile
|
||||||
|
from .forms import BackupProfileForm
|
||||||
|
from router_manager.models import Router
|
||||||
|
|
||||||
# Create your views here.
|
|
||||||
|
@login_required()
|
||||||
|
def view_backup_profile_list(request):
|
||||||
|
context = {
|
||||||
|
'backup_profile_list': BackupProfile.objects.all().order_by('name'),
|
||||||
|
'page_title': 'Backup Profiles'
|
||||||
|
}
|
||||||
|
return render(request, 'backup/backup_profile_list.html', context)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required()
|
||||||
|
def view_manage_backup_profile(request):
|
||||||
|
if request.GET.get('uuid'):
|
||||||
|
backup_profile = get_object_or_404(BackupProfile, uuid=request.GET.get('uuid'))
|
||||||
|
if request.GET.get('action') == 'delete':
|
||||||
|
if request.GET.get('confirmation') == 'delete':
|
||||||
|
if Router.objects.filter(backup_profile=backup_profile).exists():
|
||||||
|
messages.warning(request, 'Backup profile in use|Backup profile is in use and cannot be deleted')
|
||||||
|
return redirect('backup_profile_list')
|
||||||
|
else:
|
||||||
|
backup_profile.delete()
|
||||||
|
messages.success(request, 'Backup profile deleted successfully')
|
||||||
|
return redirect('backup_profile_list')
|
||||||
|
else:
|
||||||
|
messages.warning(request, 'Backup profile not deleted|Invalid confirmation')
|
||||||
|
return redirect('backup_profile_list')
|
||||||
|
else:
|
||||||
|
backup_profile = None
|
||||||
|
|
||||||
|
form = BackupProfileForm(request.POST or None, instance=backup_profile)
|
||||||
|
if form.is_valid():
|
||||||
|
form.save()
|
||||||
|
messages.success(request, 'Backup Profile saved successfully')
|
||||||
|
return redirect('backup_profile_list')
|
||||||
|
|
||||||
|
context = {
|
||||||
|
'form': form,
|
||||||
|
'page_title': 'Manage Backup Profile',
|
||||||
|
'instance': backup_profile
|
||||||
|
}
|
||||||
|
return render(request, 'backup/backup_profile_form.html', context=context)
|
||||||
|
|
|
@ -11,7 +11,7 @@ class RouterForm(forms.ModelForm):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Router
|
model = Router
|
||||||
fields = ['name', 'address', 'username', 'password', 'ssh_key', 'monitoring', 'router_type', 'enabled']
|
fields = ['name', 'address', 'username', 'password', 'ssh_key', 'monitoring', 'router_type', 'enabled', 'backup_profile']
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(RouterForm, self).__init__(*args, **kwargs)
|
super(RouterForm, self).__init__(*args, **kwargs)
|
||||||
|
@ -35,6 +35,7 @@ class RouterForm(forms.ModelForm):
|
||||||
css_class='form-row'
|
css_class='form-row'
|
||||||
),
|
),
|
||||||
'ssh_key',
|
'ssh_key',
|
||||||
|
'backup_profile',
|
||||||
'router_type',
|
'router_type',
|
||||||
'monitoring',
|
'monitoring',
|
||||||
'enabled',
|
'enabled',
|
||||||
|
|
|
@ -73,5 +73,3 @@ class BackupSchedule(models.Model):
|
||||||
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)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@ from dashboard.views import view_dashboard, view_status
|
||||||
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
|
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
|
||||||
|
from backup.views import view_backup_profile_list, view_manage_backup_profile
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('admin/', admin.site.urls),
|
path('admin/', admin.site.urls),
|
||||||
|
@ -20,4 +22,7 @@ urlpatterns = [
|
||||||
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'),
|
||||||
path('router/manage_sshkey/', view_manage_sshkey, name='manage_sshkey'),
|
path('router/manage_sshkey/', view_manage_sshkey, name='manage_sshkey'),
|
||||||
|
path('backup/profile_list/', view_backup_profile_list, name='backup_profile_list'),
|
||||||
|
path('backup/manage_profile/', view_manage_backup_profile, name='manage_backup_profile')
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
65
templates/backup/backup_profile_form.html
Normal file
65
templates/backup/backup_profile_form.html
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
{% extends 'base.html' %}
|
||||||
|
{% load crispy_forms_tags %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class='row'>
|
||||||
|
<div class='{% if form_size %}{{ form_size }}{% else %}col-lg-6{% endif %}'>
|
||||||
|
<div class="card card-primary card-outline">
|
||||||
|
{% if page_title %}
|
||||||
|
<div class="card-header">
|
||||||
|
<h3 class="card-title">{{ page_title }}</h3>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<div class="card-body row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
{% csrf_token %}
|
||||||
|
{% crispy form %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block custom_page_scripts %}
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function openCommandDialog(element) {
|
||||||
|
var command = element.getAttribute('data-command');
|
||||||
|
var confirmation = prompt("{% if delete_confirmation_message %}{{ delete_confirmation_message }}{% else %}Please type 'delete' to proceed.{% endif %}");
|
||||||
|
if (confirmation) {
|
||||||
|
var url = "?uuid={{ instance.uuid }}&action=delete&confirmation=" + encodeURIComponent(confirmation);
|
||||||
|
window.location.href = url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
function toggleSectionVisibility(checkboxId, sectionId) {
|
||||||
|
var checkbox = document.getElementById(checkboxId);
|
||||||
|
var section = document.getElementById(sectionId);
|
||||||
|
|
||||||
|
if (checkbox && section) {
|
||||||
|
section.style.display = checkbox.checked ? '' : 'none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var controls = [
|
||||||
|
{checkboxId: 'id_daily_backup', sectionId: 'daily_settings'},
|
||||||
|
{checkboxId: 'id_weekly_backup', sectionId: 'weekly_settings'},
|
||||||
|
{checkboxId: 'id_monthly_backup', sectionId: 'monthly_settings'}
|
||||||
|
];
|
||||||
|
|
||||||
|
controls.forEach(function (control) {
|
||||||
|
var checkbox = document.getElementById(control.checkboxId);
|
||||||
|
if (checkbox) {
|
||||||
|
checkbox.addEventListener('change', function () {
|
||||||
|
toggleSectionVisibility(control.checkboxId, control.sectionId);
|
||||||
|
});
|
||||||
|
toggleSectionVisibility(control.checkboxId, control.sectionId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
75
templates/backup/backup_profile_list.html
Normal file
75
templates/backup/backup_profile_list.html
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class='row'>
|
||||||
|
<div class='col-lg-12'>
|
||||||
|
<div class="card card-primary card-outline">
|
||||||
|
{% if page_title %}
|
||||||
|
<div class="card-header">
|
||||||
|
<h3 class="card-title">{{ page_title }}</h3>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<table class="table table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Router Count</th>
|
||||||
|
<th>Daily</th>
|
||||||
|
<th>Weekly</th>
|
||||||
|
<th>Monthly</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
{% for backup_profile in backup_profile_list %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ backup_profile.name }}</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
{{ backup_profile.router_set.count }}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
{% if backup_profile.daily_backup %}
|
||||||
|
<i class="far fa-check-circle text-success"></i>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% if backup_profile.weekly_backup %}
|
||||||
|
<i class="far fa-check-circle text-success"></i>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
{% if backup_profile.monthly_backup %}
|
||||||
|
<i class="far fa-check-circle text-success"></i>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td class="min-width">
|
||||||
|
<a href="/backup/manage_profile/?uuid={{ backup_profile.uuid }}"><i class="fas fa-edit"></i></a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<a href="/backup/manage_profile/" class="btn btn-primary">Add Backup Profile</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
|
@ -111,7 +111,17 @@
|
||||||
</p>
|
</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
<li class="nav-item">
|
||||||
|
<a href="/backup/profile_list/" class="nav-link {% if '/backup/' in request.path %}active{% endif %}">
|
||||||
|
<i class="fas fa-box-open"></i>
|
||||||
|
<p>
|
||||||
|
Backup
|
||||||
|
</p>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a href="/user/list/" class="nav-link {% if '/user/' in request.path %}active{% endif %}">
|
<a href="/user/list/" class="nav-link {% if '/user/' in request.path %}active{% endif %}">
|
||||||
<i class="fas fa-users nav-icon"></i>
|
<i class="fas fa-users nav-icon"></i>
|
||||||
|
|
|
@ -19,40 +19,48 @@
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Type</th>
|
<th>Type</th>
|
||||||
<th>Address</th>
|
<th>Address</th>
|
||||||
<th>Enabled</th>
|
|
||||||
<th>Status</th>
|
<th>Status</th>
|
||||||
|
<th>Backup</th>
|
||||||
<th>Groups</th>
|
<th>Groups</th>
|
||||||
<th>Authentication</th>
|
<th>Auth</th>
|
||||||
<th></th>
|
<th></th>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for router in router_list %}
|
{% for router in router_list %}
|
||||||
<tr>
|
<tr {% if not router.enabled %}style="text-decoration: line-through;"{% endif %}>
|
||||||
<td>{{ router.name }}</td>
|
<td>{{ router.name }}</td>
|
||||||
<td>{{ router.get_router_type_display }}</td>
|
<td>{{ router.get_router_type_display }}</td>
|
||||||
<td>{{ router.address }}</td>
|
<td>{{ router.address }}</td>
|
||||||
<td>{{ router.enabled }}</td>
|
|
||||||
<td>
|
<td>
|
||||||
{% if router.monitoring %}
|
{% if router.monitoring %}
|
||||||
{% if router.routerstatus.status_online %}
|
{% if router.routerstatus.status_online %}
|
||||||
Online
|
<i class="far fa-check-circle text-success" title="Host is Online"></i>
|
||||||
{% else %}
|
{% else %}
|
||||||
Offline
|
<i class="far fa-times-circle text-danger" title="Host is unavailable"></i>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
---
|
---
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
{% if router.backup_profile %}
|
||||||
|
{{ router.backup_profile }} {% if router.routerstatus.last_backup_failed %}<i class="fas fa-exclamation-triangle text-danger" title="Last backup failed to complete"></i>{% endif %}
|
||||||
|
{% else %}
|
||||||
|
<i class="fas fa-exclamation-triangle text-warning" title="No backup profile selected"></i>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
{{ router.routergroup_set.count }}
|
{{ router.routergroup_set.count }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td class="min-width">
|
||||||
{% if router.ssh_key %}
|
{% if router.ssh_key %}
|
||||||
{{ router.ssh_key }}
|
<i class="fas fa-key" title="SSH Key: {{ router.ssh_key }}"></i>
|
||||||
{% elif router.password %}
|
{% elif router.password %}
|
||||||
User/Password
|
<i class="fas fa-keyboard" title="Password Authentication"></i>
|
||||||
{% else %}
|
{% else %}
|
||||||
Missing authentication
|
<i class="fas fa-exclamation-triangle text-warning" title="Missing authentication"></i>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td class="min-width">
|
<td class="min-width">
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue