Commit 35b32eaa authored by Leigh Stoller's avatar Leigh Stoller

Rework the reservations part of the instantiate wizard. No longer using

the "reservations" slot of the prediction, but now using the more
explicit "current" and "upcoming". Also, changes to the use of
"pressure" which was really confusing. Instead of showing the user a
scary warning about pressure for any reservation, only show it if they
are explicit using types that are under pressure.
parent 4a7f4feb
......@@ -44,6 +44,7 @@ $(function ()
var ppchanged = false;
var monitor = null;
var types = null;
var hardware = null;
var resinfo = null;
var mainTemplate = _.template(instantiateString);
......@@ -251,7 +252,7 @@ $(function ()
* is changed.
*/
$('#profile_pid').change(function (event) {
console.log('profile-pid change');
//console.log('profile-pid change');
UpdateGroupSelector();
UpdateImageConstraints();
ShowClusterReservations();
......@@ -1038,103 +1039,161 @@ $(function ()
var project = $('#profile_pid').val();
var projectReservations = {}
var requested = 0;
var inuse = 0;
$('#reservation_confirmation').addClass('hidden');
$('#reservation_warning').addClass('hidden');
$('#reservation_future').addClass('hidden');
$('#finalize_options .cluster-group').each(function() {
var click = false;
var click = false;
var siteid = $(this).find("> label").attr("name");
$(this).find('.dropdown-menu > .enabled:not(.hidden)').each(function() {
$(this).find('.reservation_tooltip').remove();
var start = null;
var end = null;
var earliest = null;
var hasReservation = false;
var currentReservations = false;
var target = $(this).find('a');
var cluster = $(this).attr('urn');
if (_.has(resinfo, cluster) && resinfo[cluster] != null) {
if (_.has(resinfo[cluster], 'reservations') && resinfo[cluster]['reservations'] != null) {
_.each(resinfo[cluster]['reservations'], function(types, resproj) {
var earliest = null;
// Find earliest reservation time
_.each(types, function(time) {
if (earliest == null || earliest > time) {
earliest = time;
}
});
/*
* Upcoming is lower priority so do first.
*/
if (_.has(resinfo[cluster], 'upcoming') &&
resinfo[cluster]['upcoming'] != null) {
_.each(resinfo[cluster]['upcoming'],
function(thelist, resproj) {
_.each(thelist,
function(obj) {
console.info("upcoming", obj.starttime,
resproj, project);
// Current project has a reservation
// Current project has a future reservation
// Used for cluster icons
if (project == resproj) {
hasReservation = true;
click = true;
start = earliest;
}
// Icon for projects
var projectClass = 'futureReservation';
var priority = 1; // Used for sorting projects
var now = new Date();
var startTime = new Date(parseInt(earliest)*1000);
if (startTime < now) {
projectClass = 'hasReservation';
priority = 2;
// Find earliest starting reservation time
if (earliest == null ||
earliest > obj.starttime) {
earliest = obj.starttime;
}
}
// Do not override a current entry (from above).
if (!_.has(projectReservations, resproj)) {
projectReservations[resproj] = {
// Icon for projects
class: "futureReservation",
// Used for sorting projects
attr: {'data-priority': 2}
}
}
});
});
}
if (_.has(resinfo[cluster], 'current') &&
resinfo[cluster]['current'] != null) {
_.each(resinfo[cluster]['current'],
function(thelist, resproj) {
_.each(thelist,
function(obj) {
var req = obj.reserved;
var used = obj.used;
var type = obj.nodetype;
console.info("current", req, used, type,
resproj, project);
// Current project has a current reservation
// Used for cluster icons
if (project == resproj) {
hasReservation = true;
click = true;
// All nodes for current project reservations.
requested += parseInt(req);
inuse += parseInt(used);
currentReservations = true;
}
projectReservations[resproj] = {
class: projectClass,
attr: {'data-priority': priority}
// Icon for projects
class: "hasReservation",
// Used for sorting projects
attr: {'data-priority': 1}
}
});
});
});
}
if (_.has(resinfo[cluster], 'pressure') && resinfo[cluster]['pressure'] != null) {
if (!hasReservation) {
_.each(resinfo[cluster]['pressure'], function(reslist) {
if (_.has(reslist, project)) {
if (start == null || start > reslist[project][0][0]) {
start = reslist[project][0][0];
end = reslist[project][0][1];
}
}
});
}
// These are reservations that could interfere with
// the user getting nodes.
if (!hasReservation &&
_.has(resinfo[cluster], 'pressure') &&
resinfo[cluster]['pressure'] != null) {
_.each(resinfo[cluster]['pressure'],
function(reslist, type) {
//console.info("P1", reslist,
// type, hardware, siteid);
if (_.has(hardware, siteid) &&
_.has(hardware[siteid], type) &&
_.has(reslist, project)) {
//console.info("P", siteid,
// type, project);
if (start == null ||
start > reslist[project][0][0]) {
start = reslist[project][0][0];
end = reslist[project][0][1];
}
}
});
}
if (start != null) {
if (hasReservation || start != null) {
//console.info("res", project, start, end, earliest,
// requested, inuse);
$(this).attr('data-res-pid', project);
$(this).attr('data-res-start', start);
if (end != null) {
$(this).removeAttr('data-now');
$(this).attr('data-res-end', end);
target.append(wt.ReservationWarningHTML('cluster', 2));
}
else {
$(this).attr('data-res-requested', requested);
$(this).attr('data-res-used', inuse);
if (hasReservation) {
$(this).removeAttr('data-res-end');
var now = new Date();
var startTime = new Date(parseInt(start)*1000);
if (startTime < now) {
$(this).removeAttr('data-res-upcoming');
if (currentReservations) {
$(this).attr('data-now', 'true');
target.append(wt.HasReservationHTML(project, 'cluster', 2));
}
else {
$(this).attr('data-res-upcoming', earliest);
$(this).attr('data-now', 'false');
target.append(wt.FutureReservationHTML(project, 'cluster', 2));
}
}
else if (start) {
$(this).attr('data-res-start', start);
if (end != null) {
$(this).removeAttr('data-now');
$(this).attr('data-res-end', end);
target.append(wt.ReservationWarningHTML('cluster', 2));
}
}
$('.reservation_tooltip > div').tooltip();
}
else {
$(this).removeAttr('data-now');
$(this).removeAttr('data-res-pid');
$(this).removeAttr('data-res-start');
$(this).removeAttr('data-res-end');
$(this).removeAttr('data-res-requested');
$(this).removeAttr('data-res-used');
$(this).removeAttr('data-res-upcoming');
}
}
});
......@@ -1146,6 +1205,7 @@ $(function ()
var pickerStatus = $('#'+which+' .cluster_picker_status .dropdown-menu .enabled a');
if (click) {
console.info("pickerStatus", pickerStatus);
pickerStatus[1].click();
}
else {
......@@ -1595,11 +1655,18 @@ $(function ()
// If multisite is disabled for the user, or no sites or 1 site.
if (!multisite || Object.keys(sites).length <= 1) {
var siteid;
if (Object.keys(sites).length == 0) {
siteid = "Site 1";
}
else {
siteid = _.values(sites)[0]
}
html =
"<div id='nosite_selector' " +
" class='form-horizontal experiment_option'>" +
" <div class='form-group cluster-group'>" +
" <label class='col-sm-4 control-label' name='" + _.values(sites)[0] + "' " +
" <label class='col-sm-4 control-label' name='" + siteid + "' " +
" style='text-align: right;'>Cluster:</a>" +
" </label> " +
" <div class='col-sm-6'>" +
......@@ -1713,9 +1780,12 @@ $(function ()
function onFoundTypes(t)
{
//console.info("onFoundTypes", t);
types = {};
hardware = {};
_.each(t, function(item) {
types[item.name] = item.types;
hardware[item.name] = item.hardware;
});
}
......
......@@ -45,16 +45,18 @@ window.wt = (function() {
}
if ($(that).parent().attr('data-res-start')) {
if ($(that).parent().attr('data-res-pid')) {
var project = $(that).parent().attr('data-res-pid');
var start = new Date(parseInt($(that).parent()
.attr('data-res-start')) * 1000);
var requested = $(that).parent().attr('data-res-requested');
var used = $(that).parent().attr('data-res-used');
if ($(that).parent().attr('data-res-end')) {
$('#reservation_confirmation').addClass('hidden');
if ($(that).parent().attr('data-res-start')) {
var start = new Date(parseInt($(that).parent()
.attr('data-res-start')) * 1000);
var end = new Date(parseInt($(that).parent()
.attr('data-res-end')) * 1000);
$('#reservation_confirmation').addClass('hidden');
$('#reservation_warning .reservation_start')
.html(moment(start).format('lll'));
$('#reservation_warning .reservation_end')
......@@ -67,15 +69,20 @@ window.wt = (function() {
if ($(that).parent().attr('data-now') == 'true') {
$('#reservation_future').addClass('hidden');
$('#reservation_confirmation .reservation_start')
.html(moment(start).format('lll'));
$('#reservation_confirmation .reservation_requested')
.html(requested);
$('#reservation_confirmation .reservation_used')
.html(used);
$('#reservation_confirmation .reservation_project')
.html(project);
$('#reservation_confirmation').removeClass('hidden');
}
else {
$('#reservation_confirmation').addClass('hidden');
var start = new Date(parseInt($(that).parent()
.attr('data-res-upcoming')) * 1000);
$('#reservation_confirmation').addClass('hidden');
$('#reservation_future .reservation_start')
.html(moment(start).format('lll'));
$('#reservation_future .reservation_project')
......@@ -225,9 +232,9 @@ window.wt = (function() {
}
function HasReservationHTML(project, type, position) {
var title = 'Your project ' + project + ' has an active cluster reservation.';
var title = 'Project ' + project + ' has an active cluster reservation.';
if (type == 'cluster') {
title = 'Your project ' + project + 'has an active reservation on this cluster.';
title = 'Project ' + project + ' has an active reservation on this cluster.';
}
return '<div class="reservation_tooltip has_reservation">'
+'<div class="warning_icon confirm icon_position_'+position+'" '
......@@ -240,9 +247,9 @@ window.wt = (function() {
}
function FutureReservationHTML(project, type, position) {
var title = 'Your project ' + project + ' has an upcoming cluster reservation.';
var title = 'Project ' + project + ' has an upcoming cluster reservation.';
if (type == 'cluster') {
title = 'Your project ' + project + 'has an upcoming reservation on this cluster.';
title = 'Project ' + project + ' has an upcoming reservation on this cluster.';
}
return '<div class="reservation_tooltip future_reservation">'
+'<div class="warning_icon warn icon_position_'+position+'" '
......
......@@ -357,10 +357,10 @@
<label id='reservation_text' class='alert-warning col-sm-10 col-sm-offset-1'>There is an upcoming reservation on this cluster that may impact your ability to reserve or extend resources. This reservation is from <span class='reservation_start'>start</span> until <span class='reservation_end'>end</span>.</label>
</div>
<div id='reservation_confirmation' class='hidden col-sm-12'>
<label id='reservation_text' class='alert-success col-sm-10 col-sm-offset-1'>Your project <span class="reservation_project"></span> has a reservation on this cluster that began <span class='reservation_start'>start</span>.</label>
<label id='reservation_text' class='alert-success col-sm-10 col-sm-offset-1'>Project <span class="reservation_project"></span> has reservations on this cluster for <span class="reservation_requested"></span> nodes, of which <span class="reservation_used"></span> are already allocated by the project.</label>
</div>
<div id='reservation_future' class='hidden col-sm-12'>
<label id='reservation_text' class='alert-warning col-sm-10 col-sm-offset-1'>Your project <span class="reservation_project"></span> has a reservation on this cluster beginning <span class='reservation_start'>start</span>.</label>
<label id='reservation_text' class='alert-warning col-sm-10 col-sm-offset-1'>Project <span class="reservation_project"></span> has a reservation on this cluster beginning <span class='reservation_start'>start</span>.</label>
</div>
</div>
<% } %>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment