/** * Global variables */ var origAttrs = new Object(); // Original image attributes var defAttrs; // Definable image attributes var imgTableId = 'imagesDatatable'; // Images datatable ID var softwareList = { "rsct" : ["rsct.core.utils", "rsct.core", "src"], "pe" : ["IBMJava2-142-ppc64-JRE", "ibm_lapi_ip_rh6p", "ibm_lapi_us_rh6p", "IBM_pe_license", "ibm_pe_rh6p", "ppe_pdb_ppc64_rh600", "sci_ppc_32bit_rh600", "sci_ppc_64bit_rh600", "vac.cmp", "vac.lib", "vac.lic", "vacpp.cmp", "vacpp.help.pdf", "vacpp.lib", "vacpp.man", "vacpp.rte", "vacpp.rte.lnk", "vacpp.samples", "xlf.cmp", "xlf.help.pdf", "xlf.lib", "xlf.lic", "xlf.man", "xlf.msg.rte", "xlf.rte", "xlf.rte.lnk", "xlf.samples", "xlmass.lib", "xlsmp.lib", "xlsmp.msg.rte", "xlsmp.rte"], "gpfs" : ["gpfs.base", "gpfs.gpl", "gpfs.gplbin", "gpfs.msg.en_US"], "essl" : ["essl.3232.rte", "essl.3264.rte", "essl.6464.rte", "essl.common", "essl.license", "essl.man", "essl.msg", "essl.rte", "ibm-java2", "pessl.common", "pessl.license", "pessl.man", "pessl.msg", "pessl.rte.ppe"], "loadl" : ["IBMJava2", "LoadL-full-license-RH6", "LoadL-resmgr-full-RH6", "LoadL-scheduler-full-RH6"], "ganglia" : ["rrdtool", "ganglia", "ganglia-gmetad", "ganglia-gmond"], "base" : ["createrepo"] }; /** * Load images page */ function loadImagesPage() { // Set padding for images page $('#imagesTab').css('padding', '20px 60px'); // Get images within the database $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'lsdef', tgt : '', args : '-t;osimage;-l', msg : '' }, success : loadImages }); } /** * Load images within the database * * @param data Data returned from HTTP request */ function loadImages(data) { // Data returned var rsp = data.rsp; if (rsp[0].indexOf('Could not find any object definitions') > -1) { rsp = new Array(); } // Image attributes hash var attrs = new Object(); // Image attributes var headers = new Object(); // Clear hash table containing image attributes origAttrs = ''; var image; var args; for (var i in rsp) { // Get the image var pos = rsp[i].indexOf('Object name:'); if (pos > -1) { var temp = rsp[i].split(': '); image = jQuery.trim(temp[1]); // Create a hash for the image attributes attrs[image] = new Object(); i++; } // Get key and value args = rsp[i].split('='); var key = jQuery.trim(args[0]); var val = jQuery.trim(args[1]); // Create a hash table attrs[image][key] = val; headers[key] = 1; } // Save attributes in hash table origAttrs = attrs; // Sort headers var sorted = new Array(); for (var key in headers) { sorted.push(key); } sorted.sort(); // Add column for check box and image name sorted.unshift('<input type="checkbox" onclick="selectAllCheckbox(event, $(this))">', 'imagename'); // Create a datatable var dTable = new DataTable(imgTableId); dTable.init(sorted); // Go through each image for (var img in attrs) { // Create a row var row = new Array(); // Create a check box var checkBx = '<input type="checkbox" name="' + img + '"/>'; // Push in checkbox and image name row.push(checkBx, img); // Go through each header for (var i = 2; i < sorted.length; i++) { // Add the node attributes to the row var key = sorted[i]; var val = attrs[img][key]; if (val) { row.push(val); } else { row.push(''); } } // Add the row to the table dTable.add(row); } // Clear the tab before inserting the table $('#imagesTab').children().remove(); // Create info bar for images tab var info = createInfoBar('Double click on a cell to edit. Click outside the table to save changes. Hit the Escape key to ignore changes.'); $('#imagesTab').append(info); /** * The following actions are available for images: * copy Linux distribution and edit image properties */ // Copy CD into install directory var copyCDLnk = $('<a>Copy CD</a>'); copyCDLnk.click(function() { openCopyCdDialog(); }); // Generate stateless or statelite image var generateLnk = $('<a>Generate image</a>'); generateLnk.click(function() { loadCreateImage(); }); // Edit image attributes var editLnk = $('<a>Edit</a>'); editLnk.click(function() { var tgtImages = getNodesChecked(imgTableId).split(','); if (tgtImages) { for (var i in tgtImages) { openEditImagePage(tgtImages[i]); } } }); // Add a row var addLnk = $('<a>Add</a>'); addLnk.click(function() { openAddImageDialog(); }); // Remove a row var removeLnk = $('<a>Remove</a>'); removeLnk.click(function() { var images = getNodesChecked(imgTableId); if (images) { confirmImageDeleteDialog(images); } }); // Refresh image table var refreshLnk = $('<a>Refresh</a>'); refreshLnk.click(function() { // Get images within the database $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'lsdef', tgt : '', args : '-t;osimage;-l', msg : '' }, success : loadImages }); }); // Insert table $('#imagesTab').append(dTable.object()); // Turn table into a datatable var myDataTable = $('#' + imgTableId).dataTable({ 'iDisplayLength': 50, 'bLengthChange': false, "bScrollCollapse": true, "sScrollY": "400px", "sScrollX": "110%", "bAutoWidth": true, "oLanguage": { "oPaginate": { "sNext": "", "sPrevious": "" } } }); // Set datatable width $('#' + imgTableId + '_wrapper').css({ 'width': '880px' }); // Actions var actionBar = $('<div class="actionBar"></div>').css("width", "450px"); var advancedLnk = '<a>Advanced</a>'; var advancedMenu = createMenu([copyCDLnk, generateLnk]); // Create an action menu var actionsMenu = createMenu([refreshLnk, addLnk, editLnk, removeLnk, [advancedLnk, advancedMenu]]); 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="' + imgTableId + '_menuDiv" class="menuDiv"></div>'); $('#' + imgTableId + '_wrapper').prepend(menuDiv); menuDiv.append(actionBar); $('#' + imgTableId + '_filter').appendTo(menuDiv); /** * Enable editable columns */ // Do not make 1st or 2nd columns editable $('#' + imgTableId + ' td:not(td:nth-child(1),td:nth-child(2))').editable( function(value, settings) { // Get column index var colPos = this.cellIndex; // Get row index var dTable = $('#' + imgTableId).dataTable(); var rowPos = dTable.fnGetPosition(this.parentNode); // Update datatable dTable.fnUpdate(value, rowPos, colPos); // Get image name var image = $(this).parent().find('td:eq(1)').text(); // Get table headers var headers = $('#' + imgTableId).parents('.dataTables_scroll').find('.dataTables_scrollHead thead tr:eq(0) th'); // Get attribute name var attrName = jQuery.trim(headers.eq(colPos).text()); // Get column value var value = $(this).text(); // Build argument var args = attrName + '=' + value; // Send command to change image attributes $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'chdef', tgt : '', args : '-t;osimage;-o;' + image + ';' + args, msg : 'out=imagesTab;tgt=' + image }, success: showChdefOutput }); return value; }, { onblur : 'submit', // Clicking outside editable area submits changes type : 'textarea', // Input type to use placeholder: ' ', event : "dblclick", // Double click and edit height : '30px' // The height of the text area }); // Get definable node attributes $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'lsdef', tgt : '', args : '-t;osimage;-h', msg : '' }, success : setImageDefAttrs }); } /** * Open dialog to confirm deleting image * * @param images Comma delimited image names */ function confirmImageDeleteDialog(images) { // Make images list more readable var dialogId = 'confirmImageRemove'; var tmp = images.replace(new RegExp(',', 'g'), ', '); var confirmDialog = $('<div id="' + dialogId + '">' + '<p>Are you sure you want to remove ' + tmp + '?</p>' + '</div>'); // Open dialog to confirm delete confirmDialog.dialog({ modal: true, close: function(){ $(this).remove(); }, title: 'Confirm', width: 500, buttons: { "Ok": function(){ // Change dialog buttons $(this).dialog('option', 'buttons', { 'Close': function() {$(this).dialog("close");} }); // Add image to xCAT $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'rmdef', tgt : '', args : '-t;osimage;-o;' + images, msg : dialogId }, success : updateImageDialog }); }, "Cancel": function(){ $(this).dialog("close"); } } }); } /** * Open a dialog to add an image */ function openAddImageDialog() { // Create dialog to add image var dialogId = 'addImage'; var addImageForm = $('<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.'); var imageFS = $('<fieldset></fieldset>'); var imageLegend = $('<legend>Image</legend>'); imageFS.append(imageLegend); var imageAttr = $('<div style="display: inline-table; vertical-align: middle;"></div>'); imageFS.append($('<div style="display: inline-table; vertical-align: middle;"><img src="images/provision/operating_system.png"></img></div>')); imageFS.append(imageAttr); var optionFS = $('<fieldset></fieldset>'); var optionLegend = $('<legend>Options</legend>'); optionFS.append(optionLegend); var optionAttr = $('<div style="display: inline-table; vertical-align: middle;"></div>'); optionFS.append($('<div style="display: inline-table; vertical-align: middle;"><img src="images/provision/setting.png" style="width: 70px;"></img></div>')); optionFS.append(optionAttr); addImageForm.append(info, imageFS, optionFS); // Create inputs for image attributes var imageName = $('<div><label>Image name:</label><input type="text" name="imagename" disabled="disabled" title="The name of this xCAT OS image definition"/></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 image. Valid values: x86_64, x86, ia64, ppc64, 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 operating system deployed on this node. Valid values: rhel*, centos*, fedora*, 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); // Create inputs for optional attributes var otherpkgDirectory = $('<div><label>Other package directory:</label></div>'); var otherpkgDirectoryInput = $('<input type="text" name="otherpkgdir" title="The base directory where the non-distro packages are stored"/>'); otherpkgDirectory.append(otherpkgDirectoryInput); otherpkgDirectoryInput.serverBrowser({ onSelect : function(path) { $('#addImage input[name="otherpkgdir"]').val(path); }, onLoad : function() { return $('#addImage input[name="otherpkgdir"]').val(); }, knownPaths : [{ text : 'Install', image : 'desktop.png', path : '/install' }], imageUrl : 'images/serverbrowser/', systemImageUrl : 'images/serverbrowser/', handlerUrl : 'lib/getpath.php', title : 'Browse', requestMethod : 'POST', width : '500', height : '300', basePath : '/install' // Limit user to only install directory }); var packageDirectory = $('<div><label>Package directory:</label></div>'); var packageDirectoryInput = $('<input type="text" name="pkgdir" title="The name of the directory where the distro packages are stored"/>'); packageDirectory.append(packageDirectoryInput); packageDirectoryInput.serverBrowser({ onSelect : function(path) { $('#addImage input[name="pkgdir"]').val(path); }, onLoad : function() { return $('#addImage input[name="pkgdir"]').val(); }, knownPaths : [{ text : 'Install', image : 'desktop.png', path : '/install' }], imageUrl : 'images/serverbrowser/', systemImageUrl : 'images/serverbrowser/', handlerUrl : 'lib/getpath.php', title : 'Browse', requestMethod : 'POST', width : '500', height : '300', basePath : '/install' // Limit user to only install directory }); var packageList = $('<div><label>Package list:</label></div>'); var packageListInput = $('<input type="text" name="pkglist" title="The fully qualified name of the file that stores the distro packages list that will be included in the image"/>'); packageList.append(packageListInput); packageListInput.serverBrowser({ onSelect : function(path) { $('#addImage input[name="pkglist"]').val(path); }, onLoad : function() { return $('#addImage input[name="pkglist"]').val(); }, knownPaths : [{ text : 'Install', image : 'desktop.png', path : '/install' }], imageUrl : 'images/serverbrowser/', systemImageUrl : 'images/serverbrowser/', handlerUrl : 'lib/getpath.php', title : 'Browse', requestMethod : 'POST', width : '500', height : '300', basePath : '/install' // Limit user to only install directory }); var template = $('<div><label>Template:</label></div>'); var templateInput = $('<input type="text" name="template" title="The fully qualified name of the template file that is used to create the kickstart or autoyast file for diskful installation"/>'); template.append(templateInput); templateInput.serverBrowser({ onSelect : function(path) { $('#addImage input[name="template"]').val(path); }, onLoad : function() { return $('#addImage input[name="template"]').val(); }, knownPaths : [{ text : 'Install', image : 'desktop.png', path : '/install' }], imageUrl : 'images/serverbrowser/', systemImageUrl : 'images/serverbrowser/', handlerUrl : 'lib/getpath.php', title : 'Browse', requestMethod : 'POST', width : '500', height : '300', basePath : '/install' // Limit user to only install directory }); imageAttr.append(imageName, imageType, architecture, osName, osVersion, profile, provisionMethod); optionAttr.append(otherpkgDirectory, packageDirectory, packageList, template); // Generate tooltips addImageForm.find('div input[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 addImageForm.dialog({ title:'Add image', modal: true, close: function(){ $(this).remove(); }, beight: 400, width: 600, buttons: { "Ok": function(){ // Remove any warning messages $(this).find('.ui-state-error').remove(); // Get image attributes var imageType = $(this).find('input[name="imagetype"]'); 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"]'); // Get optional image attributes var otherpkgDirectory = $(this).find('input[name="otherpkgdir"]'); var pkgDirectory = $(this).find('input[name="pkgdir"]'); var pkgList = $(this).find('input[name="pkglist"]'); var template = $(this).find('input[name="template"]'); // 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");} }); // Create arguments to send via AJAX var args = '-t;osimage;-o;' + imageName.val() + ';' + 'imagetype=' + imageType.val() + ';' + 'osarch=' + architecture.val() + ';' + 'osname=' + osName.val() + ';' + 'osvers=' + osVersion.val() + ';' + 'profile=' + profile.val() + ';' + 'provmethod=' + provisionMethod.val(); // Get optional attributes if (otherpkgDirectory.val()) args += ';otherpkgdir=' + otherpkgDirectory.val(); if (pkgDirectory.val()) args += ';pkgdir=' + pkgDirectory.val(); if (pkgList.val()) args += ';pkglist=' + pkgList.val(); if (template.val()) args += ';template=' + template.val(); // Add image to xCAT $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'chdef', tgt : '', args : args, msg : dialogId }, success : updateImageDialog }); } }, "Cancel": function() { $(this).dialog( "close" ); } } }); } /** * Update image dialog * * @param data HTTP request data */ function updateImageDialog(data) { var dialogId = data.msg; var infoMsg; // Delete loader if one does exist $('.ui-dialog #' + dialogId + ' img[src="images/loader.gif"]').remove(); // Create info message if (jQuery.isArray(data.rsp)) { infoMsg = ''; // If the data returned is more than 10 lines, get only the last line var i, start; if (data.rsp.length > 10) start = data.rsp.length - 1; else start = 0; for (i = start; i < data.rsp.length; i++) infoMsg += data.rsp[i] + '</br>'; } else { infoMsg = data.rsp; } // Create info bar with close button var infoBar = $('<div class="ui-state-highlight ui-corner-all"></div>').css('margin', '5px 0px'); var icon = $('<span class="ui-icon ui-icon-info"></span>').css({ 'display': 'inline-block', 'margin': '10px 5px' }); // Create close button to close info bar var close = $('<span class="ui-icon ui-icon-close"></span>').css({ 'display': 'inline-block', 'float': 'right' }).click(function() { $(this).parent().remove(); }); var msg = $('<p>' + infoMsg + '</p>').css({ 'display': 'inline-block', 'width': '90%' }); infoBar.append(icon, msg, close); infoBar.prependTo($('.ui-dialog #' + dialogId)); } /** * Set definable image attributes * * @param data Data returned from HTTP request */ function setImageDefAttrs(data) { // Clear hash table containing definable image attributes defAttrs = new Array(); // Get definable attributes var attrs = data.rsp[2].split(/\n/); // Go through each line var attr, key, descr; for (var i in attrs) { attr = attrs[i]; // If the line is not empty if (attr) { // If the line has the attribute name if (attr.indexOf(':') && attr.indexOf(' ')) { // Get attribute name and description key = jQuery.trim(attr.substring(0, attr.indexOf(':'))); descr = jQuery.trim(attr.substring(attr.indexOf(':') + 1)); descr = descr.replace(new RegExp('<', 'g'), '[').replace(new RegExp('>', 'g'), ']'); // Set hash table where key = attribute name and value = description defAttrs[key] = descr; } else { // Append description to hash table defAttrs[key] = defAttrs[key] + '\n' + attr.replace(new RegExp('<', 'g'), '[').replace(new RegExp('>', 'g'), ']'); } } // End of if } // End of for } /** * Load create image page */ function loadCreateImage() { // Get nodes tab var tab = getProvisionTab(); var tabId = 'createImageTab'; // Generate new tab ID if ($('#' + tabId).size()) { tab.select(tabId); return; } var imageOsVers = $.cookie("osvers").split(","); var imageArch = $.cookie("osarchs").split(","); var profiles = $.cookie("profiles").split(","); var createImgForm = $('<div class="form"></div>'); var createImgFS = $('<fieldset></fieldset>').append('<legend>Create Image</legend>'); createImgForm.append(createImgFS); // Show info bar var infoBar = createInfoBar('Specify the parameters for the image (stateless or statelite) you want to create, then click Create.'); createImgFS.append(infoBar); // Drop down for OS versions var osVerSelect = $('<select id="osvers" onchange="hpcShow()"></select>'); for (var i in imageOsVers) osVerSelect.append('<option value="' + imageOsVers[i] + '">' + imageOsVers[i] + '</option>'); createImgFS.append($('<div><label>OS version:</label></div>').append(osVerSelect)); // Drop down for OS architectures var imgSelect = $('<select id="osarch" onchange="hpcShow()"></select>'); for (var i in imageArch) imgSelect.append('<option value="' + imageArch[i] + '">' + imageArch[i] + '</option>'); createImgFS.append($('<div><label>OS architecture:</label></div>').append(imgSelect)); // Netboot interface input createImgFS.append($('<div><label>Netboot interface:</label><input type="text" id="netbootif"/></div>')); // Profile selector var profileSelect = $('<select id="profile" onchange="hpcShow()">'); for (var i in profiles) profileSelect.append('<option value="' + profiles[i] + '">' + profiles[i] + '</option>'); createImgFS.append($('<div><label>Profile:</label></div>').append(profileSelect)); // Boot method drop down createImgFS.append($('<div><label>Boot method:</label>' + '<select id="bootmethod">' + '<option value="stateless">stateless</option>' + '<option value="statelite">statelite</option>' + '</select></div>')); // Create HPC software stack fieldset createHpcFS(createImgForm); // The button used to create images is created here var createImageBtn = createButton("Create"); createImageBtn.bind('click', function(event) { createImage(); }); createImgForm.append(createImageBtn); // Add tab tab.add(tabId, 'Create', createImgForm, true); tab.select(tabId); // Check the selected OS version and OS arch for HPC stack // If they are valid, show the HCP stack fieldset hpcShow(); } /** * Create HPC fieldset * * @param container The container to hold the HPC fieldset */ function createHpcFS(container) { var hpcFieldset = $('<fieldset id="hpcsoft"></fieldset>'); hpcFieldset.append('<legend>HPC Software Stack</legend>'); var str = 'Before selecting the software, you should have the following already completed on your xCAT cluster:<br/><br/>' + '1. If you are using the xCAT hierarchy, your service nodes are installed and running.<br/>' + '2. Your compute nodes are defined in xCAT, and you have verified your hardware control capabilities, ' + 'gathered MAC addresses, and done all the other necessary preparations for a diskless install.<br/>' + '3. You should have a diskless image created with the base OS installed and verified it on at least one test node.<br/>' + '4. You should install the software on the management node and copy all correponding packages into the location "/install/custom/otherpkgs/" based on ' + 'these <a href="http://sourceforge.net/apps/mediawiki/xcat/index.php?title=IBM_HPC_Stack_in_an_xCAT_Cluster" target="_blank">documents</a>.<br/>'; hpcFieldset.append(createInfoBar(str)); // Advanced software str = '<div id="partlysupport"><ul><li id="gpfsli"><input type="checkbox" onclick="softwareCheck(this)" name="gpfs">GPFS</li>' + '<li id="rsctli"><input type="checkbox" onclick="softwareCheck(this)" name="rsct">RSCT</li>' + '<li id="peli"><input type="checkbox" onclick="softwareCheck(this)" name="pe">PE</li>' + '<li id="esslli"><input type="checkbox" onclick="esslCheck(this)" name="essl">ESSl & PESSL</li>' + '</ul></div>' + '<div><ul><li id="gangliali"><input type="checkbox" onclick="softwareCheck(this)" name="ganglia">Ganglia</li>' + '</ul></div>'; hpcFieldset.append(str); container.append($('<div></div>').append(hpcFieldset)); } /** * Check the dependance for ESSL and start the software check for ESSL * * @param softwareObject The checkbox object of ESSL */ function esslCheck(softwareObject) { var softwareName = softwareObject.name; if (!$('#createImageTab input[name=pe]').attr('checked')) { var warnBar = createWarnBar('You must first select the PE'); $(':checkbox[name=essl]').attr("checked", false); // Clear existing warnings and append new warning $('#hpcsoft .ui-state-error').remove(); $('#hpcsoft').prepend(warnBar); return; } else { softwareCheck(softwareObject); } } /** * Check the parameters for the HPC software * * @param softwareObject Checkbox object of the HPC software * @return True if the checkbox is checked, false otherwise */ function softwareCheck(softwareObject) { var softwareName = softwareObject.name; $('#createImageTab #' + softwareName + 'li .ui-state-error').remove(); $('#createImageTab #' + softwareName + 'li').append(createLoader()); var cmdString = genRpmCmd(softwareName); $.ajax( { url : 'lib/systemcmd.php', dataType : 'json', data : { cmd : cmdString, msg : softwareName }, success : function(data) { if (rpmCheck(data.rsp, data.msg)) { genLsCmd(data.msg); $.ajax( { url : 'lib/systemcmd.php', dataType : 'json', data : { cmd : genLsCmd(data.msg), msg : data.msg }, success : rpmCopyCheck }); } } }); } /** * Check if the RPMs are copied to the special location * * @param data Data returned from HTTP request */ function rpmCopyCheck(data) { // Remove the loading image var errorStr = ''; var softwareName = data.msg; // Check the return information var reg = /.+:(.+): No such.*/; var resultArray = data.rsp.split("\n"); for ( var i in resultArray) { var temp = reg.exec(resultArray[i]); if (temp) { // Find out the path and RPM name var pos = temp[1].lastIndexOf('/'); var path = temp[1].substring(0, pos); var rpmName = temp[1].substring(pos + 1).replace('*', ''); errorStr += 'copy ' + rpmName + ' to ' + path + '<br/>'; } } $('#createImageTab #' + softwareName + 'li').find('img').remove(); // No error, show the check image if (!errorStr) { var infoPart = '<div style="display:inline-block; margin:0px"><span class="ui-icon ui-icon-circle-check"></span></div>'; $('#createImageTab #' + softwareName + 'li').append(infoPart); } else { // Show the error message errorStr = 'To install the RSCT on your compute node. You should:<br/>' + errorStr + '</div>'; var warnBar = createWarnBar(errorStr); $(':checkbox[name=' + softwareName + ']').attr("checked", false); // Clear existing warnings and append new warning $('#hpcsoft .ui-state-error').remove(); $('#hpcsoft').prepend(warnBar); } } /** * Generate the RPM command for rpmcheck * * @param softwareName The name of the software * @return The RPM command */ function genRpmCmd(softwareName) { var cmdString; cmdString = 'rpm -q '; for (var i in softwareList[softwareName]) { cmdString += softwareList[softwareName][i] + ' '; } for (var i in softwareList['base']) { cmdString += softwareList['base'][i] + ' '; } return cmdString; } /** * Check if the RPMs for the HPC software are copied to the special location * * @param softwareName The name of the software */ function genLsCmd(softwareName) { var osvers = $('#createImageTab #osvers').val(); var osarch = $('#createImageTab #osarch').val(); var path = '/install/post/otherpkgs/' + osvers + '/' + osarch + '/' + softwareName; var checkCmd = 'ls '; for (var i in softwareList[softwareName]) { checkCmd += path + '/' + softwareList[softwareName][i] + '*.rpm '; } checkCmd += '2>&1'; return checkCmd; } /** * Check if all RPMs are installed * * @param checkInfo 'rpm -q' output * @return True if all RPMs are installed, false otherwise */ function rpmCheck(checkInfo, name) { var errorStr = ''; var checkArray = checkInfo.split('\n'); for (var i in checkArray) { if (checkArray[i].indexOf('not install') != -1) { errorStr += checkArray[i] + '<br/>'; } } if (!errorStr) { return true; } errorStr = errorStr.substr(0, errorStr.length - 1); $(':checkbox[name=' + name + ']').attr('checked', false); // Add the error var warnBar = createWarnBar(errorStr); $('#createImageTab #' + name + 'li').find('img').remove(); // Clear existing warnings and append new warning $('#hpcsoft .ui-state-error').remove(); $('#hpcsoft').prepend(warnBar); return; } /** * Check the option and decide whether to show the hpcsoft or not */ function hpcShow() { // The current UI only supports RHELS 6 // If you want to support all, delete the subcheck if ($('#createImageTab #osvers').attr('value') != "rhels6" || $('#createImageTab #osarch').attr('value') != "ppc64" || $('#createImageTab #profile').attr('value') != "compute") { $('#createImageTab #partlysupport').hide(); } else { $('#createImageTab #partlysupport').show(); } } /** * Load set image properties page * * @param tgtImage Target image to set properties */ function openEditImagePage(tgtImage) { // Get nodes tab var tab = getProvisionTab(); // Generate new tab ID var inst = 0; var newTabId = 'editImageTab' + inst; while ($('#' + newTabId).length) { // If one already exists, generate another one inst = inst + 1; newTabId = 'editImageTab' + inst; } // Open new tab // Create set properties form var setPropsForm = $('<div class="form"></div>'); // Create info bar var infoBar = createInfoBar('Choose the properties you wish to change on the node. When you are finished, click Save.'); setPropsForm.append(infoBar); // Create an input for each definable attribute var div, label, input, value; var attrIndex = 0; // Set node attribute origAttrs[tgtImage]['imagename'] = tgtImage; for (var key in defAttrs) { // If an attribute value exists if (origAttrs[tgtImage][key]) { // Set the value value = origAttrs[tgtImage][key]; } else { value = ''; } // Create label and input for attribute div = $('<div></div>').css('display', 'inline'); label = $('<label>' + key + ':</label>').css('vertical-align', 'middle'); input = $('<input type="text" id="' + key + '" value="' + value + '" title="' + defAttrs[key] + '"/>').css({ 'margin-top': '5px', 'float': 'none', 'width': 'inherit' }); // There is an element called groups that will override the defaults for the groups attribute. // Hence, the input must have use CSS to override the float and width. // Split attributes into 2 per row if (attrIndex > 0 && !(attrIndex % 2)) { div.css('display', 'inline-block'); } attrIndex++; // Create server browser switch (key) { case 'pkgdir': input.serverBrowser({ onSelect : function(path) { $('#pkgdir').val(path); }, onLoad : function() { return $('#pkgdir').val(); }, knownExt : [ 'exe', 'js', 'txt' ], knownPaths : [{ text : 'Install', image : 'desktop.png', path : '/install' }], imageUrl : 'images/serverbrowser/', systemImageUrl : 'images/serverbrowser/', handlerUrl : 'lib/getpath.php', title : 'Browse', requestMethod : 'POST', width : '500', height : '300', basePath : '/install' // Limit user to only install directory }); break; case 'otherpkgdir': input.serverBrowser({ onSelect : function(path) { $('#otherpkgdir').val(path); }, onLoad : function() { return $('#otherpkgdir').val(); }, knownExt : [ 'exe', 'js', 'txt' ], knownPaths : [{ text : 'Install', image : 'desktop.png', path : '/install' }], imageUrl : 'images/serverbrowser/', systemImageUrl : 'images/serverbrowser/', handlerUrl : 'lib/getpath.php', title : 'Browse', requestMethod : 'POST', width : '500', height : '300', basePath : '/install' // Limit user to only install directory }); break; case 'pkglist': input.serverBrowser({ onSelect : function(path) { $('#pkglist').val(path); }, onLoad : function() { return $('#pkglist').val(); }, knownExt : [ 'exe', 'js', 'txt' ], knownPaths : [{ text : 'Install', image : 'desktop.png', path : '/install' }], imageUrl : 'images/serverbrowser/', systemImageUrl : 'images/serverbrowser/', handlerUrl : 'lib/getpath.php', title : 'Browse', requestMethod : 'POST', width : '500', height : '300', basePath : '/opt/xcat/share' // Limit user to only install directory }); break; case 'otherpkglist': input.serverBrowser({ onSelect : function(path) { $('#otherpkglist').val(path); }, onLoad : function() { return $('#otherpkglist').val(); }, knownExt : [ 'exe', 'js', 'txt' ], knownPaths : [{ text : 'Install', image : 'desktop.png', path : '/install' }], imageUrl : 'images/serverbrowser/', systemImageUrl : 'images/serverbrowser/', handlerUrl : 'lib/getpath.php', title : 'Browse', requestMethod : 'POST', width : '500', height : '300', basePath : '/install' // Limit user to only install directory }); break; case 'template': input.serverBrowser({ onSelect : function(path) { $('#template').val(path); }, onLoad : function() { return $('#template').val(); }, knownExt : [ 'exe', 'js', 'txt' ], knownPaths : [{ text : 'Install', image : 'desktop.png', path : '/install' }], imageUrl : 'images/serverbrowser/', systemImageUrl : 'images/serverbrowser/', handlerUrl : 'lib/getpath.php', title : 'Browse', requestMethod : 'POST', width : '500', height : '300', basePath : '/opt/xcat/share' // Limit user to only install directory }); break; default: // Do nothing } // Change border to blue onchange input.bind('change', function(event) { $(this).css('border-color', 'blue'); }); div.append(label, input); setPropsForm.append(div); } // Change style for last division div.css({ 'display': 'block', 'margin': '0px 0px 10px 0px' }); // Generate tooltips setPropsForm.find('div input[title]').tooltip({ position: "center right", offset: [-2, 10], effect: "fade", opacity: 0.8, delay: 500, predelay: 800, events: { def: "mouseover,mouseout", input: "mouseover,mouseout", widget: "focus mouseover,blur mouseout", tooltip: "mouseover,mouseout" } }); /** * Save */ var saveBtn = createButton('Save'); saveBtn.bind('click', function(event) { // Get all inputs var inputs = $('#' + newTabId + ' input'); // Go through each input var args = ''; var attrName, attrVal; inputs.each(function(){ // If the border color is blue if ($(this).css('border-left-color') == 'rgb(0, 0, 255)') { // Change border color back to normal $(this).css('border-color', ''); // Get attribute name and value attrName = $(this).parent().find('label').text().replace(':', ''); attrVal = $(this).val(); // Build argument string if (args) { // Handle subsequent arguments args += ';' + attrName + '=' + attrVal; } else { // Handle the 1st argument args += attrName + '=' + attrVal; } } }); // Send command to change image attributes $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'chdef', tgt : '', args : '-t;osimage;-o;' + tgtImage + ';' + args, msg : 'out=' + newTabId + ';tgt=' + tgtImage }, success: showChdefOutput }); }); setPropsForm.append(saveBtn); /** * Cancel */ var cancelBtn = createButton('Cancel'); cancelBtn.bind('click', function(event) { // Close the tab tab.remove($(this).parent().parent().attr('id')); }); setPropsForm.append(cancelBtn); // Append to discover tab tab.add(newTabId, 'Edit', setPropsForm, true); // Select new tab tab.select(newTabId); } /** * Load copy CD page */ function openCopyCdDialog() { // Create copy Linux form var dialogId = 'imageCopyCd'; var copyLinuxForm = $('<div id="' + dialogId + '" class="form"></div>'); // Create info bar var infoBar = createInfoBar('Copy Linux distributions and service levels from CDs or DVDs to the install directory.'); copyLinuxForm.append(infoBar); // Create Linux ISO input var iso = $('<div></div>'); var isoLabel = $('<label> Linux ISO/DVD:</label>').css('vertical-align', 'middle'); var isoInput = $('<input type="text" id="iso" name="iso" title="The fully qualified name of the disk image file"/>').css('width', '300px'); iso.append(isoLabel); iso.append(isoInput); copyLinuxForm.append(iso); // Create architecture input copyLinuxForm.append('<div><label>Architecture:</label><input type="text" id="arch" name="arch" title="The hardware architecture of this node. Valid values: x86_64, x86, ia64, ppc64, and s390x."/></div>'); // Create distribution input copyLinuxForm.append('<div><label>Distribution:</label><input type="text" id="distro" name="distro" title="The operating system name. Valid values: rhel*, centos*, fedora*, sles* (where * is the version #)."/></div>'); /** * Browse */ var browseBtn = createButton('Browse'); iso.append(browseBtn); // Browse server directory and files browseBtn.serverBrowser({ onSelect : function(path) { $('#imageCopyCd #iso').val(path); }, onLoad : function() { return $('#imageCopyCd #iso').val(); }, knownExt : [ 'exe', 'js', 'txt' ], knownPaths : [ { text : 'Install', image : 'desktop.png', path : '/install' } ], imageUrl : 'images/serverbrowser/', systemImageUrl : 'images/serverbrowser/', handlerUrl : 'lib/getpath.php', title : 'Browse', requestMethod : 'POST', width : '500', height : '300', basePath : '/install' // Limit user to only install directory }); // Generate tooltips copyLinuxForm.find('div input[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 copy CD copyLinuxForm.dialog({ title:'Copy CD', close: function(){ $(this).remove(); }, modal: true, width: 600, buttons: { "Copy": function() { // Show loader $('.ui-dialog #imageCopyCd').append(createLoader('')); // Change dialog buttons $(this).dialog('option', 'buttons', { 'Close': function() {$(this).dialog("close");} }); // Get image attributes var iso = $(this).find('input[name="iso"]'); var arch = $(this).find('input[name="arch"]'); var distro = $(this).find('input[name="distro"]'); // Send ajax request to copy ISO $.ajax({ url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'copycds', tgt : '', args : '-n;' + distro.val() + ';-a;' + arch.val() + ';' + iso.val(), msg : dialogId }, success : updateImageDialog }); }, "Cancel": function() { $(this).dialog( "close" ); } } }); } /** * Use user input or select to create image */ function createImage() { var osvers = $("#createImageTab #osvers").val(); var osarch = $("#createImageTab #osarch").val(); var profile = $("#createImageTab #profile").val(); var bootInterface = $("#createImageTab #netbootif").val(); var bootMethod = $("#createImageTab #bootmethod").val(); $('#createImageTab .ui-state-error').remove(); // If there no input for the bootInterface if (!bootInterface) { var warnBar = createWarnBar('Please specify the netboot interface'); $("#createImageTab").prepend(warnBar); return; } var createImageArgs = "createimage;" + osvers + ";" + osarch + ";" + profile + ";" + bootInterface + ";" + bootMethod + ";"; $("#createImageTab :checkbox:checked").each(function() { createImageArgs += $(this).attr("name") + ","; }); createImageArgs = createImageArgs.substring(0, (createImageArgs.length - 1)); $.ajax({ url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'webrun', tgt : '', args : createImageArgs, msg : '' }, success : function(data) { } }); }