aboutsummaryrefslogtreecommitdiffstats
path: root/src/account
diff options
context:
space:
mode:
Diffstat (limited to 'src/account')
-rw-r--r--src/account/jira_util.py2
-rw-r--r--src/account/middleware.py3
-rw-r--r--src/account/models.py67
-rw-r--r--src/account/tests/test_general.py6
-rw-r--r--src/account/urls.py3
-rw-r--r--src/account/views.py2
6 files changed, 77 insertions, 6 deletions
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
"""