aboutsummaryrefslogtreecommitdiffstats
path: root/src/booking
diff options
context:
space:
mode:
Diffstat (limited to 'src/booking')
-rw-r--r--src/booking/forms.py2
-rw-r--r--src/booking/models.py7
-rw-r--r--src/booking/quick_deployer.py39
-rw-r--r--src/booking/stats.py2
-rw-r--r--src/booking/tests/test_models.py16
-rw-r--r--src/booking/urls.py3
6 files changed, 68 insertions, 1 deletions
diff --git a/src/booking/forms.py b/src/booking/forms.py
index df88cc6..9b4db86 100644
--- a/src/booking/forms.py
+++ b/src/booking/forms.py
@@ -62,6 +62,8 @@ class QuickBookingForm(forms.Form):
def build_user_list(self):
"""
+ Build list of UserProfiles.
+
returns a mapping of UserProfile ids to displayable objects expected by
searchable multiple select widget
"""
diff --git a/src/booking/models.py b/src/booking/models.py
index 9836730..8f2446f 100644
--- a/src/booking/models.py
+++ b/src/booking/models.py
@@ -18,16 +18,22 @@ import resource_inventory.resource_manager
class Booking(models.Model):
id = models.AutoField(primary_key=True)
+ # 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')
+ # start and end time
start = models.DateTimeField()
end = models.DateTimeField()
reset = models.BooleanField(default=False)
jira_issue_id = models.IntegerField(null=True, blank=True)
jira_issue_status = models.CharField(max_length=50, blank=True)
purpose = models.CharField(max_length=300, blank=False)
+ # 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)
+ # configuration for the above hardware
config_bundle = models.ForeignKey(ConfigBundle, on_delete=models.SET_NULL, null=True)
opnfv_config = models.ForeignKey(OPNFVConfig, on_delete=models.SET_NULL, null=True)
project = models.CharField(max_length=100, default="", blank=True, null=True)
@@ -41,6 +47,7 @@ class Booking(models.Model):
def save(self, *args, **kwargs):
"""
Save the booking if self.user is authorized and there is no overlapping booking.
+
Raise PermissionError if the user is not authorized
Raise ValueError if there is an overlapping booking
"""
diff --git a/src/booking/quick_deployer.py b/src/booking/quick_deployer.py
index 4ec488e..743cdcf 100644
--- a/src/booking/quick_deployer.py
+++ b/src/booking/quick_deployer.py
@@ -97,6 +97,11 @@ class BookingPermissionException(Exception):
def parse_host_field(host_json):
+ """
+ Parse the json from the frontend.
+
+ returns a reference to the selected Lab and HostProfile objects
+ """
lab, profile = (None, None)
lab_dict = host_json['lab']
for lab_info in lab_dict.values():
@@ -117,6 +122,12 @@ def parse_host_field(host_json):
def check_available_matching_host(lab, hostprofile):
+ """
+ Check the resources are available.
+
+ Returns true if the requested host type is availble,
+ Or throws an exception
+ """
available_host_types = ResourceManager.getInstance().getAvailableHostTypes(lab)
if hostprofile not in available_host_types:
# TODO: handle deleting generic resource in this instance along with grb
@@ -129,7 +140,10 @@ def check_available_matching_host(lab, hostprofile):
return True
+# Functions to create models
+
def generate_grb(owner, lab, common_id):
+ """Create a Generic Resource Bundle."""
grbundle = GenericResourceBundle(owner=owner)
grbundle.lab = lab
grbundle.name = "grbundle for quick booking with uid " + common_id
@@ -140,6 +154,7 @@ def generate_grb(owner, lab, common_id):
def generate_gresource(bundle, hostname):
+ """Create a Generic Resource."""
if not re.match(r"(?=^.{1,253}$)(^([A-Za-z0-9-_]{1,62}\.)*[A-Za-z0-9-_]{1,63})$", hostname):
raise InvalidHostnameException("Hostname must comply to RFC 952 and all extensions to it until this point")
gresource = GenericResource(bundle=bundle, name=hostname)
@@ -149,6 +164,7 @@ def generate_gresource(bundle, hostname):
def generate_ghost(generic_resource, host_profile):
+ """Create a Generic Host."""
ghost = GenericHost()
ghost.resource = generic_resource
ghost.profile = host_profile
@@ -158,6 +174,7 @@ def generate_ghost(generic_resource, host_profile):
def generate_config_bundle(owner, common_id, grbundle):
+ """Create a Configuration Bundle."""
cbundle = ConfigBundle()
cbundle.owner = owner
cbundle.name = "configbundle for quick booking with uid " + common_id
@@ -169,6 +186,7 @@ def generate_config_bundle(owner, common_id, grbundle):
def generate_opnfvconfig(scenario, installer, config_bundle):
+ """Create an OPNFV Configuration."""
opnfvconfig = OPNFVConfig()
opnfvconfig.scenario = scenario
opnfvconfig.installer = installer
@@ -179,6 +197,7 @@ def generate_opnfvconfig(scenario, installer, config_bundle):
def generate_hostconfig(generic_host, image, config_bundle):
+ """Create a Host Configuration."""
hconf = HostConfiguration()
hconf.host = generic_host
hconf.image = image
@@ -190,6 +209,7 @@ def generate_hostconfig(generic_host, image, config_bundle):
def generate_hostopnfv(hostconfig, opnfvconfig):
+ """Relate the Host and OPNFV Configs."""
config = HostOPNFVConfig()
role = None
try:
@@ -207,6 +227,7 @@ def generate_hostopnfv(hostconfig, opnfvconfig):
def generate_resource_bundle(generic_resource_bundle, config_bundle): # warning: requires cleanup
+ """Create a Resource Bundle."""
try:
resource_manager = ResourceManager.getInstance()
resource_bundle = resource_manager.convertResourceBundle(generic_resource_bundle, config=config_bundle)
@@ -218,6 +239,11 @@ def generate_resource_bundle(generic_resource_bundle, config_bundle): # warning
def check_invariants(request, **kwargs):
+ """
+ Verify all the contraints on the requested booking.
+
+ verifies software compatibility, booking length, etc
+ """
installer = kwargs['installer']
image = kwargs['image']
scenario = kwargs['scenario']
@@ -256,6 +282,12 @@ def configure_networking(grb, config):
def create_from_form(form, request):
+ """
+ Create a Booking from the user's form.
+
+ Large, nasty method to create a booking or return a useful error
+ based on the form from the frontend
+ """
quick_booking_id = str(uuid.uuid4())
host_field = form.cleaned_data['filter_field']
@@ -330,6 +362,13 @@ def create_from_form(form, request):
def drop_filter(user):
+ """
+ Return a dictionary that contains filters.
+
+ Only certain installlers are supported on certain images, etc
+ so the image filter indexed at [imageid][installerid] is truthy if
+ that installer is supported on that image
+ """
installer_filter = {}
for image in Image.objects.all():
installer_filter[image.id] = {}
diff --git a/src/booking/stats.py b/src/booking/stats.py
index 383723a..47de80b 100644
--- a/src/booking/stats.py
+++ b/src/booking/stats.py
@@ -16,6 +16,8 @@ class StatisticsManager(object):
@staticmethod
def getContinuousBookingTimeSeries(span=28):
"""
+ Calculate Booking usage data points.
+
Will return a dictionary of names and 2-D array of x and y data points.
e.g. {"plot1": [["x1", "x2", "x3"],["y1", "y2", "y3]]}
x values will be dates in string
diff --git a/src/booking/tests/test_models.py b/src/booking/tests/test_models.py
index 6170295..c8c8ea8 100644
--- a/src/booking/tests/test_models.py
+++ b/src/booking/tests/test_models.py
@@ -21,10 +21,20 @@ from resource_inventory.models import ResourceBundle, GenericResourceBundle, Con
class BookingModelTestCase(TestCase):
+ """
+ Test the Booking model.
+
+ Creates all the scafolding needed and tests the Booking model
+ """
count = 0
def setUp(self):
+ """
+ Prepare for Booking model tests.
+
+ Creates all the needed models, such as users, resources, and configurations
+ """
self.owner = User.objects.create(username='owner')
self.res1 = ResourceBundle.objects.create(
@@ -52,6 +62,8 @@ class BookingModelTestCase(TestCase):
def test_start_end(self):
"""
+ Verify the start and end fields.
+
if the start of a booking is greater or equal then the end,
saving should raise a ValueException
"""
@@ -79,6 +91,8 @@ class BookingModelTestCase(TestCase):
def test_conflicts(self):
"""
+ Verify conflicting dates are dealt with.
+
saving an overlapping booking on the same resource
should raise a ValueException
saving for different resources should succeed
@@ -207,6 +221,8 @@ class BookingModelTestCase(TestCase):
def test_extensions(self):
"""
+ Test booking extensions.
+
saving a booking with an extended end time is allows to happen twice,
and each extension must be a maximum of one week long
"""
diff --git a/src/booking/urls.py b/src/booking/urls.py
index 54e29c9..d5287e9 100644
--- a/src/booking/urls.py
+++ b/src/booking/urls.py
@@ -9,7 +9,8 @@
##############################################################################
-"""laas_dashboard URL Configuration
+"""
+laas_dashboard URL Configuration.
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/1.10/topics/http/urls/