From cc54ba0f73023a46924a478b4fb1b375aff84735 Mon Sep 17 00:00:00 2001
From: Eduardo Silva Daily Backups
'), 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('Weekly Backups
'), 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('Monthly Backups
'), 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('Backup Settings
'), 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(' Back '),
+ 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
\ No newline at end of file
diff --git a/backup/migrations/0002_alter_backupprofile_weekly_day.py b/backup/migrations/0002_alter_backupprofile_weekly_day.py
new file mode 100644
index 0000000..0e51011
--- /dev/null
+++ b/backup/migrations/0002_alter_backupprofile_weekly_day.py
@@ -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),
+ ),
+ ]
diff --git a/backup/migrations/0003_alter_backupprofile_retry_interval.py b/backup/migrations/0003_alter_backupprofile_retry_interval.py
new file mode 100644
index 0000000..b1f20cc
--- /dev/null
+++ b/backup/migrations/0003_alter_backupprofile_retry_interval.py
@@ -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),
+ ),
+ ]
diff --git a/backup/models.py b/backup/models.py
index c813d6f..35e9b14 100644
--- a/backup/models.py
+++ b/backup/models.py
@@ -29,7 +29,7 @@ class BackupProfile(models.Model):
daily_day_saturday = 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')))
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)
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')))
updated = models.DateTimeField(auto_now=True)
diff --git a/backup/views.py b/backup/views.py
index 91ea44a..83944de 100644
--- a/backup/views.py
+++ b/backup/views.py
@@ -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)
diff --git a/router_manager/forms.py b/router_manager/forms.py
index b5fbb36..7ac1c92 100644
--- a/router_manager/forms.py
+++ b/router_manager/forms.py
@@ -11,7 +11,7 @@ class RouterForm(forms.ModelForm):
class Meta:
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):
super(RouterForm, self).__init__(*args, **kwargs)
@@ -35,6 +35,7 @@ class RouterForm(forms.ModelForm):
css_class='form-row'
),
'ssh_key',
+ 'backup_profile',
'router_type',
'monitoring',
'enabled',
diff --git a/router_manager/models.py b/router_manager/models.py
index 9132270..e26e2ee 100644
--- a/router_manager/models.py
+++ b/router_manager/models.py
@@ -73,5 +73,3 @@ class BackupSchedule(models.Model):
created = models.DateTimeField(auto_now_add=True)
uuid = models.UUIDField(unique=True, editable=False, default=uuid.uuid4)
-
-
diff --git a/routerfleet/urls.py b/routerfleet/urls.py
index 34b755d..56fe537 100644
--- a/routerfleet/urls.py
+++ b/routerfleet/urls.py
@@ -4,6 +4,8 @@ from dashboard.views import view_dashboard, view_status
from user_manager.views import view_manage_user, view_user_list
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 backup.views import view_backup_profile_list, view_manage_backup_profile
+
urlpatterns = [
path('admin/', admin.site.urls),
@@ -20,4 +22,7 @@ urlpatterns = [
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_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')
+
]
diff --git a/templates/backup/backup_profile_form.html b/templates/backup/backup_profile_form.html
new file mode 100644
index 0000000..36a5383
--- /dev/null
+++ b/templates/backup/backup_profile_form.html
@@ -0,0 +1,65 @@
+{% extends 'base.html' %}
+{% load crispy_forms_tags %}
+
+{% block content %}
+ {{ page_title }}
+ {{ page_title }}
+
+ Backup +
+ +