summaryrefslogtreecommitdiffstats
path: root/dashboard
diff options
context:
space:
mode:
Diffstat (limited to 'dashboard')
-rw-r--r--dashboard/__init__.py2
-rw-r--r--dashboard/src/__init__.py2
-rw-r--r--dashboard/src/account/__init__.py2
-rw-r--r--dashboard/src/account/jira_util.py2
-rw-r--r--dashboard/src/account/models.py4
-rw-r--r--dashboard/src/account/tests/__init__.py2
-rw-r--r--dashboard/src/account/tests/test_general.py4
-rw-r--r--dashboard/src/account/urls.py13
-rw-r--r--dashboard/src/account/views.py15
-rw-r--r--dashboard/src/api/__init__.py2
-rw-r--r--dashboard/src/api/admin.py13
-rw-r--r--dashboard/src/api/models.py114
-rw-r--r--dashboard/src/api/serializers/booking_serializer.py37
-rw-r--r--dashboard/src/api/tests/__init__.py2
-rw-r--r--dashboard/src/api/tests/test_serializers.py80
-rw-r--r--dashboard/src/api/urls.py14
-rw-r--r--dashboard/src/api/views.py6
-rw-r--r--dashboard/src/booking/admin.py2
-rw-r--r--dashboard/src/booking/models.py7
-rw-r--r--dashboard/src/booking/stats.py10
-rw-r--r--dashboard/src/booking/tests/test_models.py63
-rw-r--r--dashboard/src/booking/urls.py9
-rw-r--r--dashboard/src/booking/views.py28
-rw-r--r--dashboard/src/dashboard/context_processors.py1
-rw-r--r--dashboard/src/dashboard/exceptions.py6
-rw-r--r--dashboard/src/dashboard/populate_db_iol.py228
-rw-r--r--dashboard/src/dashboard/tasks.py20
-rw-r--r--dashboard/src/dashboard/templatetags/__init__.py2
-rw-r--r--dashboard/src/dashboard/tests/__init__.py2
-rw-r--r--dashboard/src/dashboard/urls.py9
-rw-r--r--dashboard/src/dashboard/views.py39
-rwxr-xr-xdashboard/src/manage.py3
-rw-r--r--dashboard/src/notifier/manager.py74
-rw-r--r--dashboard/src/notifier/tests/test_dispatcher.py4
-rw-r--r--dashboard/src/notifier/tests/test_models.py3
-rw-r--r--dashboard/src/notifier/urls.py6
-rw-r--r--dashboard/src/pharos_dashboard/celery.py2
-rw-r--r--dashboard/src/pharos_dashboard/settings.py7
-rw-r--r--dashboard/src/resource_inventory/admin.py25
-rw-r--r--dashboard/src/resource_inventory/models.py37
-rw-r--r--dashboard/src/resource_inventory/resource_manager.py24
-rw-r--r--dashboard/src/resource_inventory/tests/test_managers.py49
-rw-r--r--dashboard/src/resource_inventory/tests/test_models.py109
-rw-r--r--dashboard/src/resource_inventory/views.py5
-rw-r--r--dashboard/src/workflow/booking_workflow.py39
-rw-r--r--dashboard/src/workflow/forms.py161
-rw-r--r--dashboard/src/workflow/models.py52
-rw-r--r--dashboard/src/workflow/resource_bundle_workflow.py69
-rw-r--r--dashboard/src/workflow/snapshot_workflow.py11
-rw-r--r--dashboard/src/workflow/sw_bundle_workflow.py34
-rw-r--r--dashboard/src/workflow/tests/test_steps.py40
-rw-r--r--dashboard/src/workflow/tests/test_steps_render.py7
-rw-r--r--dashboard/src/workflow/tests/test_workflows.py8
-rw-r--r--dashboard/src/workflow/urls.py10
-rw-r--r--dashboard/src/workflow/views.py32
-rw-r--r--dashboard/src/workflow/workflow_factory.py55
-rw-r--r--dashboard/src/workflow/workflow_manager.py26
-rwxr-xr-xdashboard/test.sh4
58 files changed, 947 insertions, 689 deletions
diff --git a/dashboard/__init__.py b/dashboard/__init__.py
index ce1acf3..b6fef6c 100644
--- a/dashboard/__init__.py
+++ b/dashboard/__init__.py
@@ -5,4 +5,4 @@
# 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
-############################################################################## \ No newline at end of file
+##############################################################################
diff --git a/dashboard/src/__init__.py b/dashboard/src/__init__.py
index ce1acf3..b6fef6c 100644
--- a/dashboard/src/__init__.py
+++ b/dashboard/src/__init__.py
@@ -5,4 +5,4 @@
# 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
-############################################################################## \ No newline at end of file
+##############################################################################
diff --git a/dashboard/src/account/__init__.py b/dashboard/src/account/__init__.py
index b5914ce..b6fef6c 100644
--- a/dashboard/src/account/__init__.py
+++ b/dashboard/src/account/__init__.py
@@ -6,5 +6,3 @@
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
-
-
diff --git a/dashboard/src/account/jira_util.py b/dashboard/src/account/jira_util.py
index fdb87f7..18b0e26 100644
--- a/dashboard/src/account/jira_util.py
+++ b/dashboard/src/account/jira_util.py
@@ -62,4 +62,4 @@ def get_jira(user):
'key_cert': key_cert
}
- return JIRA(server=settings.JIRA_URL, oauth=oauth_dict) \ No newline at end of file
+ return JIRA(server=settings.JIRA_URL, oauth=oauth_dict)
diff --git a/dashboard/src/account/models.py b/dashboard/src/account/models.py
index 18a8cbb..bfeead0 100644
--- a/dashboard/src/account/models.py
+++ b/dashboard/src/account/models.py
@@ -23,6 +23,7 @@ class LabStatus(object):
def upload_to(object, filename):
return object.user.username + '/' + filename
+
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
timezone = models.CharField(max_length=100, blank=False, default='UTC')
@@ -81,7 +82,6 @@ class VlanManager(models.Model):
net = PublicNetwork.objects.get(lab=self.lab_set.first(), vlan=vlan)
return not net.in_use
-
def is_available(self, vlans):
"""
'vlans' is either a single vlan id integer or a list of integers
@@ -139,7 +139,6 @@ class VlanManager(models.Model):
self.save()
-
class Lab(models.Model):
lab_user = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField(max_length=200, primary_key=True, unique=True, null=False, blank=False)
@@ -159,7 +158,6 @@ class Lab(models.Model):
key += random.choice(alphabet)
return key
-
def __str__(self):
return self.name
diff --git a/dashboard/src/account/tests/__init__.py b/dashboard/src/account/tests/__init__.py
index b5914ce..b6fef6c 100644
--- a/dashboard/src/account/tests/__init__.py
+++ b/dashboard/src/account/tests/__init__.py
@@ -6,5 +6,3 @@
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
-
-
diff --git a/dashboard/src/account/tests/test_general.py b/dashboard/src/account/tests/test_general.py
index e8f483b..57ad291 100644
--- a/dashboard/src/account/tests/test_general.py
+++ b/dashboard/src/account/tests/test_general.py
@@ -30,7 +30,7 @@ class AccountMiddlewareTestCase(TestCase):
The timezone should be UTC for anonymous users, for authenticated users it should be set
to user.userprofile.timezone
"""
- #default
+ # default
self.assertEqual(timezone.get_current_timezone_name(), 'UTC')
url = reverse('account:settings')
@@ -56,5 +56,3 @@ class AccountMiddlewareTestCase(TestCase):
self.client.login(username='user2', password='user2')
self.client.get(url)
self.assertTrue(user2.userprofile)
-
-
diff --git a/dashboard/src/account/urls.py b/dashboard/src/account/urls.py
index 6ce2115..85f0f1a 100644
--- a/dashboard/src/account/urls.py
+++ b/dashboard/src/account/urls.py
@@ -26,7 +26,18 @@ Including another URLconf
"""
from django.conf.urls import url
-from account.views import *
+from account.views import (
+ AccountSettingsView,
+ JiraAuthenticatedView,
+ JiraLoginView,
+ JiraLogoutView,
+ UserListView,
+ account_resource_view,
+ account_booking_view,
+ account_images_view,
+ account_configuration_view,
+ account_detail_view
+)
app_name = "account"
urlpatterns = [
diff --git a/dashboard/src/account/views.py b/dashboard/src/account/views.py
index 04d21b8..09c5266 100644
--- a/dashboard/src/account/views.py
+++ b/dashboard/src/account/views.py
@@ -63,7 +63,7 @@ class JiraLoginView(RedirectView):
# Step 1. Get a request token from Jira.
try:
resp, content = client.request(settings.OAUTH_REQUEST_TOKEN_URL, "POST")
- except Exception as e:
+ except Exception:
messages.add_message(self.request, messages.ERROR,
'Error: Connection to Jira failed. Please contact an Administrator')
return '/'
@@ -76,8 +76,8 @@ class JiraLoginView(RedirectView):
self.request.session['request_token'] = dict(urllib.parse.parse_qsl(content.decode()))
# Step 3. Redirect the user to the authentication URL.
url = settings.OAUTH_AUTHORIZE_URL + '?oauth_token=' + \
- self.request.session['request_token']['oauth_token'] + \
- '&oauth_callback=' + settings.OAUTH_CALLBACK_URL
+ self.request.session['request_token']['oauth_token'] + \
+ '&oauth_callback=' + settings.OAUTH_CALLBACK_URL
return url
@@ -99,7 +99,7 @@ class JiraAuthenticatedView(RedirectView):
# Step 2. Request the authorized access token from Jira.
try:
resp, content = client.request(settings.OAUTH_ACCESS_TOKEN_URL, "POST")
- except Exception as e:
+ except Exception:
messages.add_message(self.request, messages.ERROR,
'Error: Connection to Jira failed. Please contact an Administrator')
return '/'
@@ -163,6 +163,7 @@ def account_detail_view(request):
template = "account/details.html"
return render(request, template)
+
def account_resource_view(request):
"""
gathers a users genericResoureBundles and
@@ -175,6 +176,7 @@ def account_resource_view(request):
context = {"resources": resources, "title": "My Resources"}
return render(request, template, context=context)
+
def account_booking_view(request):
if not request.user.is_authenticated:
return render(request, "dashboard/login.html", {'title': 'Authentication Required'})
@@ -184,6 +186,7 @@ def account_booking_view(request):
context = {"title": "My Bookings", "bookings": bookings, "collab_bookings": collab_bookings}
return render(request, template, context=context)
+
def account_configuration_view(request):
if not request.user.is_authenticated:
return render(request, "dashboard/login.html", {'title': 'Authentication Required'})
@@ -192,12 +195,12 @@ def account_configuration_view(request):
context = {"title": "Configuration List", "configurations": configs}
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)
- context = {"title": "Images", "images": my_images, "public_images": public_images }
+ context = {"title": "Images", "images": my_images, "public_images": public_images}
return render(request, template, context=context)
-
diff --git a/dashboard/src/api/__init__.py b/dashboard/src/api/__init__.py
index b5914ce..b6fef6c 100644
--- a/dashboard/src/api/__init__.py
+++ b/dashboard/src/api/__init__.py
@@ -6,5 +6,3 @@
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
-
-
diff --git a/dashboard/src/api/admin.py b/dashboard/src/api/admin.py
index f1bc70a..3d32c78 100644
--- a/dashboard/src/api/admin.py
+++ b/dashboard/src/api/admin.py
@@ -11,12 +11,23 @@
from django.apps import AppConfig
from django.contrib import admin
-from api.models import *
+from api.models import (
+ Job,
+ OpnfvApiConfig,
+ HardwareConfig,
+ NetworkConfig,
+ SoftwareConfig,
+ AccessRelation,
+ SoftwareRelation,
+ HostHardwareRelation,
+ HostNetworkRelation,
+)
class ApiConfig(AppConfig):
name = 'apiJobs'
+
admin.site.register(Job)
admin.site.register(OpnfvApiConfig)
admin.site.register(HardwareConfig)
diff --git a/dashboard/src/api/models.py b/dashboard/src/api/models.py
index 4237559..78ec920 100644
--- a/dashboard/src/api/models.py
+++ b/dashboard/src/api/models.py
@@ -8,14 +8,21 @@
##############################################################################
+from django.contrib.auth.models import User
from django.db import models
from django.core.exceptions import PermissionDenied
import json
import uuid
-from resource_inventory.models import *
from booking.models import Booking
+from resource_inventory.models import (
+ Lab,
+ HostProfile,
+ Host,
+ Image,
+ Interface
+)
class JobStatus(object):
@@ -57,16 +64,18 @@ class LabManager(object):
prof = {}
prof['name'] = self.lab.name
prof['contact'] = {
- "phone": self.lab.contact_phone,
- "email": self.lab.contact_email
- }
+ "phone": self.lab.contact_phone,
+ "email": self.lab.contact_email
+ }
prof['host_count'] = []
for host in HostProfile.objects.filter(labs=self.lab):
count = Host.objects.filter(profile=host, lab=self.lab).count()
- prof['host_count'].append({
- "type": host.name,
- "count": count
- })
+ prof['host_count'].append(
+ {
+ "type": host.name,
+ "count": count
+ }
+ )
return prof
def get_inventory(self):
@@ -135,11 +144,13 @@ class LabManager(object):
def serialize_images(self, images):
images_ser = []
for image in images:
- images_ser.append({
- "name": image.name,
- "lab_id": image.lab_id,
- "dashboard_id": image.id
- })
+ images_ser.append(
+ {
+ "name": image.name,
+ "lab_id": image.lab_id,
+ "dashboard_id": image.id
+ }
+ )
return images_ser
def serialize_host_profiles(self, profiles):
@@ -147,25 +158,27 @@ class LabManager(object):
for profile in profiles:
p = {}
p['cpu'] = {
- "cores": profile.cpuprofile.first().cores,
- "arch": profile.cpuprofile.first().architecture,
- "cpus": profile.cpuprofile.first().cpus,
- }
+ "cores": profile.cpuprofile.first().cores,
+ "arch": profile.cpuprofile.first().architecture,
+ "cpus": profile.cpuprofile.first().cpus,
+ }
p['disks'] = []
for disk in profile.storageprofile.all():
d = {
- "size": disk.size,
- "type": disk.media_type,
- "name": disk.name
- }
+ "size": disk.size,
+ "type": disk.media_type,
+ "name": disk.name
+ }
p['disks'].append(d)
p['description'] = profile.description
p['interfaces'] = []
for iface in profile.interfaceprofile.all():
- p['interfaces'].append({
- "speed": iface.speed,
- "name": iface.name
- })
+ p['interfaces'].append(
+ {
+ "speed": iface.speed,
+ "name": iface.name
+ }
+ )
p['ram'] = {"amount": profile.ramprofile.first().amount}
p['name'] = profile.name
@@ -228,7 +241,6 @@ class Job(models.Model):
return False
return True
-
def get_delta(self, status):
d = {}
j = {}
@@ -270,6 +282,7 @@ class TaskConfig(models.Model):
def clear_delta(self):
self.delta = '{}'
+
class OpnfvApiConfig(models.Model):
installer = models.CharField(max_length=100)
@@ -324,6 +337,7 @@ class OpnfvApiConfig(models.Model):
self.save()
return json.loads(self.delta)
+
class AccessConfig(TaskConfig):
access_type = models.CharField(max_length=50)
user = models.ForeignKey(User, on_delete=models.CASCADE)
@@ -380,6 +394,7 @@ class AccessConfig(TaskConfig):
d['context'] = context
self.delta = json.dumps(d)
+
class SoftwareConfig(TaskConfig):
"""
handled opnfv installations, etc
@@ -409,6 +424,7 @@ class SoftwareConfig(TaskConfig):
def to_json(self):
return json.dumps(self.to_dict())
+
class HardwareConfig(TaskConfig):
"""
handles imaging, user accounts, etc
@@ -609,37 +625,37 @@ class JobFactory(object):
except:
job = Job.objects.create(status=JobStatus.NEW, booking=booking)
cls.makeHardwareConfigs(
- hosts=hosts,
- job=job
- )
+ hosts=hosts,
+ job=job
+ )
cls.makeNetworkConfigs(
- hosts=hosts,
- job=job
- )
+ hosts=hosts,
+ job=job
+ )
cls.makeSoftware(
- hosts=hosts,
- job=job
- )
+ hosts=hosts,
+ job=job
+ )
all_users = list(booking.collaborators.all())
all_users.append(booking.owner)
cls.makeAccessConfig(
- users=all_users,
- access_type="vpn",
- revoke=False,
- job=job
- )
+ users=all_users,
+ access_type="vpn",
+ revoke=False,
+ job=job
+ )
for user in all_users:
try:
cls.makeAccessConfig(
- users=[user],
- access_type="ssh",
- revoke=False,
- job=job,
- context={
- "key": user.userprofile.ssh_public_key.read(),
- "hosts": [host.labid for host in hosts]
- }
- )
+ users=[user],
+ access_type="ssh",
+ revoke=False,
+ job=job,
+ context={
+ "key": user.userprofile.ssh_public_key.read(),
+ "hosts": [host.labid for host in hosts]
+ }
+ )
except Exception:
continue
diff --git a/dashboard/src/api/serializers/booking_serializer.py b/dashboard/src/api/serializers/booking_serializer.py
index e891de4..9b5c059 100644
--- a/dashboard/src/api/serializers/booking_serializer.py
+++ b/dashboard/src/api/serializers/booking_serializer.py
@@ -10,7 +10,16 @@
from rest_framework import serializers
-from resource_inventory.models import *
+from resource_inventory.models import (
+ HostConfiguration,
+ CpuProfile,
+ DiskProfile,
+ InterfaceProfile,
+ RamProfile,
+ Image,
+ Interface
+)
+
class BookingField(serializers.Field):
@@ -28,17 +37,17 @@ class BookingField(serializers.Field):
host_configs[host.name] = HostConfiguration.objects.get(host=host.template)
if "jumphost" not in ser and host_configs[host.name].opnfvRole.name.lower() == "jumphost":
ser['jumphost'] = host.name
- #host is a Host model
+ # host is a Host model
for i in range(len(host.interfaces.all())):
interface = host.interfaces.all()[i]
- #interface is an Interface model
+ # interface is an Interface model
for vlan in interface.config.all():
- #vlan is Vlan model
+ # vlan is Vlan model
if vlan.id not in networks:
networks[vlan.id] = []
- net_host = {"hostname": host.name, "tagged": vlan.tagged, "interface":i}
+ net_host = {"hostname": host.name, "tagged": vlan.tagged, "interface": i}
networks[vlan.id].append(net_host)
- #creates networking object of proper form
+ # creates networking object of proper form
networking = []
for vlanid in networks:
network = {}
@@ -47,7 +56,7 @@ class BookingField(serializers.Field):
ser['networking'] = networking
- #creates hosts object of correct form
+ # creates hosts object of correct form
hosts = []
for hostname in host_configs:
host = {"hostname": hostname}
@@ -75,32 +84,37 @@ class BookingField(serializers.Field):
"""
return None
+
class BookingSerializer(serializers.Serializer):
booking = BookingField()
-#Host Type stuff, for inventory
+# Host Type stuff, for inventory
class CPUSerializer(serializers.ModelSerializer):
class Meta:
model = CpuProfile
fields = ('cores', 'architecture', 'cpus')
+
class DiskSerializer(serializers.ModelSerializer):
class Meta:
model = DiskProfile
fields = ('size', 'media_type', 'name')
+
class InterfaceProfileSerializer(serializers.ModelSerializer):
class Meta:
model = InterfaceProfile
fields = ('speed', 'name')
+
class RamSerializer(serializers.ModelSerializer):
class Meta:
model = RamProfile
fields = ('amount', 'channels')
+
class HostTypeSerializer(serializers.Serializer):
name = serializers.CharField(max_length=200)
ram = RamSerializer()
@@ -109,20 +123,24 @@ class HostTypeSerializer(serializers.Serializer):
disks = DiskSerializer()
cpu = CPUSerializer()
-#the rest of the inventory stuff
+
+# the rest of the inventory stuff
class NetworkSerializer(serializers.Serializer):
cidr = serializers.CharField(max_length=200)
gateway = serializers.IPAddressField(max_length=200)
vlan = serializers.IntegerField()
+
class ImageSerializer(serializers.ModelSerializer):
lab_id = serializers.IntegerField()
id = serializers.IntegerField(source="dashboard_id")
name = serializers.CharField(max_length=50)
description = serializers.CharField(max_length=200)
+
class Meta:
model = Image
+
class InterfaceField(serializers.Field):
def to_representation(self, interface):
pass
@@ -143,6 +161,7 @@ class InterfaceField(serializers.Field):
port_name=port_name
)
+
class InventoryHostSerializer(serializers.Serializer):
hostname = serializers.CharField(max_length=100)
host_type = serializers.CharField(max_length=100)
diff --git a/dashboard/src/api/tests/__init__.py b/dashboard/src/api/tests/__init__.py
index fe2a32d..2435a9f 100644
--- a/dashboard/src/api/tests/__init__.py
+++ b/dashboard/src/api/tests/__init__.py
@@ -5,4 +5,4 @@
# 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
-############################################################################## \ No newline at end of file
+##############################################################################
diff --git a/dashboard/src/api/tests/test_serializers.py b/dashboard/src/api/tests/test_serializers.py
index c49010c..c1fa5af 100644
--- a/dashboard/src/api/tests/test_serializers.py
+++ b/dashboard/src/api/tests/test_serializers.py
@@ -8,12 +8,29 @@
##############################################################################
from django.test import TestCase
from booking.models import Booking
-from resource_inventory.models import *
from account.models import Lab
-from api.serializers.booking_serializer import *
+from api.serializers.booking_serializer import BookingField
from datetime import timedelta
from django.utils import timezone
from django.contrib.auth.models import Permission, User
+from resource_inventory.models import (
+ Image,
+ OPNFVRole,
+ HostConfiguration,
+ HostProfile,
+ InterfaceProfile,
+ DiskProfile,
+ CpuProfile,
+ RamProfile,
+ GenericResourceBundle,
+ GenericResource,
+ GenericHost,
+ Host,
+ Vlan,
+ Interface,
+ ConfigBundle,
+ ResourceBundle
+)
class BookingSerializerTestCase(TestCase):
@@ -24,35 +41,34 @@ class BookingSerializerTestCase(TestCase):
lab_user = User.objects.create(username="asfasdfasdf")
owner = User.objects.create(username="asfasdfasdffffff")
lab = Lab.objects.create(
- lab_user=lab_user,
- name="TestLab123123",
- contact_email="mail@email.com",
- contact_phone=""
- )
- jumphost=True
+ lab_user=lab_user,
+ name="TestLab123123",
+ contact_email="mail@email.com",
+ contact_phone=""
+ )
+ jumphost = True
for host in hosts:
image = Image.objects.create(
- lab_id=12,
- from_lab=lab,
- name="this is a test image",
- owner=owner
- )
+ lab_id=12,
+ from_lab=lab,
+ name="this is a test image",
+ owner=owner
+ )
name = "jumphost"
if not jumphost:
name = "compute"
role = OPNFVRole.objects.create(
- name=name,
- description="stuff"
- )
+ name=name,
+ description="stuff"
+ )
HostConfiguration.objects.create(
- host=host,
- image=image,
- bundle=config,
- opnfvRole=role
- )
- jumphost=False
-
+ host=host,
+ image=image,
+ bundle=config,
+ opnfvRole=role
+ )
+ jumphost = False
def setUp(self):
self.serializer = BookingField()
@@ -64,30 +80,30 @@ class BookingSerializerTestCase(TestCase):
name='Test profile',
description='a test profile'
)
- interfaceProfile = InterfaceProfile.objects.create(
+ InterfaceProfile.objects.create(
speed=1000,
name='eno3',
host=hostProfile
)
- diskProfile = DiskProfile.objects.create(
+ DiskProfile.objects.create(
size=1000,
media_type="SSD",
name='/dev/sda',
host=hostProfile
)
- cpuProfile = CpuProfile.objects.create(
+ CpuProfile.objects.create(
cores=96,
architecture="x86_64",
cpus=2,
host=hostProfile
)
- ramProfile = RamProfile.objects.create(
+ RamProfile.objects.create(
amount=256,
channels=4,
host=hostProfile
)
- #create GenericResourceBundle
+ # create GenericResourceBundle
genericBundle = GenericResourceBundle.objects.create()
gres1 = GenericResource.objects.create(
@@ -119,9 +135,9 @@ class BookingSerializerTestCase(TestCase):
conf = ConfigBundle.objects.create(owner=user1, name="test conf")
self.makeHostConfigurations([gHost1, gHost2], conf)
- #actual resource bundle
+ # actual resource bundle
bundle = ResourceBundle.objects.create(
- template = genericBundle
+ template=genericBundle
)
host1 = Host.objects.create(
@@ -168,8 +184,8 @@ class BookingSerializerTestCase(TestCase):
# finally, can create booking
self.booking = Booking.objects.create(
owner=user1,
- start = timezone.now(),
- end = timezone.now() + timedelta(weeks=1),
+ start=timezone.now(),
+ end=timezone.now() + timedelta(weeks=1),
purpose='Testing',
resource=bundle,
config_bundle=conf
diff --git a/dashboard/src/api/urls.py b/dashboard/src/api/urls.py
index 4b1fe40..50cc6ac 100644
--- a/dashboard/src/api/urls.py
+++ b/dashboard/src/api/urls.py
@@ -28,7 +28,19 @@ from django.conf.urls import url, include
from django.urls import path
from rest_framework import routers
-from api.views import *
+from api.views import (
+ BookingViewSet,
+ UserViewSet,
+ lab_profile,
+ lab_status,
+ lab_inventory,
+ specific_job,
+ specific_task,
+ new_jobs,
+ current_jobs,
+ done_jobs,
+ GenerateTokenView
+)
router = routers.DefaultRouter()
router.register(r'bookings', BookingViewSet)
diff --git a/dashboard/src/api/views.py b/dashboard/src/api/views.py
index cc3a668..c72c85c 100644
--- a/dashboard/src/api/views.py
+++ b/dashboard/src/api/views.py
@@ -18,13 +18,11 @@ from rest_framework import viewsets
from rest_framework.authtoken.models import Token
from django.views.decorators.csrf import csrf_exempt
-import json
-
-from api.serializers.booking_serializer import *
+from api.serializers.booking_serializer import BookingSerializer
from api.serializers.old_serializers import UserSerializer
from account.models import UserProfile
from booking.models import Booking
-from api.models import *
+from api.models import LabManagerTracker, get_task
from notifier.manager import NotificationHandler
diff --git a/dashboard/src/booking/admin.py b/dashboard/src/booking/admin.py
index 2beb05b..162777e 100644
--- a/dashboard/src/booking/admin.py
+++ b/dashboard/src/booking/admin.py
@@ -11,6 +11,6 @@
from django.contrib import admin
-from booking.models import *
+from booking.models import Booking
admin.site.register(Booking)
diff --git a/dashboard/src/booking/models.py b/dashboard/src/booking/models.py
index adfc28d..d0c77b4 100644
--- a/dashboard/src/booking/models.py
+++ b/dashboard/src/booking/models.py
@@ -11,11 +11,8 @@
from resource_inventory.models import ResourceBundle, ConfigBundle
from account.models import Lab
-from django.conf import settings
from django.contrib.auth.models import User
from django.db import models
-from jira import JIRA
-from jira import JIRAError
import resource_inventory.resource_manager
@@ -47,7 +44,7 @@ class Opsys(models.Model):
class Booking(models.Model):
id = models.AutoField(primary_key=True)
- owner = models.ForeignKey(User, models.CASCADE, related_name='owner') # delete if user is deleted
+ owner = models.ForeignKey(User, models.CASCADE, related_name='owner')
collaborators = models.ManyToManyField(User, related_name='collaborators')
start = models.DateTimeField()
end = models.DateTimeField()
@@ -56,7 +53,7 @@ class Booking(models.Model):
jira_issue_status = models.CharField(max_length=50, blank=True)
purpose = models.CharField(max_length=300, blank=False)
ext_count = models.IntegerField(default=2)
- resource = models.ForeignKey(ResourceBundle, on_delete=models.SET_NULL, null=True) #need to decide behavior here on delete
+ resource = models.ForeignKey(ResourceBundle, on_delete=models.SET_NULL, null=True)
config_bundle = models.ForeignKey(ConfigBundle, on_delete=models.SET_NULL, null=True)
project = models.CharField(max_length=100, default="", blank=True, null=True)
lab = models.ForeignKey(Lab, null=True, on_delete=models.SET_NULL)
diff --git a/dashboard/src/booking/stats.py b/dashboard/src/booking/stats.py
index 31f7ef1..b706577 100644
--- a/dashboard/src/booking/stats.py
+++ b/dashboard/src/booking/stats.py
@@ -19,9 +19,11 @@ class StatisticsManager(object):
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
- every change (booking start / end) will be reflected, instead of one data point per day
- y values are the integer number of bookings/users active at some point in the given date
- span is the number of days to plot. The last x value will always be the current time
+ every change (booking start / end) will be reflected,
+ instead of one data point per day
+ y values are the integer number of bookings/users active at
+ some point in the given date span is the number of days to plot.
+ The last x value will always be the current time
"""
x_set = set()
x = []
@@ -29,7 +31,7 @@ class StatisticsManager(object):
users = []
now = datetime.datetime.now(pytz.utc)
delta = datetime.timedelta(days=span)
- end = now-delta
+ end = now - delta
bookings = Booking.objects.filter(start__lte=now, end__gte=end)
for booking in bookings:
x_set.add(booking.start)
diff --git a/dashboard/src/booking/tests/test_models.py b/dashboard/src/booking/tests/test_models.py
index a83f817..c7fb25d 100644
--- a/dashboard/src/booking/tests/test_models.py
+++ b/dashboard/src/booking/tests/test_models.py
@@ -11,25 +11,33 @@
from datetime import timedelta
-from django.contrib.auth.models import Permission
+from django.contrib.auth.models import Permission, User
from django.test import TestCase
from django.utils import timezone
-from booking.models import *
+# from booking.models import *
+from booking.models import Booking
from resource_inventory.models import ResourceBundle, GenericResourceBundle, ConfigBundle
+
class BookingModelTestCase(TestCase):
+
count = 0
+
def setUp(self):
self.owner = User.objects.create(username='owner')
self.res1 = ResourceBundle.objects.create(
- template=GenericResourceBundle.objects.create(name="gbundle" + str(self.count))
- )
+ template=GenericResourceBundle.objects.create(
+ name="gbundle" + str(self.count)
+ )
+ )
self.count += 1
self.res2 = ResourceBundle.objects.create(
- template=GenericResourceBundle.objects.create(name="gbundle2" + str(self.count))
- )
+ template=GenericResourceBundle.objects.create(
+ name="gbundle2" + str(self.count)
+ )
+ )
self.count += 1
self.user1 = User.objects.create(username='user1')
@@ -37,12 +45,15 @@ class BookingModelTestCase(TestCase):
self.user1.user_permissions.add(self.add_booking_perm)
self.user1 = User.objects.get(pk=self.user1.id)
- self.config_bundle = ConfigBundle.objects.create(owner=self.user1, name="test config")
+ self.config_bundle = ConfigBundle.objects.create(
+ owner=self.user1,
+ name="test config"
+ )
def test_start_end(self):
"""
- if the start of a booking is greater or equal then the end, saving should raise a
- ValueException
+ if the start of a booking is greater or equal then the end,
+ saving should raise a ValueException
"""
start = timezone.now()
end = start - timedelta(weeks=1)
@@ -54,7 +65,7 @@ class BookingModelTestCase(TestCase):
resource=self.res1,
owner=self.user1,
config_bundle=self.config_bundle
- )
+ )
end = start
self.assertRaises(
ValueError,
@@ -64,11 +75,12 @@ class BookingModelTestCase(TestCase):
resource=self.res1,
owner=self.user1,
config_bundle=self.config_bundle
- )
+ )
def test_conflicts(self):
"""
- saving an overlapping booking on the same resource should raise a ValueException
+ saving an overlapping booking on the same resource
+ should raise a ValueException
saving for different resources should succeed
"""
start = timezone.now()
@@ -80,8 +92,8 @@ class BookingModelTestCase(TestCase):
owner=self.user1,
resource=self.res1,
config_bundle=self.config_bundle
- )
)
+ )
self.assertRaises(
ValueError,
@@ -91,7 +103,8 @@ class BookingModelTestCase(TestCase):
resource=self.res1,
owner=self.user1,
config_bundle=self.config_bundle
- )
+ )
+
self.assertRaises(
ValueError,
Booking.objects.create,
@@ -100,7 +113,7 @@ class BookingModelTestCase(TestCase):
resource=self.res1,
owner=self.user1,
config_bundle=self.config_bundle
- )
+ )
self.assertRaises(
ValueError,
@@ -110,7 +123,7 @@ class BookingModelTestCase(TestCase):
resource=self.res1,
owner=self.user1,
config_bundle=self.config_bundle
- )
+ )
self.assertRaises(
ValueError,
@@ -120,7 +133,7 @@ class BookingModelTestCase(TestCase):
resource=self.res1,
owner=self.user1,
config_bundle=self.config_bundle
- )
+ )
self.assertRaises(
ValueError,
@@ -130,7 +143,7 @@ class BookingModelTestCase(TestCase):
resource=self.res1,
owner=self.user1,
config_bundle=self.config_bundle
- )
+ )
self.assertRaises(
ValueError,
@@ -140,7 +153,7 @@ class BookingModelTestCase(TestCase):
resource=self.res1,
owner=self.user1,
config_bundle=self.config_bundle
- )
+ )
self.assertTrue(
Booking.objects.create(
@@ -149,8 +162,9 @@ class BookingModelTestCase(TestCase):
owner=self.user1,
resource=self.res1,
config_bundle=self.config_bundle
- )
)
+ )
+
self.assertTrue(
Booking.objects.create(
start=end,
@@ -158,8 +172,8 @@ class BookingModelTestCase(TestCase):
owner=self.user1,
resource=self.res1,
config_bundle=self.config_bundle
- )
)
+ )
self.assertTrue(
Booking.objects.create(
@@ -168,8 +182,8 @@ class BookingModelTestCase(TestCase):
owner=self.user1,
resource=self.res1,
config_bundle=self.config_bundle
- )
)
+ )
self.assertTrue(
Booking.objects.create(
@@ -178,8 +192,8 @@ class BookingModelTestCase(TestCase):
owner=self.user1,
resource=self.res1,
config_bundle=self.config_bundle
- )
)
+ )
self.assertTrue(
Booking.objects.create(
@@ -188,8 +202,8 @@ class BookingModelTestCase(TestCase):
owner=self.user1,
resource=self.res2,
config_bundle=self.config_bundle
- )
)
+ )
def test_extensions(self):
"""
@@ -223,4 +237,3 @@ class BookingModelTestCase(TestCase):
self.assertTrue(booking.save())
except Exception:
self.fail("save() threw an exception")
-
diff --git a/dashboard/src/booking/urls.py b/dashboard/src/booking/urls.py
index 88fbb0a..4d00b7f 100644
--- a/dashboard/src/booking/urls.py
+++ b/dashboard/src/booking/urls.py
@@ -26,7 +26,14 @@ Including another URLconf
"""
from django.conf.urls import url
-from booking.views import *
+from booking.views import (
+ booking_detail_view,
+ BookingDeleteView,
+ bookingDelete,
+ BookingListView,
+ booking_stats_view,
+ booking_stats_json
+)
app_name = "booking"
urlpatterns = [
diff --git a/dashboard/src/booking/views.py b/dashboard/src/booking/views.py
index a0ea31d..ab43519 100644
--- a/dashboard/src/booking/views.py
+++ b/dashboard/src/booking/views.py
@@ -11,10 +11,8 @@
from django.contrib import messages
from django.shortcuts import get_object_or_404
from django.http import JsonResponse
-from django.urls import reverse
from django.utils import timezone
from django.views import View
-from django.views.generic import FormView
from django.views.generic import TemplateView
from django.shortcuts import redirect, render
import json
@@ -107,22 +105,24 @@ def booking_detail_view(request, booking_id):
allowed_users.add(booking.owner)
if user not in allowed_users:
return render(request, "dashboard/login.html", {'title': 'This page is private'})
- return render(request, "booking/booking_detail.html", {
- 'title': 'Booking Details',
- 'booking': booking,
- 'pdf': ResourceManager().makePDF(booking.resource),
- 'user_id': user.id})
+
+ return render(
+ request,
+ "booking/booking_detail.html",
+ {
+ 'title': 'Booking Details',
+ 'booking': booking,
+ 'pdf': ResourceManager().makePDF(booking.resource),
+ 'user_id': user.id
+ })
def booking_stats_view(request):
return render(
- request,
- "booking/stats.html",
- context={
- "data": StatisticsManager.getContinuousBookingTimeSeries(),
- "title": "Booking Statistics"
- }
- )
+ request,
+ "booking/stats.html",
+ context={"data": StatisticsManager.getContinuousBookingTimeSeries(), "title": "Booking Statistics"}
+ )
def booking_stats_json(request):
diff --git a/dashboard/src/dashboard/context_processors.py b/dashboard/src/dashboard/context_processors.py
index 32c70b8..338f609 100644
--- a/dashboard/src/dashboard/context_processors.py
+++ b/dashboard/src/dashboard/context_processors.py
@@ -8,5 +8,6 @@
##############################################################################
from django.conf import settings
+
def debug(context):
return {'DEBUG': settings.DEBUG}
diff --git a/dashboard/src/dashboard/exceptions.py b/dashboard/src/dashboard/exceptions.py
index bc3fcac..9c16a06 100644
--- a/dashboard/src/dashboard/exceptions.py
+++ b/dashboard/src/dashboard/exceptions.py
@@ -14,18 +14,21 @@ class ResourceProvisioningException(Exception):
"""
pass
+
class ModelValidationException(Exception):
"""
Validation before saving model returned issues
"""
pass
+
class ResourceAvailabilityException(ResourceProvisioningException):
"""
Requested resources are not *currently* available
"""
pass
+
class ResourceExistenceException(ResourceAvailabilityException):
"""
Requested resources do not exist or do not match any known resources
@@ -36,11 +39,14 @@ class ResourceExistenceException(ResourceAvailabilityException):
class NonUniqueHostnameException(Exception):
pass
+
class InvalidHostnameException(Exception):
pass
+
class InvalidVlanConfigurationException(Exception):
pass
+
class NetworkExistsException(Exception):
pass
diff --git a/dashboard/src/dashboard/populate_db_iol.py b/dashboard/src/dashboard/populate_db_iol.py
index 8c8b271..4368520 100644
--- a/dashboard/src/dashboard/populate_db_iol.py
+++ b/dashboard/src/dashboard/populate_db_iol.py
@@ -7,18 +7,27 @@
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
-
-from django.test import TestCase
-from booking.models import Booking
-from resource_inventory.models import *
-from account.models import *
-from api.serializers.booking_serializer import *
-from datetime import timedelta
-from django.utils import timezone
-from django.contrib.auth.models import Permission, User
import json
import yaml
+from account.models import Lab, UserProfile
+from django.contrib.auth.models import User
+from resource_inventory.models import (
+ HostProfile,
+ InterfaceProfile,
+ DiskProfile,
+ CpuProfile,
+ RamProfile,
+ VlanManager,
+ Scenario,
+ Installer,
+ Opsys,
+ OPNFVRole,
+ Image,
+ Interface,
+ Host
+)
+
class Populator:
@@ -29,7 +38,6 @@ class Populator:
self.generic_bundle_count = 0
self.booking_count = 0
-
def make_host_profile(self, lab, data):
hostProfile = HostProfile.objects.create(
host_type=data['host']['type'],
@@ -47,7 +55,6 @@ class Populator:
)
interfaceProfile.save()
-
for disk_data in data['disks']:
diskProfile = DiskProfile.objects.create(
@@ -84,41 +91,38 @@ class Populator:
user_sbergeron.save()
user_sbergeron_prof = UserProfile.objects.create(user=user_sbergeron)
user_sbergeron_prof.save()
- return [user_sbergeron, user_pberberian,]
-
+ return [user_sbergeron, user_pberberian]
def make_labs(self):
unh_iol = User.objects.create(username="unh_iol")
unh_iol.save()
vlans = []
reserved = []
- for i in range(1,4096):
+ for i in range(1, 4096):
vlans.append(1)
reserved.append(0)
- # TODO: put reserved vlans here
iol = Lab.objects.create(
- lab_user=unh_iol,
- name="UNH_IOL",
- vlan_manager=VlanManager.objects.create(
- vlans = json.dumps(vlans),
- reserved_vlans = json.dumps(reserved),
- allow_overlapping = False,
- block_size = 20,
- ),
- api_token = Lab.make_api_token(),
- contact_email = "nfv-lab@iol.unh.edu",
- location = "University of New Hampshire, Durham NH, 03824 USA"
- )
+ lab_user=unh_iol,
+ name="UNH_IOL",
+ vlan_manager=VlanManager.objects.create(
+ vlans=json.dumps(vlans),
+ reserved_vlans=json.dumps(reserved),
+ allow_overlapping=False,
+ block_size=20,
+ ),
+ api_token=Lab.make_api_token(),
+ contact_email="nfv-lab@iol.unh.edu",
+ location="University of New Hampshire, Durham NH, 03824 USA"
+ )
return [iol]
-
def make_configurations(self):
- #scenarios
+ # scenarios
scen1 = Scenario.objects.create(name="os-nosdn-nofeature-noha")
scen2 = Scenario.objects.create(name="os-odl-kvm-ha")
scen3 = Scenario.objects.create(name="os-nosdn-nofeature-ha")
- #installers
+ # installers
fuel = Installer.objects.create(name="Fuel")
fuel.sup_scenarios.add(scen1)
fuel.sup_scenarios.add(scen3)
@@ -141,7 +145,7 @@ class Populator:
compass.sup_scenarios.add(scen3)
compass.save()
- #operating systems
+ # operating systems
ubuntu = Opsys.objects.create(name="Ubuntu")
ubuntu.sup_installers.add(compass)
ubuntu.sup_installers.add(joid)
@@ -154,61 +158,61 @@ class Populator:
suse.sup_installers.add(fuel)
suse.save()
-
- #opnfv roles
- compute = OPNFVRole.objects.create(name="Compute", description="Does the heavy lifting")
- controller = OPNFVRole.objects.create(name="Controller", description="Controls everything")
- jumphost = OPNFVRole.objects.create(name="Jumphost", description="Entry Point")
+ # opnfv roles
+ OPNFVRole.objects.create(name="Compute", description="Does the heavy lifting")
+ OPNFVRole.objects.create(name="Controller", description="Controls everything")
+ OPNFVRole.objects.create(name="Jumphost", description="Entry Point")
lab = Lab.objects.first()
user = UserProfile.objects.first().user
- image = Image.objects.create(
- lab_id=23,
- name="hpe centos",
- from_lab=lab,
- owner=user,
- host_type=HostProfile.objects.get(name="hpe")
- )
- image = Image.objects.create(
- lab_id=25,
- name="hpe ubuntu",
- from_lab=lab,
- owner=user,
- host_type=HostProfile.objects.get(name="hpe")
- )
+ Image.objects.create(
+ lab_id=23,
+ name="hpe centos",
+ from_lab=lab,
+ owner=user,
+ host_type=HostProfile.objects.get(name="hpe")
+ )
+ Image.objects.create(
+ lab_id=25,
+ name="hpe ubuntu",
+ from_lab=lab,
+ owner=user,
+ host_type=HostProfile.objects.get(name="hpe")
+ )
- image = Image.objects.create(
- lab_id=26,
- name="hpe suse",
- from_lab=lab,
- owner=user,
- host_type=HostProfile.objects.get(name="hpe")
- )
- image = Image.objects.create(
- lab_id=27,
- name="arm ubuntu",
- from_lab=lab,
- owner=user,
- host_type=HostProfile.objects.get(name="arm")
- )
+ Image.objects.create(
+ lab_id=26,
+ name="hpe suse",
+ from_lab=lab,
+ owner=user,
+ host_type=HostProfile.objects.get(name="hpe")
+ )
+
+ Image.objects.create(
+ lab_id=27,
+ name="arm ubuntu",
+ from_lab=lab,
+ owner=user,
+ host_type=HostProfile.objects.get(name="arm")
+ )
def make_lab_hosts(self, hostcount, profile, lab, data, offset=1):
for i in range(hostcount):
- name="Host_" + lab.name + "_" + profile.name + "_" + str(i + offset)
+ name = "Host_" + lab.name + "_" + profile.name + "_" + str(i + offset)
host = Host.objects.create(
- name=name,
- lab=lab,
- profile=profile,
- labid=data[i]['labid']
- )
+ name=name,
+ lab=lab,
+ profile=profile,
+ labid=data[i]['labid']
+ )
for iface_profile in profile.interfaceprofile.all():
iface_data = data[i]['interfaces'][iface_profile.name]
Interface.objects.create(
- mac_address=iface_data['mac'],
- bus_address=iface_data['bus'],
- name=iface_profile.name,
- host=host
- )
+ mac_address=iface_data['mac'],
+ bus_address=iface_data['bus'],
+ name=iface_profile.name,
+ host=host
+ )
def make_profile_data(self):
"""
@@ -219,10 +223,10 @@ class Populator:
for prof in ["hpe", "arm"]: # TODO
profile_dict = {}
host = {
- "name": prof,
- "type": 0,
- "description": "some LaaS servers"
- }
+ "name": prof,
+ "type": 0,
+ "description": "some LaaS servers"
+ }
profile_dict['host'] = host
profile_dict['interfaces'] = []
for interface in [{"name": "eno1", "speed": 1000}, {"name": "eno2", "speed": 10000}]: # TODO
@@ -277,64 +281,64 @@ class Populator:
if len(host_data_dict) < 1:
continue
host_profile = HostProfile.objects.create(
- name=host_profile_name,
- description=""
- )
+ name=host_profile_name,
+ description=""
+ )
host_profile.labs.add(lab)
example_host_data = list(host_data_dict.values())[0]
cpu_data = example_host_data['cpu']
CpuProfile.objects.create(
- cores=cpu_data['cores'],
- architecture=cpu_data['arch'],
- cpus=cpu_data['cpus'],
- host=host_profile
- )
+ cores=cpu_data['cores'],
+ architecture=cpu_data['arch'],
+ cpus=cpu_data['cpus'],
+ host=host_profile
+ )
ram_data = example_host_data['memory']
RamProfile.objects.create(
- amount=int(ram_data[:-1]),
- channels=1,
- host=host_profile
- )
+ amount=int(ram_data[:-1]),
+ channels=1,
+ host=host_profile
+ )
disks_data = example_host_data['disk']
for disk_data in disks_data:
size = 0
try:
- size=int(disk_data['size'].split('.')[0])
+ size = int(disk_data['size'].split('.')[0])
except:
- size=int(disk_data['size'].split('.')[0][:-1])
+ size = int(disk_data['size'].split('.')[0][:-1])
DiskProfile.objects.create(
- size=size,
- media_type="SSD",
- name=disk_data['name'],
- host=host_profile
- )
+ size=size,
+ media_type="SSD",
+ name=disk_data['name'],
+ host=host_profile
+ )
ifaces_data = example_host_data['interface']
for iface_data in ifaces_data:
InterfaceProfile.objects.create(
- speed=iface_data['speed'],
- name=iface_data['name'],
- host=host_profile
- )
+ speed=iface_data['speed'],
+ name=iface_data['name'],
+ host=host_profile
+ )
# all profiles created
for hostname, host_data in host_data_dict.items():
host = Host.objects.create(
- name=hostname,
- labid=hostname,
- profile=host_profile,
- lab=lab
- )
+ name=hostname,
+ labid=hostname,
+ profile=host_profile,
+ lab=lab
+ )
for iface_data in host_data['interface']:
Interface.objects.create(
- mac_address=iface_data['mac'],
- bus_address=iface_data['busaddr'],
- name=iface_data['name'],
- host=host
- )
+ mac_address=iface_data['mac'],
+ bus_address=iface_data['busaddr'],
+ name=iface_data['name'],
+ host=host
+ )
def populate(self):
self.labs = self.make_labs()
diff --git a/dashboard/src/dashboard/tasks.py b/dashboard/src/dashboard/tasks.py
index d4b4189..b1d97b7 100644
--- a/dashboard/src/dashboard/tasks.py
+++ b/dashboard/src/dashboard/tasks.py
@@ -14,7 +14,7 @@ from django.utils import timezone
from django.db.models import Q
from booking.models import Booking
from notifier.manager import NotificationHandler
-from api.models import *
+from api.models import JobStatus, SoftwareRelation, HostHardwareRelation, HostNetworkRelation, AccessRelation
from resource_inventory.resource_manager import ResourceManager
@@ -26,7 +26,7 @@ def booking_poll():
config.clear_delta()
config.set_power("off")
config.save()
- hostrelation.status=JobStatus.NEW
+ hostrelation.status = JobStatus.NEW
hostrelation.save()
def cleanup_network(qs):
@@ -53,7 +53,7 @@ def booking_poll():
interface.config.clear()
network.add_interface(interface)
network.save()
- hostrelation.status=JobStatus.NEW
+ hostrelation.status = JobStatus.NEW
hostrelation.save()
def cleanup_software(qs):
@@ -62,7 +62,7 @@ def booking_poll():
software = relation.config.opnfv
software.clear_delta()
software.save()
- relation.status=JobStatus.NEW
+ relation.status = JobStatus.NEW
relation.save()
def cleanup_access(qs):
@@ -96,11 +96,11 @@ def free_hosts():
hardware = ~Q(~Q(job__hosthardwarerelation__status=200))
bookings = Booking.objects.filter(
- networks,
- hardware,
- end__lt=timezone.now(),
- job__complete=True,
- resource__isnull=False
- )
+ networks,
+ hardware,
+ end__lt=timezone.now(),
+ job__complete=True,
+ resource__isnull=False
+ )
for booking in bookings:
ResourceManager.getInstance().deleteResourceBundle(booking.resource)
diff --git a/dashboard/src/dashboard/templatetags/__init__.py b/dashboard/src/dashboard/templatetags/__init__.py
index b5914ce..b6fef6c 100644
--- a/dashboard/src/dashboard/templatetags/__init__.py
+++ b/dashboard/src/dashboard/templatetags/__init__.py
@@ -6,5 +6,3 @@
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
-
-
diff --git a/dashboard/src/dashboard/tests/__init__.py b/dashboard/src/dashboard/tests/__init__.py
index b5914ce..b6fef6c 100644
--- a/dashboard/src/dashboard/tests/__init__.py
+++ b/dashboard/src/dashboard/tests/__init__.py
@@ -6,5 +6,3 @@
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
-
-
diff --git a/dashboard/src/dashboard/urls.py b/dashboard/src/dashboard/urls.py
index 0d7ee87..571a987 100644
--- a/dashboard/src/dashboard/urls.py
+++ b/dashboard/src/dashboard/urls.py
@@ -25,9 +25,14 @@ Including another URLconf
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
-from dashboard.views import *
+from dashboard.views import (
+ landing_view,
+ lab_list_view,
+ lab_detail_view,
+ host_profile_detail_view
+)
-app_name="dashboard"
+app_name = "dashboard"
urlpatterns = [
url(r'^$', landing_view, name='index'),
url(r'^lab/$', lab_list_view, name='all_labs'),
diff --git a/dashboard/src/dashboard/views.py b/dashboard/src/dashboard/views.py
index 2d1f8b2..36c3253 100644
--- a/dashboard/src/dashboard/views.py
+++ b/dashboard/src/dashboard/views.py
@@ -14,12 +14,11 @@ from django.views.generic import TemplateView
from django.shortcuts import render
from django.http import HttpResponseRedirect
-from booking.models import Booking
from account.models import Lab
-from resource_inventory.models import *
-from workflow.views import *
-from workflow.workflow_manager import *
+from resource_inventory.models import Image, HostProfile
+from workflow.views import create_session
+from workflow.workflow_manager import ManagerTracker
def lab_list_view(request):
@@ -40,18 +39,27 @@ def lab_detail_view(request, lab_name):
if user:
images = images | Image.objects.filter(from_lab=lab).filter(owner=user)
- return render(request, "dashboard/lab_detail.html",
- {'title': "Lab Overview",
- 'lab': lab,
- 'hostprofiles': lab.hostprofiles.all(),
- 'images': images})
+ return render(
+ request,
+ "dashboard/lab_detail.html",
+ {
+ 'title': "Lab Overview",
+ 'lab': lab,
+ 'hostprofiles': lab.hostprofiles.all(),
+ 'images': images
+ }
+ )
def host_profile_detail_view(request):
- return render(request, "dashboard/host_profile_detail.html",
- {'title': "Host Types",
- })
+ return render(
+ request,
+ "dashboard/host_profile_detail.html",
+ {
+ 'title': "Host Types",
+ }
+ )
def landing_view(request):
@@ -62,12 +70,11 @@ def landing_view(request):
try:
manager = ManagerTracker.managers[request.session['manager_session']]
-
- except KeyError as e:
+ except KeyError:
pass
if manager is not None:
- #no manager detected, don't display continue button
+ # no manager detected, don't display continue button
manager_detected = True
if request.method == 'GET':
@@ -84,7 +91,7 @@ def landing_view(request):
request.session['manager_session'] = mgr_uuid
return HttpResponseRedirect('/wf/')
- except KeyError as e:
+ except KeyError:
pass
diff --git a/dashboard/src/manage.py b/dashboard/src/manage.py
index 80c496f..3c7aba5 100755
--- a/dashboard/src/manage.py
+++ b/dashboard/src/manage.py
@@ -1,3 +1,5 @@
+#!/usr/bin/env python
+
##############################################################################
# Copyright (c) 2016 Max Breitenfeldt and others.
#
@@ -8,7 +10,6 @@
##############################################################################
-#!/usr/bin/env python
import os
import sys
diff --git a/dashboard/src/notifier/manager.py b/dashboard/src/notifier/manager.py
index cc1aa16..a754241 100644
--- a/dashboard/src/notifier/manager.py
+++ b/dashboard/src/notifier/manager.py
@@ -36,23 +36,29 @@ class NotificationHandler(object):
the last is the title for the collaborators'
"""
owner_notif = Notification.objects.create(
- title=titles[0],
- content=render_to_string(template, context={
+ title=titles[0],
+ content=render_to_string(
+ template,
+ context={
"booking": booking,
"owner": True
- })
- )
+ }
+ )
+ )
owner_notif.recipients.add(booking.owner)
if not booking.collaborators.all().exists():
return # no collaborators - were done
collab_notif = Notification.objects.create(
- title=titles[-1],
- content=render_to_string(template, context={
+ title=titles[-1],
+ content=render_to_string(
+ template,
+ context={
"booking": booking,
"owner": False
- })
- )
+ }
+ )
+ )
for c in booking.collaborators.all():
collab_notif.recipients.add(c)
@@ -67,28 +73,30 @@ class NotificationHandler(object):
# gather up all the relevant messages from the lab
for task in all_tasks:
if (not hasattr(task, "user")) or task.user == user:
- user_tasklist.append({
- "title": task.type_str + " Message: ",
- "content": task.message
- })
+ user_tasklist.append(
+ {
+ "title": task.type_str + " Message: ",
+ "content": task.message
+ }
+ )
# gather up all the other needed info
context = {
- "user_name": user.userprofile.full_name,
- "messages": user_tasklist,
- "booking_url": os.environ.get("DASHBOARD_URL", "<Dashboard url>") + "/booking/detail/" + str(job.booking.id) + "/"
- }
+ "user_name": user.userprofile.full_name,
+ "messages": user_tasklist,
+ "booking_url": os.environ.get("DASHBOARD_URL", "<Dashboard url>") + "/booking/detail/" + str(job.booking.id) + "/"
+ }
# render email template
message = render_to_string(template_name, context)
# finally, send the email
send_mail(
- "Your Booking is Ready",
- message,
- os.environ.get("DEFAULT_FROM_EMAIL", "opnfv@pharos-dashboard"),
- user.userprofile.email_addr,
- fail_silently=False
- )
+ "Your Booking is Ready",
+ message,
+ os.environ.get("DEFAULT_FROM_EMAIL", "opnfv@pharos-dashboard"),
+ user.userprofile.email_addr,
+ fail_silently=False
+ )
@classmethod
def email_booking_over(cls, booking):
@@ -98,21 +106,21 @@ class NotificationHandler(object):
users.append(booking.owner)
for user in users:
context = {
- "user_name": user.userprofile.full_name,
- "booking": booking,
- "hosts": hostnames,
- "booking_url": os.environ.get("DASHBOARD_URL", "<Dashboard url>") + "/booking/detail/" + str(booking.id) + "/"
- }
+ "user_name": user.userprofile.full_name,
+ "booking": booking,
+ "hosts": hostnames,
+ "booking_url": os.environ.get("DASHBOARD_URL", "<Dashboard url>") + "/booking/detail/" + str(booking.id) + "/"
+ }
message = render_to_string(template_name, context)
send_mail(
- "Your Booking has Expired",
- message,
- os.environ.get("DEFAULT_FROM_EMAIL", "opnfv@pharos-dashboard"),
- user.userprofile.email_addr,
- fail_silently=False
- )
+ "Your Booking has Expired",
+ message,
+ os.environ.get("DEFAULT_FROM_EMAIL", "opnfv@pharos-dashboard"),
+ user.userprofile.email_addr,
+ fail_silently=False
+ )
@classmethod
def task_updated(cls, task):
diff --git a/dashboard/src/notifier/tests/test_dispatcher.py b/dashboard/src/notifier/tests/test_dispatcher.py
index 07d8387..086f621 100644
--- a/dashboard/src/notifier/tests/test_dispatcher.py
+++ b/dashboard/src/notifier/tests/test_dispatcher.py
@@ -7,10 +7,8 @@
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
-
from django.test import TestCase
-from notifier.models import *
-from django.contrib.auth.models import User
+
class DispatchTestCase(TestCase):
# This is a stub, it will be filled out as this feature is remade with saner practices.
diff --git a/dashboard/src/notifier/tests/test_models.py b/dashboard/src/notifier/tests/test_models.py
index 10aec3e..d332254 100644
--- a/dashboard/src/notifier/tests/test_models.py
+++ b/dashboard/src/notifier/tests/test_models.py
@@ -9,9 +9,10 @@
from django.test import TestCase
-from notifier.models import *
+from notifier.models import Notifier
from django.contrib.auth.models import User
+
class NotifierTestCase(TestCase):
def test_valid_notifier_saves(self):
diff --git a/dashboard/src/notifier/urls.py b/dashboard/src/notifier/urls.py
index 9bbc3bf..fedb9e8 100644
--- a/dashboard/src/notifier/urls.py
+++ b/dashboard/src/notifier/urls.py
@@ -10,12 +10,10 @@
from django.conf.urls import url
-from notifier.views import *
+from notifier.views import InboxView, NotificationView
app_name = "notifier"
urlpatterns = [
-
-
url(r'^$', InboxView, name='messages'),
- url(r'^notification/(?P<notification_id>[0-9]+)/$', NotificationView, name='notifier_single')
+ url(r'^notification/(?P<notification_id>[0-9]+)/$', NotificationView, name='notifier_single')
]
diff --git a/dashboard/src/pharos_dashboard/celery.py b/dashboard/src/pharos_dashboard/celery.py
index f60f243..2a44a3d 100644
--- a/dashboard/src/pharos_dashboard/celery.py
+++ b/dashboard/src/pharos_dashboard/celery.py
@@ -27,4 +27,4 @@ app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
@app.task(bind=True)
def debug_task(self):
- print('Request: {0!r}'.format(self.request)) \ No newline at end of file
+ print('Request: {0!r}'.format(self.request))
diff --git a/dashboard/src/pharos_dashboard/settings.py b/dashboard/src/pharos_dashboard/settings.py
index 91fc93e..793eec7 100644
--- a/dashboard/src/pharos_dashboard/settings.py
+++ b/dashboard/src/pharos_dashboard/settings.py
@@ -57,8 +57,7 @@ ROOT_URLCONF = 'pharos_dashboard.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
- 'DIRS': [os.path.join(BASE_DIR, 'templates')]
- ,
+ 'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
@@ -201,6 +200,6 @@ EMAIL_HOST = os.environ['EMAIL_HOST']
EMAIL_PORT = os.environ['EMAIL_PORT']
EMAIL_HOST_USER = os.environ['EMAIL_HOST_USER']
EMAIL_HOST_PASSWORD = os.environ['EMAIL_HOST_PASSWORD']
-EMAIL_USE_TLS=True
+EMAIL_USE_TLS = True
DEFAULT_EMAIL_FROM = os.environ.get('DEFAULT_EMAIL_FROM', 'webmaster@localhost')
-SESSION_ENGINE="django.contrib.sessions.backends.signed_cookies"
+SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies"
diff --git a/dashboard/src/resource_inventory/admin.py b/dashboard/src/resource_inventory/admin.py
index 37b0c45..e063cc0 100644
--- a/dashboard/src/resource_inventory/admin.py
+++ b/dashboard/src/resource_inventory/admin.py
@@ -10,7 +10,30 @@
from django.contrib import admin
-from resource_inventory.models import *
+from resource_inventory.models import (
+ HostProfile,
+ InterfaceProfile,
+ DiskProfile,
+ CpuProfile,
+ RamProfile,
+ GenericResourceBundle,
+ GenericResource,
+ GenericHost,
+ GenericInterface,
+ Host,
+ Interface,
+ Network,
+ Vlan,
+ ResourceBundle,
+ Scenario,
+ Installer,
+ Opsys,
+ ConfigBundle,
+ OPNFVConfig,
+ OPNFVRole,
+ Image,
+ HostConfiguration
+)
profiles = [HostProfile, InterfaceProfile, DiskProfile, CpuProfile, RamProfile]
diff --git a/dashboard/src/resource_inventory/models.py b/dashboard/src/resource_inventory/models.py
index b71748e..b56317b 100644
--- a/dashboard/src/resource_inventory/models.py
+++ b/dashboard/src/resource_inventory/models.py
@@ -40,10 +40,14 @@ class InterfaceProfile(models.Model):
speed = models.IntegerField()
name = models.CharField(max_length=100)
host = models.ForeignKey(HostProfile, on_delete=models.DO_NOTHING, related_name='interfaceprofile')
- nic_type = models.CharField(max_length=50, choices=[
- ("onboard", "onboard"),
- ("pcie", "pcie")
- ], default="onboard")
+ nic_type = models.CharField(
+ max_length=50,
+ choices=[
+ ("onboard", "onboard"),
+ ("pcie", "pcie")
+ ],
+ default="onboard"
+ )
def __str__(self):
return self.name + " for " + str(self.host)
@@ -59,14 +63,18 @@ class DiskProfile(models.Model):
name = models.CharField(max_length=50)
host = models.ForeignKey(HostProfile, on_delete=models.DO_NOTHING, related_name='storageprofile')
rotation = models.IntegerField(default=0)
- interface = models.CharField(max_length=50, choices=[
+ interface = models.CharField(
+ max_length=50,
+ choices=[
("sata", "sata"),
("sas", "sas"),
("ssd", "ssd"),
("nvme", "nvme"),
("scsi", "scsi"),
("iscsi", "iscsi"),
- ], default="sata")
+ ],
+ default="sata"
+ )
def __str__(self):
return self.name + " for " + str(self.host)
@@ -97,7 +105,7 @@ class RamProfile(models.Model):
return str(self.amount) + "G for " + str(self.host)
-##Networking -- located here due to import order requirements
+# Networking -- located here due to import order requirements
class Network(models.Model):
id = models.AutoField(primary_key=True)
vlan_id = models.IntegerField()
@@ -106,6 +114,7 @@ class Network(models.Model):
def __str__(self):
return self.name
+
class Vlan(models.Model):
id = models.AutoField(primary_key=True)
vlan_id = models.IntegerField()
@@ -194,6 +203,7 @@ class Scenario(models.Model):
def __str__(self):
return self.name
+
class Installer(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=200)
@@ -202,6 +212,7 @@ class Installer(models.Model):
def __str__(self):
return self.name
+
class Opsys(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=100)
@@ -210,9 +221,10 @@ class Opsys(models.Model):
def __str__(self):
return self.name
+
class ConfigBundle(models.Model):
id = models.AutoField(primary_key=True)
- owner = models.ForeignKey(User, on_delete=models.CASCADE) #consider setting to root user?
+ owner = models.ForeignKey(User, on_delete=models.CASCADE) # consider setting to root user?
name = models.CharField(max_length=200, unique=True)
description = models.CharField(max_length=1000, default="")
bundle = models.ForeignKey(GenericResourceBundle, null=True, on_delete=models.CASCADE)
@@ -220,6 +232,7 @@ class ConfigBundle(models.Model):
def __str__(self):
return self.name
+
class OPNFVConfig(models.Model):
id = models.AutoField(primary_key=True)
installer = models.ForeignKey(Installer, on_delete=models.CASCADE)
@@ -229,6 +242,7 @@ class OPNFVConfig(models.Model):
def __str__(self):
return "OPNFV job with " + str(self.installer) + " and " + str(self.scenario)
+
class OPNFVRole(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=200)
@@ -237,6 +251,7 @@ class OPNFVRole(models.Model):
def __str__(self):
return self.name
+
class Image(models.Model):
"""
model for representing OS images / snapshots of hosts
@@ -247,12 +262,14 @@ class Image(models.Model):
name = models.CharField(max_length=200)
owner = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
public = models.BooleanField(default=True)
- host_type = models.ForeignKey(HostProfile, on_delete=models.CASCADE) #may need to change to models.SET() once images are transferrable between compatible host types
+ # may need to change host_type.on_delete to models.SET() once images are transferrable between compatible host types
+ host_type = models.ForeignKey(HostProfile, on_delete=models.CASCADE)
description = models.TextField()
def __str__(self):
return self.name
+
class HostConfiguration(models.Model):
"""
model to represent a complete configuration for a single
@@ -262,7 +279,7 @@ class HostConfiguration(models.Model):
host = models.ForeignKey(GenericHost, related_name="configuration", on_delete=models.CASCADE)
image = models.ForeignKey(Image, on_delete=models.PROTECT)
bundle = models.ForeignKey(ConfigBundle, related_name="hostConfigurations", null=True, on_delete=models.CASCADE)
- opnfvRole = models.ForeignKey(OPNFVRole, on_delete=models.PROTECT) #need protocol for phasing out a role if we are going to allow that to happen
+ opnfvRole = models.ForeignKey(OPNFVRole, on_delete=models.PROTECT)
def __str__(self):
return "config with " + str(self.host) + " and image " + str(self.image)
diff --git a/dashboard/src/resource_inventory/resource_manager.py b/dashboard/src/resource_inventory/resource_manager.py
index cd70867..3380990 100644
--- a/dashboard/src/resource_inventory/resource_manager.py
+++ b/dashboard/src/resource_inventory/resource_manager.py
@@ -8,12 +8,17 @@
##############################################################################
-from django.core.exceptions import *
from django.template.loader import render_to_string
import booking
-from dashboard.exceptions import *
-from resource_inventory.models import *
+from dashboard.exceptions import (
+ ResourceExistenceException,
+ ResourceAvailabilityException,
+ ResourceProvisioningException,
+ ModelValidationException
+)
+from resource_inventory.models import Host, HostConfiguration, ResourceBundle
+
class ResourceManager:
@@ -28,7 +33,7 @@ class ResourceManager:
ResourceManager.instance = ResourceManager()
return ResourceManager.instance
- #public interface
+ # public interface
def deleteResourceBundle(self, resourceBundle):
for host in Host.objects.filter(bundle=resourceBundle):
self.releaseHost(host)
@@ -44,13 +49,13 @@ class ResourceManager:
hosts = genericResourceBundle.getHosts()
- #current supported case: user creating new booking
- #currently unsupported: editing existing booking
+ # current supported case: user creating new booking
+ # currently unsupported: editing existing booking
physical_hosts = []
for host in hosts:
- host_config=None
+ host_config = None
if config:
host_config = HostConfiguration.objects.get(bundle=config, host=host)
try:
@@ -84,7 +89,7 @@ class ResourceManager:
for vlan in generic_interface.vlans.all():
physical_interface.config.add(vlan)
- #private interface
+ # private interface
def acquireHost(self, genericHost, labName):
host_full_set = Host.objects.filter(lab__name__exact=labName, profile=genericHost.profile)
if not host_full_set.first():
@@ -135,7 +140,7 @@ class ResourceManager:
booking_owner = booking.models.Booking.objects.get(resource=resource).owner
owner = booking_owner.username
email = booking_owner.userprofile.email_addr
- except Exception as e:
+ except Exception:
pass
details['owner'] = owner
@@ -159,7 +164,6 @@ class ResourceManager:
return pdf_nodes
-
def get_pdf_host(self, host):
host_info = {}
host_info['name'] = host.template.resource.name
diff --git a/dashboard/src/resource_inventory/tests/test_managers.py b/dashboard/src/resource_inventory/tests/test_managers.py
index 5a13b2e..0e7c673 100644
--- a/dashboard/src/resource_inventory/tests/test_managers.py
+++ b/dashboard/src/resource_inventory/tests/test_managers.py
@@ -12,7 +12,20 @@ from django.contrib.auth.models import User
from resource.inventory_manager import InventoryManager
from resource.resource_manager import ResourceManager
-from resource.models import *
+from account.models import Lab
+from resource.models import (
+ Host,
+ Vlan,
+ Interface,
+ ResourceBundle,
+ GenericHost,
+ GenericResourceBundle,
+ CpuProfile,
+ RamProfile,
+ DiskProfile,
+ HostProfile,
+ InterfaceProfile
+)
class InventoryManagerTestCase(TestCase):
@@ -39,30 +52,30 @@ class InventoryManagerTestCase(TestCase):
name='Test profile',
description='a test profile'
)
- interfaceProfile = InterfaceProfile.objects.create(
+ InterfaceProfile.objects.create(
speed=1000,
name='eno3',
host=hostProfile
)
- diskProfile = DiskProfile.objects.create(
+ DiskProfile.objects.create(
size=1000,
media_type="SSD",
name='/dev/sda',
host=hostProfile
)
- cpuProfile = CpuProfile.objects.create(
+ CpuProfile.objects.create(
cores=96,
architecture="x86_64",
cpus=2,
host=hostProfile
)
- ramProfile = RamProfile.objects.create(
+ RamProfile.objects.create(
amount=256,
channels=4,
host=hostProfile
)
- #create GenericResourceBundle
+ # create GenericResourceBundle
genericBundle = GenericResourceBundle.objects.create()
self.gHost1 = GenericHost.objects.create(
@@ -76,7 +89,7 @@ class InventoryManagerTestCase(TestCase):
profile=hostProfile
)
- #actual resource bundle
+ # actual resource bundle
bundle = ResourceBundle.objects.create(template=genericBundle)
self.host1 = Host.objects.create(
@@ -100,7 +113,7 @@ class InventoryManagerTestCase(TestCase):
vlan1 = Vlan.objects.create(vlan_id=300, tagged=False)
vlan2 = Vlan.objects.create(vlan_id=300, tagged=False)
- iface1 = Interface.objects.create(
+ Interface.objects.create(
mac_address='00:11:22:33:44:55',
bus_address='some bus address',
switch_name='switch1',
@@ -108,7 +121,7 @@ class InventoryManagerTestCase(TestCase):
config=vlan1,
host=self.host1
)
- iface2 = Interface.objects.create(
+ Interface.objects.create(
mac_address='00:11:22:33:44:56',
bus_address='some bus address',
switch_name='switch1',
@@ -153,30 +166,30 @@ class ResourceManagerTestCase(TestCase):
name='Test profile',
description='a test profile'
)
- interfaceProfile = InterfaceProfile.objects.create(
+ InterfaceProfile.objects.create(
speed=1000,
name='eno3',
host=hostProfile
)
- diskProfile = DiskProfile.objects.create(
+ DiskProfile.objects.create(
size=1000,
media_type="SSD",
name='/dev/sda',
host=hostProfile
)
- cpuProfile = CpuProfile.objects.create(
+ CpuProfile.objects.create(
cores=96,
architecture="x86_64",
cpus=2,
host=hostProfile
)
- ramProfile = RamProfile.objects.create(
+ RamProfile.objects.create(
amount=256,
channels=4,
host=hostProfile
)
- #create GenericResourceBundle
+ # create GenericResourceBundle
genericBundle = GenericResourceBundle.objects.create()
self.gHost1 = GenericHost.objects.create(
@@ -190,7 +203,7 @@ class ResourceManagerTestCase(TestCase):
profile=hostProfile
)
- #actual resource bundle
+ # actual resource bundle
bundle = ResourceBundle.objects.create(template=genericBundle)
self.host1 = Host.objects.create(
@@ -214,7 +227,7 @@ class ResourceManagerTestCase(TestCase):
vlan1 = Vlan.objects.create(vlan_id=300, tagged=False)
vlan2 = Vlan.objects.create(vlan_id=300, tagged=False)
- iface1 = Interface.objects.create(
+ Interface.objects.create(
mac_address='00:11:22:33:44:55',
bus_address='some bus address',
switch_name='switch1',
@@ -222,7 +235,7 @@ class ResourceManagerTestCase(TestCase):
config=vlan1,
host=self.host1
)
- iface2 = Interface.objects.create(
+ Interface.objects.create(
mac_address='00:11:22:33:44:56',
bus_address='some bus address',
switch_name='switch1',
@@ -232,5 +245,5 @@ class ResourceManagerTestCase(TestCase):
)
def test_convert_bundle(self):
- bundle = ResourceManager.getInstance().convertResoureBundle(self.genericBundle, self.lab.name)
+ ResourceManager.getInstance().convertResoureBundle(self.genericBundle, self.lab.name)
# verify bundle configuration
diff --git a/dashboard/src/resource_inventory/tests/test_models.py b/dashboard/src/resource_inventory/tests/test_models.py
index 4ddedf2..e1b2106 100644
--- a/dashboard/src/resource_inventory/tests/test_models.py
+++ b/dashboard/src/resource_inventory/tests/test_models.py
@@ -9,11 +9,24 @@
from django.test import TestCase
from django.contrib.auth.models import User
from account.models import Lab
-from resource_inventory.models import *
+from resource_inventory.models import (
+ Scenario,
+ Installer,
+ Opsys,
+ ConfigBundle,
+ OPNFVConfig,
+ OPNFVRole,
+ Image,
+ HostProfile,
+ GenericResourceBundle,
+ GenericResource,
+ GenericHost,
+ HostConfiguration
+)
class ConfigUtil():
- count=0
+ count = 0
@staticmethod
def makeScenario():
@@ -21,17 +34,13 @@ class ConfigUtil():
@staticmethod
def makeInstaller():
- inst = Installer.objects.create(
- name = "testInstaller"
- )
+ inst = Installer.objects.create(name="testInstaller")
inst.sup_scenarios = [ConfigUtil.makeScenario()]
return inst
@staticmethod
def makeOpsys():
- os = Opsys.objects.create(
- name = "test Operating System"
- )
+ os = Opsys.objects.create(name="test Operating System")
os.sup_installers = [ConfigUtil.makeInstaller()]
return os
@@ -39,9 +48,7 @@ class ConfigUtil():
def makeConfigBundle():
user = User.objects.create(username="test_user" + str(ConfigUtil.count))
ConfigUtil.count += 1
- return ConfigBundle.objects.create(
- owner = user
- )
+ return ConfigBundle.objects.create(owner=user)
@staticmethod
def makeOPNFVConfig():
@@ -49,61 +56,60 @@ class ConfigUtil():
scenario = ConfigUtil.makeScenario()
bundle = ConfigUtil.makeConfigBundle()
return OPNFVConfig.objects.create(
- installer=installer,
- scenario=scenario,
- bundle=bundle
- )
+ installer=installer,
+ scenario=scenario,
+ bundle=bundle
+ )
@staticmethod
def makeOPNFVRole():
return OPNFVRole.objects.create(
- name="Test role",
- description="This is a test role"
- )
+ name="Test role",
+ description="This is a test role"
+ )
@staticmethod
def makeImage():
owner = User.objects.create(username="another test user")
lab_user = User.objects.create(username="labUserForTests")
lab = Lab.objects.create(
- lab_user=lab_user,
- name="this is lab for testing",
- contact_email="email@mail.com",
- contact_phone="123-4567"
- )
+ lab_user=lab_user,
+ name="this is lab for testing",
+ contact_email="email@mail.com",
+ contact_phone="123-4567"
+ )
return Image.objects.create(
- lab_id=0,
- from_lab=lab,
- name="an image for testing",
- owner=owner
- )
-
+ lab_id=0,
+ from_lab=lab,
+ name="an image for testing",
+ owner=owner
+ )
@staticmethod
def makeGenericHost():
profile = HostProfile.objects.create(
- host_type=0,
- name="test lab for config bundle",
- description="this is a test profile"
- )
+ host_type=0,
+ name="test lab for config bundle",
+ description="this is a test profile"
+ )
user = User.objects.create(username="test sample user 12")
bundle = GenericResourceBundle.objects.create(
- name="Generic bundle for config tests",
- xml="",
- owner=user,
- description=""
- )
+ name="Generic bundle for config tests",
+ xml="",
+ owner=user,
+ description=""
+ )
resource = GenericResource.objects.create(
- bundle=bundle,
- name="a test generic resource"
- )
+ bundle=bundle,
+ name="a test generic resource"
+ )
return GenericHost.objects.create(
- profile=profile,
- resource=resource
- )
+ profile=profile,
+ resource=resource
+ )
@staticmethod
def makeHostConfiguration():
@@ -112,11 +118,11 @@ class ConfigUtil():
bundle = ConfigUtil.makeConfigBundle()
opnfvRole = ConfigUtil.makeOPNFVRole()
return HostConfiguration.objects.create(
- host=host,
- image=image,
- bundle=bundle,
- opnfvRole=opnfvRole
- )
+ host=host,
+ image=image,
+ bundle=bundle,
+ opnfvRole=opnfvRole
+ )
class ScenarioTestCase(TestCase):
@@ -124,26 +130,31 @@ class ScenarioTestCase(TestCase):
def test_save(self):
self.assertTrue(ConfigUtil.makeScenario())
+
class InstallerTestCase(TestCase):
def test_save(self):
self.assertTrue(ConfigUtil.makeInstaller())
+
class OperatingSystemTestCase(TestCase):
def test_save(self):
self.assertTrue(ConfigUtil.makeOpsys())
+
class ConfigBundleTestCase(TestCase):
def test_save(self):
self.assertTrue(ConfigUtil.makeConfigBundle())
+
class OPNFVConfigTestCase(TestCase):
def test_save(self):
self.assertTrue(ConfigUtil.makeOPNFVConfig())
+
class OPNFVRoleTestCase(TestCase):
def test_save(self):
diff --git a/dashboard/src/resource_inventory/views.py b/dashboard/src/resource_inventory/views.py
index 7e73006..2937bd7 100644
--- a/dashboard/src/resource_inventory/views.py
+++ b/dashboard/src/resource_inventory/views.py
@@ -8,17 +8,16 @@
##############################################################################
-from django.shortcuts import render
-from django.views import View
from django.views.generic import TemplateView
from resource_inventory.models import Host
+
class HostView(TemplateView):
template_name = "resource/hosts.html"
def get_context_data(self, **kwargs):
context = super(HostView, self).get_context_data(**kwargs)
hosts = Host.objects.filter(working=True)
- context.update({'hosts':hosts, 'title':"Hardware Resources"})
+ context.update({'hosts': hosts, 'title': "Hardware Resources"})
return context
diff --git a/dashboard/src/workflow/booking_workflow.py b/dashboard/src/workflow/booking_workflow.py
index 213b9e6..cd12ab6 100644
--- a/dashboard/src/workflow/booking_workflow.py
+++ b/dashboard/src/workflow/booking_workflow.py
@@ -15,12 +15,12 @@ from django.utils import timezone
import json
from datetime import timedelta
-from account.models import UserProfile
from booking.models import Booking
from workflow.models import WorkflowStep
-from workflow.forms import ResourceSelectorForm, SWConfigSelectorForm, BookingMetaForm, ConfirmationForm
+from workflow.forms import ResourceSelectorForm, SWConfigSelectorForm, BookingMetaForm
from resource_inventory.models import GenericResourceBundle, ResourceBundle, ConfigBundle
+
class Resource_Select(WorkflowStep):
template = 'booking/steps/resource_select.html'
title = "Select Resource"
@@ -62,14 +62,14 @@ class Resource_Select(WorkflowStep):
edit = self.repo_get(self.repo.EDIT, False)
user = self.repo_get(self.repo.SESSION_USER)
context['form'] = ResourceSelectorForm(
- data={"user": user},
- chosen_resource=default,
- bundle=bundle,
- edit=edit
- )
+ data={"user": user},
+ chosen_resource=default,
+ bundle=bundle,
+ edit=edit
+ )
return context
- def post_render(self, request):
+ def post_render(self, request):
form = ResourceSelectorForm(request.POST)
context = self.get_context()
if form.is_valid():
@@ -86,11 +86,14 @@ class Resource_Select(WorkflowStep):
gresource_bundle = GenericResourceBundle.objects.get(id=selected_id)
except ValueError:
# we want the bundle in the repo
- gresource_bundle = self.repo_get(self.repo.GRESOURCE_BUNDLE_MODELS,{}).get("bundle", GenericResourceBundle())
+ gresource_bundle = self.repo_get(
+ self.repo.GRESOURCE_BUNDLE_MODELS,
+ {}
+ ).get("bundle", GenericResourceBundle())
self.repo_put(
- self.repo_key,
- gresource_bundle
- )
+ self.repo_key,
+ gresource_bundle
+ )
confirm = self.repo_get(self.repo.CONFIRMATION)
if self.confirm_key not in confirm:
confirm[self.confirm_key] = {}
@@ -104,6 +107,7 @@ class Resource_Select(WorkflowStep):
self.metastep.set_invalid("Please complete the fields highlighted in red to continue")
return render(request, self.template, context)
+
class Booking_Resource_Select(Resource_Select):
def __init__(self, *args, **kwargs):
@@ -119,7 +123,7 @@ class Booking_Resource_Select(Resource_Select):
try:
config_bundle = self.repo_get(self.repo.BOOKING_MODELS)['booking'].config_bundle
if default:
- return default # select created grb, even if preselected config bundle
+ return default # select created grb, even if preselected config bundle
return config_bundle.bundle
except:
pass
@@ -145,6 +149,7 @@ class Booking_Resource_Select(Resource_Select):
self.repo_put(self.repo.BOOKING_MODELS, models)
return response
+
class SWConfig_Select(WorkflowStep):
template = 'booking/steps/swconfig_select.html'
title = "Select Software Configuration"
@@ -186,7 +191,6 @@ class SWConfig_Select(WorkflowStep):
return self.render(request)
-
def get_context(self):
context = super(SWConfig_Select, self).get_context()
default = []
@@ -197,7 +201,7 @@ class SWConfig_Select(WorkflowStep):
try:
chosen_bundle = booking.config_bundle
default.append(chosen_bundle.id)
- bundle=chosen_bundle
+ bundle = chosen_bundle
except:
if created_bundle:
default.append("repo bundle")
@@ -208,6 +212,7 @@ class SWConfig_Select(WorkflowStep):
context['form'] = SWConfigSelectorForm(chosen_software=default, bundle=bundle, edit=edit, resource=grb)
return context
+
class Booking_Meta(WorkflowStep):
template = 'booking/steps/booking_meta.html'
title = "Extra Info"
@@ -231,7 +236,7 @@ class Booking_Meta(WorkflowStep):
users = models.get("collaborators", [])
for user in users:
default.append(user.id)
- except Exception as e:
+ except Exception:
pass
default_user = self.repo_get(self.repo.SESSION_USER)
@@ -271,7 +276,7 @@ class Booking_Meta(WorkflowStep):
user_data = form.cleaned_data['users']
confirm['booking']['collaborators'] = []
- user_data = user_data[2:-2] #fixes malformed string from querydict
+ user_data = user_data[2:-2] # fixes malformed string from querydict
if user_data:
form_users = json.loads(user_data)
for user_json in form_users:
diff --git a/dashboard/src/workflow/forms.py b/dashboard/src/workflow/forms.py
index d4abbc3..feb32f2 100644
--- a/dashboard/src/workflow/forms.py
+++ b/dashboard/src/workflow/forms.py
@@ -10,18 +10,20 @@
import django.forms as forms
from django.forms import widgets
-from django.contrib.auth.models import User
from django.utils.safestring import mark_safe
from django.template.loader import render_to_string
-from django.core import serializers
from django.forms.widgets import NumberInput
-from django.db.models import F
-import json
-
-from resource_inventory.models import *
from account.models import Lab
from account.models import UserProfile
+from resource_inventory.models import (
+ GenericResourceBundle,
+ ConfigBundle,
+ OPNFVRole,
+ Image,
+ Installer,
+ Scenario
+)
class SearchableSelectMultipleWidget(widgets.SelectMultiple):
@@ -47,20 +49,22 @@ class SearchableSelectMultipleWidget(widgets.SelectMultiple):
context = self.get_context(attrs)
return mark_safe(render_to_string(self.template_name, context))
- def get_context(self,attrs):
- return {'items':self.items,
- 'name':self.name,
- 'show_from_noentry':self.show_from_noentry,
- 'show_x_results':self.show_x_results,
- 'results_scrollable':self.results_scrollable,
- 'selectable_limit':self.selectable_limit,
- 'placeholder':self.placeholder,
- 'initial':self.initial,
- 'default_entry':self.default_entry,
- 'edit': self.edit,
- 'wf_type': self.wf_type
+ def get_context(self, attrs):
+ return {
+ 'items': self.items,
+ 'name': self.name,
+ 'show_from_noentry': self.show_from_noentry,
+ 'show_x_results': self.show_x_results,
+ 'results_scrollable': self.results_scrollable,
+ 'selectable_limit': self.selectable_limit,
+ 'placeholder': self.placeholder,
+ 'initial': self.initial,
+ 'default_entry': self.default_entry,
+ 'edit': self.edit,
+ 'wf_type': self.wf_type
}
+
class ResourceSelectorForm(forms.Form):
def __init__(self, data=None, **kwargs):
@@ -73,7 +77,7 @@ class ResourceSelectorForm(forms.Form):
bundle = kwargs.pop("bundle")
if "edit" in kwargs:
edit = kwargs.pop("edit")
- super(ResourceSelectorForm, self).__init__(data=data,**kwargs)
+ super(ResourceSelectorForm, self).__init__(data=data, **kwargs)
queryset = GenericResourceBundle.objects.select_related("owner").all()
if data and 'user' in data:
queryset = queryset.filter(owner=data['user'])
@@ -81,8 +85,8 @@ class ResourceSelectorForm(forms.Form):
attrs = self.build_search_widget_attrs(chosen_resource, bundle, edit, queryset)
self.fields['generic_resource_bundle'] = forms.CharField(
- widget=SearchableSelectMultipleWidget(attrs=attrs)
- )
+ widget=SearchableSelectMultipleWidget(attrs=attrs)
+ )
def build_search_widget_attrs(self, chosen_resource, bundle, edit, queryset):
resources = {}
@@ -104,7 +108,7 @@ class ResourceSelectorForm(forms.Form):
displayable['string'] = bundle.description
displayable['id'] = "repo bundle"
resources["repo bundle"] = displayable
- attrs={
+ attrs = {
'set': resources,
'show_from_noentry': "true",
'show_x_results': -1,
@@ -118,6 +122,7 @@ class ResourceSelectorForm(forms.Form):
}
return attrs
+
class SWConfigSelectorForm(forms.Form):
def __init__(self, *args, **kwargs):
@@ -134,11 +139,11 @@ class SWConfigSelectorForm(forms.Form):
edit = kwargs.pop("edit")
if "resource" in kwargs:
resource = kwargs.pop("resource")
- super(SWConfigSelectorForm, self).__init__(*args,**kwargs)
- attrs = self.build_search_widget_attrs(chosen_software,bundle, edit, resource)
+ super(SWConfigSelectorForm, self).__init__(*args, **kwargs)
+ attrs = self.build_search_widget_attrs(chosen_software, bundle, edit, resource)
self.fields['software_bundle'] = forms.CharField(
- widget=SearchableSelectMultipleWidget(attrs=attrs)
- )
+ widget=SearchableSelectMultipleWidget(attrs=attrs)
+ )
def build_search_widget_attrs(self, chosen, bundle, edit, resource):
configs = {}
@@ -162,7 +167,7 @@ class SWConfigSelectorForm(forms.Form):
displayable['id'] = "repo bundle"
configs['repo bundle'] = displayable
- attrs={
+ attrs = {
'set': configs,
'show_from_noentry': "true",
'show_x_results': -1,
@@ -176,9 +181,19 @@ class SWConfigSelectorForm(forms.Form):
}
return attrs
+
class BookingMetaForm(forms.Form):
- length = forms.IntegerField(widget=NumberInput(attrs={'type':'range', 'min':"0", "max":"21", "value":"0"}))
+ length = forms.IntegerField(
+ widget=NumberInput(
+ attrs={
+ "type": "range",
+ 'min': "0",
+ "max": "21",
+ "value": "0"
+ }
+ )
+ )
purpose = forms.CharField(max_length=1000)
project = forms.CharField(max_length=400)
info_file = forms.CharField(max_length=1000, required=False)
@@ -202,9 +217,9 @@ class BookingMetaForm(forms.Form):
self.fields['users'] = forms.CharField(
widget=SearchableSelectMultipleWidget(
attrs=self.build_search_widget_attrs(chosen_users, default_user=default_user)
- ),
+ ),
required=False
- )
+ )
def build_user_list(self):
"""
@@ -213,24 +228,24 @@ class BookingMetaForm(forms.Form):
"""
try:
users = {}
- d_qset = UserProfile.objects.select_related('user').all().exclude(user__username=self.default_user);
+ d_qset = UserProfile.objects.select_related('user').all().exclude(user__username=self.default_user)
for userprofile in d_qset:
user = {
- 'id':userprofile.user.id,
- 'expanded_name':userprofile.full_name,
- 'small_name':userprofile.user.username,
- 'string':userprofile.email_addr
- }
+ 'id': userprofile.user.id,
+ 'expanded_name': userprofile.full_name,
+ 'small_name': userprofile.user.username,
+ 'string': userprofile.email_addr
+ }
users[userprofile.user.id] = user
return users
- except Exception as e:
+ except Exception:
pass
def build_search_widget_attrs(self, chosen_users, default_user="you"):
- attrs={
+ attrs = {
'set': self.build_user_list(),
'show_from_noentry': "false",
'show_x_results': 10,
@@ -243,11 +258,12 @@ class BookingMetaForm(forms.Form):
}
return attrs
+
class MultipleSelectFilterWidget(forms.Widget):
def __init__(self, attrs=None):
super(MultipleSelectFilterWidget, self).__init__(attrs)
self.attrs = attrs
- self.template_name="dashboard/multiple_select_filter_widget.html"
+ self.template_name = "dashboard/multiple_select_filter_widget.html"
def render(self, name, value, attrs=None, renderer=None):
attrs = self.attrs
@@ -258,10 +274,12 @@ class MultipleSelectFilterWidget(forms.Widget):
def get_context(self, name, value, attrs):
return attrs
+
class MultipleSelectFilterField(forms.Field):
- def __init__( self, required=True, widget=None, label=None, initial=None,
- help_text='', error_messages=None, show_hidden_initial=False,
- validators=(), localize=False, disabled=False, label_suffix=None):
+
+ def __init__(self, required=True, widget=None, label=None, initial=None,
+ help_text='', error_messages=None, show_hidden_initial=False,
+ validators=(), localize=False, disabled=False, label_suffix=None):
"""from the documentation:
# required -- Boolean that specifies whether the field is required.
# True by default.
@@ -287,8 +305,8 @@ class MultipleSelectFilterField(forms.Field):
# label_suffix -- Suffix to be added to the label. Overrides
# form's label_suffix.
"""
- #this is bad, but django forms are annoying
- self.widget=widget
+ # this is bad, but django forms are annoying
+ self.widget = widget
if self.widget is None:
self.widget = MultipleSelectFilterWidget()
super(MultipleSelectFilterField, self).__init__(
@@ -311,6 +329,7 @@ class MultipleSelectFilterField(forms.Field):
"""
return data
+
class FormUtils:
@staticmethod
def getLabData():
@@ -355,12 +374,13 @@ class FormUtils:
filter_objects = [("labs", labs.values()), ("hosts", hosts.values())]
context = {
- 'filter_objects': filter_objects,
- 'mapping': mapping,
- 'items': items
- }
+ 'filter_objects': filter_objects,
+ 'mapping': mapping,
+ 'items': items
+ }
return context
+
class HardwareDefinitionForm(forms.Form):
def __init__(self, *args, **kwargs):
@@ -369,38 +389,40 @@ class HardwareDefinitionForm(forms.Form):
attrs = FormUtils.getLabData()
attrs['selection_data'] = selection_data
self.fields['filter_field'] = MultipleSelectFilterField(
- widget=MultipleSelectFilterWidget(
- attrs=attrs
- )
- )
+ widget=MultipleSelectFilterWidget(
+ attrs=attrs
+ )
+ )
+
class PodDefinitionForm(forms.Form):
- fields = [ "xml" ]
+ fields = ["xml"]
xml = forms.CharField()
+
class ResourceMetaForm(forms.Form):
bundle_name = forms.CharField(label="POD Name")
bundle_description = forms.CharField(label="POD Description", widget=forms.Textarea)
+
class GenericHostMetaForm(forms.Form):
host_profile = forms.CharField(label="Host Type", disabled=True, required=False)
host_name = forms.CharField(label="Host Name")
+
class NetworkDefinitionForm(forms.Form):
def __init__(self, *args, **kwargs):
- fields = []
-
super(NetworkDefinitionForm, self).__init__(**kwargs)
+
class NetworkConfigurationForm(forms.Form):
def __init__(self, *args, **kwargs):
- fields = []
-
super(NetworkConfigurationForm).__init__(**kwargs)
+
class HostSoftwareDefinitionForm(forms.Form):
fields = ["host_name", "role", "image"]
@@ -408,6 +430,7 @@ class HostSoftwareDefinitionForm(forms.Form):
role = forms.ModelChoiceField(queryset=OPNFVRole.objects.all())
image = forms.ModelChoiceField(queryset=Image.objects.all())
+
class SoftwareConfigurationForm(forms.Form):
name = forms.CharField(max_length=200)
@@ -416,31 +439,39 @@ class SoftwareConfigurationForm(forms.Form):
installer = forms.ModelChoiceField(queryset=Installer.objects.all(), disabled=True, required=False)
scenario = forms.ModelChoiceField(queryset=Scenario.objects.all(), disabled=True, required=False)
+
class WorkflowSelectionForm(forms.Form):
fields = ['workflow']
empty_permitted = False
- workflow = forms.ChoiceField( choices=(
- (0, 'Booking'),
- (1, 'Resource Bundle'),
- (2, 'Software Configuration')
+ workflow = forms.ChoiceField(
+ choices=(
+ (0, 'Booking'),
+ (1, 'Resource Bundle'),
+ (2, 'Software Configuration')
),
label="Choose Workflow",
initial='booking',
- required=True)
+ required=True
+ )
+
class SnapshotHostSelectForm(forms.Form):
host = forms.CharField()
+
class SnapshotMetaForm(forms.Form):
name = forms.CharField()
description = forms.CharField()
+
class ConfirmationForm(forms.Form):
fields = ['confirm']
- confirm = forms.ChoiceField( choices=(
- (True, "Confirm"),
- (False, "Cancel"))
+ confirm = forms.ChoiceField(
+ choices=(
+ (True, "Confirm"),
+ (False, "Cancel")
)
+ )
diff --git a/dashboard/src/workflow/models.py b/dashboard/src/workflow/models.py
index e5a23b2..966582c 100644
--- a/dashboard/src/workflow/models.py
+++ b/dashboard/src/workflow/models.py
@@ -8,8 +8,6 @@
##############################################################################
-from django.contrib.auth.models import User
-from django.db import models
from django.shortcuts import render
from django.contrib import messages
@@ -17,11 +15,12 @@ import yaml
import requests
from workflow.forms import ConfirmationForm
-from api.models import *
-from dashboard.exceptions import *
-from resource_inventory.models import *
+from api.models import JobFactory
+from dashboard.exceptions import ResourceAvailabilityException, ModelValidationException
+from resource_inventory.models import Image, GenericInterface
from resource_inventory.resource_manager import ResourceManager
from notifier.manager import NotificationHandler
+from booking.models import Booking
class BookingAuthManager():
@@ -52,10 +51,9 @@ class BookingAuthManager():
return None
return ptl
- except Exception as e:
+ except Exception:
return None
-
def booking_allowed(self, booking, repo):
"""
This is the method that will have to change whenever the booking policy changes in the Infra
@@ -64,14 +62,13 @@ class BookingAuthManager():
which is checked using the provided info file
"""
if len(booking.resource.template.getHosts()) < 2:
- return True #if they only have one server, we dont care
+ return True # if they only have one server, we dont care
if booking.owner.userprofile.booking_privledge:
return True # admin override for this user
if repo.BOOKING_INFO_FILE not in repo.el:
return False # INFO file not provided
ptl_info = self.parse_url(repo.BOOKING_INFO_FILE)
- return ptl_info and ptl_info == booking.owner.userprofile.email_addr
-
+ return ptl_info and ptl_info == booking.owner.userprofile.email_addr
class WorkflowStep(object):
@@ -116,6 +113,7 @@ class WorkflowStep(object):
def repo_put(self, key, value):
return self.repo.put(key, value, self.id)
+
class Confirmation_Step(WorkflowStep):
template = 'workflow/confirm.html'
title = "Confirm Changes"
@@ -140,14 +138,13 @@ class Confirmation_Step(WorkflowStep):
return 1 # There is a problem with these vlans
return 0
-
def get_context(self):
context = super(Confirmation_Step, self).get_context()
context['form'] = ConfirmationForm()
context['confirmation_info'] = yaml.dump(
- self.repo_get(self.repo.CONFIRMATION),
- default_flow_style=False
- ).strip()
+ self.repo_get(self.repo.CONFIRMATION),
+ default_flow_style=False
+ ).strip()
context['vlan_warning'] = self.get_vlan_warning()
return context
@@ -211,6 +208,7 @@ class Workflow():
steps = []
active_index = 0
+
class Repository():
EDIT = "editing"
@@ -240,12 +238,11 @@ class Repository():
SNAPSHOT_DESC = "description of the snapshot"
BOOKING_INFO_FILE = "the INFO.yaml file for this user's booking"
-
def get(self, key, default, id):
self.add_get_history(key, id)
return self.el.get(key, default)
- def put(self,key,val, id):
+ def put(self, key, val, id):
self.add_put_history(key, id)
self.el[key] = val
@@ -256,7 +253,7 @@ class Repository():
self.add_history(key, id, self.put_history)
def add_history(self, key, id, history):
- if not key in history:
+ if key not in history:
history[key] = [id]
else:
history[key].append(id)
@@ -266,7 +263,7 @@ class Repository():
errors = self.make_snapshot()
if errors:
return errors
- #if GRB WF, create it
+ # if GRB WF, create it
if self.GRESOURCE_BUNDLE_MODELS in self.el:
errors = self.make_generic_resource_bundle()
if errors:
@@ -285,7 +282,6 @@ class Repository():
booking = self.el[self.BOOKING_MODELS]['booking']
NotificationHandler.notify_new_booking(booking)
-
def make_snapshot(self):
owner = self.el[self.SESSION_USER]
models = self.el[self.SNAPSHOT_MODELS]
@@ -310,7 +306,6 @@ class Repository():
image.host_type = host.profile
image.save()
-
def make_generic_resource_bundle(self):
owner = self.el[self.SESSION_USER]
if self.GRESOURCE_BUNDLE_MODELS in self.el:
@@ -354,10 +349,10 @@ class Repository():
for resource_name, mapping in models['vlans'].items():
for profile_name, vlan_set in mapping.items():
interface = GenericInterface.objects.get(
- profile__name=profile_name,
- host__resource__name=resource_name,
- host__resource__bundle=models['bundle']
- )
+ profile__name=profile_name,
+ host__resource__name=resource_name,
+ host__resource__bundle=models['bundle']
+ )
for vlan in vlan_set:
try:
vlan.save()
@@ -367,16 +362,13 @@ class Repository():
else:
return "GRB, no vlan set provided. CODE:0x0018"
-
else:
return "GRB no models given. CODE:0x0001"
self.el[self.VALIDATED_MODEL_GRB] = bundle
return False
-
def make_software_config_bundle(self):
- owner = self.el[self.SESSION_USER]
models = self.el[self.CONFIG_MODELS]
if 'bundle' in models:
bundle = models['bundle']
@@ -402,7 +394,7 @@ class Repository():
if 'opnfv' in models:
opnfvconfig = models['opnfv']
opnfvconfig.bundle = opnfvconfig.bundle
- if not opnfvconfig.scenario in opnfvconfig.installer.sup_scenarios.all():
+ if opnfvconfig.scenario not in opnfvconfig.installer.sup_scenarios.all():
return "SWC, scenario not supported by installer. CODE:0x000d"
try:
opnfvconfig.save()
@@ -414,7 +406,6 @@ class Repository():
self.el[self.VALIDATED_MODEL_CONFIG] = bundle
return False
-
def make_booking(self):
models = self.el[self.BOOKING_MODELS]
owner = self.el[self.SESSION_USER]
@@ -498,10 +489,9 @@ class Repository():
vlan_manager.reserve_vlans(vlans)
vlan_manager.reserve_public_vlan(public_vlan.vlan_id)
return True
- except Exception as e:
+ except Exception:
return False
-
def __init__(self):
self.el = {}
self.el[self.CONFIRMATION] = {}
diff --git a/dashboard/src/workflow/resource_bundle_workflow.py b/dashboard/src/workflow/resource_bundle_workflow.py
index 63ce3bd..9fb4ae1 100644
--- a/dashboard/src/workflow/resource_bundle_workflow.py
+++ b/dashboard/src/workflow/resource_bundle_workflow.py
@@ -16,9 +16,27 @@ import re
from xml.dom import minidom
from workflow.models import WorkflowStep
-from workflow.forms import *
-from resource_inventory.models import *
-from dashboard.exceptions import *
+from account.models import Lab
+from workflow.forms import (
+ HardwareDefinitionForm,
+ NetworkDefinitionForm,
+ ResourceMetaForm,
+ GenericHostMetaForm
+)
+from resource_inventory.models import (
+ GenericResourceBundle,
+ Vlan,
+ GenericInterface,
+ GenericHost,
+ GenericResource,
+ HostProfile
+)
+from dashboard.exceptions import (
+ InvalidVlanConfigurationException,
+ NetworkExistsException,
+ InvalidHostnameException,
+ NonUniqueHostnameException
+)
import logging
logger = logging.getLogger(__name__)
@@ -30,6 +48,7 @@ class Define_Hardware(WorkflowStep):
title = "Define Hardware"
description = "Choose the type and amount of machines you want"
short_title = "hosts"
+
def get_context(self):
context = super(Define_Hardware, self).get_context()
selection_data = {"hosts": {}, "labs": {}}
@@ -45,8 +64,8 @@ class Define_Hardware(WorkflowStep):
selection_data['labs'] = {"lab_" + str(models.get("bundle").lab.lab_user.id): "true"}
form = HardwareDefinitionForm(
- selection_data=selection_data
- )
+ selection_data=selection_data
+ )
context['form'] = form
return context
@@ -54,7 +73,6 @@ class Define_Hardware(WorkflowStep):
self.context = self.get_context()
return render(request, self.template, self.context)
-
def update_models(self, data):
data = json.loads(data['filter_field'])
models = self.repo_get(self.repo.GRESOURCE_BUNDLE_MODELS, {})
@@ -90,12 +108,11 @@ class Define_Hardware(WorkflowStep):
if list(lab_dict.values())[0]: # True for lab the user selected
lab_user_id = int(list(lab_dict.keys())[0].split("_")[-1])
models['bundle'].lab = Lab.objects.get(lab_user__id=lab_user_id)
- break # if somehow we get two 'true' labs, we only use one
+ break # if somehow we get two 'true' labs, we only use one
# return to repo
self.repo_put(self.repo.GRESOURCE_BUNDLE_MODELS, models)
-
def update_confirmation(self):
confirm = self.repo_get(self.repo.CONFIRMATION, {})
if "resource" not in confirm:
@@ -109,7 +126,6 @@ class Define_Hardware(WorkflowStep):
confirm['resource']['lab'] = models['lab'].lab_user.username
self.repo_put(self.repo.CONFIRMATION, confirm)
-
def post_render(self, request):
try:
self.form = HardwareDefinitionForm(request.POST)
@@ -125,6 +141,7 @@ class Define_Hardware(WorkflowStep):
self.context = self.get_context()
return render(request, self.template, self.context)
+
class Define_Nets(WorkflowStep):
template = 'resource/steps/pod_definition.html'
title = "Define Networks"
@@ -147,7 +164,7 @@ class Define_Nets(WorkflowStep):
vlans = lab.vlan_manager.get_vlan(count=lab.vlan_manager.block_size)
self.repo_put(self.repo.VLANS, vlans)
return vlans
- except Exception as e:
+ except Exception:
return None
def get_context(self):
@@ -165,7 +182,7 @@ class Define_Nets(WorkflowStep):
added_list = []
added_dict = {}
context['added_hosts'] = []
- if not hostlist is None:
+ if hostlist is not None:
new_hostlist = []
for host in models['hosts']:
intcount = host.profile.interfaceprofile.count()
@@ -181,9 +198,12 @@ class Define_Nets(WorkflowStep):
host['id'] = generic_host.resource.name
host['interfaces'] = []
for iface in host_profile.interfaceprofile.all():
- host['interfaces'].append({
+ host['interfaces'].append(
+ {
"name": iface.name,
- "description": "speed: " + str(iface.speed) + "M\ntype: " + iface.nic_type})
+ "description": "speed: " + str(iface.speed) + "M\ntype: " + iface.nic_type
+ }
+ )
host['value'] = {"name": generic_host.resource.name}
host['value']['description'] = generic_host.profile.description
context['hosts'].append(json.dumps(host))
@@ -195,8 +215,9 @@ class Define_Nets(WorkflowStep):
else:
context['xml'] = False
- except Exception as e:
+ except Exception:
pass
+
return context
def post_render(self, request):
@@ -212,7 +233,7 @@ class Define_Nets(WorkflowStep):
self.updateModels(xmlData)
# update model with xml
self.metastep.set_valid("Networks applied successfully")
- except Exception as e:
+ except Exception:
self.metastep.set_invalid("An error occurred when applying networks")
return self.render(request)
@@ -222,7 +243,7 @@ class Define_Nets(WorkflowStep):
given_hosts, interfaces = self.parseXml(xmlData)
vlan_manager = models['bundle'].lab.vlan_manager
existing_host_list = models.get("hosts", [])
- existing_hosts = {} # maps id to host
+ existing_hosts = {} # maps id to host
for host in existing_host_list:
existing_hosts[host.resource.name] = host
@@ -233,7 +254,6 @@ class Define_Nets(WorkflowStep):
for ifaceId in given_host['interfaces']:
iface = interfaces[ifaceId]
- iface_profile = existing_host.profile.interfaceprofile.get(name=iface['profile_name'])
if existing_host.resource.name not in models['vlans']:
models['vlans'][existing_host.resource.name] = {}
models['vlans'][existing_host.resource.name][iface['profile_name']] = []
@@ -255,14 +275,13 @@ class Define_Nets(WorkflowStep):
interfaces = {} # maps id -> interface
xmlDom = minidom.parseString(xmlString)
root = xmlDom.documentElement.firstChild
- connections = []
netids = {}
untagged_ints = {}
for cell in root.childNodes:
cellId = cell.getAttribute('id')
if cell.getAttribute("edge"):
- #cell is a network connection
+ # cell is a network connection
escaped_json_str = cell.getAttribute("value")
json_str = escaped_json_str.replace('&quot;', '"')
attributes = json.loads(json_str)
@@ -272,15 +291,15 @@ class Define_Nets(WorkflowStep):
src = cell.getAttribute("source")
tgt = cell.getAttribute("target")
if src in parent_nets:
- #src is a network port
+ # src is a network port
network = networks[parent_nets[src]]
- if tgt in untagged_ints and tagged==False:
+ if tgt in untagged_ints and not tagged:
raise InvalidVlanConfigurationException("More than one untagged vlan on an interface")
interface = interfaces[tgt]
untagged_ints[tgt] = True
else:
network = networks[parent_nets[tgt]]
- if src in untagged_ints and tagged==False:
+ if src in untagged_ints and not tagged:
raise InvalidVlanConfigurationException("More than one untagged vlan on an interface")
interface = interfaces[src]
untagged_ints[src] = True
@@ -296,7 +315,7 @@ class Define_Nets(WorkflowStep):
int_netid = int(nid)
assert public or int_netid > 1, "Net id is 1 or lower"
assert int_netid < 4095, "Net id is 4095 or greater"
- except Exception as e:
+ except Exception:
raise InvalidVlanConfigurationException("VLAN ID is not an integer more than 1 and less than 4095")
if nid in netids:
raise NetworkExistsException("Non unique network id found")
@@ -307,7 +326,7 @@ class Define_Nets(WorkflowStep):
networks[cellId] = network
elif "host" in cellId: # cell is a host/machine
- #TODO gather host info
+ # TODO gather host info
cell_json_str = cell.getAttribute("value")
cell_json = json.loads(cell_json_str)
host = {"interfaces": [], "name": cellId, "profile_name": cell_json['name']}
@@ -318,7 +337,7 @@ class Define_Nets(WorkflowStep):
if "network" in parentId:
parent_nets[cellId] = parentId
elif "host" in parentId:
- #TODO gather iface info
+ # TODO gather iface info
cell_json_str = cell.getAttribute("value")
cell_json = json.loads(cell_json_str)
iface = {"name": cellId, "networks": [], "profile_name": cell_json['name']}
diff --git a/dashboard/src/workflow/snapshot_workflow.py b/dashboard/src/workflow/snapshot_workflow.py
index 9d4b880..4ddc397 100644
--- a/dashboard/src/workflow/snapshot_workflow.py
+++ b/dashboard/src/workflow/snapshot_workflow.py
@@ -11,9 +11,11 @@
import datetime
import json
-from resource_inventory.models import *
-from workflow.models import *
-from workflow.forms import *
+from booking.models import Booking
+from resource_inventory.models import Host, Image
+from workflow.models import WorkflowStep
+from workflow.forms import SnapshotMetaForm, SnapshotHostSelectForm
+
class Select_Host_Step(WorkflowStep):
template = "snapshot_workflow/steps/select_host.html"
@@ -37,7 +39,6 @@ class Select_Host_Step(WorkflowStep):
for genericHost in booking.resource.template.getHosts():
booking_hosts[booking.id]['hosts'].append({"name": genericHost.resource.name})
-
context['booking_hosts'] = booking_hosts
chosen_host = self.repo_get(self.repo.SNAPSHOT_MODELS, {}).get("host")
@@ -77,6 +78,7 @@ class Select_Host_Step(WorkflowStep):
self.metastep.set_valid("Success")
return self.render(request)
+
class Image_Meta_Step(WorkflowStep):
template = "snapshot_workflow/steps/meta.html"
title = "Additional Information"
@@ -88,7 +90,6 @@ class Image_Meta_Step(WorkflowStep):
context['form'] = SnapshotMetaForm()
return context
-
def post_render(self, request):
form = SnapshotMetaForm(request.POST)
if form.is_valid():
diff --git a/dashboard/src/workflow/sw_bundle_workflow.py b/dashboard/src/workflow/sw_bundle_workflow.py
index 0e9be95..56d0a5d 100644
--- a/dashboard/src/workflow/sw_bundle_workflow.py
+++ b/dashboard/src/workflow/sw_bundle_workflow.py
@@ -8,18 +8,15 @@
##############################################################################
-from django.forms import formset_factory, modelformset_factory
+from django.forms import formset_factory
from workflow.models import WorkflowStep
from workflow.forms import SoftwareConfigurationForm, HostSoftwareDefinitionForm
from workflow.booking_workflow import Resource_Select
-from resource_inventory.models import *
+from resource_inventory.models import Image, GenericHost, ConfigBundle, HostConfiguration, Installer, OPNFVConfig
-#resource selection step is reused from Booking workflow
-
-#TODO: change this: too hacky, just for presentation
-
+# resource selection step is reused from Booking workflow
class SWConf_Resource_Select(Resource_Select):
def __init__(self, *args, **kwargs):
super(SWConf_Resource_Select, self).__init__(*args, **kwargs)
@@ -42,6 +39,7 @@ class SWConf_Resource_Select(Resource_Select):
self.repo_put(self.repo.CONFIG_MODELS, models)
return response
+
class Define_Software(WorkflowStep):
template = 'config_bundle/steps/define_software.html'
title = "Pick Software"
@@ -69,7 +67,7 @@ class Define_Software(WorkflowStep):
filter_data = {}
user = self.repo_get(self.repo.SESSION_USER)
- i=0;
+ i = 0
for host_data in hosts_initial:
host = GenericHost.objects.get(pk=host_data['host_id'])
excluded_images = Image.objects.exclude(owner=user).exclude(public=True)
@@ -143,10 +141,10 @@ class Define_Software(WorkflowStep):
role = form.cleaned_data['role']
bundle = models['bundle']
hostConfig = HostConfiguration(
- host=host,
- image=image,
- bundle=bundle,
- opnfvRole=role
+ host=host,
+ image=image,
+ bundle=bundle,
+ opnfvRole=role
)
models['host_configs'].append(hostConfig)
confirm_host = {"name": host.resource.name, "image": image.name, "role": role.name}
@@ -163,10 +161,11 @@ class Define_Software(WorkflowStep):
return self.render(request)
+
class Config_Software(WorkflowStep):
template = 'config_bundle/steps/config_software.html'
form = SoftwareConfigurationForm
- context = {'workspace_form':form}
+ context = {'workspace_form': form}
title = "Other Info"
description = "Give your software config a name, description, and other stuff"
short_title = "config info"
@@ -203,7 +202,6 @@ class Config_Software(WorkflowStep):
if "bundle" not in models:
models['bundle'] = ConfigBundle(owner=self.repo_get(self.repo.SESSION_USER))
-
confirm = self.repo_get(self.repo.CONFIRMATION, {})
if "configuration" not in confirm:
confirm['configuration'] = {}
@@ -216,10 +214,10 @@ class Config_Software(WorkflowStep):
installer = form.cleaned_data['installer']
scenario = form.cleaned_data['scenario']
opnfv = OPNFVConfig(
- bundle=models['bundle'],
- installer=installer,
- scenario=scenario
- )
+ bundle=models['bundle'],
+ installer=installer,
+ scenario=scenario
+ )
models['opnfv'] = opnfv
confirm['configuration']['installer'] = form.cleaned_data['installer'].name
confirm['configuration']['scenario'] = form.cleaned_data['scenario'].name
@@ -233,6 +231,6 @@ class Config_Software(WorkflowStep):
self.repo_put(self.repo.CONFIG_MODELS, models)
self.repo_put(self.repo.CONFIRMATION, confirm)
- except Exception as e:
+ except Exception:
pass
return self.render(request)
diff --git a/dashboard/src/workflow/tests/test_steps.py b/dashboard/src/workflow/tests/test_steps.py
index 602d3dd..380102a 100644
--- a/dashboard/src/workflow/tests/test_steps.py
+++ b/dashboard/src/workflow/tests/test_steps.py
@@ -6,18 +6,28 @@
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
-from django.test import TestCase, client
+
+from django.test import TestCase
from dashboard.populate_db import Populator
from workflow.tests import constants
from workflow.workflow_factory import WorkflowFactory
from workflow.models import Repository
-from workflow.resource_bundle_workflow import *
-from workflow.sw_bundle_workflow import *
-from workflow.booking_workflow import *
+from workflow.resource_bundle_workflow import Define_Hardware, Define_Nets, Resource_Meta_Info, Host_Meta_Info
+from workflow.sw_bundle_workflow import SWConf_Resource_Select, Define_Software, Config_Software
+from workflow.booking_workflow import Booking_Resource_Select, SWConfig_Select, Booking_Meta
from django.http import QueryDict, HttpRequest
from django.contrib.auth.models import User
-from django.core.management import call_command
-from resource_inventory.models import *
+from resource_inventory.models import (
+ Scenario,
+ Installer,
+ OPNFVRole,
+ Image,
+ GenericResourceBundle,
+ GenericHost,
+ HostProfile,
+ GenericResource,
+ ConfigBundle
+)
class BaseStepTestCase(TestCase):
@@ -48,7 +58,7 @@ class BookingResourceSelectTestCase(BaseStepTestCase):
grb_model = GenericResourceBundle.objects.filter(owner__username="user 1").first()
grb = [{"small_name": grb_model.name, "expanded_name": "user 1", "id": grb_model.id, "string": ""}]
grb = str(grb).replace("'", '"')
- data = {"generic_resource_bundle": grb }
+ data = {"generic_resource_bundle": grb}
response, context = self.step_test(Booking_Resource_Select, data)
self.assertTrue(True)
@@ -60,11 +70,12 @@ class BookingResourceSelectTestCase(BaseStepTestCase):
data = {}
response, context = self.step_test(SWConfig_Select, data)
+
class SoftwareConfigSelectTestCase(BaseStepTestCase):
def test_step_with_good_data(self):
config_model = ConfigBundle.objects.filter(owner__username="user 1").first()
- config = [{"expanded_name":"user 1", "small_name":config_model.name, "id":config_model.id, "string":""}]
+ config = [{"expanded_name": "user 1", "small_name": config_model.name, "id": config_model.id, "string": ""}]
config = str(config).replace("'", '"')
data = {"software_bundle": config}
response, context = self.step_test(SWConfig_Select, data)
@@ -77,6 +88,7 @@ class SoftwareConfigSelectTestCase(BaseStepTestCase):
data = {}
response, context = self.step_test(SWConfig_Select, data)
+
class BookingMetaTestCase(BaseStepTestCase):
def test_step_with_good_data(self):
@@ -84,9 +96,9 @@ class BookingMetaTestCase(BaseStepTestCase):
user2 = User.objects.get(username="user 2")
john = User.objects.get(username="johnsmith")
users = [
- {"expanded_name":"", "id":user2.id, "small_name":user2.username, "string":user2.email},
- {"expanded_name":"", "id":john.id, "small_name":john.username, "string":john.email}
- ]
+ {"expanded_name": "", "id": user2.id, "small_name": user2.username, "string": user2.email},
+ {"expanded_name": "", "id": john.id, "small_name": john.username, "string": john.email}
+ ]
users = str(users).replace("'", '"')
data['users'] = users
response, context = self.step_test(Booking_Meta, data)
@@ -104,7 +116,7 @@ class DefineHardwareTestCase(BaseStepTestCase):
def test_step_with_good_data(self):
hosts = {"host_4": 1, "host_1": 1}
- labs = {"lab_1":"true"}
+ labs = {"lab_1": "true"}
data = {"hosts": hosts, "labs": labs}
response, context = self.step_test(Define_Hardware, data)
@@ -197,7 +209,7 @@ class SWConfResourceSelectTestCase(BaseStepTestCase):
grb_model = GenericResourceBundle.objects.filter(owner__username="user 1").first()
grb = [{"small_name": grb_model.name, "expanded_name": "user 1", "id": grb_model.id, "string": ""}]
grb = str(grb).replace("'", '"')
- data = {"generic_resource_bundle": grb }
+ data = {"generic_resource_bundle": grb}
response, context = self.step_test(SWConf_Resource_Select, data)
def test_step_with_bad_data(self): # TODO
@@ -220,7 +232,6 @@ class DefineSoftwareTestCase(BaseStepTestCase):
repo.el[repo.SWCONF_SELECTED_GRB] = grb
return repo
-
def test_step_with_good_data(self):
data = {"form-INITIAL_FORMS": 3, "form-MAX_NUM_FORMS": 1000}
data["form-MIN_NUM_FORMS"] = 0
@@ -268,4 +279,3 @@ class ConfigSoftwareTestCase(BaseStepTestCase):
def test_step_with_empty_data(self):
data = {}
response, context = self.step_test(Config_Software, data)
-
diff --git a/dashboard/src/workflow/tests/test_steps_render.py b/dashboard/src/workflow/tests/test_steps_render.py
index 3da3b3d..f3df8f2 100644
--- a/dashboard/src/workflow/tests/test_steps_render.py
+++ b/dashboard/src/workflow/tests/test_steps_render.py
@@ -6,8 +6,10 @@
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
+
from django.test import TestCase, Client
+
class SuperViewTestCase(TestCase):
url = "/"
client = Client()
@@ -20,17 +22,22 @@ class SuperViewTestCase(TestCase):
class DefineHardwareViewTestCase(SuperViewTestCase):
url = "/wf/workflow/step/define_hardware"
+
class DefineNetworkViewTestCase(SuperViewTestCase):
url = "/wf/workflow/step/define_net"
+
class ResourceMetaViewTestCase(SuperViewTestCase):
url = "/wf/workflow/step/resource_meta"
+
class BookingMetaViewTestCase(SuperViewTestCase):
url = "/wf/workflow/step/booking_meta"
+
class SoftwareSelectViewTestCase(SuperViewTestCase):
url = "/wf/workflow/step/software_select"
+
class ResourceSelectViewTestCase(SuperViewTestCase):
url = "/wf/workflow/step/resource_select"
diff --git a/dashboard/src/workflow/tests/test_workflows.py b/dashboard/src/workflow/tests/test_workflows.py
index 71d0144..7a53521 100644
--- a/dashboard/src/workflow/tests/test_workflows.py
+++ b/dashboard/src/workflow/tests/test_workflows.py
@@ -6,10 +6,10 @@
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
-from django.test import TestCase, client
+
+from django.test import TestCase
from workflow.workflow_factory import WorkflowFactory
from dashboard.populate_db import Populator
-from resource_inventory.models import *
"""
@@ -25,6 +25,7 @@ To remove a workflow:
POST to /wf/workflow {"cancel": ""}
"""
+
class WorkflowTestCase(TestCase):
@classmethod
@@ -62,6 +63,7 @@ class WorkflowTestCase(TestCase):
self.assertIsNone(exception)
+
class BookingWorkflowTestCase(WorkflowTestCase):
@classmethod
@@ -73,6 +75,7 @@ class BookingWorkflowTestCase(WorkflowTestCase):
def test_steps_render(self):
super(BookingWorkflowTestCase, self).render_steps()
+
class ResourceWorkflowTestCase(WorkflowTestCase):
@classmethod
@@ -84,6 +87,7 @@ class ResourceWorkflowTestCase(WorkflowTestCase):
def test_steps_render(self):
super(ResourceWorkflowTestCase, self).render_steps()
+
class ConfigWorkflowTestCase(WorkflowTestCase):
@classmethod
diff --git a/dashboard/src/workflow/urls.py b/dashboard/src/workflow/urls.py
index c7f8acb..b131d84 100644
--- a/dashboard/src/workflow/urls.py
+++ b/dashboard/src/workflow/urls.py
@@ -8,13 +8,13 @@
##############################################################################
-from django.conf.urls import url, include
+from django.conf.urls import url
from django.conf import settings
-from workflow.views import *
-from workflow.models import *
-from workflow.resource_bundle_workflow import *
-from workflow.booking_workflow import *
+from workflow.views import step_view, delete_session, manager_view, viewport_view
+from workflow.models import Repository
+from workflow.resource_bundle_workflow import Define_Hardware, Define_Nets, Resource_Meta_Info
+from workflow.booking_workflow import SWConfig_Select, Resource_Select, Booking_Meta
app_name = 'workflow'
urlpatterns = [
diff --git a/dashboard/src/workflow/views.py b/dashboard/src/workflow/views.py
index 85e4eac..e5ef5c6 100644
--- a/dashboard/src/workflow/views.py
+++ b/dashboard/src/workflow/views.py
@@ -8,15 +8,12 @@
##############################################################################
-from django.http import HttpResponse, HttpRequest, HttpResponseGone
-from django.urls import reverse
-from django.shortcuts import render, redirect
-from django import forms
+from django.http import HttpResponse, HttpResponseGone
+from django.shortcuts import render
import uuid
-from workflow.forms import *
-from workflow.workflow_manager import *
+from workflow.workflow_manager import ManagerTracker, SessionManager
import logging
logger = logging.getLogger(__name__)
@@ -31,32 +28,35 @@ def attempt_auth(request):
except KeyError:
return None
+
def delete_session(request):
try:
- manager = ManagerTracker.managers[request.session['manager_session']]
del ManagerTracker.managers[request.session['manager_session']]
return HttpResponse('')
- except KeyError:
+ except Exception:
return None
+
def step_view(request):
manager = attempt_auth(request)
if not manager:
- #no manager found, redirect to "lost" page
+ # no manager found, redirect to "lost" page
return no_workflow(request)
if request.GET.get('step') is not None:
manager.goto(int(request.GET.get('step')))
return manager.render(request)
+
def manager_view(request):
manager = attempt_auth(request)
if not manager:
return HttpResponseGone("No session found that relates to current request")
- if request.method == 'GET': #no need for this statement if only intercepting post requests
+ if request.method == 'GET':
+ # no need for this statement if only intercepting post requests
- #return general context for viewport page
+ # return general context for viewport page
return manager.status(request)
if request.method == 'POST':
@@ -64,18 +64,17 @@ def manager_view(request):
logger.debug("add found")
target_id = None
if 'target' in request.POST:
- target_id=int(request.POST.get('target'))
+ target_id = int(request.POST.get('target'))
manager.add_workflow(workflow_type=int(request.POST.get('add')), target_id=target_id)
elif request.POST.get('edit') is not None and request.POST.get('edit_id') is not None:
logger.debug("edit found")
manager.add_workflow(workflow_type=request.POST.get('edit'), edit_object=int(request.POST.get('edit_id')))
elif request.POST.get('cancel') is not None:
- mgr = ManagerTracker.managers[request.session['manager_session']]
del ManagerTracker.managers[request.session['manager_session']]
- del mgr
return manager.status(request)
+
def viewport_view(request):
if not request.user.is_authenticated:
return login(request)
@@ -84,11 +83,12 @@ def viewport_view(request):
if manager is None:
return no_workflow(request)
- if request.method == 'GET':
+ if request.method == 'GET':
return render(request, 'workflow/viewport-base.html')
else:
pass
+
def create_session(wf_type, request):
wf = int(wf_type)
smgr = SessionManager(request=request)
@@ -98,11 +98,13 @@ def create_session(wf_type, request):
return manager_uuid
+
def no_workflow(request):
logger.debug("There is no active workflow")
return render(request, 'workflow/no_workflow.html', {'title': "Not Found"})
+
def login(request):
return render(request, "dashboard/login.html", {'title': 'Authentication Required'})
diff --git a/dashboard/src/workflow/workflow_factory.py b/dashboard/src/workflow/workflow_factory.py
index 7c0dcb9..9a42d86 100644
--- a/dashboard/src/workflow/workflow_factory.py
+++ b/dashboard/src/workflow/workflow_factory.py
@@ -8,30 +8,33 @@
##############################################################################
-from workflow.booking_workflow import *
-from workflow.resource_bundle_workflow import *
-from workflow.sw_bundle_workflow import *
-from workflow.snapshot_workflow import *
-from workflow.models import Workflow, Repository
+from workflow.booking_workflow import Booking_Resource_Select, SWConfig_Select, Booking_Meta
+from workflow.resource_bundle_workflow import Define_Hardware, Define_Nets, Resource_Meta_Info
+from workflow.sw_bundle_workflow import Config_Software, Define_Software, SWConf_Resource_Select
+from workflow.snapshot_workflow import Select_Host_Step, Image_Meta_Step
import uuid
import logging
logger = logging.getLogger(__name__)
+
class BookingMetaWorkflow(object):
workflow_type = 0
color = "#0099ff"
is_child = False
+
class ResourceMetaWorkflow(object):
workflow_type = 1
color = "#ff6600"
+
class ConfigMetaWorkflow(object):
workflow_type = 2
color = "#00ffcc"
+
class MetaRelation(object):
def __init__(self, *args, **kwargs):
self.color = "#cccccc"
@@ -47,8 +50,8 @@ class MetaRelation(object):
'depth': self.depth,
}
+
class MetaStep(object):
- #valid = 0 #0 is not checked, 1 is invalid, 2 is valid
UNTOUCHED = 0
INVALID = 100
@@ -89,37 +92,37 @@ class MetaStep(object):
def __ne__(self, other):
return self.id.int != other.id.int
+
class WorkflowFactory():
- #def __init__(self, *args, **kwargs):
booking_steps = [
- Booking_Resource_Select,
- SWConfig_Select,
- Booking_Meta
- ]
+ Booking_Resource_Select,
+ SWConfig_Select,
+ Booking_Meta
+ ]
resource_steps = [
- Define_Hardware,
- Define_Nets,
- Resource_Meta_Info,
- ]
+ Define_Hardware,
+ Define_Nets,
+ Resource_Meta_Info,
+ ]
config_steps = [
- SWConf_Resource_Select,
- Define_Software,
- Config_Software,
- ]
+ SWConf_Resource_Select,
+ Define_Software,
+ Config_Software,
+ ]
snapshot_steps = [
- Select_Host_Step,
- Image_Meta_Step
- ]
+ Select_Host_Step,
+ Image_Meta_Step
+ ]
def conjure(self, workflow_type=None, repo=None):
workflow_types = [
- self.booking_steps,
- self.resource_steps,
- self.config_steps,
- self.snapshot_steps,
+ self.booking_steps,
+ self.resource_steps,
+ self.config_steps,
+ self.snapshot_steps,
]
steps = self.make_steps(workflow_types[workflow_type], repository=repo)
diff --git a/dashboard/src/workflow/workflow_manager.py b/dashboard/src/workflow/workflow_manager.py
index 16fa468..95fefbf 100644
--- a/dashboard/src/workflow/workflow_manager.py
+++ b/dashboard/src/workflow/workflow_manager.py
@@ -8,23 +8,24 @@
##############################################################################
-from django.db import models
-from django.contrib.auth.models import User
-from django.core import serializers
-from django.http import HttpResponse, JsonResponse
+from django.http import JsonResponse
-import json
-import uuid
import random
-from resource_inventory.models import *
from booking.models import Booking
from workflow.workflow_factory import WorkflowFactory, MetaStep, MetaRelation
from workflow.models import Repository, Confirmation_Step
+from resource_inventory.models import (
+ GenericResourceBundle,
+ ConfigBundle,
+ HostConfiguration,
+ OPNFVConfig
+)
import logging
logger = logging.getLogger(__name__)
+
class SessionManager():
def __init__(self, request=None):
@@ -38,7 +39,7 @@ class SessionManager():
metaconfirm = MetaStep()
metaconfirm.index = 0
metaconfirm.short_title = "confirm"
- self.repository.el['steps'] = 1;
+ self.repository.el['steps'] = 1
self.metaworkflow = None
self.metaworkflows = []
self.metarelations = []
@@ -85,10 +86,8 @@ class SessionManager():
self.metarelations.append(relation)
self.initialized = True
-
def status(self, request):
try:
- workflows = []
steps = []
for step in self.step_meta:
steps.append(step.to_json())
@@ -109,11 +108,11 @@ class SessionManager():
responsejson['parents'] = parents
responsejson['children'] = children
return JsonResponse(responsejson, safe=False)
- except Exception as e:
+ except Exception:
pass
def render(self, request, **kwargs):
- #filter out when a step needs to handle post/form data
+ # filter out when a step needs to handle post/form data
# if 'workflow' in post data, this post request was meant for me, not step
if request.method == 'POST' and request.POST.get('workflow', None) is None:
return self.steps[self.active_index].post_render(request)
@@ -125,7 +124,7 @@ class SessionManager():
def goto(self, num, **kwargs):
self.repository.el['active_step'] = int(num)
self.active_index = int(num)
- #TODO: change to include some checking
+ # TODO: change to include some checking
def prefill_repo(self, target_id, workflow_type):
self.repository.el[self.repository.EDIT] = True
@@ -140,7 +139,6 @@ class SessionManager():
edit_object = ConfigBundle.objects.get(pk=target_id)
self.prefill_config(edit_object)
-
def prefill_booking(self, booking):
models = self.make_booking_models(booking)
confirmation = self.make_booking_confirm(booking)
diff --git a/dashboard/test.sh b/dashboard/test.sh
index 68fe903..7931cf0 100755
--- a/dashboard/test.sh
+++ b/dashboard/test.sh
@@ -8,5 +8,9 @@
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
+# first, basic lint with flake8
+find . -type f -name "*.py" -not -name "manage.py" | xargs flake8 --count --ignore E501
+
+
# this file should be executed from the dir it is in
docker exec -it dg01 python manage.py test -t ../src/