aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/account/models.py31
-rw-r--r--src/api/models.py32
-rw-r--r--src/booking/models.py6
-rw-r--r--src/booking/quick_deployer.py2
-rw-r--r--src/resource_inventory/models.py2
-rw-r--r--src/templates/laas/dashboard/landing.html4
-rw-r--r--src/workflow/resource_bundle_workflow.py2
7 files changed, 42 insertions, 37 deletions
diff --git a/src/account/models.py b/src/account/models.py
index 03b31df..6828ee1 100644
--- a/src/account/models.py
+++ b/src/account/models.py
@@ -16,6 +16,8 @@ import random
from collections import Counter
+from dashboard.exceptions import ResourceAvailabilityException
+
class LabStatus(object):
"""
@@ -87,12 +89,25 @@ class VlanManager(models.Model):
"""
allocated = []
vlans = json.loads(self.vlans)
- for i in range(count):
- new_vlan = vlans.index(1) # will throw if none available
- vlans[new_vlan] = 0
- allocated.append(new_vlan)
- if count == 1:
- return allocated[0]
+ reserved = json.loads(self.reserved_vlans)
+
+ for i in range(0, len(vlans) - 1):
+ if len(allocated) >= count:
+ break
+
+ if vlans[i] == 0 and self.allow_overlapping is False:
+ continue
+
+ if reserved[i] == 1:
+ continue
+
+ # vlan is available and not reserved, so safe to add
+ allocated.append(i)
+ continue
+
+ if len(allocated) != count:
+ raise ResourceAvailabilityException("can't allocate the vlans requested")
+
return allocated
def get_public_vlan(self):
@@ -171,6 +186,8 @@ class VlanManager(models.Model):
"""
my_vlans = json.loads(self.vlans)
+ reserved = json.loads(self.reserved_vlans)
+
try:
iter(vlans)
except Exception:
@@ -179,7 +196,7 @@ class VlanManager(models.Model):
vlans = set(vlans)
for vlan in vlans:
- if my_vlans[vlan] == 0:
+ if my_vlans[vlan] == 0 or reserved[vlan] == 1:
raise ValueError("vlan " + str(vlan) + " is not available")
my_vlans[vlan] = 0
diff --git a/src/api/models.py b/src/api/models.py
index 8de3ec7..9b9b778 100644
--- a/src/api/models.py
+++ b/src/api/models.py
@@ -384,7 +384,7 @@ class Job(models.Model):
class TaskConfig(models.Model):
- state = models.IntegerField(default=ConfigState.CLEAN)
+ state = models.IntegerField(default=ConfigState.NEW)
keys = set() # TODO: This needs to be an instance variable, not a class variable
delta_keys_list = models.CharField(max_length=200, default="[]")
@@ -525,10 +525,7 @@ class OpnfvApiConfig(models.Model):
self.delta = '{}'
def get_delta(self):
- if not self.delta:
- self.delta = self.to_json()
- self.save()
- return json.loads(self.delta)
+ return json.loads(self.to_json())
class AccessConfig(TaskConfig):
@@ -550,10 +547,7 @@ class AccessConfig(TaskConfig):
return d
def get_delta(self):
- if not self.delta:
- self.delta = self.to_json()
- self.save()
- d = json.loads(self.delta)
+ d = json.loads(self.to_json())
d["lab_token"] = self.accessrelation.lab_token
return d
@@ -649,10 +643,11 @@ class NetworkConfig(TaskConfig):
d[hid] = {}
for interface in self.interfaces.all():
d[hid][interface.mac_address] = []
- for vlan in interface.config.all():
- # TODO: should this come from the interface?
- # e.g. will different interfaces for different resources need different configs?
- d[hid][interface.mac_address].append({"vlan_id": vlan.vlan_id, "tagged": vlan.tagged})
+ if self.state != ConfigState.CLEAN:
+ for vlan in interface.config.all():
+ # TODO: should this come from the interface?
+ # e.g. will different interfaces for different resources need different configs?
+ d[hid][interface.mac_address].append({"vlan_id": vlan.vlan_id, "tagged": vlan.tagged})
return d
@@ -660,10 +655,7 @@ class NetworkConfig(TaskConfig):
return json.dumps(self.to_dict())
def get_delta(self):
- if not self.delta:
- self.delta = self.to_json()
- self.save()
- d = json.loads(self.delta)
+ d = json.loads(self.to_json())
d['lab_token'] = self.hostnetworkrelation.lab_token
return d
@@ -703,11 +695,7 @@ class SnapshotConfig(TaskConfig):
return json.dumps(self.to_dict())
def get_delta(self):
- if not self.delta:
- self.delta = self.to_json()
- self.save()
-
- d = json.loads(self.delta)
+ d = json.loads(self.to_json())
return d
def clear_delta(self):
diff --git a/src/booking/models.py b/src/booking/models.py
index cf8bf1d..cfdf7bc 100644
--- a/src/booking/models.py
+++ b/src/booking/models.py
@@ -21,7 +21,7 @@ class Booking(models.Model):
# All bookings are owned by the user who requested it
owner = models.ForeignKey(User, on_delete=models.PROTECT, related_name='owner')
# an owner can add other users to the booking
- collaborators = models.ManyToManyField(User, related_name='collaborators')
+ collaborators = models.ManyToManyField(User, blank=True, related_name='collaborators')
# start and end time
start = models.DateTimeField()
end = models.DateTimeField()
@@ -32,8 +32,8 @@ class Booking(models.Model):
# bookings can be extended a limited number of times
ext_count = models.IntegerField(default=2)
# the hardware that the user has booked
- resource = models.ForeignKey(ResourceBundle, on_delete=models.SET_NULL, null=True)
- opnfv_config = models.ForeignKey(OPNFVConfig, on_delete=models.SET_NULL, null=True)
+ resource = models.ForeignKey(ResourceBundle, on_delete=models.SET_NULL, null=True, blank=True)
+ opnfv_config = models.ForeignKey(OPNFVConfig, on_delete=models.SET_NULL, null=True, blank=True)
project = models.CharField(max_length=100, default="", blank=True, null=True)
lab = models.ForeignKey(Lab, null=True, on_delete=models.SET_NULL)
pdf = models.TextField(blank=True, default="")
diff --git a/src/booking/quick_deployer.py b/src/booking/quick_deployer.py
index 0d4e5ea..8b3af6c 100644
--- a/src/booking/quick_deployer.py
+++ b/src/booking/quick_deployer.py
@@ -87,7 +87,7 @@ def update_template(old_template, image, hostname, user):
Network.objects.create(
name=old_network.name,
bundle=template,
- is_public=False
+ is_public=old_network.is_public
)
# We are assuming there is only one opnfv config per public resource template
old_opnfv = template.opnfv_config.first()
diff --git a/src/resource_inventory/models.py b/src/resource_inventory/models.py
index 4a6375d..7a1f259 100644
--- a/src/resource_inventory/models.py
+++ b/src/resource_inventory/models.py
@@ -122,7 +122,7 @@ class CpuProfile(models.Model):
])
cpus = models.IntegerField()
host = models.ForeignKey(ResourceProfile, on_delete=models.CASCADE, related_name='cpuprofile')
- cflags = models.TextField(null=True)
+ cflags = models.TextField(null=True, blank=True)
def __str__(self):
return str(self.architecture) + " " + str(self.cpus) + "S" + str(self.cores) + " C for " + str(self.host)
diff --git a/src/templates/laas/dashboard/landing.html b/src/templates/laas/dashboard/landing.html
index b1ac7c5..a8e0ff8 100644
--- a/src/templates/laas/dashboard/landing.html
+++ b/src/templates/laas/dashboard/landing.html
@@ -7,6 +7,6 @@
University of New Hampshire Interoperability Lab (UNH-IOL).</p>
<p>To get started, you can request access to a server at the right. PTL's have the ability to design and
book a
- whole block of servers with customized layer2 networks (e.g. a Pharos Pod). Read more here: <a
- href="https://wiki.opnfv.org/display/INF/Lab+as+a+Service+2.0">LaaS Wiki</a></p>
+ whole block of servers with customized layer2 networks (e.g. a Pharos Pod). Read more here:
+ <a href="https://wiki.opnfv.org/x/HAE-Ag" target="_blank">LaaS Wiki</a></p>
{% endblock about_us %}
diff --git a/src/workflow/resource_bundle_workflow.py b/src/workflow/resource_bundle_workflow.py
index 639e7a8..404224e 100644
--- a/src/workflow/resource_bundle_workflow.py
+++ b/src/workflow/resource_bundle_workflow.py
@@ -266,7 +266,7 @@ class Define_Software(WorkflowStep):
host.image = image
host.save()
- if not has_headnode:
+ if not has_headnode and len(hosts) > 0:
self.set_invalid("No headnode. Please set a headnode.")
return