summaryrefslogtreecommitdiffstats
path: root/dashboard/src
diff options
context:
space:
mode:
Diffstat (limited to 'dashboard/src')
-rw-r--r--dashboard/src/api/models.py37
-rw-r--r--dashboard/src/booking/views.py4
-rw-r--r--dashboard/src/dashboard/tasks.py6
-rw-r--r--dashboard/src/templates/booking/booking_detail.html470
-rw-r--r--dashboard/src/templates/booking/booking_table.html4
-rw-r--r--dashboard/src/templates/booking/steps/booking_meta.html3
-rw-r--r--dashboard/src/templates/dashboard/multiple_select_filter_widget.html1
-rw-r--r--dashboard/src/workflow/forms.py4
8 files changed, 270 insertions, 259 deletions
diff --git a/dashboard/src/api/models.py b/dashboard/src/api/models.py
index 7448ac4..9afc89a 100644
--- a/dashboard/src/api/models.py
+++ b/dashboard/src/api/models.py
@@ -321,10 +321,10 @@ class AccessConfig(TaskConfig):
def to_dict(self):
d = {}
- d['access_type'] = self.access_type
+ d['access_type'] = self.access_type
d['user'] = self.user.id
d['revoke'] = self.revoke
- d['context'] = self.context
+ d['context'] = json.loads(self.context)
return d
def get_delta(self):
@@ -363,7 +363,7 @@ class AccessConfig(TaskConfig):
self.delta = json.dumps(d)
def set_context(self, context):
- self.context = context
+ self.context = json.dumps(context)
d = json.loads(self.delta)
d['context'] = context
self.delta = json.dumps(d)
@@ -608,18 +608,28 @@ class JobFactory(object):
hosts=hosts,
job=job
)
+ all_users = list(booking.collaborators.all())
+ all_users.append(booking.owner)
cls.makeAccessConfig(
- users=booking.collaborators.all(),
- access_type="vpn",
- revoke=False,
- job=job
- )
- cls.makeAccessConfig(
- users=[booking.owner],
+ 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]
+ }
+ )
+ except Exception:
+ continue
@classmethod
def makeHardwareConfigs(cls, hosts=[], job=Job()):
@@ -646,13 +656,15 @@ class JobFactory(object):
hardware_config.save()
@classmethod
- def makeAccessConfig(cls, users, access_type, revoke=False, job=Job()):
+ def makeAccessConfig(cls, users, access_type, revoke=False, job=Job(), context=False):
for user in users:
relation = AccessRelation()
relation.job = job
config = AccessConfig()
config.access_type = access_type
config.user = user
+ if context:
+ config.set_context(context)
config.save()
relation.config = config
relation.save()
@@ -709,6 +721,3 @@ class JobFactory(object):
return software_relation
except:
return None
-
- def makeAccess(cls, user, access_type, revoke):
- pass
diff --git a/dashboard/src/booking/views.py b/dashboard/src/booking/views.py
index 9b9860f..a0ea31d 100644
--- a/dashboard/src/booking/views.py
+++ b/dashboard/src/booking/views.py
@@ -103,6 +103,10 @@ def booking_detail_view(request, booking_id):
return render(request, "dashboard/login.html", {'title': 'Authentication Required'})
booking = get_object_or_404(Booking, id=booking_id)
+ allowed_users = set(list(booking.collaborators.all()))
+ 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,
diff --git a/dashboard/src/dashboard/tasks.py b/dashboard/src/dashboard/tasks.py
index 48008b6..0f7af1c 100644
--- a/dashboard/src/dashboard/tasks.py
+++ b/dashboard/src/dashboard/tasks.py
@@ -73,7 +73,11 @@ def booking_poll():
def cleanup_access(qs):
for relation in qs:
- pass # TODO
+ if "vpn" in relation.config.access_type.lower():
+ relation.config.set_revoke(True)
+ relation.config.save()
+ relation.status = JobStatus.NEW
+ relation.save()
cleanup_set = Booking.objects.filter(end__lte=timezone.now()).filter(job__complete=False)
diff --git a/dashboard/src/templates/booking/booking_detail.html b/dashboard/src/templates/booking/booking_detail.html
index 126aaab..cae0e25 100644
--- a/dashboard/src/templates/booking/booking_detail.html
+++ b/dashboard/src/templates/booking/booking_detail.html
@@ -3,289 +3,281 @@
{% block extrahead %}
{{block.super}}
- <script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js?lang=yaml"></script>
+<script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js?lang=yaml"></script>
<script src="https://unpkg.com/masonry-layout@4/dist/masonry.pkgd.min.js"></script>
{% endblock %}
{% block content %}
<div class="container-fluid">
<div class="row">
- <div class="col-lg-6">
- <div class="panel panel-default">
- <div class="panel-heading clearfix">
- <h4 style="display: inline;">Overview</h4>
- <a data-toggle="collapse" data-target="#panel_overview" class="btn pull-right" style="line-height: 1;" >Expand</a>
- </div>
- <div class="panel-body" id="panel_overview">
- <table class="table">
- <tr>
- <td>Purpose</td>
- <td>{{ booking.purpose }}</td>
- </tr>
- <tr>
- <td>Project</td>
- <td>{{ booking.project }}</td>
- </tr>
- <tr>
- <td>Start Time</td>
- <td>{{ booking.start }}</td>
- </tr>
- <tr>
- <td>End Time</td>
- <td>{{ booking.end }}</td>
- </tr>
- <tr>
- <td>Pod Definition</td>
- <td>{{ booking.resource.template }}</td>
- </tr>
- <tr>
- <td>Pod Configuration</td>
- <td>{{ booking.config_bundle }}</td>
- </tr>
- <tr>
- <td>Lab Deployed At</td>
- <td>{{ booking.lab }}</td>
- </tr>
- </table>
- </div>
- </div>
- <div class="row">
-
<div class="col-lg-6">
-
<div class="panel panel-default">
- <div class="panel-heading clearfix">
- <h4 style="display: inline;">Pod</h4>
-
- <a data-toggle="collapse" data-target="#pod_panel" class="btn pull-right" style="line-height: 1;" >Expand</a>
+ <div class="panel-heading clearfix">
+ <h4 style="display: inline;">Overview</h4>
+ <a data-toggle="collapse" data-target="#panel_overview" class="btn pull-right" style="line-height: 1;" >Expand</a>
+ </div>
+ <div class="panel-body" id="panel_overview">
+ <table class="table">
+ <tr>
+ <td>Purpose</td>
+ <td>{{ booking.purpose }}</td>
+ </tr>
+ <tr>
+ <td>Project</td>
+ <td>{{ booking.project }}</td>
+ </tr>
+ <tr>
+ <td>Start Time</td>
+ <td>{{ booking.start }}</td>
+ </tr>
+ <tr>
+ <td>End Time</td>
+ <td>{{ booking.end }}</td>
+ </tr>
+ <tr>
+ <td>Pod Definition</td>
+ <td>{{ booking.resource.template }}</td>
+ </tr>
+ <tr>
+ <td>Pod Configuration</td>
+ <td>{{ booking.config_bundle }}</td>
+ </tr>
+ <tr>
+ <td>Lab Deployed At</td>
+ <td>{{ booking.lab }}</td>
+ </tr>
+ </table>
+ </div>
</div>
- <div class="panel-body pod_panel" id="pod_panel">
- <table class="table">
- {% for host in booking.resource.hosts.all %}
- <tr>
- <td><h4>{{host.template.resource.name}}</h4></td>
- <td>
- <table class="table">
- <tr>
- <td>Hostname:</td>
- <td>{{host.template.resource.name}}</td>
- </tr>
- <tr>
- <td>Profile:</td>
- <td>{{host.name}}</td>
- </tr>
- <tr>
- <td>Role:</td>
- <td>{{host.config.opnfvRole}}</td>
- </tr>
- <tr>
- <td>Image:</td>
- <td>{{host.config.image}}</td>
- </tr>
- <tr>
- <td>RAM:</td>
- <td>{{host.profile.ramprofile.first.amount}}G,
- {{host.profile.ramprofile.first.channels}} channels</td>
- </tr>
+ <div class="row">
+
+ <div class="col-lg-6">
+
+ <div class="panel panel-default">
+ <div class="panel-heading clearfix">
+ <h4 style="display: inline;">Pod</h4>
+ <a data-toggle="collapse" data-target="#pod_panel" class="btn pull-right" style="line-height: 1;" >Expand</a>
+ </div>
+ <div class="panel-body pod_panel" id="pod_panel">
+ <table class="table">
+ {% for host in booking.resource.hosts.all %}
<tr>
- <td>CPU:</td>
+ <td><h4>{{host.template.resource.name}}</h4></td>
<td>
<table class="table">
<tr>
- <td>Arch:</td>
- <td>{{host.profile.cpuprofile.first.architecture}}</td>
+ <td>Hostname:</td>
+ <td>{{host.template.resource.name}}</td>
</tr>
<tr>
- <td>Cores:</td>
- <td>{{host.profile.cpuprofile.first.cores}}</td>
+ <td>Profile:</td>
+ <td>{{host.name}}</td>
</tr>
<tr>
- <td>Sockets:</td>
- <td>{{host.profile.cpuprofile.first.cpus}}</td>
+ <td>Role:</td>
+ <td>{{host.config.opnfvRole}}</td>
</tr>
- </table>
- </td>
- </tr>
- <tr>
- <td>DISK:</td>
- <td>
- <table class="table">
<tr>
- <td>Size:</td>
- <td>{{host.profile.diskprofile.first.size}}GiB</td>
+ <td>Image:</td>
+ <td>{{host.config.image}}</td>
</tr>
<tr>
- <td>Type:</td>
- <td>{{host.profile.diskprofile.first.media_type}}</td>
+ <td>RAM:</td>
+ <td>{{host.profile.ramprofile.first.amount}}G,
+ {{host.profile.ramprofile.first.channels}} channels</td>
</tr>
<tr>
- <td>Mount Point:</td>
- <td>{{host.profile.diskprofile.first.name}}</td>
+ <td>CPU:</td>
+ <td>
+ <table class="table">
+ <tr>
+ <td>Arch:</td>
+ <td>{{host.profile.cpuprofile.first.architecture}}</td>
+ </tr>
+ <tr>
+ <td>Cores:</td>
+ <td>{{host.profile.cpuprofile.first.cores}}</td>
+ </tr>
+ <tr>
+ <td>Sockets:</td>
+ <td>{{host.profile.cpuprofile.first.cpus}}</td>
+ </tr>
+ </table>
+ </td>
</tr>
+ <tr>
+ <td>DISK:</td>
+ <td>
+ <table class="table">
+ <tr>
+ <td>Size:</td>
+ <td>{{host.profile.diskprofile.first.size}}GiB</td>
+ </tr>
+ <tr>
+ <td>Type:</td>
+ <td>{{host.profile.diskprofile.first.media_type}}</td>
+ </tr>
+ <tr>
+ <td>Mount Point:</td>
+ <td>{{host.profile.diskprofile.first.name}}</td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td>Interfaces:</td>
+ <td>
+ <style>
+ .borderless td {
+ border: none !important;
+ }
+ </style>
+ <table class="table">
+ {% for intprof in host.profile.interfaceprofile.all %}
+ <tr>
+ <td>
+ <table class="table borderless">
+ <tr>
+ <td>Name:</td>
+ <td>{{intprof.name}}</td>
+ </tr>
+ <tr>
+ <td>Speed:</td>
+ <td>{{intprof.speed}}</td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ {% endfor %}
+ </table>
+ </td>
+ </tr>
+
+
</table>
+
</td>
+ {% endfor %}
</tr>
- <tr>
- <td>Interfaces:</td>
- <td>
- <style>
- .borderless td {
- border: none !important;
- }
- </style>
- <table class="table">
- {% for intprof in host.profile.interfaceprofile.all %}
- <tr>
- <td>
- <table class="table borderless">
- <tr>
- <td>Name:</td>
- <td>{{intprof.name}}</td>
- </tr>
- <tr>
- <td>Speed:</td>
- <td>{{intprof.speed}}</td>
- </tr>
- </table>
- </td>
- </tr>
- {% endfor %}
- </table>
- </td>
- </tr>
+ </table>
+ </div>
+ </div>
+ </div>
+ <div class="col-lg-6">
+ <div class="panel panel-default">
+ <div class="panel-heading clearfix">
+ <h4 style="display: inline;">PDF</h4>
+ <a data-toggle="collapse" data-target="#pdf_panel" class="btn pull-right" style="line-height: 1;" >Expand</a>
+ </div>
- </table>
-
- </td>
- {% endfor %}
- </tr>
- </table>
+ <div class="panel-body" id="pdf_panel" style="padding: 0px;">
+ <pre class="prettyprint lang-yaml" style="margin: 0px; padding: 0px; border: none;">
+{{pdf}}
+ </pre>
+ </div>
+ </div>
+ </div>
</div>
</div>
- </div>
<div class="col-lg-6">
+ <div class="panel panel-default">
+ <div class="panel-heading clearfix">
+ <h4 style="display: inline;">Deployment Progress</h4>
+ <p style="display: inline; margin-left: 10px;"> These are the different tasks that have to be completed before your deployment is ready</p>
+ <a data-toggle="collapse" data-target="#panel_tasks" class="btn pull-right" style="line-height: 1;" >Expand</a>
+ </div>
- <div class="panel panel-default">
- <div class="panel-heading clearfix">
- <h4 style="display: inline;">PDF</h4>
- <a data-toggle="collapse" data-target="#pdf_panel" class="btn pull-right" style="line-height: 1;" >Expand</a>
- </div>
-
- <div class="panel-body" id="pdf_panel" style="padding: 0px;">
- <pre class="prettyprint lang-yaml" style="margin: 0px; padding: 0px; border: none;">
-
- {{pdf}}
-
-
- </pre>
- </div>
- </div>
- </div>
- </div>
- </div>
-
-
+ <div class="panel-body" id="panel_tasks">
+ <table class="table">
+ <style>
+ .progress {
+ display: inline-block;
+ border: 3px solid #f3f3f3;
+ border-radius: 50%;
+ border-top: 3px solid #12aebb;
+ width: 20px;
+ height: 20px;
+ -webkit-animation: spin 2s linear infinite; /* Safari */
+ animation: spin 2s linear infinite;
+ }
- <div class="col-lg-6">
- <div class="panel panel-default">
- <div class="panel-heading clearfix">
- <h4 style="display: inline;">Deployment Progress</h4>
- <p style="display: inline; margin-left: 10px;"> These are the different tasks that have to be completed before your deployment is ready</p>
- <a data-toggle="collapse" data-target="#panel_tasks" class="btn pull-right" style="line-height: 1;" >Expand</a>
- </div>
+ @keyframes spin {
+ 0% {transform: rotate(0deg);}
+ 100% {transform: rotate(360deg);}
+ }
- <div class="panel-body" id="panel_tasks">
- <table class="table">
- <style>
- .progress {
- display: inline-block;
- border: 3px solid #f3f3f3;
- border-radius: 50%;
- border-top: 3px solid #12aebb;
- width: 20px;
- height: 20px;
- -webkit-animation: spin 2s linear infinite; /* Safari */
- animation: spin 2s linear infinite;
- }
+ .new {
+ display: inline-block;
+ width: 20px;
+ height: 20px;
+ background: #f3f3f3;
+ border-radius: 50%;
+ animation: fadeInOut 1s infinite alternate;
- @keyframes spin {
- 0% {transform: rotate(0deg);}
- 100% {transform: rotate(360deg);}
- }
- .new {
- display: inline-block;
- width: 20px;
- height: 20px;
- background: #f3f3f3;
- border-radius: 50%;
- animation: fadeInOut 1s infinite alternate;
+ }
+ @keyframes fadeInOut {
+ from { opacity: 0;}
+ }
+ .done {
+ display: inline-block;
+ width: 20px;
+ height: 20px;
+ background: #40B976;
+ border-radius: 50%;
+ }
+ </style>
+ <tr>
+ <th></th>
+ <th>Status</th>
+ <th>Lab Response</th>
+ <th>Type</th>
+ </tr>
+ {% for task in booking.job.get_tasklist %}
+ <tr>
+ <td>
+ {% if task.status < 100 %}
+ <div class="new"></div>
+ {% elif task.status < 200 %}
+ <div class="progress"></div>
+ {% else %}
+ <div class="done"></div>
+ {% endif %}
+ </td>
- }
- @keyframes fadeInOut {
- from { opacity: 0;}
- }
- .done {
- display: inline-block;
- width: 20px;
- height: 20px;
- background: #40B976;
- border-radius: 50%;
- }
- </style>
- <tr>
- <th></th>
- <th>Status</th>
- <th>Lab Response</th>
- <th>Type</th>
- </tr>
- {% for task in booking.job.get_tasklist %}
- <tr>
- <td>
- {% if task.status < 100 %}
- <div class="new"></div>
- {% elif task.status < 200 %}
- <div class="progress"></div>
- {% else %}
- <div class="done"></div>
- {% endif %}
+ <td>
+ {% if task.status < 100 %}
+ PENDING
+ {% elif task.status < 200 %}
+ IN PROGRESS
+ {% else %}
+ DONE
+ {% endif %}
</td>
+ <td>
+ {% if task.message %}
+ {% if task.type_str == "Access Task" and user_id != task.config.user.id %}
+ Message from Lab: <pre>--secret--</pre>
+ {% else %}
+ Message from Lab: <pre>{{ task.message }}</pre>
+ {% endif %}
+ {% else %}
+ No response provided (yet)
+ {% endif %}
+ </td>
+ <td>
+ {{ task.type_str }}
- <td>
- {% if task.status < 100 %}
- PENDING
- {% elif task.status < 200 %}
- IN PROGRESS
- {% else %}
- DONE
- {% endif %}
- </td>
- <td>
-
- {% if task.message %}
- {% if task.type_str == "Access Task" and user_id != task.config.user.id %}
- Message from Lab: <pre>--secret--</pre>
- {% else %}
- Message from Lab: <pre>{{ task.message }}</pre>
- {% endif %}
- {% else %}
- No response provided (yet)
- {% endif %}
- </td>
- <td>
- {{ task.type_str }}
-
- </td>
- </tr>
- {% endfor %}
- </table>
+ </td>
+ </tr>
+ {% endfor %}
+ </table>
+ </div>
</div>
</div>
-
- </div>
</div>
</div>
diff --git a/dashboard/src/templates/booking/booking_table.html b/dashboard/src/templates/booking/booking_table.html
index af2248c..5e82645 100644
--- a/dashboard/src/templates/booking/booking_table.html
+++ b/dashboard/src/templates/booking/booking_table.html
@@ -3,7 +3,7 @@
<thead>
<tr>
- <th>User</th>
+ <th>Owner</th>
<th>Purpose</th>
<th>Start</th>
<th>End</th>
@@ -16,7 +16,7 @@
{% for booking in bookings %}
<tr>
<td>
- {{ booking.user.username }}
+ {{ booking.owner.username }}
</td>
<td>
{{ booking.purpose }}
diff --git a/dashboard/src/templates/booking/steps/booking_meta.html b/dashboard/src/templates/booking/steps/booking_meta.html
index fa8f7a9..a42e158 100644
--- a/dashboard/src/templates/booking/steps/booking_meta.html
+++ b/dashboard/src/templates/booking/steps/booking_meta.html
@@ -43,7 +43,8 @@
<div class="panel panel_center">
</div>
<div class="panel">
- {% bootstrap_field form.users %}
+ <p>You may add collaborators on your booking to share resources with coworkers.</p>
+ {% bootstrap_field form.users label="Collaborators" %}
</div>
{% buttons %}
diff --git a/dashboard/src/templates/dashboard/multiple_select_filter_widget.html b/dashboard/src/templates/dashboard/multiple_select_filter_widget.html
index ed29ed6..31b8f33 100644
--- a/dashboard/src/templates/dashboard/multiple_select_filter_widget.html
+++ b/dashboard/src/templates/dashboard/multiple_select_filter_widget.html
@@ -337,6 +337,7 @@ function add_item_prepopulate(node, prepopulate){
button.appendChild(document.createTextNode("Remove"));
div.appendChild(button);
document.getElementById("dropdown_wrapper").appendChild(div);
+ updateObjectResult(div);
return div;
}
diff --git a/dashboard/src/workflow/forms.py b/dashboard/src/workflow/forms.py
index c770e38..d4abbc3 100644
--- a/dashboard/src/workflow/forms.py
+++ b/dashboard/src/workflow/forms.py
@@ -189,6 +189,7 @@ class BookingMetaForm(forms.Form):
default_user = kwargs.pop("default_user")
else:
default_user = "you"
+ self.default_user = default_user
if "chosen_users" in kwargs:
chosen_users = kwargs.pop("chosen_users")
elif data and "users" in data:
@@ -212,7 +213,7 @@ class BookingMetaForm(forms.Form):
"""
try:
users = {}
- d_qset = UserProfile.objects.select_related('user').all();
+ d_qset = UserProfile.objects.select_related('user').all().exclude(user__username=self.default_user);
for userprofile in d_qset:
user = {
'id':userprofile.user.id,
@@ -237,7 +238,6 @@ class BookingMetaForm(forms.Form):
'selectable_limit': -1,
'name': "users",
'placeholder': "username",
- 'default_entry': default_user,
'initial': chosen_users,
'edit': False
}