aboutsummaryrefslogtreecommitdiffstats
path: root/src/account
diff options
context:
space:
mode:
Diffstat (limited to 'src/account')
-rw-r--r--src/account/admin.py4
-rw-r--r--src/account/migrations/0010_auto_20230608_1913.py23
-rw-r--r--src/account/models.py178
-rw-r--r--src/account/tests/__init__.py8
-rw-r--r--src/account/tests/test_general.py60
-rw-r--r--src/account/urls.py4
-rw-r--r--src/account/views.py82
7 files changed, 52 insertions, 307 deletions
diff --git a/src/account/admin.py b/src/account/admin.py
index b4c142c..fd03e60 100644
--- a/src/account/admin.py
+++ b/src/account/admin.py
@@ -11,9 +11,7 @@
from django.contrib import admin
-from account.models import UserProfile, Lab, VlanManager, PublicNetwork
+from account.models import UserProfile, Lab
admin.site.register(UserProfile)
admin.site.register(Lab)
-admin.site.register(VlanManager)
-admin.site.register(PublicNetwork)
diff --git a/src/account/migrations/0010_auto_20230608_1913.py b/src/account/migrations/0010_auto_20230608_1913.py
new file mode 100644
index 0000000..3e597b9
--- /dev/null
+++ b/src/account/migrations/0010_auto_20230608_1913.py
@@ -0,0 +1,23 @@
+# Generated by Django 2.2 on 2023-06-08 19:13
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('account', '0009_auto_20210324_2107'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='lab',
+ name='vlan_manager',
+ ),
+ migrations.DeleteModel(
+ name='PublicNetwork',
+ ),
+ migrations.DeleteModel(
+ name='VlanManager',
+ ),
+ ]
diff --git a/src/account/models.py b/src/account/models.py
index 32229b1..f1deca7 100644
--- a/src/account/models.py
+++ b/src/account/models.py
@@ -16,9 +16,6 @@ import random
from collections import Counter
-from dashboard.exceptions import ResourceAvailabilityException
-
-
class LabStatus(object):
"""
A Poor man's enum for the status of a lab.
@@ -63,163 +60,6 @@ class UserProfile(models.Model):
def __str__(self):
return self.user.username
-
-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()
-
- def get_vlans(self, count=1, within=None):
- """
- Return the IDs of available vlans as a list[int], but does not reserve them.
-
- Will throw index exception if not enough vlans are available.
- Always returns a list of ints
-
- If `within` is not none, will filter against that as a set, requiring that any vlans returned are within that set
- """
- allocated = []
- vlans = json.loads(self.vlans)
- 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
- if within is not None:
- if i in within:
- allocated.append(i)
- else:
- allocated.append(i)
- continue
-
- if len(allocated) != count:
- raise ResourceAvailabilityException("There were not enough available private vlans for the allocation. Please contact the administrators.")
-
- return allocated
-
- def get_public_vlan(self, within=None):
- """Return reference to an available public network without reserving it."""
- r = PublicNetwork.objects.filter(lab=self.lab_set.first(), in_use=False)
- if within is not None:
- r = r.filter(vlan__in=within)
-
- if r.count() < 1:
- raise ResourceAvailabilityException("There were not enough available public vlans for the allocation. Please contact the administrators.")
-
- return r.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
- """
- if self.allow_overlapping:
- return True
-
- reserved = json.loads(self.reserved_vlans)
- vlan_master_list = json.loads(self.vlans)
- try:
- iter(vlans)
- except Exception:
- vlans = [vlans]
-
- for vlan in vlans:
- if not vlan_master_list[vlan] or reserved[vlan]:
- return False
- return True
-
- 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
- """
- my_vlans = json.loads(self.vlans)
-
- try:
- iter(vlans)
- except Exception:
- vlans = [vlans]
-
- for vlan in vlans:
- my_vlans[vlan] = 1
- self.vlans = json.dumps(my_vlans)
- 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)
-
- reserved = json.loads(self.reserved_vlans)
-
- try:
- iter(vlans)
- except Exception:
- vlans = [vlans]
-
- vlans = set(vlans)
-
- for vlan in vlans:
- if my_vlans[vlan] == 0 or reserved[vlan] == 1:
- raise ValueError("vlan " + str(vlan) + " is not available")
-
- my_vlans[vlan] = 0
- self.vlans = json.dumps(my_vlans)
- self.save()
-
-
class Lab(models.Model):
"""
Model representing a Hosting Lab.
@@ -233,7 +73,6 @@ class Lab(models.Model):
contact_email = models.EmailField(max_length=200, null=True, blank=True)
contact_phone = models.CharField(max_length=20, null=True, blank=True)
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)
@@ -250,26 +89,9 @@ class Lab(models.Model):
key += random.choice(alphabet)
return key
- def get_available_resources(self):
- # Cannot import model normally due to ciruclar import
- Server = apps.get_model('resource_inventory', 'Server') # TODO: Find way to import ResourceQuery
- resources = [str(resource.profile) for resource in Server.objects.filter(lab=self, working=True, booked=False)]
- return dict(Counter(resources))
-
def __str__(self):
return self.name
-
-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)
- cidr = models.CharField(max_length=50, default="0.0.0.0/0")
- gateway = models.CharField(max_length=50, default="0.0.0.0")
-
-
class Downtime(models.Model):
"""
A Downtime event.
diff --git a/src/account/tests/__init__.py b/src/account/tests/__init__.py
deleted file mode 100644
index b6fef6c..0000000
--- a/src/account/tests/__init__.py
+++ /dev/null
@@ -1,8 +0,0 @@
-##############################################################################
-# Copyright (c) 2016 Max Breitenfeldt and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-##############################################################################
diff --git a/src/account/tests/test_general.py b/src/account/tests/test_general.py
deleted file mode 100644
index 4020d89..0000000
--- a/src/account/tests/test_general.py
+++ /dev/null
@@ -1,60 +0,0 @@
-##############################################################################
-# Copyright (c) 2016 Max Breitenfeldt and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-##############################################################################
-
-
-from django.contrib.auth.models import User
-from django.test import Client
-from django.test import TestCase
-from django.urls import reverse
-from django.utils import timezone
-
-from account.models import UserProfile
-
-
-class AccountMiddlewareTestCase(TestCase):
- def setUp(self):
- self.client = Client()
- self.user1 = User.objects.create(username='user1')
- self.user1.set_password('user1')
- self.user1profile = UserProfile.objects.create(user=self.user1)
- self.user1.save()
-
- def test_timezone_middleware(self):
- """
- 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')
-
- url = reverse('account:settings')
- # anonymous request
- self.client.get(url)
- self.assertEqual(timezone.get_current_timezone_name(), 'UTC')
-
- # authenticated user with UTC timezone (userprofile default)
- self.client.login(username='user1', password='user1')
- self.client.get(url)
- self.assertEqual(timezone.get_current_timezone_name(), 'UTC')
-
- # authenticated user with custom timezone (userprofile default)
- self.user1profile.timezone = 'Etc/Greenwich'
- self.user1profile.save()
- self.client.get(url)
- self.assertEqual(timezone.get_current_timezone_name(), 'GMT')
-
- # if there is no profile for a user, it should be created
- user2 = User.objects.create(username='user2')
- user2.set_password('user2')
- user2.save()
- self.client.login(username='user2', password='user2')
- self.client.get(url)
- self.assertTrue(user2.userprofile)
diff --git a/src/account/urls.py b/src/account/urls.py
index 6d4ef2f..23ce122 100644
--- a/src/account/urls.py
+++ b/src/account/urls.py
@@ -35,11 +35,9 @@ from account.views import (
UserListView,
account_resource_view,
account_booking_view,
- account_images_view,
account_detail_view,
template_delete_view,
booking_cancel_view,
- image_delete_view,
)
app_name = 'account'
@@ -53,7 +51,5 @@ urlpatterns = [
path('my/resources/delete/<int:resource_id>', template_delete_view),
url(r'^my/bookings/$', account_booking_view, name='my-bookings'),
path('my/bookings/cancel/<int:booking_id>', booking_cancel_view),
- url(r'^my/images/$', account_images_view, name='my-images'),
- path('my/images/delete/<int:image_id>', image_delete_view),
url(r'^my/$', account_detail_view, name='my-account'),
]
diff --git a/src/account/views.py b/src/account/views.py
index 8976ff9..2d280cd 100644
--- a/src/account/views.py
+++ b/src/account/views.py
@@ -9,6 +9,7 @@
##############################################################################
+import json
import os
from django.utils import timezone
@@ -30,9 +31,7 @@ from mozilla_django_oidc.auth import OIDCAuthenticationBackend
from account.forms import AccountSettingsForm
from account.models import UserProfile
from booking.models import Booking
-from resource_inventory.models import ResourceTemplate, Image
-
-
+from api.views import delete_template, liblaas_templates
@method_decorator(login_required, name='dispatch')
class AccountSettingsView(UpdateView):
model = UserProfile
@@ -134,17 +133,21 @@ def account_resource_view(request):
return render(request, "dashboard/login.html", {'title': 'Authentication Required'})
template = "account/resource_list.html"
- active_bundles = [book.resource for book in Booking.objects.filter(
- owner=request.user, end__gte=timezone.now(), resource__template__temporary=False)]
- active_resources = [bundle.template.id for bundle in active_bundles]
- resource_list = list(ResourceTemplate.objects.filter(owner=request.user, temporary=False))
+ if request.method == "GET":
- context = {
- "resources": resource_list,
- "active_resources": active_resources,
- "title": "My Resources"
- }
- return render(request, template, context=context)
+ r = liblaas_templates(request)
+ usable_templates = r.json()
+ user_templates = [ t for t in usable_templates if t["owner"] == str(request.user)]
+ context = {
+ "templates": user_templates,
+ "title": "My Resources"
+ }
+ return render(request, template, context=context)
+
+ if request.method == "POST":
+ return delete_template(request)
+
+ return HttpResponse(status_code=405)
def account_booking_view(request):
@@ -165,37 +168,20 @@ def account_booking_view(request):
return render(request, template, context=context)
-def account_images_view(request):
- if not request.user.is_authenticated:
- return render(request, "dashboard/login.html", {'title': 'Authentication Required'})
- template = "account/image_list.html"
- my_images = Image.objects.filter(owner=request.user)
- public_images = Image.objects.filter(public=True)
- used_images = {}
- for image in my_images:
- if image.in_use():
- used_images[image.id] = "true"
- context = {
- "title": "Images",
- "images": my_images,
- "public_images": public_images,
- "used_images": used_images
- }
- return render(request, template, context=context)
-
def template_delete_view(request, resource_id=None):
- if not request.user.is_authenticated:
- return HttpResponse(status=403)
- template = get_object_or_404(ResourceTemplate, pk=resource_id)
- if not request.user.id == template.owner.id:
- return HttpResponse(status=403)
- if Booking.objects.filter(resource__template=template, end__gt=timezone.now()).exists():
- return HttpResponse(status=403)
- template.public = False
- template.temporary = True
- template.save()
- return HttpResponse(status=200)
+ # if not request.user.is_authenticated:
+ # return HttpResponse(status=403)
+ # template = get_object_or_404(ResourceTemplate, pk=resource_id)
+ # if not request.user.id == template.owner.id:
+ # return HttpResponse(status=403)
+ # if Booking.objects.filter(resource__template=template, end__gt=timezone.now()).exists():
+ # return HttpResponse(status=403)
+ # template.public = False
+ # template.temporary = True
+ # template.save()
+ # return HttpResponse(status=200)
+ return HttpResponse(status=404) # todo - LL Integration
def booking_cancel_view(request, booking_id=None):
@@ -212,15 +198,3 @@ def booking_cancel_view(request, booking_id=None):
booking.save()
return HttpResponse('')
-
-def image_delete_view(request, image_id=None):
- if not request.user.is_authenticated:
- return HttpResponse('no') # 403?
- image = get_object_or_404(Image, pk=image_id)
- if image.public or image.owner.id != request.user.id:
- return HttpResponse('no') # 403?
- # check if used in booking
- if image.in_use():
- return HttpResponse('no') # 403?
- image.delete()
- return HttpResponse('')