9a08f260ef
git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/branches/2.8@16300 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
1280 lines
48 KiB
JavaScript
1280 lines
48 KiB
JavaScript
/**
|
|
* Global variables
|
|
*/
|
|
var topPriority = 0;
|
|
|
|
/**
|
|
* Load the service portal's provision page
|
|
*
|
|
* @param tabId Tab ID where page will reside
|
|
*/
|
|
function loadServicePage(tabId) {
|
|
// Create info bar
|
|
var infoBar = createInfoBar('Select a platform to configure, then click Ok.');
|
|
|
|
// Create self-service portal page
|
|
var tabId = 'serviceTab';
|
|
var servicePg = $('<div class="form"></div>');
|
|
$('#' + tabId).append(infoBar, servicePg);
|
|
|
|
// Create radio buttons for platforms
|
|
var hwList = $('<ol>Platforms available:</ol>');
|
|
var esx = $('<li><input type="radio" name="hw" value="esx" disabled/>ESX</li>');
|
|
var kvm = $('<li><input type="radio" name="hw" value="kvm" disabled/>KVM</li>');
|
|
var zvm = $('<li><input type="radio" name="hw" value="zvm" checked/>z\/VM</li>');
|
|
|
|
hwList.append(esx);
|
|
hwList.append(kvm);
|
|
hwList.append(zvm);
|
|
servicePg.append(hwList);
|
|
|
|
/**
|
|
* Ok
|
|
*/
|
|
var okBtn = createButton('Ok');
|
|
okBtn.bind('click', function(event) {
|
|
var configTabs = getConfigTab();
|
|
|
|
// Get hardware that was selected
|
|
var hw = $(this).parent().find('input[name="hw"]:checked').val();
|
|
var newTabId = hw + 'ProvisionTab';
|
|
|
|
if ($('#' + newTabId).size() > 0){
|
|
configTabs.select(newTabId);
|
|
} else {
|
|
var title = '';
|
|
|
|
// Create an instance of the plugin
|
|
var plugin = null;
|
|
switch (hw) {
|
|
case "kvm":
|
|
plugin = new kvmPlugin();
|
|
title = 'KVM';
|
|
break;
|
|
case "esx":
|
|
plugin = new esxPlugin();
|
|
title = 'ESX';
|
|
break;
|
|
case "zvm":
|
|
plugin = new zvmPlugin();
|
|
title = 'z/VM';
|
|
|
|
// Get zVM host names
|
|
if (!$.cookie('zvms')){
|
|
$.ajax( {
|
|
url : 'lib/cmd.php',
|
|
dataType : 'json',
|
|
data : {
|
|
cmd : 'webportal',
|
|
tgt : '',
|
|
args : 'lszvm',
|
|
msg : ''
|
|
},
|
|
|
|
success : function(data) {
|
|
setzVMCookies(data);
|
|
}
|
|
});
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
// Select tab
|
|
configTabs.add(newTabId, title, '', true);
|
|
configTabs.select(newTabId);
|
|
plugin.loadConfigPage(newTabId);
|
|
}
|
|
});
|
|
|
|
servicePg.append(okBtn);
|
|
}
|
|
|
|
/**
|
|
* Round a floating point to a given precision
|
|
*
|
|
* @param value Floating point
|
|
* @param precision Decimal precision
|
|
* @returns Floating point number
|
|
*/
|
|
function toFixed(value, precision) {
|
|
var power = Math.pow(10, precision || 0);
|
|
return String(Math.round(value * power) / power);
|
|
}
|
|
|
|
/**
|
|
* Query the images that exists
|
|
*
|
|
* @param panelId Panel ID
|
|
*/
|
|
function queryImages(panelId) {
|
|
$.ajax( {
|
|
url : 'lib/cmd.php',
|
|
dataType : 'json',
|
|
data : {
|
|
cmd : 'tabdump',
|
|
tgt : '',
|
|
args : 'osimage',
|
|
msg : panelId
|
|
},
|
|
|
|
success : configImagePanel
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Panel to configure OS images
|
|
*
|
|
* @param data Data from HTTP request
|
|
*/
|
|
function configImagePanel(data) {
|
|
var panelId = data.msg;
|
|
var rsp = data.rsp;
|
|
|
|
// Wipe panel clean
|
|
$('#' + panelId).empty();
|
|
|
|
// Add info bar
|
|
$('#' + panelId).append(createInfoBar('Create, edit, and delete operating system images for the self-service portal.'));
|
|
|
|
// Create table
|
|
var tableId = panelId + 'Datatable';
|
|
var table = new DataTable(tableId);
|
|
table.init(['<input type="checkbox" onclick="selectAllCheckbox(event, $(this))">', 'Name', 'Selectable', 'OS Version', 'OS Arch', 'OS Name', 'Type', 'Profile', 'Method', 'Description']);
|
|
|
|
// Insert images into table
|
|
var imagePos = 0;
|
|
var profilePos = 0;
|
|
var osversPos = 0;
|
|
var osarchPos = 0;
|
|
var osnamePos = 0;
|
|
var imagetypePos = 0;
|
|
var provMethodPos = 0;
|
|
var comments = 0;
|
|
var desc, selectable, tmp;
|
|
// Get column index for each attribute
|
|
var colNameArray = rsp[0].substr(1).split(',');
|
|
for (var i in colNameArray){
|
|
switch (colNameArray[i]){
|
|
case 'imagename': {
|
|
imagePos = i;
|
|
}
|
|
break;
|
|
|
|
case 'profile':{
|
|
profilePos = i;
|
|
}
|
|
break;
|
|
|
|
case 'osvers':{
|
|
osversPos = i;
|
|
}
|
|
break;
|
|
|
|
case 'osarch':{
|
|
osarchPos = i;
|
|
}
|
|
break;
|
|
|
|
case 'osname':{
|
|
osnamePos = i;
|
|
}
|
|
break;
|
|
|
|
case 'imagetype':{
|
|
imagetypePos = i;
|
|
}
|
|
break;
|
|
|
|
case 'comments':{
|
|
comments = i;
|
|
}
|
|
break;
|
|
|
|
case 'provmethod':{
|
|
provMethodPos = i;
|
|
}
|
|
break;
|
|
|
|
default :
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Go through each index
|
|
for (var i = 1; i < rsp.length; i++) {
|
|
// Get image name
|
|
var cols = rsp[i].split(',');
|
|
var name = cols[imagePos].replace(new RegExp('"', 'g'), '');
|
|
var profile = cols[profilePos].replace(new RegExp('"', 'g'), '');
|
|
var provMethod = cols[provMethodPos].replace(new RegExp('"', 'g'), '');
|
|
var osVer = cols[osversPos].replace(new RegExp('"', 'g'), '');
|
|
var osArch = cols[osarchPos].replace(new RegExp('"', 'g'), '');
|
|
var osName = cols[osnamePos].replace(new RegExp('"', 'g'), '');
|
|
var imageType = cols[imagetypePos].replace(new RegExp('"', 'g'), '');
|
|
var osComments = cols[comments].replace(new RegExp('"', 'g'), '');
|
|
|
|
// Only save install boot and s390x architectures
|
|
if (osArch == "s390x") {
|
|
// Set default description and selectable
|
|
selectable = "no";
|
|
desc = "No description";
|
|
|
|
if (osComments) {
|
|
tmp = osComments.split('|');
|
|
for (var j = 0; j < tmp.length; j++) {
|
|
// Save description
|
|
if (tmp[j].indexOf('description:') > -1) {
|
|
desc = tmp[j].replace('description:', '');
|
|
desc = jQuery.trim(desc);
|
|
}
|
|
|
|
// Is the image selectable?
|
|
if (tmp[j].indexOf('selectable:') > -1) {
|
|
selectable = tmp[j].replace('selectable:', '');
|
|
selectable = jQuery.trim(selectable);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Columns are: name, selectable, OS version, OS arch, OS name, type, profile, method, and description
|
|
var cols = new Array(name, selectable, osVer, osArch, osName, imageType, profile, provMethod, desc);
|
|
|
|
// Add remove button where id = user name
|
|
cols.unshift('<input type="checkbox" name="' + name + '"/>');
|
|
|
|
// Add row
|
|
table.add(cols);
|
|
}
|
|
}
|
|
|
|
// Append datatable to tab
|
|
$('#' + panelId).append(table.object());
|
|
|
|
// Turn into datatable
|
|
$('#' + tableId).dataTable({
|
|
'iDisplayLength': 50,
|
|
'bLengthChange': false,
|
|
"bScrollCollapse": true,
|
|
"sScrollY": "400px",
|
|
"sScrollX": "110%",
|
|
"bAutoWidth": true,
|
|
"oLanguage": {
|
|
"oPaginate": {
|
|
"sNext": "",
|
|
"sPrevious": ""
|
|
}
|
|
}
|
|
});
|
|
|
|
// Create action bar
|
|
var actionBar = $('<div class="actionBar"></div>').css("width", "400px");
|
|
|
|
// Create a profile
|
|
var createLnk = $('<a>Create</a>');
|
|
createLnk.click(function() {
|
|
imageDialog();
|
|
});
|
|
|
|
// Edit a profile
|
|
var editLnk = $('<a>Edit</a>');
|
|
editLnk.click(function() {
|
|
var images = $('#' + tableId + ' input[type=checkbox]:checked');
|
|
for (var i in images) {
|
|
var image = images.eq(i).attr('name');
|
|
if (image) {
|
|
// Columns are: name, selectable, OS version, OS arch, OS name, type, profile, method, and description
|
|
var cols = images.eq(i).parents('tr').find('td');
|
|
var selectable = cols.eq(2).text();
|
|
var osVersion = cols.eq(3).text();
|
|
var osArch = cols.eq(4).text();
|
|
var osName = cols.eq(5).text();
|
|
var type = cols.eq(6).text();
|
|
var profile = cols.eq(7).text();
|
|
var method = cols.eq(8).text();
|
|
var description = cols.eq(9).text();
|
|
|
|
editImageDialog(image, selectable, osVersion, osArch, osName, type, profile, method, description);
|
|
}
|
|
}
|
|
});
|
|
|
|
// Delete a profile
|
|
var deleteLnk = $('<a>Delete</a>');
|
|
deleteLnk.click(function() {
|
|
var images = getNodesChecked(tableId);
|
|
if (images) {
|
|
deleteImageDialog(images);
|
|
}
|
|
});
|
|
|
|
// Refresh profiles table
|
|
var refreshLnk = $('<a>Refresh</a>');
|
|
refreshLnk.click(function() {
|
|
queryImages(panelId);
|
|
});
|
|
|
|
// Create an action menu
|
|
var actionsMenu = createMenu([refreshLnk, createLnk, editLnk, deleteLnk]);
|
|
actionsMenu.superfish();
|
|
actionsMenu.css('display', 'inline-block');
|
|
actionBar.append(actionsMenu);
|
|
|
|
// Set correct theme for action menu
|
|
actionsMenu.find('li').hover(function() {
|
|
setMenu2Theme($(this));
|
|
}, function() {
|
|
setMenu2Normal($(this));
|
|
});
|
|
|
|
// Create a division to hold actions menu
|
|
var menuDiv = $('<div id="' + tableId + '_menuDiv" class="menuDiv"></div>');
|
|
$('#' + tableId + '_wrapper').prepend(menuDiv);
|
|
menuDiv.append(actionBar);
|
|
$('#' + tableId + '_filter').appendTo(menuDiv);
|
|
|
|
// Resize accordion
|
|
$('#' + tableId).parents('.ui-accordion').accordion('resize');
|
|
}
|
|
|
|
/**
|
|
* Open image dialog
|
|
*/
|
|
function imageDialog() {
|
|
// Create form to add profile
|
|
var dialogId = 'createImage';
|
|
var imageForm = $('<div id="' + dialogId + '" class="form"></div>');
|
|
|
|
// Create info bar
|
|
var info = createInfoBar('Provide the following attributes for the image. The image name will be generated based on the attributes you will give.');
|
|
imageForm.append(info);
|
|
|
|
var imageName = $('<div><label>Image name:</label><input type="text" name="imagename" disabled="disabled" title="The name of the image"/></div>');
|
|
var selectable = $('<div><label>Selectable:</label><input type="checkbox" name="selectable" title="Select if you want this image to appear on the self service portal"/></div>');
|
|
var imageType = $('<div><label>Image type:</label><input type="text" name="imagetype" value="linux" title="The type of operating system image this definition represents"/></div>');
|
|
var architecture = $('<div><label>OS architecture:</label><input type="text" name="osarch" title="The hardware architecture of this node. Valid values: x86_64, ppc64, x86, ia64, and s390x."/></div>');
|
|
var osName = $('<div><label>OS name:</label><input type="text" name="osname" value="Linux" title="Operating system name"/></div>');
|
|
var osVersion = $('<div><label>OS version:</label><input type="text" name="osvers" title="The Linux operating system deployed on this node. Valid values: rhel*, centos*, fedora*, and sles* (where * is the version #)."/></div>');
|
|
var profile = $('<div><label>Profile:</label><input type="text" name="profile" title="The node usage category"/></div>');
|
|
var provisionMethod = $('<div><label>Provision method:</label></div>');
|
|
var provisionSelect = $('<select name="provmethod" title="The provisioning method for node deployment">'
|
|
+ '<option value=""></option>'
|
|
+ '<option value="install">install</option>'
|
|
+ '<option value="netboot">netboot</option>'
|
|
+ '<option value="statelite">statelite</option>'
|
|
+ '</select>');
|
|
provisionMethod.append(provisionSelect);
|
|
var comments = $('<div><label>Description:</label><input type="text" name="comments" title="Any user-written notes"/></div>');
|
|
imageForm.append(imageName, selectable, imageType, architecture, osName, osVersion, profile, provisionMethod, comments);
|
|
|
|
// Generate tooltips
|
|
imageForm.find('div input[title],textarea[title],select[title]').tooltip({
|
|
position: "center right",
|
|
offset: [-2, 10],
|
|
effect: "fade",
|
|
opacity: 0.8,
|
|
delay: 0,
|
|
predelay: 800,
|
|
events: {
|
|
def: "mouseover,mouseout",
|
|
input: "mouseover,mouseout",
|
|
widget: "focus mouseover,blur mouseout",
|
|
tooltip: "mouseover,mouseout"
|
|
},
|
|
|
|
// Change z index to show tooltip in front
|
|
onBeforeShow: function() {
|
|
this.getTip().css('z-index', $.topZIndex());
|
|
}
|
|
});
|
|
|
|
// Open dialog to add image
|
|
imageForm.dialog({
|
|
title:'Create image',
|
|
modal: true,
|
|
close: function(){
|
|
$(this).remove();
|
|
},
|
|
width: 400,
|
|
buttons: {
|
|
"Ok": function() {
|
|
// Remove any warning messages
|
|
$(this).find('.ui-state-error').remove();
|
|
|
|
// Get image attributes
|
|
var imageType = $(this).find('input[name="imagetype"]');
|
|
var selectable = $(this).find('input[name="selectable"]');
|
|
var architecture = $(this).find('input[name="osarch"]');
|
|
var osName = $(this).find('input[name="osname"]');
|
|
var osVersion = $(this).find('input[name="osvers"]');
|
|
var profile = $(this).find('input[name="profile"]');
|
|
var provisionMethod = $(this).find('select[name="provmethod"]');
|
|
var comments = $(this).find('input[name="comments"]');
|
|
|
|
// Check that image attributes are provided before continuing
|
|
var ready = 1;
|
|
var inputs = new Array(imageType, architecture, osName, osVersion, profile, provisionMethod);
|
|
for (var i in inputs) {
|
|
if (!inputs[i].val()) {
|
|
inputs[i].css('border-color', 'red');
|
|
ready = 0;
|
|
} else
|
|
inputs[i].css('border-color', '');
|
|
}
|
|
|
|
// If inputs are not complete, show warning message
|
|
if (!ready) {
|
|
var warn = createWarnBar('Please provide a value for each missing field.');
|
|
warn.prependTo($(this));
|
|
} else {
|
|
// Override image name
|
|
$(this).find('input[name="imagename"]').val(osVersion.val() + '-' + architecture.val() + '-' + provisionMethod.val() + '-' + profile.val());
|
|
var imageName = $(this).find('input[name="imagename"]');
|
|
|
|
// Change dialog buttons
|
|
$(this).dialog('option', 'buttons', {
|
|
'Close': function() {$(this).dialog("close");}
|
|
});
|
|
|
|
// Set default description
|
|
if (!comments.val())
|
|
comments.val('No description');
|
|
|
|
// Create arguments to send via AJAX
|
|
var args = 'updateosimage;' + imageName.val() + ';' +
|
|
imageType.val() + ';' +
|
|
architecture.val() + ';' +
|
|
osName.val() + ';' +
|
|
osVersion.val() + ';' +
|
|
profile.val() + ';' +
|
|
provisionMethod.val() + ';';
|
|
|
|
if (selectable.attr('checked'))
|
|
args += '"description:' + comments.val() + '|selectable:yes"';
|
|
else
|
|
args += '"description:' + comments.val() + '|selectable:no"';
|
|
|
|
// Add image to xCAT
|
|
$.ajax( {
|
|
url : 'lib/cmd.php',
|
|
dataType : 'json',
|
|
data : {
|
|
cmd : 'webrun',
|
|
tgt : '',
|
|
args : args,
|
|
msg : dialogId
|
|
},
|
|
|
|
success : updatePanel
|
|
});
|
|
}
|
|
},
|
|
"Cancel": function() {
|
|
$(this).dialog( "close" );
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Edit image dialog
|
|
*
|
|
* @param iName Image name
|
|
* @param iSelectable Is image selectable from service page
|
|
* @param iOsVersion OS version
|
|
* @param iProfile Profile name
|
|
* @param iMethod Provisioning method
|
|
* @param iComments Image description
|
|
*/
|
|
function editImageDialog(iName, iSelectable, iOsVersion, iOsArch, iOsName, iType, iProfile, iMethod, iComments) {
|
|
var inst = 0;
|
|
var dialogId = 'editImage' + inst;
|
|
while ($('#' + dialogId).length) {
|
|
// If one already exists, generate another one
|
|
inst = inst + 1;
|
|
dialogId = 'editImage' + inst;
|
|
}
|
|
|
|
// Create form to add profile
|
|
var imageForm = $('<div id="' + dialogId + '" class="form"></div>');
|
|
|
|
// Create info bar
|
|
var info = createInfoBar('Provide the following attributes for the image. The image name will be generated based on the attributes you will give.');
|
|
imageForm.append(info);
|
|
|
|
var imageName = $('<div><label>Image name:</label><input type="text" name="imagename" disabled="disabled" title="The name of the image"/></div>');
|
|
var selectable = $('<div><label>Selectable:</label><input type="checkbox" name="selectable" title="Select if you want this image to appear on the self service portal"/></div>');
|
|
var imageType = $('<div><label>Image type:</label><input type="text" name="imagetype" value="linux" title="The type of operating system image this definition represents"/></div>');
|
|
var architecture = $('<div><label>OS architecture:</label><input type="text" name="osarch" title="The hardware architecture of this node. Valid values: x86_64, ppc64, x86, ia64, and s390x."/></div>');
|
|
var osName = $('<div><label>OS name:</label><input type="text" name="osname" value="Linux" title="Operating system name"/></div>');
|
|
var osVersion = $('<div><label>OS version:</label><input type="text" name="osvers" title="The Linux operating system deployed on this node. Valid values: rhel*, centos*, fedora*, and sles* (where * is the version #)."/></div>');
|
|
var profile = $('<div><label>Profile:</label><input type="text" name="profile" title="The node usage category"/></div>');
|
|
var provisionMethod = $('<div><label>Provision method:</label></div>');
|
|
var provisionSelect = $('<select name="provmethod" title="The provisioning method for node deployment">'
|
|
+ '<option value=""></option>'
|
|
+ '<option value="install">install</option>'
|
|
+ '<option value="netboot">netboot</option>'
|
|
+ '<option value="statelite">statelite</option>'
|
|
+ '</select>');
|
|
provisionMethod.append(provisionSelect);
|
|
var comments = $('<div><label>Description:</label><input type="text" name="comments" title="Any user-written notes"/></div>');
|
|
imageForm.append(imageName, selectable, imageType, architecture, osName, osVersion, profile, provisionMethod, comments);
|
|
|
|
// Fill in image attributes
|
|
imageForm.find('input[name="imagename"]').val(iName);
|
|
imageForm.find('input[name="osvers"]').val(iOsVersion);
|
|
imageForm.find('input[name="osarch"]').val(iOsArch);
|
|
imageForm.find('input[name="osname"]').val(iOsName);
|
|
imageForm.find('input[name="imagetype"]').val(iType);
|
|
imageForm.find('input[name="profile"]').val(iProfile);
|
|
imageForm.find('select[name="provmethod"]').val(iMethod);
|
|
imageForm.find('input[name="comments"]').val(iComments);
|
|
if (iSelectable == "yes")
|
|
imageForm.find('input[name="selectable"]').attr('checked', 'checked');
|
|
|
|
// Generate tooltips
|
|
imageForm.find('div input[title],textarea[title],select[title]').tooltip({
|
|
position: "center right",
|
|
offset: [-2, 10],
|
|
effect: "toggle",
|
|
opacity: 0.8,
|
|
delay: 0,
|
|
predelay: 800,
|
|
events: {
|
|
def: "mouseover,mouseout",
|
|
input: "mouseover,mouseout",
|
|
widget: "focus mouseover,blur mouseout",
|
|
tooltip: "mouseover,mouseout"
|
|
},
|
|
|
|
// Change z index to show tooltip in front
|
|
onBeforeShow: function() {
|
|
this.getTip().css('z-index', $.topZIndex());
|
|
}
|
|
});
|
|
|
|
// Open dialog to add image
|
|
imageForm.dialog({
|
|
title:'Edit image',
|
|
modal: true,
|
|
close: function(){
|
|
$(this).remove();
|
|
},
|
|
width: 400,
|
|
buttons: {
|
|
"Ok": function() {
|
|
// Remove any warning messages
|
|
$(this).find('.ui-state-error').remove();
|
|
|
|
// Get image attributes
|
|
var imageType = $(this).find('input[name="imagetype"]');
|
|
var selectable = $(this).find('input[name="selectable"]');
|
|
var architecture = $(this).find('input[name="osarch"]');
|
|
var osName = $(this).find('input[name="osname"]');
|
|
var osVersion = $(this).find('input[name="osvers"]');
|
|
var profile = $(this).find('input[name="profile"]');
|
|
var provisionMethod = $(this).find('select[name="provmethod"]');
|
|
var comments = $(this).find('input[name="comments"]');
|
|
|
|
// Check that image attributes are provided before continuing
|
|
var ready = 1;
|
|
var inputs = new Array(imageType, architecture, osName, osVersion, profile, provisionMethod);
|
|
for (var i in inputs) {
|
|
if (!inputs[i].val()) {
|
|
inputs[i].css('border-color', 'red');
|
|
ready = 0;
|
|
} else
|
|
inputs[i].css('border-color', '');
|
|
}
|
|
|
|
// If inputs are not complete, show warning message
|
|
if (!ready) {
|
|
var warn = createWarnBar('Please provide a value for each missing field.');
|
|
warn.prependTo($(this));
|
|
} else {
|
|
// Override image name
|
|
$(this).find('input[name="imagename"]').val(osVersion.val() + '-' + architecture.val() + '-' + provisionMethod.val() + '-' + profile.val());
|
|
var imageName = $(this).find('input[name="imagename"]');
|
|
|
|
// Change dialog buttons
|
|
$(this).dialog('option', 'buttons', {
|
|
'Close': function() {$(this).dialog("close");}
|
|
});
|
|
|
|
// Set default description
|
|
if (!comments.val())
|
|
comments.val('No description');
|
|
|
|
// Create arguments to send via AJAX
|
|
var args = 'updateosimage;' + imageName.val() + ';' +
|
|
imageType.val() + ';' +
|
|
architecture.val() + ';' +
|
|
osName.val() + ';' +
|
|
osVersion.val() + ';' +
|
|
profile.val() + ';' +
|
|
provisionMethod.val() + ';';
|
|
|
|
if (selectable.attr('checked'))
|
|
args += '"description:' + comments.val() + '|selectable:yes"';
|
|
else
|
|
args += '"description:' + comments.val() + '|selectable:no"';
|
|
|
|
// Add image to xCAT
|
|
$.ajax( {
|
|
url : 'lib/cmd.php',
|
|
dataType : 'json',
|
|
data : {
|
|
cmd : 'webrun',
|
|
tgt : '',
|
|
args : args,
|
|
msg : dialogId
|
|
},
|
|
|
|
success : updatePanel
|
|
});
|
|
}
|
|
},
|
|
"Cancel": function() {
|
|
$(this).dialog( "close" );
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Open dialog to confirm image delete
|
|
*
|
|
* @param images Images to delete
|
|
*/
|
|
function deleteImageDialog(images) {
|
|
// Create form to delete disk to pool
|
|
var dialogId = 'deleteImage';
|
|
var deleteForm = $('<div id="' + dialogId + '" class="form"></div>');
|
|
|
|
// Create info bar
|
|
var info = createInfoBar('Are you sure you want to delete ' + images.replace(new RegExp(',', 'g'), ', ') + '?');
|
|
deleteForm.append(info);
|
|
|
|
// Open dialog to delete user
|
|
deleteForm.dialog({
|
|
title:'Delete image',
|
|
modal: true,
|
|
width: 400,
|
|
close: function(){
|
|
$(this).remove();
|
|
},
|
|
buttons: {
|
|
"Ok": function(){
|
|
// Remove any warning messages
|
|
$(this).find('.ui-state-error').remove();
|
|
|
|
// Change dialog buttons
|
|
$(this).dialog('option', 'buttons', {
|
|
'Close': function() {$(this).dialog("close");}
|
|
});
|
|
|
|
// Delete user
|
|
$.ajax( {
|
|
url : 'lib/cmd.php',
|
|
dataType : 'json',
|
|
data : {
|
|
cmd : 'webrun',
|
|
tgt : '',
|
|
args : 'rmosimage;' + images,
|
|
msg : dialogId
|
|
},
|
|
success : updatePanel
|
|
});
|
|
},
|
|
"Cancel": function() {
|
|
$(this).dialog( "close" );
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Query the groups that exists
|
|
*
|
|
* @param panelId Panel ID
|
|
*/
|
|
function queryGroups(panelId) {
|
|
$.ajax( {
|
|
url : 'lib/cmd.php',
|
|
dataType : 'json',
|
|
data : {
|
|
cmd : 'tabdump',
|
|
tgt : '',
|
|
args : 'hosts',
|
|
msg : panelId
|
|
},
|
|
|
|
success : configGroupPanel
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Panel to configure groups
|
|
*
|
|
* @param data Data from HTTP request
|
|
*/
|
|
function configGroupPanel(data) {
|
|
var panelId = data.msg;
|
|
var rsp = data.rsp;
|
|
|
|
// Wipe panel clean
|
|
$('#' + panelId).empty();
|
|
|
|
// Add info bar
|
|
$('#' + panelId).append(createInfoBar('Create, edit, and delete groups for the self-service portal.'));
|
|
|
|
// Create table
|
|
var tableId = panelId + 'Datatable';
|
|
var table = new DataTable(tableId);
|
|
table.init(['<input type="checkbox" onclick="selectAllCheckbox(event, $(this))">', 'Name', 'Selectable', 'IP', 'Hostname', 'Description']);
|
|
|
|
// Insert groups into table
|
|
var nodePos = 0;
|
|
var ipPos = 0;
|
|
var hostnamePos = 0;
|
|
var commentsPos = 0;
|
|
var desc, selectable, tmp;
|
|
// Get column index for each attribute
|
|
var colNameArray = rsp[0].substr(1).split(',');
|
|
for (var i in colNameArray){
|
|
switch (colNameArray[i]){
|
|
case 'node':
|
|
nodePos = i;
|
|
break;
|
|
|
|
case 'ip':
|
|
ipPos = i;
|
|
break;
|
|
|
|
case 'hostnames':
|
|
hostnamePos = i;
|
|
break;
|
|
|
|
case 'comments':
|
|
commentsPos = i;
|
|
break;
|
|
|
|
default :
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Go through each index
|
|
for (var i = 1; i < rsp.length; i++) {
|
|
// Get image name
|
|
var cols = rsp[i].split(',');
|
|
var name = cols[nodePos].replace(new RegExp('"', 'g'), '');
|
|
var ip = cols[ipPos].replace(new RegExp('"', 'g'), '');
|
|
var hostname = cols[hostnamePos].replace(new RegExp('"', 'g'), '');
|
|
var comments = cols[commentsPos].replace(new RegExp('"', 'g'), '');
|
|
|
|
// Set default description and selectable
|
|
selectable = "no";
|
|
network = "";
|
|
desc = "No description";
|
|
|
|
if (comments) {
|
|
tmp = comments.split('|');
|
|
for (var j = 0; j < tmp.length; j++) {
|
|
// Save description
|
|
if (tmp[j].indexOf('description:') > -1) {
|
|
desc = tmp[j].replace('description:', '');
|
|
desc = jQuery.trim(desc);
|
|
}
|
|
|
|
// Is the group selectable?
|
|
if (tmp[j].indexOf('selectable:') > -1) {
|
|
selectable = tmp[j].replace('selectable:', '');
|
|
selectable = jQuery.trim(selectable);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Columns are: name, selectable, network, and description
|
|
var cols = new Array(name, selectable, ip, hostname, desc);
|
|
|
|
// Add remove button where id = user name
|
|
cols.unshift('<input type="checkbox" name="' + name + '"/>');
|
|
|
|
// Add row
|
|
table.add(cols);
|
|
}
|
|
|
|
// Append datatable to tab
|
|
$('#' + panelId).append(table.object());
|
|
|
|
// Turn into datatable
|
|
$('#' + tableId).dataTable({
|
|
'iDisplayLength': 50,
|
|
'bLengthChange': false,
|
|
"bScrollCollapse": true,
|
|
"sScrollY": "400px",
|
|
"sScrollX": "110%",
|
|
"bAutoWidth": true,
|
|
"oLanguage": {
|
|
"oPaginate": {
|
|
"sNext": "",
|
|
"sPrevious": ""
|
|
}
|
|
}
|
|
});
|
|
|
|
// Create action bar
|
|
var actionBar = $('<div class="actionBar"></div>').css("width", "400px");
|
|
|
|
// Create a group
|
|
var createLnk = $('<a>Create</a>');
|
|
createLnk.click(function() {
|
|
groupDialog();
|
|
});
|
|
|
|
// Edit a group
|
|
var editLnk = $('<a>Edit</a>');
|
|
editLnk.click(function() {
|
|
var groups = $('#' + tableId + ' input[type=checkbox]:checked');
|
|
for (var i in groups) {
|
|
var group = groups.eq(i).attr('name');
|
|
if (group) {
|
|
// Column order is: name, selectable, network, and description
|
|
var cols = groups.eq(i).parents('tr').find('td');
|
|
var selectable = cols.eq(2).text();
|
|
var ip = cols.eq(3).text();
|
|
var hostnames = cols.eq(4).text();
|
|
var description = cols.eq(5).text();
|
|
|
|
editGroupDialog(group, selectable, ip, hostnames, description);
|
|
}
|
|
}
|
|
});
|
|
|
|
// Delete a profile
|
|
var deleteLnk = $('<a>Delete</a>');
|
|
deleteLnk.click(function() {
|
|
var groups = getNodesChecked(tableId);
|
|
if (groups) {
|
|
deleteGroupDialog(groups);
|
|
}
|
|
});
|
|
|
|
// Refresh profiles table
|
|
var refreshLnk = $('<a>Refresh</a>');
|
|
refreshLnk.click(function() {
|
|
queryGroups(panelId);
|
|
});
|
|
|
|
// Create an action menu
|
|
var actionsMenu = createMenu([refreshLnk, createLnk, editLnk, deleteLnk]);
|
|
actionsMenu.superfish();
|
|
actionsMenu.css('display', 'inline-block');
|
|
actionBar.append(actionsMenu);
|
|
|
|
// Set correct theme for action menu
|
|
actionsMenu.find('li').hover(function() {
|
|
setMenu2Theme($(this));
|
|
}, function() {
|
|
setMenu2Normal($(this));
|
|
});
|
|
|
|
// Create a division to hold actions menu
|
|
var menuDiv = $('<div id="' + tableId + '_menuDiv" class="menuDiv"></div>');
|
|
$('#' + tableId + '_wrapper').prepend(menuDiv);
|
|
menuDiv.append(actionBar);
|
|
$('#' + tableId + '_filter').appendTo(menuDiv);
|
|
|
|
// Resize accordion
|
|
$('#' + tableId).parents('.ui-accordion').accordion('resize');
|
|
}
|
|
|
|
/**
|
|
* Open group dialog
|
|
*/
|
|
function groupDialog() {
|
|
// Create form to add profile
|
|
var dialogId = 'createGroup';
|
|
var groupForm = $('<div id="' + dialogId + '" class="form"></div>');
|
|
|
|
// Create info bar
|
|
var info = createInfoBar('Provide the following attributes for the group.');
|
|
groupForm.append(info);
|
|
|
|
var group = $('<div><label>Group:</label><input type="text" name="group" title="The group name"/></div>');
|
|
var selectable = $('<div><label>Selectable:</label><input type="checkbox" name="selectable" title="Select if you want this group to appear on the self service portal"/></div>');
|
|
var ip = $('<div><label>IP:</label><input type="text" name="ip" title="The IP address of the nodes, usually given as a regular expression, e.g. |ihost(\d+)|10.1.1.($1+0)|"/></div>');
|
|
var hostnames = $('<div><label>Hostnames:</label><input type="text" name="hostnames" title="The hostname of the nodes, usually given as a regular expression, e.g. |(.*)|($1).sourceforge.net|"/></div>');
|
|
var comments = $('<div><label>Description:</label><input type="text" name="comments" title="A description of the group"/></div>');
|
|
var ipPool = $('<div><label style="vertical-align: top;">IP pool:</label><textarea name="ip_pool" title="A pool of node names, IP addresses, and hostnames that can be chosen from for a newly provisioned virtual machine. An entry in the pool could be: ihost12,10.1.2.12,ihost12.endicott.ibm.com. A newline separates each entry."/></div>');
|
|
|
|
groupForm.append(group, selectable, ip, hostnames, comments, ipPool);
|
|
|
|
// Generate tooltips
|
|
groupForm.find('div input[title],textarea[title],select[title]').tooltip({
|
|
position: "center right",
|
|
offset: [-2, 10],
|
|
effect: "fade",
|
|
opacity: 0.8,
|
|
delay: 0,
|
|
predelay: 800,
|
|
events: {
|
|
def: "mouseover,mouseout",
|
|
input: "mouseover,mouseout",
|
|
widget: "focus mouseover,blur mouseout",
|
|
tooltip: "mouseover,mouseout"
|
|
},
|
|
|
|
// Change z index to show tooltip in front
|
|
onBeforeShow: function() {
|
|
this.getTip().css('z-index', $.topZIndex());
|
|
}
|
|
});
|
|
|
|
// Open dialog to add image
|
|
groupForm.dialog({
|
|
title:'Create group',
|
|
modal: true,
|
|
close: function(){
|
|
$(this).remove();
|
|
},
|
|
width: 600,
|
|
buttons: {
|
|
"Ok": function() {
|
|
// Remove any warning messages
|
|
$(this).find('.ui-state-error').remove();
|
|
|
|
// Get group attributes
|
|
var group = $(this).find('input[name="group"]');
|
|
var selectable = $(this).find('input[name="selectable"]');
|
|
var ip = $(this).find('input[name="ip"]');
|
|
var hostnames = $(this).find('input[name="hostnames"]');
|
|
var comments = $(this).find('input[name="comments"]');
|
|
var ipPool = $(this).find('textarea[name=ip_pool]').val();
|
|
|
|
// Check that group attributes are provided before continuing
|
|
var ready = 1;
|
|
var inputs = new Array(group, ip, hostnames);
|
|
for (var i in inputs) {
|
|
if (!inputs[i].val()) {
|
|
inputs[i].css('border-color', 'red');
|
|
ready = 0;
|
|
} else
|
|
inputs[i].css('border-color', '');
|
|
}
|
|
|
|
// If inputs are not complete, show warning message
|
|
if (!ready) {
|
|
var warn = createWarnBar('Please provide a value for each missing field.');
|
|
warn.prependTo($(this));
|
|
} else {
|
|
// Change dialog buttons
|
|
$(this).dialog('option', 'buttons', {
|
|
'Close': function() {$(this).dialog("close");}
|
|
});
|
|
|
|
// A newline at the end of IP pool is needed
|
|
ipPool = ipPool.replace(/^\s+|\s+$/g, '');
|
|
ipPool += '\n';
|
|
|
|
// Set default description
|
|
if (!comments.val())
|
|
comments.val('No description');
|
|
|
|
// Create arguments to send via AJAX
|
|
var args = "updategroup;" + group.val() + ";'" + ip.val() + "';'" + hostnames.val() + "';";
|
|
|
|
if (selectable.attr("checked"))
|
|
args += "'description:" + comments.val() + "|selectable:yes";
|
|
else
|
|
args += "'description:" + comments.val() + "|selectable:no";
|
|
|
|
// Add image to xCAT
|
|
$.ajax({
|
|
url : 'lib/cmd.php',
|
|
dataType : 'json',
|
|
data : {
|
|
cmd : 'webrun',
|
|
tgt : '',
|
|
args : args,
|
|
msg : dialogId
|
|
},
|
|
|
|
success : updatePanel
|
|
});
|
|
|
|
// Write IP pool file to /var/tmp
|
|
$.ajax({
|
|
url : 'lib/cmd.php',
|
|
dataType : 'json',
|
|
data : {
|
|
cmd : 'write',
|
|
tgt : '/var/tmp/' + group.val() + '.pool',
|
|
args : '',
|
|
cont : ipPool,
|
|
msg : dialogId + ';' + group.val()
|
|
},
|
|
|
|
success : function(data) {
|
|
var args = data.msg.split(';');
|
|
|
|
// Create profile in xCAT
|
|
$.ajax({
|
|
url : 'lib/cmd.php',
|
|
dataType : 'json',
|
|
data : {
|
|
cmd : 'webrun',
|
|
tgt : '',
|
|
args : 'mkippool;' + args[1],
|
|
msg : args[0]
|
|
},
|
|
|
|
success: updatePanel
|
|
});
|
|
}
|
|
});
|
|
}
|
|
},
|
|
"Cancel": function() {
|
|
$(this).dialog( "close" );
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Edit group dialog
|
|
*
|
|
* @param iGroup Group name
|
|
* @param iSelectable Is group selectable from the service page
|
|
* @param iIp Group IP regex
|
|
* @param iHostnames Group hostnames regex
|
|
* @param iComments Group description
|
|
*/
|
|
function editGroupDialog(iGroup, iSelectable, iIp, iHostnames, iComments) {
|
|
// Create form to add profile
|
|
var dialogId = 'createGroup-' + iGroup;
|
|
var groupForm = $('<div id="' + dialogId + '" class="form"></div>');
|
|
|
|
// Create info bar
|
|
var info = createInfoBar('Provide the following attributes for the group.');
|
|
groupForm.append(info);
|
|
|
|
var group = $('<div><label>Group:</label><input type="text" name="group" title="The group name"/></div>');
|
|
var selectable = $('<div><label>Selectable:</label><input type="checkbox" name="selectable" title="Select if you want this group to appear on the self service portal"/></div>');
|
|
var ip = $('<div><label>IP:</label><input type="text" name="ip" title="The IP address for the group, usually given as a regular expression, e.g. |ihost(\d+)|10.1.1.($1+0)|"/></div>');
|
|
var hostnames = $('<div><label>Hostnames:</label><input type="text" name="hostnames" title="The hostname for the group, usually given as a regular expression, e.g. |(.*)|($1).sourceforge.net|"/></div>');
|
|
var comments = $('<div><label>Description:</label><input type="text" name="comments" title="A description of the group"/></div>');
|
|
var ipPool = $('<div><label style="vertical-align: top;">IP pool:</label><textarea name="ip_pool" title="A pool of node names, IP addresses, and hostnames that can be chosen from for a newly provisioned virtual machine."/></div>');
|
|
|
|
groupForm.append(group, selectable, ip, hostnames, comments, ipPool);
|
|
|
|
// Query IP pool based on group name
|
|
$.ajax({
|
|
url : 'lib/cmd.php',
|
|
dataType : 'json',
|
|
data : {
|
|
cmd : 'webrun',
|
|
tgt : '',
|
|
args : 'lsippool;' + iGroup,
|
|
msg : dialogId
|
|
},
|
|
|
|
success : function(data) {
|
|
// Populate textarea with IP pool entries
|
|
$('#' + data.msg).find('textarea[name="ip_pool"]').val(data.rsp[0]);
|
|
}
|
|
});
|
|
|
|
// Fill in group attributes
|
|
groupForm.find('input[name="group"]').val(iGroup);
|
|
groupForm.find('input[name="ip"]').val(iIp);
|
|
groupForm.find('input[name="hostnames"]').val(iHostnames);
|
|
groupForm.find('input[name="comments"]').val(iComments);
|
|
if (iSelectable == "yes")
|
|
groupForm.find('input[name="selectable"]').attr('checked', 'checked');
|
|
|
|
// Generate tooltips
|
|
groupForm.find('div input[title],textarea[title],select[title]').tooltip({
|
|
position: "center right",
|
|
offset: [-2, 10],
|
|
effect: "toggle",
|
|
opacity: 0.8,
|
|
delay: 0,
|
|
predelay: 800,
|
|
events: {
|
|
def: "mouseover,mouseout",
|
|
input: "mouseover,mouseout",
|
|
widget: "focus mouseover,blur mouseout",
|
|
tooltip: "mouseover,mouseout"
|
|
},
|
|
|
|
// Change z index to show tooltip in front
|
|
onBeforeShow: function() {
|
|
this.getTip().css('z-index', $.topZIndex());
|
|
}
|
|
});
|
|
|
|
// Open dialog to add image
|
|
groupForm.dialog({
|
|
title:'Edit group',
|
|
modal: true,
|
|
close: function(){
|
|
$(this).remove();
|
|
},
|
|
width: 600,
|
|
buttons: {
|
|
"Ok": function() {
|
|
// Remove any warning messages
|
|
$(this).find('.ui-state-error').remove();
|
|
|
|
// Get group attributes
|
|
var group = $(this).find('input[name="group"]');
|
|
var selectable = $(this).find('input[name="selectable"]');
|
|
var ip = $(this).find('input[name="ip"]');
|
|
var hostnames = $(this).find('input[name="hostnames"]');
|
|
var comments = $(this).find('input[name="comments"]');
|
|
var ipPool = $(this).find('textarea[name=ip_pool]').val();
|
|
|
|
// Check that group attributes are provided before continuing
|
|
var ready = 1;
|
|
var inputs = new Array(group);
|
|
for (var i in inputs) {
|
|
if (!inputs[i].val()) {
|
|
inputs[i].css('border-color', 'red');
|
|
ready = 0;
|
|
} else
|
|
inputs[i].css('border-color', '');
|
|
}
|
|
|
|
// If inputs are not complete, show warning message
|
|
if (!ready) {
|
|
var warn = createWarnBar('Please provide a value for each missing field.');
|
|
warn.prependTo($(this));
|
|
} else {
|
|
// Change dialog buttons
|
|
$(this).dialog('option', 'buttons', {
|
|
'Close': function() {$(this).dialog("close");}
|
|
});
|
|
|
|
// A newline at the end of IP pool is needed
|
|
ipPool = ipPool.replace(/^\s+|\s+$/g, '');
|
|
ipPool += '\n';
|
|
|
|
// Set default description
|
|
if (!comments.val())
|
|
comments.val('No description');
|
|
|
|
// Create arguments to send via AJAX
|
|
var args = "updategroup;" + group.val() + ";'" + ip.val() + "';'" + hostnames.val() + "';";
|
|
|
|
if (selectable.attr("checked"))
|
|
args += "'description:" + comments.val() + "|selectable:yes";
|
|
else
|
|
args += "'description:" + comments.val() + "|selectable:no";
|
|
|
|
// Add image to xCAT
|
|
$.ajax( {
|
|
url : 'lib/cmd.php',
|
|
dataType : 'json',
|
|
data : {
|
|
cmd : 'webrun',
|
|
tgt : '',
|
|
args : args,
|
|
msg : dialogId
|
|
},
|
|
|
|
success : updatePanel
|
|
});
|
|
|
|
// Write IP pool file to /var/tmp
|
|
$.ajax({
|
|
url : 'lib/cmd.php',
|
|
dataType : 'json',
|
|
data : {
|
|
cmd : 'write',
|
|
tgt : '/var/tmp/' + group.val() + '.pool',
|
|
args : '',
|
|
cont : ipPool,
|
|
msg : dialogId + ';' + group.val()
|
|
},
|
|
|
|
success : function(data) {
|
|
var args = data.msg.split(';');
|
|
|
|
// Create profile in xCAT
|
|
$.ajax({
|
|
url : 'lib/cmd.php',
|
|
dataType : 'json',
|
|
data : {
|
|
cmd : 'webrun',
|
|
tgt : '',
|
|
args : 'mkippool;' + args[1],
|
|
msg : args[0]
|
|
},
|
|
|
|
success: updatePanel
|
|
});
|
|
}
|
|
});
|
|
}
|
|
},
|
|
"Cancel": function() {
|
|
$(this).dialog( "close" );
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Open dialog to confirm group delete
|
|
*
|
|
* @param groups Groups to delete
|
|
*/
|
|
function deleteGroupDialog(groups) {
|
|
// Create form to delete disk to pool
|
|
var dialogId = 'deleteImage';
|
|
var deleteForm = $('<div id="' + dialogId + '" class="form"></div>');
|
|
|
|
// Create info bar
|
|
var info = createInfoBar('Are you sure you want to delete ' + groups.replace(new RegExp(',', 'g'), ', ') + '?');
|
|
deleteForm.append(info);
|
|
|
|
// Open dialog to delete user
|
|
deleteForm.dialog({
|
|
title:'Delete group',
|
|
modal: true,
|
|
width: 400,
|
|
close: function(){
|
|
$(this).remove();
|
|
},
|
|
buttons: {
|
|
"Ok": function(){
|
|
// Remove any warning messages
|
|
$(this).find('.ui-state-error').remove();
|
|
|
|
// Change dialog buttons
|
|
$(this).dialog('option', 'buttons', {
|
|
'Close': function() {$(this).dialog("close");}
|
|
});
|
|
|
|
// Delete user
|
|
$.ajax( {
|
|
url : 'lib/cmd.php',
|
|
dataType : 'json',
|
|
data : {
|
|
cmd : 'webrun',
|
|
tgt : '',
|
|
args : 'rmgroup;' + groups,
|
|
msg : dialogId
|
|
},
|
|
success : updatePanel
|
|
});
|
|
},
|
|
"Cancel": function() {
|
|
$(this).dialog( "close" );
|
|
}
|
|
}
|
|
});
|
|
} |