BOOKING_EXPIRE_TIME=30
BOOKING_MAXIMUM_NUMBER=10
-TEMPLATE_OVERRIDE_DIR=laas
+PROJECT=anuket
LIBLAAS_BASE_URL=http://<address>:<port>/
from account.models import Lab, UserProfile
from booking.models import Booking
from laas_dashboard import settings
+from laas_dashboard.settings import PROJECT
from liblaas.utils import get_ipa_status
from liblaas.views import flavor_list_flavors, flavor_list_hosts
user = request.user
lab = get_object_or_404(Lab, name=lab_name)
- origin = "anuket" if os.environ.get("TEMPLATE_OVERRIDE_DIR") == 'laas' else "lfedge"
-
- flavors_list = flavor_list_flavors(origin)
- host_list = flavor_list_hosts(origin)
+ flavors_list = flavor_list_flavors(PROJECT)
+ host_list = flavor_list_hosts(PROJECT)
flavor_map = {}
for flavor in flavors_list:
flavor_map[flavor['flavor_id']] = flavor['name']
-
+
# Apparently Django Templating lacks many features that regular Jinja offers, so I need to get creative
for host in host_list:
ROOT_URLCONF = 'laas_dashboard.urls'
-TEMPLATE_OVERRIDE = os.environ.get("TEMPLATE_OVERRIDE_DIR", "") # the user's custom template dir
+PROJECT = os.environ.get("PROJECT", "") # the project for the current deployment (i.e. anuket or lfedge)
TEMPLATE_DIRS = ["base"] # where all the base templates are
# If the user has a custom template directory,
# We should search that first. Then we search the
# root template directory so that we can extend the base
# templates within the custom template dir.
-if TEMPLATE_OVERRIDE:
- TEMPLATE_DIRS = [TEMPLATE_OVERRIDE, ""] + TEMPLATE_DIRS
+if PROJECT:
+ TEMPLATE_DIRS = [PROJECT, ""] + TEMPLATE_DIRS
# all template dirs are relative to /project_root/templates/
dirs = [os.path.join(BASE_DIR, "templates", d) for d in TEMPLATE_DIRS]
from account.models import Lab
from django.utils import timezone
from datetime import timedelta
+from laas_dashboard.settings import PROJECT
def request_list_flavors(request) -> HttpResponse:
data = json.loads(request.body.decode('utf-8'))
"project": data["metadata"]["project"],
"length": int(data["metadata"]["length"])
},
- "origin": "anuket" if os.environ.get("TEMPLATE_OVERRIDE_DIR") == 'laas' else "lfedge" # todo - refactor
+ "origin": PROJECT
}
# Create booking in dashboard
print(f"Error at {url}")
return None
-# GET
-def flavor_get_flavor_by_id(flavor_id: str) -> requests.Response:
- endpoint = f'flavor/name/{flavor_id}/'
- url = f'{base}{endpoint}'
- try:
- response = requests.get(url)
- return response.json()
- except:
- print(f"Error at {url}")
- return None
-
# GET
def flavor_list_hosts(project: str) -> requests.Response:
- endpoint = f'flavor/hosts/{project}'
+ endpoint = f'flavor/hosts/{project}' #todo - support project in liblaas
url = f'{base}{endpoint}'
try:
response = requests.get(url)
# GET
def template_list_templates(uid: str) -> requests.Response:
- endpoint = f'template/list/{uid}'
+ endpoint = f'template/list/{uid}' # todo - templates need to be restricted by project
url = f'{base}{endpoint}'
try:
response = requests.get(url)
#POST
def template_make_template(template_blob: dict) -> requests.Response:
- endpoint = f'template/create'
+ endpoint = f'template/create' # todo - needs to be restricted by project
url = f'{base}{endpoint}'
try:
response = requests.post(url, data=json.dumps(template_blob), headers=post_headers)
import os
from django.shortcuts import render
from django.http import HttpResponse
+from laas_dashboard.settings import PROJECT
from liblaas.views import flavor_list_hosts, flavor_list_flavors
-origin = "anuket" if os.environ.get("TEMPLATE_OVERRIDE_DIR") == 'laas' else "lfedge"
-
def host_list_view(request):
if request.method != "GET":
return HttpResponse(status=405)
- host_list = flavor_list_hosts(origin)
- flavor_list = flavor_list_flavors(origin)
+ host_list = flavor_list_hosts(PROJECT)
+ flavor_list = flavor_list_flavors(PROJECT)
flavor_map = {}
for flavor in flavor_list:
if request.method != "GET":
return HttpResponse(status=405)
- flavor_list = flavor_list_flavors(origin)
+ flavor_list = flavor_list_flavors(PROJECT)
selected_flavor = {}
for flavor in flavor_list:
if flavor["flavor_id"] == resource_id:
return;
}
- if (this.templateBlob.host_list.length >= 8) {
- showError("You may not add more than 8 hosts to a single pod.", -1)
+ if (max_hosts && this.templateBlob.host_list.length >= max_hosts) {
+ showError(`You may not add more than ${max_hosts} hosts to a single pod.`, -1)
return;
}
for (const [index, host] of this.resourceBuilder.user_configs.entries()) {
const new_host = new HostConfigBlob(host);
this.templateBlob.host_list.push(new_host);
- this.labFlavors.get(host.flavor).available_count--
+ this.labFlavors.get(host.flavor).available_count--
}
// Add networks
}
}
- // We are done
- GUI.refreshHostStep(this.templateBlob.host_list, this.labFlavors, this.labImages);
- GUI.refreshNetworkStep(this.templateBlob.networks);
- GUI.refreshConnectionStep(this.templateBlob.host_list);
- GUI.refreshPodSummaryHosts(this.templateBlob.host_list, this.labFlavors, this.labImages)
- $('#resource_modal').modal('hide')
+ // We are done
+ GUI.refreshHostStep(this.templateBlob.host_list, this.labFlavors, this.labImages);
+ GUI.refreshNetworkStep(this.templateBlob.networks);
+ GUI.refreshConnectionStep(this.templateBlob.host_list);
+ GUI.refreshPodSummaryHosts(this.templateBlob.host_list, this.labFlavors, this.labImages)
+ $('#resource_modal').modal('hide')
}
/**
* Takes a hostname, looks for the matching HostConfigBlob in the TemplateBlob, removes it from the list, and refreshes the appropriate views
- * @param {String} hostname
+ * @param {String} hostname
*/
onclickDeleteHost(hostname) {
this.goTo(steps.ADD_RESOURCES);
passed = false;
message = "Please select a lab";
step = steps.SELECT_LAB;
- } else if (this.templateBlob.host_list.length < 1 || this.templateBlob.host_list.length > 8) {
+ } else if (this.templateBlob.host_list.length < 1 || (max_hosts && this.templateBlob.host_list.length > max_hosts)) {
passed = false;
- message = "Pods must contain 1 to 8 hosts";
+ message = "Pod contains invalid number of resources.";
step = steps.ADD_RESOURCES;
} else if (this.templateBlob.networks.length < 1) {
passed = false;
/**
* Refreshes the step and creates a card for each host in the hostlist
- * @param {List<HostConfigBlob>} hostlist
+ * @param {List<HostConfigBlob>} hostlist
*/
static refreshHostStep(hostlist, flavors, images) {
const host_cards = document.getElementById('host_cards');
}
let span_class = ''
- if (hostlist.length == 8) {
- span_class = 'text-primary'
- } else if (hostlist.length > 8) {
- span_class = 'text-danger'
+ if (max_hosts) {
+ if (hostlist.length == max_hosts) {
+ span_class = 'text-primary'
+ } else if (hostlist.length > max_hosts) {
+ span_class = 'text-danger'
+ }
}
+
const plus_card = document.createElement("div");
plus_card.classList.add("col-xl-3", "col-md-6", "col-12");
plus_card.id = "add_resource_plus_card";
- plus_card.innerHTML = `
- <div class="card align-items-center border-0">
- <span class="` + span_class + `" id="resource-count">` + hostlist.length + `/ 8</span>
- <button class="btn btn-success add-button p-0" onclick="workflow.onclickAddResource()">+</button>
- </div>
- `
- host_cards.appendChild(plus_card);
+ if (max_hosts) {
+ plus_card.innerHTML = `
+ <div class="card align-items-center border-0">
+ <span class="${span_class}" id="resource-count">${hostlist.length} / ${max_hosts}</span>
+ <button class="btn btn-success add-button p-0" onclick="workflow.onclickAddResource()">+</button>
+ </div>
+ `
+ } else {
+ plus_card.innerHTML = `
+ <div class="card align-items-center border-0">
+ <button class="btn btn-success add-button p-0" onclick="workflow.onclickAddResource()">+</button>
+ </div>
+ `
+ }
+
+ if (max_hosts || hostlist.length == 0) {
+ host_cards.appendChild(plus_card);
+ }
}
/**
* Makes a host card element for a given host and returns a reference to the card
- * @param {HostConfigBlob} host
+ * @param {HostConfigBlob} host
*/
static makeHostCard(host, flavors, images) {
const new_card = document.createElement("div");
<script src="/static/js/workflows/design-a-pod.js"></script>
{% endblock %}
{% block content %}
-{% if dashboard == 'laas' %}
-
<!-- Main Content -->
<body>
<div class="arrow arrow-up"></div>
</button>
</div>
-
+
<div id="next" class="row w-100 m-0">
<button class="btn btn-workflow-nav stretched-link m-0 p-0 mb-3" onclick="workflow.goNext()" id="workflow-next">
<div class="arrow arrow-down"></div>
</button>
</div>
-
+
<div class="scroll-container w-100 h-100 p-0">
<!-- Select Lab -->
<!-- Add Resources -->
<div class="scroll-area pt-5 mx-5" id="add_resources">
<h2 class="mt-4 mb-3">Add Resources<span class="text-danger">*</span></h2>
- <p>Add up to 8 configurable resources to your pod, then use the navigation arrows to proceed to the next step.</p>
+ {% if constraints.max_hosts != "null" %}
+ <p>Add up to {{constraints.max_hosts}} configurable resources to your pod, then use the navigation arrows to proceed to the next step.</p>
+ {% else %}
+ <p>Select a resource bundle that you would like to configure. To change the selected resource bundle, remove all added resources.</p>
+ {% endif %}
<div class="row card-deck align-items-center" id="host_cards">
<div class="col-xl-3 col-md-6 col-12" id="add_resource_plus_card">
<div class="card align-items-center border-0">
- <span class="" id="resource-count">0 / 8</span>
+ {% if constraints.max_hosts != "null" %}
+ <span class="" id="resource-count">0 / {{constraints.max_hosts}}</span>
+ {% endif %}
<button class="btn btn-success add-button p-0" onclick="workflow.onclickAddResource()">+</button>
</div>
</div>
</div>
</div>
- <!-- Add Networks -->
+ <!-- Add Networks -->
<div class="scroll-area pt-5 mx-5" id="add_networks">
<h2 class="mt-4 mb-3">Add Networks<span class="text-danger">*</span></h2>
<p>Define networks to use in your pod. A network may be set as public or private.</p>
<script>
const user = "{{user}}"
+ const max_hosts = {{constraints.max_hosts}}
const workflow = new DesignWorkflow();
workflow.startWorkflow();
</script>
-{% endif %}
{% endblock %}
</a>
</div>
{% endblock logo %}
-{% block dropDown %}
-{% endblock dropDown %}
{% block userDropDownText %}
<a class="nav-link p-0 wtext p-2" data-toggle="dropdown" href="#">
{% if request.user.username %}
{% extends "base/dashboard/landing.html" %}
+
{% block about_us %}
<p>The Shared Community Lab at the IOL aims to help development and testing of LF Edge projects by hosting hardware and providing access to the community.</p>
<p>To get started, you can request access to a pod at the right.</p>
{% endblock about_us %}
-
-{% block btnGrp %}
-<style>
-.btnLFEdge {
- color: #fff;
- background-color: #0049b0;
-}
-.btnLFEdge:hover{
- color: #fff;
- background-color: #001776;
-}
-</style>
-<p>To get started, book a pod below:</p>
-<a class="btn btnLFEdge btn-lg d-flex flex-column justify-content-center align-content-center border text-white p-4" href="/booking/quick/">Book a Pod</a>
-{% endblock btnGrp %}
-
-{% block returningUsers %}
-{% endblock returningUsers %}
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
-import json
from django.shortcuts import render, redirect
-from laas_dashboard.settings import TEMPLATE_OVERRIDE
+from laas_dashboard.settings import PROJECT
from django.http import HttpResponse
from liblaas.views import user_get_user
from workflow.forms import BookingMetaForm
if (not profile or profile.ipa_username == None):
return redirect("dashboard:index")
+ constraints = get_workflow_contraints(PROJECT)
template = "workflow/design_a_pod.html"
context = {
- "dashboard": str(TEMPLATE_OVERRIDE)
+ "constraints": constraints,
}
return render(request, template, context)
return redirect("dashboard:index")
vpn_user = user_get_user(profile.ipa_username)
-
+
# These booleans need to be represented as strings, due to the way jinja interprets them
prereqs = {
"company": "true" if ("ou" in vpn_user and vpn_user["ou"] != "") else "false",
template = "workflow/book_a_pod.html"
context = {
- "dashboard": str(TEMPLATE_OVERRIDE),
"form": BookingMetaForm(initial={}, user_initial=[], owner=request.user),
"prereqs": prereqs
}
return render(request, template, context)
+def get_workflow_contraints(project: str) -> dict:
+
+ if project == 'anuket':
+ return {
+ "max_hosts": 8,
+ }
+
+ if project == 'lfedge':
+ return {
+ "max_hosts": "null",
+ }
+
+ return {}
+