From 0f5dda618b644a7de62b1bdeeef651ebe7a35e5f Mon Sep 17 00:00:00 2001 From: Eduardo Silva Date: Thu, 14 Aug 2025 21:36:14 -0300 Subject: [PATCH] Add cluster app with initial migrations, models, and settings integration --- cluster/__init__.py | 0 cluster/admin.py | 3 ++ cluster/apps.py | 6 +++ cluster/migrations/0001_initial.py | 69 ++++++++++++++++++++++++++++++ cluster/migrations/__init__.py | 0 cluster/models.py | 60 ++++++++++++++++++++++++++ cluster/tests.py | 1 + cluster/views.py | 1 + wireguard_webadmin/settings.py | 5 ++- 9 files changed, 143 insertions(+), 2 deletions(-) create mode 100644 cluster/__init__.py create mode 100644 cluster/admin.py create mode 100644 cluster/apps.py create mode 100644 cluster/migrations/0001_initial.py create mode 100644 cluster/migrations/__init__.py create mode 100644 cluster/models.py create mode 100644 cluster/tests.py create mode 100644 cluster/views.py diff --git a/cluster/__init__.py b/cluster/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/cluster/admin.py b/cluster/admin.py new file mode 100644 index 0000000..b28b04f --- /dev/null +++ b/cluster/admin.py @@ -0,0 +1,3 @@ + + + diff --git a/cluster/apps.py b/cluster/apps.py new file mode 100644 index 0000000..38a53f8 --- /dev/null +++ b/cluster/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class ClusterConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'cluster' diff --git a/cluster/migrations/0001_initial.py b/cluster/migrations/0001_initial.py new file mode 100644 index 0000000..9147310 --- /dev/null +++ b/cluster/migrations/0001_initial.py @@ -0,0 +1,69 @@ +# Generated by Django 5.2.5 on 2025-08-15 00:34 + +import uuid + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='ClusterSettings', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(default='cluster_settings', max_length=16, unique=True)), + ('enabled', models.BooleanField(default=False)), + ('primary_enable_wireguard', models.BooleanField(default=True)), + ('stats_sync_interval', models.IntegerField(default=60)), + ('stats_cache_interval', models.IntegerField(default=60)), + ('cluster_mode', models.CharField(default='mirror', max_length=16)), + ('restart_mode', models.CharField(choices=[('auto', 'Automatically restart/reload'), ('manual', 'Manual')], default='auto', max_length=16)), + ('worker_display', models.CharField(choices=[('name', 'Name'), ('server_address', 'Server Address'), ('location', 'Location'), ('address_location', 'Address + Location')], default='server_address', max_length=16)), + ('config_version', models.PositiveIntegerField(default=0)), + ('updated', models.DateTimeField(auto_now=True)), + ('created', models.DateTimeField(auto_now_add=True)), + ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ], + ), + migrations.CreateModel( + name='Worker', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100, unique=True)), + ('enabled', models.BooleanField(default=True)), + ('token', models.UUIDField(default=uuid.uuid4)), + ('ip_lock', models.BooleanField(default=False)), + ('ip_address', models.GenericIPAddressField(blank=True, null=True)), + ('force_reload', models.BooleanField(default=False)), + ('force_restart', models.BooleanField(default=False)), + ('country', models.CharField(blank=True, max_length=100, null=True)), + ('city', models.CharField(blank=True, max_length=100, null=True)), + ('hostname', models.CharField(blank=True, max_length=100, null=True)), + ('updated', models.DateTimeField(auto_now=True)), + ('created', models.DateTimeField(auto_now_add=True)), + ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ], + ), + migrations.CreateModel( + name='WorkerStatus', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('last_seen', models.DateTimeField(auto_now=True)), + ('last_reload', models.DateTimeField(blank=True, null=True)), + ('last_restart', models.DateTimeField(blank=True, null=True)), + ('config_version', models.PositiveIntegerField(default=0)), + ('config_pending', models.BooleanField(default=False)), + ('updated', models.DateTimeField(auto_now=True)), + ('created', models.DateTimeField(auto_now_add=True)), + ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('worker', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='cluster.worker')), + ], + ), + ] diff --git a/cluster/migrations/__init__.py b/cluster/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/cluster/models.py b/cluster/models.py new file mode 100644 index 0000000..b5a42a4 --- /dev/null +++ b/cluster/models.py @@ -0,0 +1,60 @@ +import uuid + +from django.db import models + + +class ClusterSettings(models.Model): + name = models.CharField(default='cluster_settings', max_length=16, unique=True) + enabled = models.BooleanField(default=False) + primary_enable_wireguard = models.BooleanField(default=True) + stats_sync_interval = models.IntegerField(default=60) + stats_cache_interval = models.IntegerField(default=60) + cluster_mode = models.CharField(default='mirror', max_length=16) + restart_mode = models.CharField(default='auto', max_length=16, choices=(('auto', 'Automatically restart/reload'), ('manual', 'Manual'))) + worker_display = models.CharField( + default='server_address', max_length=16, choices=( + ('name', 'Name'), ('server_address', 'Server Address'), + ('location', 'Location'), ('address_location', 'Address + Location') + ) + ) + config_version = models.PositiveIntegerField(default=0) + + updated = models.DateTimeField(auto_now=True) + created = models.DateTimeField(auto_now_add=True) + uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True) + + def __str__(self): + return self.name + + +class Worker(models.Model): + name = models.CharField(max_length=100, unique=True) + enabled = models.BooleanField(default=True) + token = models.UUIDField(default=uuid.uuid4) + ip_lock = models.BooleanField(default=False) + ip_address = models.GenericIPAddressField(blank=True, null=True) + + force_reload = models.BooleanField(default=False) + force_restart = models.BooleanField(default=False) + + country = models.CharField(max_length=100, blank=True, null=True) + city = models.CharField(max_length=100, blank=True, null=True) + hostname = models.CharField(max_length=100, blank=True, null=True) + + + updated = models.DateTimeField(auto_now=True) + created = models.DateTimeField(auto_now_add=True) + uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True) + + +class WorkerStatus(models.Model): + worker = models.OneToOneField(Worker, on_delete=models.CASCADE) + last_seen = models.DateTimeField(auto_now=True) + last_reload = models.DateTimeField(blank=True, null=True) + last_restart = models.DateTimeField(blank=True, null=True) + config_version = models.PositiveIntegerField(default=0) + config_pending = models.BooleanField(default=False) + + updated = models.DateTimeField(auto_now=True) + created = models.DateTimeField(auto_now_add=True) + uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True) diff --git a/cluster/tests.py b/cluster/tests.py new file mode 100644 index 0000000..a39b155 --- /dev/null +++ b/cluster/tests.py @@ -0,0 +1 @@ +# Create your tests here. diff --git a/cluster/views.py b/cluster/views.py new file mode 100644 index 0000000..60f00ef --- /dev/null +++ b/cluster/views.py @@ -0,0 +1 @@ +# Create your views here. diff --git a/wireguard_webadmin/settings.py b/wireguard_webadmin/settings.py index af7ce06..90766cd 100644 --- a/wireguard_webadmin/settings.py +++ b/wireguard_webadmin/settings.py @@ -45,7 +45,8 @@ INSTALLED_APPS = [ 'wireguard_tools', 'firewall', 'dns', - 'vpn_invite' + 'vpn_invite', + 'cluster' ] MIDDLEWARE = [ @@ -148,6 +149,6 @@ STATICFILES_DIRS = [ DNS_CONFIG_FILE = '/etc/dnsmasq/wireguard_webadmin_dns.conf' DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' -WIREGUARD_WEBADMIN_VERSION = 9966 +WIREGUARD_WEBADMIN_VERSION = 9967 from wireguard_webadmin.production_settings import *