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/account/jira_util.py | 2 +- src/account/middleware.py | 3 ++ src/account/models.py | 67 +++++++++++++++++++++++++++++++++++++-- src/account/tests/test_general.py | 6 ++-- src/account/urls.py | 3 +- src/account/views.py | 2 ++ 6 files changed, 77 insertions(+), 6 deletions(-) (limited to 'src/account') diff --git a/src/account/jira_util.py b/src/account/jira_util.py index 18b0e26..a522594 100644 --- a/src/account/jira_util.py +++ b/src/account/jira_util.py @@ -37,7 +37,7 @@ class SignatureMethod_RSA_SHA1(oauth.SignatureMethod): return key, raw def sign(self, request, consumer, token): - """Builds the base signature string.""" + """Build the base signature string.""" key, raw = self.signing_base(request, consumer, token) module_dir = os.path.dirname(__file__) # get current directory diff --git a/src/account/middleware.py b/src/account/middleware.py index 0f1dbd8..6a46dfe 100644 --- a/src/account/middleware.py +++ b/src/account/middleware.py @@ -16,9 +16,12 @@ from account.models import UserProfile class TimezoneMiddleware(MiddlewareMixin): """ + Manage user's Timezone preference. + Activate the timezone from request.user.userprofile if user is authenticated, deactivate the timezone otherwise and use default (UTC) """ + def process_request(self, request): if request.user.is_authenticated: try: diff --git a/src/account/models.py b/src/account/models.py index 4862231..294e109 100644 --- a/src/account/models.py +++ b/src/account/models.py @@ -15,6 +15,14 @@ import random class LabStatus(object): + """ + A Poor man's enum for the status of a lab. + + If everything is working fine at a lab, it is UP. + If it is down temporarily e.g. for maintenance, it is TEMP_DOWN + If its broken, its DOWN + """ + UP = 0 TEMP_DOWN = 100 DOWN = 200 @@ -25,6 +33,8 @@ def upload_to(object, filename): class UserProfile(models.Model): + """Extend the Django User model.""" + user = models.OneToOneField(User, on_delete=models.CASCADE) timezone = models.CharField(max_length=100, blank=False, default='UTC') ssh_public_key = models.FileField(upload_to=upload_to, null=True, blank=True) @@ -47,14 +57,31 @@ class UserProfile(models.Model): class VlanManager(models.Model): + """ + Keeps track of the vlans for a lab. + + Vlans are represented as indexes into a 4096 element list. + This list is serialized to JSON for storing in the DB. + """ + # list of length 4096 containing either 0 (not available) or 1 (available) vlans = models.TextField() + # list of length 4096 containing either 0 (not reserved) or 1 (reserved) + reserved_vlans = models.TextField() + block_size = models.IntegerField() + + # True if the lab allows two different users to have the same private vlans + # if they use QinQ or a vxlan overlay, for example allow_overlapping = models.BooleanField() - # list of length 4096 containing either 0 (not rexerved) or 1 (reserved) - reserved_vlans = models.TextField() def get_vlan(self, count=1): + """ + Return the ID of available vlans, but does not reserve them. + + Will throw index exception if not enough vlans are available. + If count == 1, the return value is an int. Otherwise, it is a list of ints. + """ allocated = [] vlans = json.loads(self.vlans) for i in range(count): @@ -66,24 +93,35 @@ class VlanManager(models.Model): return allocated def get_public_vlan(self): + """Return reference to an available public network without reserving it.""" return PublicNetwork.objects.filter(lab=self.lab_set.first(), in_use=False).first() def reserve_public_vlan(self, vlan): + """Reserves the Public Network that has the given vlan.""" net = PublicNetwork.objects.get(lab=self.lab_set.first(), vlan=vlan, in_use=False) net.in_use = True net.save() def release_public_vlan(self, vlan): + """Un-reserves a public network with the given vlan.""" net = PublicNetwork.objects.get(lab=self.lab_set.first(), vlan=vlan, in_use=True) net.in_use = False net.save() def public_vlan_is_available(self, vlan): + """ + Whether the public vlan is available. + + returns true if the network with the given vlan is free to use, + False otherwise + """ net = PublicNetwork.objects.get(lab=self.lab_set.first(), vlan=vlan) return not net.in_use def is_available(self, vlans): """ + If the vlans are available. + 'vlans' is either a single vlan id integer or a list of integers will return true (available) or false """ @@ -104,6 +142,8 @@ class VlanManager(models.Model): def release_vlans(self, vlans): """ + Make the vlans available for another booking. + 'vlans' is either a single vlan id integer or a list of integers will make the vlans available doesnt return a value @@ -121,6 +161,11 @@ class VlanManager(models.Model): self.save() def reserve_vlans(self, vlans): + """ + Reserves all given vlans or throws a ValueError. + + vlans can be an integer or a list of integers. + """ my_vlans = json.loads(self.vlans) try: @@ -140,6 +185,13 @@ class VlanManager(models.Model): class Lab(models.Model): + """ + Model representing a Hosting Lab. + + Anybody that wants to host resources for LaaS needs to have a Lab model + We associate hardware with Labs so we know what is available and where. + """ + lab_user = models.OneToOneField(User, on_delete=models.CASCADE) name = models.CharField(max_length=200, primary_key=True, unique=True, null=False, blank=False) contact_email = models.EmailField(max_length=200, null=True, blank=True) @@ -147,11 +199,13 @@ class Lab(models.Model): status = models.IntegerField(default=LabStatus.UP) vlan_manager = models.ForeignKey(VlanManager, on_delete=models.CASCADE, null=True) location = models.TextField(default="unknown") + # This token must apear in API requests from this lab api_token = models.CharField(max_length=50) description = models.CharField(max_length=240) @staticmethod def make_api_token(): + """Generate random 45 character string for API token.""" alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" key = "" for i in range(45): @@ -163,6 +217,8 @@ class Lab(models.Model): class PublicNetwork(models.Model): + """L2/L3 network that can reach the internet.""" + vlan = models.IntegerField() lab = models.ForeignKey(Lab, on_delete=models.CASCADE) in_use = models.BooleanField(default=False) @@ -171,6 +227,13 @@ class PublicNetwork(models.Model): class Downtime(models.Model): + """ + A Downtime event. + + Labs can create Downtime objects so the dashboard can + alert users that the lab is down, etc + """ + start = models.DateTimeField() end = models.DateTimeField() lab = models.ForeignKey(Lab, on_delete=models.CASCADE) diff --git a/src/account/tests/test_general.py b/src/account/tests/test_general.py index 3fb52b0..4020d89 100644 --- a/src/account/tests/test_general.py +++ b/src/account/tests/test_general.py @@ -27,8 +27,10 @@ class AccountMiddlewareTestCase(TestCase): def test_timezone_middleware(self): """ - The timezone should be UTC for anonymous users, for authenticated users it should be set - to user.userprofile.timezone + Verify timezone is being set by Middleware. + + The timezone should be UTC for anonymous users, + for authenticated users it should be set to user.userprofile.timezone """ # default self.assertEqual(timezone.get_current_timezone_name(), 'UTC') diff --git a/src/account/urls.py b/src/account/urls.py index 47400e5..0c01ee0 100644 --- a/src/account/urls.py +++ b/src/account/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/ diff --git a/src/account/views.py b/src/account/views.py index 5b91550..ccc4c8d 100644 --- a/src/account/views.py +++ b/src/account/views.py @@ -169,6 +169,8 @@ def account_detail_view(request): def account_resource_view(request): """ + Display a user's resources. + gathers a users genericResoureBundles and turns them into displayable objects """ -- cgit 1.2.3-korg