summaryrefslogtreecommitdiffstats
path: root/dashboard
diff options
context:
space:
mode:
Diffstat (limited to 'dashboard')
-rw-r--r--dashboard/src/api/views.py2
-rw-r--r--dashboard/src/booking/forms.py14
-rw-r--r--dashboard/src/booking/quick_deployer.py2
-rw-r--r--dashboard/src/booking/views.py3
-rw-r--r--dashboard/src/dashboard/actions.py47
-rw-r--r--dashboard/src/dashboard/views.py2
-rw-r--r--dashboard/src/resource_inventory/models.py3
-rw-r--r--dashboard/src/resource_inventory/urls.py5
-rw-r--r--dashboard/src/resource_inventory/views.py17
-rw-r--r--dashboard/src/templates/booking/booking_table.html14
-rw-r--r--dashboard/src/templates/booking/quick_deploy.html41
-rw-r--r--dashboard/src/templates/booking/steps/booking_meta.html9
-rw-r--r--dashboard/src/templates/config_bundle/steps/config_software.html36
-rw-r--r--dashboard/src/templates/dashboard/lab_detail.html2
-rw-r--r--dashboard/src/templates/dashboard/lab_list.html103
-rw-r--r--dashboard/src/templates/dashboard/multiple_select_filter_widget.html60
-rw-r--r--dashboard/src/templates/resource/hostprofile_detail.html116
-rw-r--r--dashboard/src/templates/resource/hosts.html2
-rw-r--r--dashboard/src/templates/resource/steps/meta_info.html22
-rw-r--r--dashboard/src/templates/workflow/viewport-base.html29
20 files changed, 376 insertions, 153 deletions
diff --git a/dashboard/src/api/views.py b/dashboard/src/api/views.py
index a56dcfe..2ae1ac5 100644
--- a/dashboard/src/api/views.py
+++ b/dashboard/src/api/views.py
@@ -101,6 +101,8 @@ def specific_task(request, lab_name="", job_id="", task_id=""):
task.status = request.POST.get('status')
if 'message' in request.POST:
task.message = request.POST.get('message')
+ if 'lab_token' in request.POST:
+ task.lab_token = request.POST.get('lab_token')
task.save()
NotificationHandler.task_updated(task)
d = {}
diff --git a/dashboard/src/booking/forms.py b/dashboard/src/booking/forms.py
index 7ba5af0..9349ac1 100644
--- a/dashboard/src/booking/forms.py
+++ b/dashboard/src/booking/forms.py
@@ -8,7 +8,6 @@
##############################################################################
import django.forms as forms
from django.forms.widgets import NumberInput
-from django.db.models import Q
from workflow.forms import (
SearchableSelectMultipleWidget,
@@ -22,7 +21,6 @@ from resource_inventory.models import Image, Installer, Scenario
class QuickBookingForm(forms.Form):
purpose = forms.CharField(max_length=1000)
project = forms.CharField(max_length=400)
- image = forms.ModelChoiceField(queryset=Image.objects.all())
hostname = forms.CharField(max_length=400)
installer = forms.ModelChoiceField(queryset=Installer.objects.all(), required=False)
@@ -40,14 +38,14 @@ class QuickBookingForm(forms.Form):
elif data and "users" in data:
chosen_users = data.getlist("users")
- if user:
- self.image = forms.ModelChoiceField(queryset=Image.objects.filter(
- Q(public=True) | Q(owner=user)), required=False)
- else:
- self.image = forms.ModelChoiceField(queryset=Image.objects.all(), required=False)
-
super(QuickBookingForm, self).__init__(data=data, **kwargs)
+ self.fields["image"] = forms.ModelChoiceField(
+ queryset=Image.objects.difference(
+ Image.objects.filter(public=False).difference(Image.objects.filter(owner=user))
+ )
+ )
+
self.fields['users'] = forms.CharField(
widget=SearchableSelectMultipleWidget(
attrs=self.build_search_widget_attrs(chosen_users, default_user=default_user)
diff --git a/dashboard/src/booking/quick_deployer.py b/dashboard/src/booking/quick_deployer.py
index f8dc9ff..cc593fa 100644
--- a/dashboard/src/booking/quick_deployer.py
+++ b/dashboard/src/booking/quick_deployer.py
@@ -119,7 +119,7 @@ def check_available_matching_host(lab, hostprofile):
available_host_types = ResourceManager.getInstance().getAvailableHostTypes(lab)
if hostprofile not in available_host_types:
# TODO: handle deleting generic resource in this instance along with grb
- raise HostNotAvailable("Could not book selected host due to changed availability. Try again later")
+ raise HostNotAvailable('Requested host type is not available. Please try again later. Host availability can be viewed in the "Hosts" tab to the left.')
hostset = Host.objects.filter(lab=lab, profile=hostprofile).filter(booked=False).filter(working=True)
if not hostset.exists():
diff --git a/dashboard/src/booking/views.py b/dashboard/src/booking/views.py
index 1e14b8e..8211a0c 100644
--- a/dashboard/src/booking/views.py
+++ b/dashboard/src/booking/views.py
@@ -62,8 +62,7 @@ def quick_create(request):
try:
create_from_form(form, request)
except Exception as e:
- messages.error(request, "Whoops, looks like an error occurred. "
- "Let the admins know that you got the following message: " + str(e))
+ messages.error(request, "Whoops, an error occurred: " + str(e))
return render(request, 'workflow/exit_redirect.html', context)
messages.success(request, "We've processed your request. "
diff --git a/dashboard/src/dashboard/actions.py b/dashboard/src/dashboard/actions.py
new file mode 100644
index 0000000..44b1fdd
--- /dev/null
+++ b/dashboard/src/dashboard/actions.py
@@ -0,0 +1,47 @@
+##############################################################################
+# Copyright (c) 2019 Parker Berberian, Sawyer Bergeron, and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+from resource_inventory.models import Host, Vlan
+from account.models import Lab
+from booking.models import Booking
+from datetime import timedelta
+from django.utils import timezone
+
+
+def free_leaked_hosts(free_old_bookings=False, old_booking_age=timedelta(days=1)):
+ bundles = [booking.resource for booking in Booking.objects.filter(end__gt=timezone.now())]
+ active_hosts = set()
+ for bundle in bundles:
+ active_hosts.update([host for host in bundle.hosts.all()])
+
+ marked_hosts = set(Host.objects.filter(booked=True))
+
+ for host in (marked_hosts - active_hosts):
+ host.booked = False
+ host.save()
+
+
+def free_leaked_public_vlans():
+ booked_host_interfaces = []
+
+ for lab in Lab.objects.all():
+
+ for host in Host.objects.filter(booked=True).filter(lab=lab):
+ for interface in host.interfaces.all():
+ booked_host_interfaces.append(interface)
+
+ in_use_vlans = Vlan.objects.filter(public=True).distinct('vlan_id').filter(interface__in=booked_host_interfaces)
+
+ manager = lab.vlan_manager
+
+ for vlan in Vlan.objects.all():
+ if vlan not in in_use_vlans:
+ if vlan.public:
+ manager.release_public_vlan(vlan.vlan_id)
+ manager.release_vlans(vlan)
diff --git a/dashboard/src/dashboard/views.py b/dashboard/src/dashboard/views.py
index c4a6685..aaad7ab 100644
--- a/dashboard/src/dashboard/views.py
+++ b/dashboard/src/dashboard/views.py
@@ -46,7 +46,7 @@ def lab_detail_view(request, lab_name):
'title': "Lab Overview",
'lab': lab,
'hostprofiles': lab.hostprofiles.all(),
- 'images': images
+ 'images': images,
}
)
diff --git a/dashboard/src/resource_inventory/models.py b/dashboard/src/resource_inventory/models.py
index 0b7b24c..d3f47d4 100644
--- a/dashboard/src/resource_inventory/models.py
+++ b/dashboard/src/resource_inventory/models.py
@@ -190,6 +190,9 @@ class ResourceBundle(models.Model):
return "Resource bundle " + str(self.id) + " with no template"
return "instance of " + str(self.template)
+ def get_host(self, role="Jumphost"):
+ return Host.objects.filter(bundle=self, config__opnfvRole__name=role).first()
+
class GenericInterface(models.Model):
id = models.AutoField(primary_key=True)
diff --git a/dashboard/src/resource_inventory/urls.py b/dashboard/src/resource_inventory/urls.py
index 4e159ba..a72871b 100644
--- a/dashboard/src/resource_inventory/urls.py
+++ b/dashboard/src/resource_inventory/urls.py
@@ -25,10 +25,11 @@ Including another URLconf
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
-from resource_inventory.views import HostView
+from resource_inventory.views import HostView, hostprofile_detail_view
app_name = "resource"
urlpatterns = [
- url(r'^hosts$', HostView.as_view(), name='hosts')
+ url(r'^hosts$', HostView.as_view(), name='hosts'),
+ url(r'^profiles/(?P<hostprofile_id>.+)/$', hostprofile_detail_view, name='host_detail'),
]
diff --git a/dashboard/src/resource_inventory/views.py b/dashboard/src/resource_inventory/views.py
index 2937bd7..8c3d899 100644
--- a/dashboard/src/resource_inventory/views.py
+++ b/dashboard/src/resource_inventory/views.py
@@ -9,8 +9,10 @@
from django.views.generic import TemplateView
+from django.shortcuts import get_object_or_404
+from django.shortcuts import render
-from resource_inventory.models import Host
+from resource_inventory.models import HostProfile, Host
class HostView(TemplateView):
@@ -21,3 +23,16 @@ class HostView(TemplateView):
hosts = Host.objects.filter(working=True)
context.update({'hosts': hosts, 'title': "Hardware Resources"})
return context
+
+
+def hostprofile_detail_view(request, hostprofile_id):
+ hostprofile = get_object_or_404(HostProfile, id=hostprofile_id)
+
+ return render(
+ request,
+ "resource/hostprofile_detail.html",
+ {
+ 'title': "Host Type: " + str(hostprofile.name),
+ 'hostprofile': hostprofile
+ }
+ )
diff --git a/dashboard/src/templates/booking/booking_table.html b/dashboard/src/templates/booking/booking_table.html
index 5e82645..e0c5f49 100644
--- a/dashboard/src/templates/booking/booking_table.html
+++ b/dashboard/src/templates/booking/booking_table.html
@@ -5,11 +5,10 @@
<tr>
<th>Owner</th>
<th>Purpose</th>
+ <th>Project</th>
<th>Start</th>
<th>End</th>
<th>Operating System</th>
- <th>Installer</th>
- <th>Scenario</th>
</tr>
</thead>
<tbody>
@@ -22,19 +21,16 @@
{{ booking.purpose }}
</td>
<td>
- {{ booking.start }}
- </td>
- <td>
- {{ booking.end }}
+ {{ booking.project }}
</td>
<td>
- {{ booking.opsys }}
+ {{ booking.start }}
</td>
<td>
- {{ booking.installer }}
+ {{ booking.end }}
</td>
<td>
- {{ booking.scenario }}
+ {{ booking.resource.get_host.config.image.os.name }}
</td>
</tr>
{% endfor %}
diff --git a/dashboard/src/templates/booking/quick_deploy.html b/dashboard/src/templates/booking/quick_deploy.html
index 3837315..38294b2 100644
--- a/dashboard/src/templates/booking/quick_deploy.html
+++ b/dashboard/src/templates/booking/quick_deploy.html
@@ -26,6 +26,14 @@
.grid_element_2third {
grid-column-start: span 8;
}
+ #id_length {
+ -moz-appearance: none;
+ border: none;
+ box-shadow: none;
+ }
+ input[type=range]::-moz-range-track {
+ background: #cccccc;
+ }
</style>
{% bootstrap_form_errors form type='non_fields' %}
<form id="quick_booking_form" action="/booking/quick/" method="POST" class="form">
@@ -33,7 +41,7 @@
<div class="grid_container">
<div class="grid_element host_select_pane grid_element_wide">
<p>Please select a host type you wish to book. Only available types are shown.</p>
-{% bootstrap_field form.filter_field %}
+{% bootstrap_field form.filter_field show_label=False %}
</div>
<div class="grid_element booking_info_pane grid_element_1third">
{% bootstrap_field form.purpose %}
@@ -49,11 +57,16 @@
<label>Collaborators</label>
{{ form.users }}
</div>
-<div class="grid_element configuration_pane grid_element_1third">
- {% bootstrap_field form.hostname %}
- {% bootstrap_field form.image %}
- {% bootstrap_field form.installer %}
- {% bootstrap_field form.scenario %}
+<div class="grid_element_1third">
+ <div class="configuration_pane grid_element">
+ {% bootstrap_field form.hostname %}
+ {% bootstrap_field form.image %}
+ </div>
+ <div class="configuration_pane grid_element">
+ <strong>OPNFV: (Optional)</strong>
+ {% bootstrap_field form.installer %}
+ {% bootstrap_field form.scenario %}
+ </div>
</div>
</div>
<script type="text/javascript">
@@ -103,6 +116,12 @@
$('#id_image').children().hide();
+ for( var i = 0; i < drop.childNodes.length; i++ )
+ {
+ drop.childNodes[i].disabled = true; // closest we can get on safari to hiding it outright
+ }
+
+
var empty_map = {}
for ( var i=0; i < drop.childNodes.length; i++ )
@@ -125,12 +144,13 @@
if( image_object.host_profile == host_pk && image_object.lab == lab_pk )
{
drop.childNodes[i].style.display = "inherit";
+ drop.childNodes[i].disabled = false;
}
}
}
}
- $('#id_image').children().hide();
+ imageHider();
$('#id_installer').children().hide();
$('#id_scenario').children().hide();
@@ -160,7 +180,13 @@
}
targ_id = "#" + target;
+
$(targ_id).children().hide();
+
+ for (var i = 0; i < document.getElementById(target).childNodes.length; i++)
+ {
+ document.getElementById(target).childNodes[i].disabled = true;
+ }
var drop = document.getElementById(master);
var opts = target_filter[drop.options[drop.selectedIndex].value];
if (!opts) {
@@ -177,6 +203,7 @@
for (var i = 0; i < document.getElementById(target).childNodes.length; i++) {
if (document.getElementById(target).childNodes[i].value in opts && !(document.getElementById(target).childNodes[i].value in emptyMap) ) {
document.getElementById(target).childNodes[i].style.display = "inherit";
+ document.getElementById(target).childNodes[i].disabled = false;
}
}
}
diff --git a/dashboard/src/templates/booking/steps/booking_meta.html b/dashboard/src/templates/booking/steps/booking_meta.html
index e4881ae..fe43f53 100644
--- a/dashboard/src/templates/booking/steps/booking_meta.html
+++ b/dashboard/src/templates/booking/steps/booking_meta.html
@@ -21,6 +21,15 @@
grid-template-columns: 45% 10% 45%;
border: none;
}
+
+ #id_length {
+ -moz-appearance: none;
+ border: none;
+ box-shadow: none;
+ }
+ input[type=range]::-moz-range-track {
+ background: #cccccc;
+ }
</style>
{% bootstrap_form_errors form type='non_fields' %}
diff --git a/dashboard/src/templates/config_bundle/steps/config_software.html b/dashboard/src/templates/config_bundle/steps/config_software.html
index ca15c77..e1f9541 100644
--- a/dashboard/src/templates/config_bundle/steps/config_software.html
+++ b/dashboard/src/templates/config_bundle/steps/config_software.html
@@ -12,23 +12,25 @@
<p>And a description:</p>
{{ form.description }}
- <p>Install OPNFV?</p>
- {{ form.opnfv }}
- <p>Choose your:</p>
- <table>
- <thead>
- <tr>
- <th>Installer</th>
- <th>Scenario</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td>{{form.installer}}</td>
- <td>{{form.scenario}}</td>
- </tr>
- </tbody>
- </table>
+ <div id="hidden" style="display:none;">
+ <p>Install OPNFV?</p>
+ {{ form.opnfv }}
+ <p>Choose your:</p>
+ <table>
+ <thead>
+ <tr>
+ <th>Installer</th>
+ <th>Scenario</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>{{form.installer}}</td>
+ <td>{{form.scenario}}</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
</form>
diff --git a/dashboard/src/templates/dashboard/lab_detail.html b/dashboard/src/templates/dashboard/lab_detail.html
index 4c06245..7938e86 100644
--- a/dashboard/src/templates/dashboard/lab_detail.html
+++ b/dashboard/src/templates/dashboard/lab_detail.html
@@ -62,7 +62,7 @@
<tr>
<td>{{profile.name}}</td>
<td>{{profile.description}}</td>
- <td>{{profile.labs}}</td>
+ <td><a href="/resource/profiles/{{ profile.id }}" class="btn btn-primary">Profile</a></td>
</tr>
{% endfor %}
</table>
diff --git a/dashboard/src/templates/dashboard/lab_list.html b/dashboard/src/templates/dashboard/lab_list.html
index a86f7f4..c459dd9 100644
--- a/dashboard/src/templates/dashboard/lab_list.html
+++ b/dashboard/src/templates/dashboard/lab_list.html
@@ -1,87 +1,26 @@
{% extends "base.html" %}
-{% load staticfiles %}
-
-{% block extrahead %}
- {{block.super}}
- <script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js?lang=yaml"></script>
-{% endblock %}
-
{% block content %}
- <style>
- .grid-item-container {
- padding: 10px;
- }
-
- .grid-item {
- cursor: pointer;
- border:2px;
- border-style:none;
- border-color:black;
- border-radius: 5px;
- padding: 7px;
- color: inherit;
-
- box-shadow: 0px 0px 7px 0px rgba(0,0,0,0.75);
- transition-property: box-shadow, background-color;
- transition-duration: .2s;
- }
-
- .grid-item-text
- {
- color: inherit;
- text-decoration: none;
- }
- .grid-item-text:hover
- {
- color: #121212;
- text-decoration: none;
- }
-
- .grid-item:hover {
- box-shadow: 0px 0px 14px 0px rgba(0,0,0,0.75);
- transition-property: box-shadow;
- transition-duration: .2s;
-
- }
-
- .selected_node {
- box-shadow: 0px 0px 14px 0px rgba(0,0,0,0.75);
- background-color: #CCECD7;
- transition-property: background-color;
- transition-duration: .2s;
- }
-
- .disabled_node {
- cursor: not-allowed;
- background-color: #EFEFEF;
- box-shadow: 0px 0px 1px 0px rgba(0,0,0,0.75);
- transition-property: box-shadow;
- transition-duration: .2s;
- }
-
- .disabled_node:hover {
- box-shadow: 0px 0px 1px 0px rgba(0,0,0,0.75);
- }
-
- </style>
- <div class="container-fluid">
- <div class="row">
-
- <div class="listgrid">
- {% for lab in labs %}
- <div class="grid-item-container col-lg-2 col-mid-4 col-sm-6">
-
- <a href="{{ lab.name }}" class="grid-item-text">
-
- <div class="grid-item">
- <h4 class="grid-item-header">{{ lab.name }}</h4>
- <p class="grid-item-description">{{ lab.description }}</p>
+ <h2>Labs</h2>
+ <div class="card_container">
+ {% for lab in labs %}
+ <div class="detail_card">
+ <div>
+ <h3>{{lab.name}}</h3>
+ <ul class="list-group">
+ <li class="list-group-item">name: {{lab.name}}</li>
+ <li class="list-group-item">description: {{lab.description}}</li>
+ <li class="list-group-item">location: {{lab.location}}</li>
+ {% if lab.status == 0 %}
+ <li class="list-group-item">status: Up</li>
+ {% elif lab.status == 100 %}
+ <li class="list-group-item">status: Down for Maintenance</li>
+ {% elif lab.status == 200 %}
+ <li class="list-group-item">status: Down</li>
+ {% endif %}
+ </ul>
</div>
- </a>
+ <a class="btn btn-primary" href="/lab/{{lab.name}}/">Details</a>
</div>
- {% endfor %}
- </div>
+ {% endfor %}
</div>
- </div>
-
-{% endblock content %}
+{% endblock %}
diff --git a/dashboard/src/templates/dashboard/multiple_select_filter_widget.html b/dashboard/src/templates/dashboard/multiple_select_filter_widget.html
index 4e47ce0..628fd95 100644
--- a/dashboard/src/templates/dashboard/multiple_select_filter_widget.html
+++ b/dashboard/src/templates/dashboard/multiple_select_filter_widget.html
@@ -6,12 +6,16 @@
}
.class_grid_wrapper {
border: 0px;
- border-left: 1px;
+ text-align: center;
border-right: 1px;
border-style: solid;
border-color: grey;
- text-align: center;
}
+
+.class_grid_wrapper:last-child {
+ border-right: none;
+}
+
.grid_wrapper {
display: grid;
grid-template-columns: 1fr 1fr;
@@ -67,6 +71,45 @@
margin-top: 10px;
}
+#dropdown_wrapper > div > h5 {
+ margin: 12px;
+ display: inline-block;
+ vertical-align: middle;
+}
+
+#dropdown_wrapper > div > button {
+ padding: 7px;
+ margin: 2px;
+ float: right;
+ width: 80px;
+}
+#dropdown_wrapper > div > input {
+ padding: 7px;
+ margin: 2px;
+ float: right;
+ width: 300px;
+ width: calc(100% - 240px);
+}
+
+#dropdown_wrapper > div {
+ border:2px;
+ border-style:none;
+ border-color:black;
+ border-radius: 5px;
+ margin:20px;
+ padding: 2px;
+ box-shadow: 0px 0px 7px 0px rgba(0,0,0,0.75);
+ transition-property: box-shadow, background-color;
+ transition-duration: .2s;
+ display: inline-block;
+ vertical-align: middle;
+}
+
+#dropdown_wrapper {
+ display: grid;
+ grid-template-columns: 3fr 5fr;
+}
+
</style>
<input name="filter_field" id="filter_field" type="hidden"/>
<div id="grid_wrapper" class="grid_wrapper">
@@ -305,9 +348,14 @@ function add_item_prepopulate(node, prepopulate){
div.id = "dropdown_" + dropdown_count;
dropdown_count++;
var label = document.createElement("H5");
- label.style['display'] = 'inline';
label.appendChild(document.createTextNode(node['name']));
div.appendChild(label);
+ button = document.createElement("BUTTON");
+ button.type = "button";
+ button.appendChild(document.createTextNode("Remove"));
+ button.classList.add("btn-danger");
+ button.classList.add("btn");
+ div.appendChild(button);
for(var i=0; i<node['forms'].length; i++){
form = node['forms'][i];
var input = document.createElement("INPUT");
@@ -330,14 +378,12 @@ function add_item_prepopulate(node, prepopulate){
hiddenInput.name = "class";
hiddenInput.value = node['id'];
div.appendChild(hiddenInput);
- button = document.createElement("BUTTON");
button.onclick = function(){
remove_dropdown(div.id);
}
- button.type = "button";
- button.appendChild(document.createTextNode("Remove"));
- div.appendChild(button);
document.getElementById("dropdown_wrapper").appendChild(div);
+ var linebreak = document.createElement("BR");
+ document.getElementById("dropdown_wrapper").appendChild(linebreak);
updateObjectResult(div);
return div;
}
diff --git a/dashboard/src/templates/resource/hostprofile_detail.html b/dashboard/src/templates/resource/hostprofile_detail.html
new file mode 100644
index 0000000..0776b9e
--- /dev/null
+++ b/dashboard/src/templates/resource/hostprofile_detail.html
@@ -0,0 +1,116 @@
+{% extends "base.html" %}
+{% load staticfiles %}
+
+{% block content %}
+<div class="row">
+ <div class="col-lg-6">
+ <div class="panel panel-default">
+ <div class="panel-heading clearfix">
+ <h4 style="display: inline;">Available at</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>
+ <ul>
+ {% for lab in hostprofile.labs.all %}
+ <li>{{lab.name}}</li>
+ {% endfor %}
+ </ul>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </div>
+ <div class="panel panel-default">
+ <div class="panel-heading clearfix">
+ <h4 style="display: inline;">RAM</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>{{hostprofile.ramprofile.first.amount}}G,
+ {{hostprofile.ramprofile.first.channels}} channels</td>
+ </tr>
+ </table>
+ </div>
+ </div>
+ <div class="panel panel-default">
+ <div class="panel-heading clearfix">
+ <h4 style="display: inline;">CPU</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>Arch:</td>
+ <td>{{hostprofile.cpuprofile.first.architecture}}</td>
+ </tr>
+ <tr>
+ <td>Cores:</td>
+ <td>{{hostprofile.cpuprofile.first.cores}}</td>
+ </tr>
+ <tr>
+ <td>Sockets:</td>
+ <td>{{hostprofile.cpuprofile.first.cpus}}</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;">Interfaces</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">
+ {% for intprof in hostprofile.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>
+ </div>
+ </div>
+ </div>
+ <div class="col-lg-6">
+ <div class="panel panel-default">
+ <div class="panel-heading clearfix">
+ <h4 style="display: inline;">Disk</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>Size:</td>
+ <td>{{hostprofile.storageprofile.first.size}} GiB</td>
+ </tr>
+ <tr>
+ <td>Type:</td>
+ <td>{{hostprofile.storageprofile.first.media_type}}</td>
+ </tr>
+ <tr>
+ <td>Mount Point:</td>
+ <td>{{hostprofile.storageprofile.first.name}}</td>
+ </tr>
+ </table>
+ </div>
+ </div>
+ </div>
+</div>
+{% endblock content %}
diff --git a/dashboard/src/templates/resource/hosts.html b/dashboard/src/templates/resource/hosts.html
index 4bf64e0..69b7231 100644
--- a/dashboard/src/templates/resource/hosts.html
+++ b/dashboard/src/templates/resource/hosts.html
@@ -17,7 +17,7 @@
{{ host.name }}
</td>
<td>
- {{ host.profile }}
+ <a href="profiles/{{ host.profile.id }}">{{ host.profile }}</a>
</td>
<td>
{{ host.booked }}
diff --git a/dashboard/src/templates/resource/steps/meta_info.html b/dashboard/src/templates/resource/steps/meta_info.html
index b458842..7a1b56a 100644
--- a/dashboard/src/templates/resource/steps/meta_info.html
+++ b/dashboard/src/templates/resource/steps/meta_info.html
@@ -5,6 +5,28 @@
{% block content %}
+<style>
+#resource_meta_form {
+ margin: 80px;
+ display: grid;
+}
+
+#resource_meta_form td > * {
+ width: 100%;
+ margin-bottom: 20px;
+ margin-top: 20px;
+}
+
+#resource_meta_form > table > tbody > tr {
+ border-bottom: 1px solid #cccccc;
+}
+
+#resource_meta_form > table > tbody > tr:last-child {
+ border-bottom: none;
+}
+
+</style>
+
<form id="resource_meta_form" method="post" action="/wf/workflow/">
{% csrf_token %}
<table>
diff --git a/dashboard/src/templates/workflow/viewport-base.html b/dashboard/src/templates/workflow/viewport-base.html
index f78bc01..1329595 100644
--- a/dashboard/src/templates/workflow/viewport-base.html
+++ b/dashboard/src/templates/workflow/viewport-base.html
@@ -84,12 +84,19 @@
background: #0FD57D;
}
- #viewport-iframe
- {
- height: calc(100vh - 450);
- }
-
+ .iframe_div {
+ width: calc(100% - 450px);
+ margin-left: 70px;
+ height: calc(100vh - 155px);
+ position: absolute;
+ border: none;
+ }
+ .iframe_elem {
+ width: 100%;
+ height: calc(100vh - 155px);
+ border: none;
+ }
</style>
<button id="gof" onclick="go(step+1)" class="btn go_btn go_forward">Go Forward</button>
@@ -415,15 +422,7 @@
document.getElementById("view_message").className = "step_message";
document.getElementById("view_message").classList.add("message_" + stepstatus);
}
- function resize_iframe(){
- var page_rect = document.getElementById("wrapper").getBoundingClientRect();
- var title_rect = document.getElementById("iframe_header").getBoundingClientRect();
- var iframe_height = page_rect.bottom - title_rect.bottom;
- document.getElementById("viewport-iframe").height = iframe_height;
- }
- window.addEventListener('load', resize_iframe);
- window.addEventListener('resize', resize_iframe);
</script>
<!-- /.col-lg-12 -->
</div>
@@ -433,5 +432,7 @@
</form>
</div>
-<iframe src="/wf/workflow" style="position: absolute; left: 351px; right: 105px; width: calc(100% - 450px); border-style: none; border-width: 1px; border-color: #888888;" scrolling="yes" id="viewport-iframe" onload="resize_iframe();"></iframe>
+<div class="iframe_div">
+ <iframe src="/wf/workflow" class="iframe_elem" scrolling="yes" id="viewport-iframe"></iframe>
+</div>
{% endblock content %}