aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/account/models.py23
-rw-r--r--src/resource_inventory/migrations/0022_auto_20210925_2028.py23
-rw-r--r--src/resource_inventory/models.py18
-rw-r--r--src/resource_inventory/resource_manager.py5
4 files changed, 62 insertions, 7 deletions
diff --git a/src/account/models.py b/src/account/models.py
index b71f0ac..2501be6 100644
--- a/src/account/models.py
+++ b/src/account/models.py
@@ -82,12 +82,14 @@ class VlanManager(models.Model):
# if they use QinQ or a vxlan overlay, for example
allow_overlapping = models.BooleanField()
- def get_vlans(self, count=1):
+ def get_vlans(self, count=1, within=None):
"""
Return the IDs of available vlans as a list[int], but does not reserve them.
Will throw index exception if not enough vlans are available.
Always returns a list of ints
+
+ If `within` is not none, will filter against that as a set, requiring that any vlans returned are within that set
"""
allocated = []
vlans = json.loads(self.vlans)
@@ -104,17 +106,28 @@ class VlanManager(models.Model):
continue
# vlan is available and not reserved, so safe to add
- allocated.append(i)
+ if within is not None:
+ if i in within:
+ allocated.append(i)
+ else:
+ allocated.append(i)
continue
if len(allocated) != count:
- raise ResourceAvailabilityException("can't allocate the vlans requested")
+ raise ResourceAvailabilityException("There were not enough available private vlans for the allocation. Please contact the administrators.")
return allocated
- def get_public_vlan(self):
+ def get_public_vlan(self, within=None):
"""Return reference to an available public network without reserving it."""
- return PublicNetwork.objects.filter(lab=self.lab_set.first(), in_use=False).first()
+ r = PublicNetwork.objects.filter(lab=self.lab_set.first(), in_use=False)
+ if within is not None:
+ r = r.filter(vlan__in=within)
+
+ if r.count() < 1:
+ raise ResourceAvailabilityException("There were not enough available public vlans for the allocation. Please contact the administrators.")
+
+ return r.first()
def reserve_public_vlan(self, vlan):
"""Reserves the Public Network that has the given vlan."""
diff --git a/src/resource_inventory/migrations/0022_auto_20210925_2028.py b/src/resource_inventory/migrations/0022_auto_20210925_2028.py
new file mode 100644
index 0000000..2b0b902
--- /dev/null
+++ b/src/resource_inventory/migrations/0022_auto_20210925_2028.py
@@ -0,0 +1,23 @@
+# Generated by Django 2.2 on 2021-09-25 20:28
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('resource_inventory', '0021_resourceconfiguration_cloud_init_files'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='resourcetemplate',
+ name='private_vlan_pool',
+ field=models.TextField(default=''),
+ ),
+ migrations.AddField(
+ model_name='resourcetemplate',
+ name='public_vlan_pool',
+ field=models.TextField(default=''),
+ ),
+ ]
diff --git a/src/resource_inventory/models.py b/src/resource_inventory/models.py
index 2c631dc..1505f02 100644
--- a/src/resource_inventory/models.py
+++ b/src/resource_inventory/models.py
@@ -193,6 +193,24 @@ class ResourceTemplate(models.Model):
temporary = models.BooleanField(default=False)
copy_of = models.ForeignKey("ResourceTemplate", blank=True, null=True, on_delete=models.SET_NULL)
+ # if these fields are empty ("") then they are implicitly "every vlan",
+ # otherwise we filter any allocations we try to instantiate against this list
+ # they should be represented as a json list of integers
+ private_vlan_pool = models.TextField(default="")
+ public_vlan_pool = models.TextField(default="")
+
+ def private_vlan_pool_set(self):
+ if self.private_vlan_pool != "":
+ return set(json.loads(self.private_vlan_pool))
+ else:
+ return None
+
+ def public_vlan_pool_set(self):
+ if self.private_vlan_pool != "":
+ return set(json.loads(self.public_vlan_pool))
+ else:
+ return None
+
def getConfigs(self):
configs = self.resourceConfigurations.all()
return list(configs)
diff --git a/src/resource_inventory/resource_manager.py b/src/resource_inventory/resource_manager.py
index 9406977..14a118c 100644
--- a/src/resource_inventory/resource_manager.py
+++ b/src/resource_inventory/resource_manager.py
@@ -74,12 +74,13 @@ class ResourceManager:
vlan_manager = resourceTemplate.lab.vlan_manager
for network in resourceTemplate.networks.all():
if network.is_public:
- public_net = vlan_manager.get_public_vlan()
+ # already throws if can't get requested count, so can always expect public_net to be Some
+ public_net = vlan_manager.get_public_vlan(within=resourceTemplate.public_vlan_pool_set())
vlan_manager.reserve_public_vlan(public_net.vlan)
networks[network.name] = public_net.vlan
else:
# already throws if can't get requested count, so can always index in @ 0
- vlans = vlan_manager.get_vlans(count=1)
+ vlans = vlan_manager.get_vlans(count=1, within=resourceTemplate.private_vlan_pool_set())
vlan_manager.reserve_vlans(vlans[0])
networks[network.name] = vlans[0]
return networks