aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/account/models.py16
-rw-r--r--src/booking/views.py11
-rw-r--r--src/dashboard/admin_utils.py111
-rw-r--r--src/dashboard/views.py16
-rw-r--r--src/resource_inventory/models.py18
-rw-r--r--src/resource_inventory/pdf_templater.py6
-rw-r--r--src/templates/akraino/booking/quick_deploy.html3
-rw-r--r--src/templates/base/booking/booking_detail.html3
-rw-r--r--src/templates/base/booking/quick_deploy.html5
-rw-r--r--src/templates/base/dashboard/landing.html17
-rw-r--r--src/templates/base/workflow/viewport-base.html5
-rw-r--r--src/templates/laas/dashboard/landing.html2
-rw-r--r--src/workflow/views.py8
13 files changed, 192 insertions, 29 deletions
diff --git a/src/account/models.py b/src/account/models.py
index 2c133bb..2d0293f 100644
--- a/src/account/models.py
+++ b/src/account/models.py
@@ -11,8 +11,6 @@
from django.contrib.auth.models import User
from django.db import models
from django.apps import apps
-from django.core.exceptions import ValidationError
-import re
import json
import random
@@ -59,20 +57,6 @@ class UserProfile(models.Model):
class Meta:
db_table = 'user_profile'
- def clean(self, *args, **kwargs):
- company = self.company
- regex = r'[a-z\_\-\.\$]*'
- pattern = re.compile(regex)
-
- if not pattern.fullmatch(company):
- raise ValidationError('Company may only include lowercase letters, _, -, . and $')
-
- super().clean(*args, **kwargs)
-
- def save(self, *args, **kwargs):
- self.full_clean()
- super().save(*args, **kwargs)
-
def __str__(self):
return self.user.username
diff --git a/src/booking/views.py b/src/booking/views.py
index bd57812..c41a7d6 100644
--- a/src/booking/views.py
+++ b/src/booking/views.py
@@ -19,7 +19,7 @@ from django.db.models import Q
from django.urls import reverse
from resource_inventory.models import ResourceBundle, ResourceProfile, Image, ResourceQuery
-from account.models import Downtime
+from account.models import Downtime, Lab
from booking.models import Booking
from booking.stats import StatisticsManager
from booking.forms import HostReImageForm
@@ -44,6 +44,7 @@ def quick_create(request):
context['form'] = QuickBookingForm(lab_data=attrs, default_user=request.user.username, user=request.user)
context['lab_profile_map'] = {}
context.update(drop_filter(request.user))
+ context['contact_email'] = Lab.objects.filter(name="UNH_IOL").first().contact_email
return render(request, 'booking/quick_deploy.html', context)
if request.method == 'POST':
@@ -74,9 +75,15 @@ class BookingView(TemplateView):
def get_context_data(self, **kwargs):
booking = get_object_or_404(Booking, id=self.kwargs['booking_id'])
title = 'Booking Details'
+ contact = Lab.objects.filter(name="UNH_IOL").first().contact_email
downtime = Downtime.objects.filter(lab=booking.lab, start__lt=timezone.now, end__gt=timezone.now()).first()
context = super(BookingView, self).get_context_data(**kwargs)
- context.update({'title': title, 'booking': booking, 'downtime': downtime})
+ context.update({
+ 'title': title,
+ 'booking': booking,
+ 'downtime': downtime,
+ 'contact_email': contact
+ })
return context
diff --git a/src/dashboard/admin_utils.py b/src/dashboard/admin_utils.py
new file mode 100644
index 0000000..367c613
--- /dev/null
+++ b/src/dashboard/admin_utils.py
@@ -0,0 +1,111 @@
+from resource_inventory.models import (
+ ResourceTemplate,
+ Image,
+ Server,
+ ResourceBundle,
+)
+
+from django.contrib.auth.models import User
+
+from account.models import Lab
+
+from resource_inventory.resource_manager import ResourceManager
+from resource_inventory.pdf_templater import PDFTemplater
+
+from booking.quick_deployer import update_template
+
+from datetime import timedelta
+
+from django.utils import timezone
+
+from booking.models import Booking
+from notifier.manager import NotificationHandler
+from api.models import JobFactory
+
+
+"""
+creates a quick booking using the given host
+"""
+
+
+def book_host(owner_username, host_labid, lab_username, hostname, image_id, template_name, length_days=21, collaborator_usernames=[], purpose="internal", project="LaaS"):
+ lab = Lab.objects.get(lab_user__username=lab_username)
+ host = Server.objects.filter(lab=lab).get(labid=host_labid)
+ if host.booked:
+ print("Can't book host, already marked as booked")
+ return
+ else:
+ host.booked = True
+ host.save()
+
+ template = ResourceTemplate.objects.filter(public=True).get(name=template_name)
+ image = Image.objects.get(id=image_id)
+
+ owner = User.objects.get(username=owner_username)
+
+ new_template = update_template(template, image, hostname, owner)
+
+ rmanager = ResourceManager.getInstance()
+
+ vlan_map = rmanager.get_vlans(new_template)
+
+ # only a single host so can reuse var for iter here
+ resource_bundle = ResourceBundle.objects.create(template=new_template)
+ res_configs = new_template.getConfigs()
+
+ for config in res_configs:
+ try:
+ host.bundle = resource_bundle
+ host.config = config
+ rmanager.configureNetworking(resource_bundle, host, vlan_map)
+ host.save()
+ except Exception:
+ host.booked = False
+ host.save()
+ print("Failed to book host due to error configuring it")
+ return
+
+ new_template.save()
+
+ booking = Booking.objects.create(
+ purpose=purpose,
+ project=project,
+ lab=lab,
+ owner=owner,
+ start=timezone.now(),
+ end=timezone.now() + timedelta(days=int(length_days)),
+ resource=resource_bundle,
+ opnfv_config=None
+ )
+
+ booking.pdf = PDFTemplater.makePDF(booking)
+
+ booking.save()
+
+ for collaborator_username in collaborator_usernames:
+ try:
+ user = User.objects.get(username=collaborator_username)
+ booking.collaborators.add(user)
+ except Exception:
+ print("couldn't add user with username ", collaborator_username)
+
+ booking.save()
+
+ JobFactory.makeCompleteJob(booking)
+ NotificationHandler.notify_new_booking(booking)
+
+
+def mark_working(host_labid, lab_username, working=True):
+ lab = Lab.objects.get(lab_user__username=lab_username)
+ server = Server.objects.filter(lab=lab).get(labid=host_labid)
+ print("changing server working status from ", server.working, "to", working)
+ server.working = working
+ server.save()
+
+
+def mark_booked(host_labid, lab_username, booked=True):
+ lab = Lab.objects.get(lab_user__username=lab_username)
+ server = Server.objects.filter(lab=lab).get(labid=host_labid)
+ print("changing server booked status from ", server.booked, "to", booked)
+ server.booked = booked
+ server.save()
diff --git a/src/dashboard/views.py b/src/dashboard/views.py
index 2ace2d4..f9a908c 100644
--- a/src/dashboard/views.py
+++ b/src/dashboard/views.py
@@ -12,8 +12,12 @@
from django.shortcuts import get_object_or_404
from django.views.generic import TemplateView
from django.shortcuts import render
+from django.db.models import Q
+from datetime import datetime
+import pytz
from account.models import Lab
+from booking.models import Booking
from resource_inventory.models import Image, ResourceProfile, ResourceQuery
from workflow.workflow_manager import ManagerTracker
@@ -65,12 +69,22 @@ def host_profile_detail_view(request):
def landing_view(request):
manager = ManagerTracker.managers.get(request.session.get('manager_session'))
+ user = request.user
+ if not user.is_anonymous:
+ bookings = Booking.objects.filter(
+ Q(owner=user) | Q(collaborators=user),
+ end__gte=datetime.now(pytz.utc)
+ )
+ else:
+ bookings = None
+
return render(
request,
'dashboard/landing.html',
{
'manager': manager is not None,
- 'title': "Welcome to the Lab as a Service Dashboard"
+ 'title': "Welcome to the Lab as a Service Dashboard",
+ 'bookings': bookings
}
)
diff --git a/src/resource_inventory/models.py b/src/resource_inventory/models.py
index c918513..01da8bb 100644
--- a/src/resource_inventory/models.py
+++ b/src/resource_inventory/models.py
@@ -12,6 +12,7 @@ from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
from django.db import models
from django.db.models import Q
+import traceback
import re
from collections import Counter
@@ -201,10 +202,20 @@ class ResourceBundle(models.Model):
def release(self):
for pn in PhysicalNetwork.objects.filter(bundle=self).all():
- pn.release()
+ try:
+ pn.release()
+ except Exception as e:
+ print("Exception occurred while trying to release resource ", pn.vlan_id)
+ print(e)
+ traceback.print_exc()
for resource in self.get_resources():
- resource.release()
+ try:
+ resource.release()
+ except Exception as e:
+ print("Exception occurred while trying to release resource ", resource)
+ print(e)
+ traceback.print_exc()
def get_template_name(self):
if not self.template:
@@ -343,6 +354,7 @@ class Server(Resource):
return list(self.interfaces.all().order_by('bus_address'))
def release(self):
+ self.bundle = None
self.booked = False
self.save()
@@ -408,7 +420,7 @@ class Network(models.Model):
class PhysicalNetwork(models.Model):
vlan_id = models.IntegerField()
generic_network = models.ForeignKey(Network, on_delete=models.CASCADE)
- bundle = models.ForeignKey(ResourceBundle, null=True, on_delete=models.CASCADE)
+ bundle = models.ForeignKey(ResourceBundle, null=True, blank=True, on_delete=models.CASCADE)
def get_configuration(self, state):
"""
diff --git a/src/resource_inventory/pdf_templater.py b/src/resource_inventory/pdf_templater.py
index 86d84aa..c4b22fe 100644
--- a/src/resource_inventory/pdf_templater.py
+++ b/src/resource_inventory/pdf_templater.py
@@ -22,7 +22,11 @@ class PDFTemplater:
template = "dashboard/pdf.yaml"
info = {}
info['details'] = cls.get_pdf_details(booking.resource)
- info['jumphost'] = cls.get_pdf_jumphost(booking)
+ try:
+ info['jumphost'] = cls.get_pdf_jumphost(booking)
+ except Exception:
+ # filling in jumphost info can be optional in some cases, this shouldn't be a hard error
+ info['jumphost'] = {}
info['nodes'] = cls.get_pdf_nodes(booking)
return render_to_string(template, context=info)
diff --git a/src/templates/akraino/booking/quick_deploy.html b/src/templates/akraino/booking/quick_deploy.html
index af9b3d3..c3e519f 100644
--- a/src/templates/akraino/booking/quick_deploy.html
+++ b/src/templates/akraino/booking/quick_deploy.html
@@ -6,7 +6,8 @@
Please select a host type you wish to book.
Only available types are shown.
More information can be found here:
- <a href="https://wiki.akraino.org/display/AK/Shared+Community+Lab">Akraino Wiki</a>
+ <a href="https://wiki.akraino.org/display/AK/Shared+Community+Lab">Akraino Wiki</a>.
+ If something isn't working right, let us know <a href="mailto:{{contact_email}}"> here! </a>
</p>
{% endblock form-text %}
{% block collab %}
diff --git a/src/templates/base/booking/booking_detail.html b/src/templates/base/booking/booking_detail.html
index 4b70f69..24a654c 100644
--- a/src/templates/base/booking/booking_detail.html
+++ b/src/templates/base/booking/booking_detail.html
@@ -159,7 +159,8 @@
<div class="card mb-3">
<div class="card-header d-flex">
<h4 class="d-inline">Deployment Progress</h4>
- <p>These are the different tasks that have to be completed before your deployment is ready</p>
+ <p>These are the different tasks that have to be completed before your deployment is ready.
+ If this is taking a really long time, let us know <a href="mailto:{{contact_email}}">here!</a></p>
<button data-toggle="collapse" data-target="#panel_tasks" class="btn btn-outline-secondary ml-auto">Expand</button>
</div>
<div class="collapse show" id="panel_tasks">
diff --git a/src/templates/base/booking/quick_deploy.html b/src/templates/base/booking/quick_deploy.html
index e4b9431..c954073 100644
--- a/src/templates/base/booking/quick_deploy.html
+++ b/src/templates/base/booking/quick_deploy.html
@@ -9,7 +9,10 @@
<div class="row mx-0 px-0">
<div class="col-12 mx-0 px-0 mt-2">
{% block form-text %}
- <p class="my-0">Please select a host type you wish to book. Only available types are shown.</p>
+ <p class="my-0">
+ Please select a host type you wish to book. Only available types are shown.
+ If something isn't working right, let us know <a href="mailto:{{contact_email}}"> here! </a>
+ </p>
{% endblock form-text %}
{% bootstrap_field form.filter_field show_label=False %}
</div>
diff --git a/src/templates/base/dashboard/landing.html b/src/templates/base/dashboard/landing.html
index ed50638..ecb12c6 100644
--- a/src/templates/base/dashboard/landing.html
+++ b/src/templates/base/dashboard/landing.html
@@ -16,12 +16,27 @@
{% csrf_token %}
<div class="row">
- <!-- About us -->
<div class="col-12 col-lg-6 mb-4">
+ <!-- About us -->
<h2 class="border-bottom">About Us</h2>
{% block about_us %}
<p>Here is some information about us!</p>
{% endblock about_us %}
+ {% block welcome_back %}
+ {% if user.is_authenticated %}
+ <h2 class="border-bottom">Welcome Back!</h2>
+ {% if bookings %}
+ <h5> These are your current bookings: </h5>
+ <ul style="list-style: none;">
+ {% for book in bookings %}
+ <li><a href="/booking/detail/{{ book.id }}/">{{ book.purpose }}</a></li>
+ {% endfor %}
+ </ul>
+ {% else %}
+ <h5> You have no current bookings <h5>
+ {% endif %}
+ {% endif %}
+ {% endblock welcome_back %}
</div>
<!-- Get started -->
diff --git a/src/templates/base/workflow/viewport-base.html b/src/templates/base/workflow/viewport-base.html
index d08145c..d9648c2 100644
--- a/src/templates/base/workflow/viewport-base.html
+++ b/src/templates/base/workflow/viewport-base.html
@@ -29,6 +29,11 @@
</nav>
</div>
</div>
+ <div class=”row”>
+ <div class=”col-xs-6 col-md-4”>
+ Is something not working right? Let us know <a href="mailto::{{contact_email}}"> here! </a>
+ </div>
+</div>
<!-- Top header -->
<div class="row">
<div class="col">
diff --git a/src/templates/laas/dashboard/landing.html b/src/templates/laas/dashboard/landing.html
index a8e0ff8..fc6b3e3 100644
--- a/src/templates/laas/dashboard/landing.html
+++ b/src/templates/laas/dashboard/landing.html
@@ -9,4 +9,4 @@
book a
whole block of servers with customized layer2 networks (e.g. a Pharos Pod). Read more here:
<a href="https://wiki.opnfv.org/x/HAE-Ag" target="_blank">LaaS Wiki</a></p>
-{% endblock about_us %}
+{% endblock %} \ No newline at end of file
diff --git a/src/workflow/views.py b/src/workflow/views.py
index 9666d72..fb311b7 100644
--- a/src/workflow/views.py
+++ b/src/workflow/views.py
@@ -10,6 +10,7 @@
from django.http import HttpResponse
from django.shortcuts import render
+from account.models import Lab
import uuid
@@ -73,7 +74,12 @@ def viewport_view(request):
if request.method != 'GET':
return HttpResponse(status=405)
- return render(request, 'workflow/viewport-base.html')
+
+ context = {
+ 'contact_email': Lab.objects.get(name="UNH_IOL").contact_email
+ }
+
+ return render(request, 'workflow/viewport-base.html', context)
def create_workflow(request):