diff options
-rw-r--r-- | src/account/models.py | 31 | ||||
-rw-r--r-- | src/api/models.py | 32 | ||||
-rw-r--r-- | src/booking/models.py | 6 | ||||
-rw-r--r-- | src/booking/quick_deployer.py | 2 | ||||
-rw-r--r-- | src/resource_inventory/models.py | 2 | ||||
-rw-r--r-- | src/templates/laas/dashboard/landing.html | 4 | ||||
-rw-r--r-- | src/workflow/resource_bundle_workflow.py | 2 |
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 |