From 9bf761c88c3c320bc93b235070033ad1b6ba2b17 Mon Sep 17 00:00:00 2001
From: Nicolas Froger <nico@cri.epita.fr>
Date: Tue, 26 Sep 2023 00:15:03 +0200
Subject: [PATCH] fleet: make DHCP pools togglable

Signed-off-by: Nicolas Froger <nico@cri.epita.fr>
---
 fleet/admin.py                              |  1 +
 fleet/migrations/0016_auto_20230926_0014.py | 32 ++++++++
 fleet/models/__init__.py                    | 85 +++++++++++++++------
 fleet/views.py                              | 20 +++--
 4 files changed, 109 insertions(+), 29 deletions(-)
 create mode 100644 fleet/migrations/0016_auto_20230926_0014.py

diff --git a/fleet/admin.py b/fleet/admin.py
index 7a1496d..50131be 100644
--- a/fleet/admin.py
+++ b/fleet/admin.py
@@ -29,6 +29,7 @@ class DhcpSubnetAdmin(admin.ModelAdmin):
     list_display = ("subnet", "router", "allocation_pool_start", "allocation_pool_end")
     list_display_links = list_display
     search_fields = list_display
+    list_filter = ("enable_pool",)
 
 
 class ExtraTxtRecordRoomInline(admin.TabularInline):
diff --git a/fleet/migrations/0016_auto_20230926_0014.py b/fleet/migrations/0016_auto_20230926_0014.py
new file mode 100644
index 0000000..351bf81
--- /dev/null
+++ b/fleet/migrations/0016_auto_20230926_0014.py
@@ -0,0 +1,32 @@
+# Generated by Django 3.2.19 on 2023-09-25 22:14
+
+from django.db import migrations, models
+import netfields.fields
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ("fleet", "0015_extratxtrecordroom_extratxtrecordsite"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="dhcpsubnet",
+            name="enable_pool",
+            field=models.BooleanField(default=False),
+        ),
+        migrations.AlterField(
+            model_name="dhcpsubnet",
+            name="allocation_pool_end",
+            field=netfields.fields.InetAddressField(
+                blank=True, max_length=39, null=True
+            ),
+        ),
+        migrations.AlterField(
+            model_name="dhcpsubnet",
+            name="allocation_pool_start",
+            field=netfields.fields.InetAddressField(
+                blank=True, max_length=39, null=True
+            ),
+        ),
+    ]
diff --git a/fleet/models/__init__.py b/fleet/models/__init__.py
index 8105c78..d8d8bda 100644
--- a/fleet/models/__init__.py
+++ b/fleet/models/__init__.py
@@ -35,8 +35,14 @@ class DhcpSubnet(models.Model):
 
     router = InetAddressField(store_prefix_length=False)
 
-    allocation_pool_start = InetAddressField(store_prefix_length=False)
-    allocation_pool_end = InetAddressField(store_prefix_length=False)
+    allocation_pool_start = InetAddressField(
+        store_prefix_length=False, blank=True, null=True
+    )
+    allocation_pool_end = InetAddressField(
+        store_prefix_length=False, blank=True, null=True
+    )
+
+    enable_pool = models.BooleanField(default=False)
 
     objects = NetManager()
 
@@ -44,34 +50,69 @@ class DhcpSubnet(models.Model):
         return str(self.subnet)
 
     def clean(self):
-        if (
-            not self.allocation_pool_start  # pylint:disable=unneeded-not # noqa: E501
-            < self.allocation_pool_end
-        ):
-            raise ValidationError(
-                {
-                    "allocation_pool_start": "allocation_pool_start should be before allocation_pool_end",  # noqa: E501
-                    "allocation_pool_end": "allocation_pool_end should be after allocation_pool_start",  # noqa: E501
-                }
-            )
-        if (
-            self.allocation_pool_start
-            not in self.subnet  # pylint:disable=unsupported-membership-test # noqa: E501
-        ):
+        if self.allocation_pool_start and not self.allocation_pool_end:
             raise ValidationError(
                 {
-                    "allocation_pool_start": f"allocation_pool_start should be in subnet {self.subnet}",  # noqa: E501
+                    "allocation_pool_end": "allocation_pool_end must be set if allocation_pool_start is set"
                 }
             )
