From 77377d5e9362bd35a3b300df231e82ee974675e1 Mon Sep 17 00:00:00 2001 From: Parker Berberian Date: Thu, 19 Dec 2019 12:39:01 -0500 Subject: Comments and Documentation This change adds a ton of comments and documentation across all the code. Change-Id: Ifee0a2f534e8584f14b0f13af4dda8dc70eb7553 Signed-off-by: Parker Berberian --- src/booking/forms.py | 2 ++ src/booking/models.py | 7 +++++++ src/booking/quick_deployer.py | 39 +++++++++++++++++++++++++++++++++++++++ src/booking/stats.py | 2 ++ src/booking/tests/test_models.py | 16 ++++++++++++++++ src/booking/urls.py | 3 ++- 6 files changed, 68 insertions(+), 1 deletion(-) (limited to 'src/booking') 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/ -- cgit 1.2.3-korg