-        if (
-            self.allocation_pool_end
-            not in self.subnet  # pylint:disable=unsupported-membership-test # noqa: E501
-        ):
+        if not self.allocation_pool_start and self.allocation_pool_end:
             raise ValidationError(
                 {
-                    "allocation_pool_end": f"allocation_pool_end should be in subnet {self.subnet}",  # noqa: E501
+                    "allocation_pool_start": "allocation_pool_start must be set if allocation_pool_end is set"
                 }
             )
+
+        if self.enable_pool:
+            if not self.allocation_pool_start and not self.allocation_pool_end:
+                raise ValidationError(
+                    {
+                        "allocation_pool_start": "allocation_pool_start must be set if enable_pool is True",
+                        "allocation_pool_end": "allocation_pool_end must be set if enable_pool is True",
+                    }
+                )
+            if not self.allocation_pool_start:
+                raise ValidationError(
+                    {
+                        "allocation_pool_start": "allocation_pool_start must be set if enable_pool is True",
+                    }
+                )
+            if not self.allocation_pool_end:
+                raise ValidationError(
+                    {
+                        "allocation_pool_end": "allocation_pool_end must be set if enable_pool is True",
+                    }
+                )
+
+        if self.allocation_pool_start and self.allocation_pool_end:
+            if (
+                not self.allocation_pool_start  # pylint:disable=unneeded-not # noqa: E501
+                < self.allocation_pool_end
+            ):
+                raise ValidationError(
+                    {
+                        "allocation_pool_start": "allocation_pool_start should be before allocation_pool_end",  # noqa: E501
+                        "allocation_pool_end": "allocation_pool_end should be after allocation_pool_start",  # noqa: E501
+                    }
+                )
+            if (
+                self.allocation_pool_start
+                not in self.subnet  # pylint:disable=unsupported-membership-test # noqa: E501
+            ):
+                raise ValidationError(
+                    {
+                        "allocation_pool_start": f"allocation_pool_start should be in subnet {self.subnet}",  # noqa: E501
+                    }
+                )
+            if (
+                self.allocation_pool_end
+                not in self.subnet  # pylint:disable=unsupported-membership-test # noqa: E501
+            ):
+                raise ValidationError(
+                    {
+                        "allocation_pool_end": f"allocation_pool_end should be in subnet {self.subnet}",  # noqa: E501
+                    }
+                )
         if (
             self.router
             not in self.subnet  # pylint:disable=unsupported-membership-test # noqa: E501
diff --git a/fleet/views.py b/fleet/views.py
index c86a940..b71805e 100644
--- a/fleet/views.py
+++ b/fleet/views.py
@@ -143,12 +143,6 @@ class DhcpConfigDiscovery(View):
                         lambda subnet: {
                             "id": subnet.id,
                             "subnet": str(subnet.subnet),
-                            "pools": [
-                                {
-                                    "pool": f"{subnet.allocation_pool_start} - {subnet.allocation_pool_end}"
-                                    # noqa: E501
-                                }
-                            ],
                             "option-data": [
                                 {
                                     "name": "domain-name",
@@ -176,7 +170,19 @@ class DhcpConfigDiscovery(View):
                                 ).select_related("machine")
                                 if hasattr(workstation, "machine")
                             ],
-                        },
+                        }
+                        | (
+                            {
+                                "pools": [
+                                    {
+                                        "pool": f"{subnet.allocation_pool_start} - {subnet.allocation_pool_end}"
+                                        # noqa: E501
+                                    }
+                                ],
+                            }
+                            if subnet.enable_pool
+                            else {}
+                        ),
                         DhcpSubnet.objects.all(),
                     )
                 ),
-- 
GitLab