/** * 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 = $('
'); $('#' + tabId).append(infoBar, servicePg); // Create radio buttons for platforms var hwList = $('
    Platforms available:
'); var esx = $('
  • ESX
  • '); var kvm = $('
  • KVM
  • '); var zvm = $('
  • z\/VM
  • '); 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('srv_zvm')){ $.ajax( { url : 'lib/srv_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); } /** * Load the user panel where users can be created, modified, or deleted * * @param panelId Panel ID */ function loadUserPanel(panelId) { // Get users list $.ajax({ url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'tabdump', tgt : '', args : 'passwd', msg : panelId }, success : loadUserTable }); } /** * Load user datatable * * @param data HTTP request data */ function loadUserTable(data) { // Get response var rsp = data.rsp; // Get panel ID var panelId = data.msg; // Wipe panel clean $('#' + panelId).empty(); // Add info bar $('#' + panelId).append(createInfoBar('Create, edit, and delete users for the self-service portal. Double-click on a cell to edit a users properties. Click outside the table to save changes. Hit the Escape key to ignore changes.')); // Get table headers // The table headers in the passwd table are: key, username, password, cryptmethod, comments, and disable var headers = new Array('priority', 'username', 'password', 'max-vm'); // Create a new datatable var tableId = panelId + 'Datatable'; var table = new DataTable(tableId); // Add column for the checkbox headers.unshift(''); table.init(headers); headers.shift(); // Append datatable to panel $('#' + panelId).append(table.object()); // Add table rows // Start with the 2nd row (1st row is the headers) for ( var i = 1; i < rsp.length; i++) { // Split into columns var tmp = rsp[i].split(','); // Go through each column for (var j = 0; j < tmp.length; j++) { // Replace quote tmp[j] = tmp[j].replace(new RegExp('"', 'g'), ''); } // Only add users having the key = xcat if (tmp[0] == 'xcat') { // Columns are: priority, username, password, and max-vm var cols = new Array('', tmp[1], tmp[2], ''); // Add remove button where id = user name cols.unshift(''); // Add row table.add(cols); } } // Turn table into datatable $('#' + tableId).dataTable({ 'iDisplayLength': 50, 'bLengthChange': false, "sScrollX": "100%", "bAutoWidth": true }); // Create action bar var actionBar = $('
    '); var createLnk = $('Create'); createLnk.click(function() { openCreateUserDialog(); }); var deleteLnk = $('Delete'); deleteLnk.click(function() { var users = getNodesChecked(tableId); if (users) { openDeleteUserDialog(users); } }); var refreshLnk = $('Refresh'); refreshLnk.click(function() { loadUserPanel(panelId); }); // Create an action menu var actionsMenu = createMenu([createLnk, deleteLnk, refreshLnk]); 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 = $(''); $('#' + tableId + '_wrapper').prepend(menuDiv); menuDiv.append(actionBar); $('#' + tableId + '_filter').appendTo(menuDiv); // Get policy data $.ajax({ url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'tabdump', tgt : '', args : 'policy', msg : tableId }, success : loadUserTable4Policy }); /** * Enable editable cells */ // Do not make 1st or 2nd column editable $('#' + tableId + ' td:not(td:nth-child(1),td:nth-child(2))').editable( function(value, settings) { // If users did not make changes, return the value directly // jeditable saves the old value in this.revert if ($(this).attr('revert') == value){ return value; } var panelId = $(this).parents('.ui-accordion-content').attr('id'); // Get column index var colPos = this.cellIndex; // Get row index var dTable = $('#' + tableId).dataTable(); var rowPos = dTable.fnGetPosition(this.parentNode); // Update datatable dTable.fnUpdate(value, rowPos, colPos, false); // Get table headers var headers = $('#' + nodesTableId).parents('.dataTables_scroll').find('.dataTables_scrollHead thead tr:eq(0) th'); // Get user attributes var priority = $(this).parent().find('td:eq(1)').text(); var user = $(this).parent().find('td:eq(2)').text(); var password = $(this).parent().find('td:eq(3)').text(); var maxVM = $(this).parent().find('td:eq(4)').text(); // Send command to change user attributes $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'webrun', tgt : '', args : 'updateuser;' + priority + ';' + user + ';' + password + ';' + maxVM, msg : panelId }, success : updatePanel }); return value; }, { onblur : 'submit', // Clicking outside editable area submits changes type : 'textarea', placeholder: ' ', event : "dblclick", // Double click and edit height : '30px' // The height of the text area }); // Resize accordion $('#' + tableId).parents('.ui-accordion').accordion('resize'); } /** * Update user datatable for policy * * @param data HTTP request data */ function loadUserTable4Policy(data) { // Get response var rsp = data.rsp; // Get datatable ID var tableId = data.msg; // Get datatable var datatable = $('#' + tableId).dataTable(); // Update max-vm column // The data coming back contains: priority, name, host, commands, noderange, parameters, time, rule, comments, disable // Start with the 2nd row (1st row is the headers) topPriority = 0; for (var i = 1; i < rsp.length; i++) { // Split into columns var tmp = rsp[i].split(','); // Go through each column for (var j = 0; j < tmp.length; j++) { // Replace quote tmp[j] = tmp[j].replace(new RegExp('"', 'g'), ''); } // Get the row containing the user name var rowPos = -1; if (tmp[1]) rowPos = findRow(tmp[1], '#' + tableId, 2); // Update the priority and max-vm columns if (rowPos > -1) { var maxVM = 0; var comments = tmp[8].split(';'); for (var k in comments) { if (comments[k].indexOf('max-vm:') > -1) maxVM = comments[k].replace('max-vm:', ''); } datatable.fnUpdate(maxVM, rowPos, 4, false); var priority = tmp[0]; datatable.fnUpdate(priority, rowPos, 1, false); // Set the highest priority if (priority > topPriority) topPriority = priority; } } // Adjust column sizes adjustColumnSize(tableId); // Resize accordion $('#' + tableId).parents('.ui-accordion').accordion('resize'); } /** * Open a dialog to create a user */ function openCreateUserDialog() { var dialogId = 'createUser'; var dialog = $('
    '); var info = createInfoBar('Create an xCAT user. A priority will be generated for the new user.'); dialog.append(info); // Generate the user priority var userPriority = parseFloat(topPriority) + 0.01; userPriority = userPriority.toPrecision(3); // Create node inputs dialog.append($('
    ')); dialog.append($('
    ')); dialog.append($('
    ')); dialog.append($('
    ')); dialog.dialog({ title: 'Create user', modal: true, width: 400, close: function(){ $(this).remove(); }, buttons: { "OK" : function(){ // Remove any warning messages $(this).find('.ui-state-error').remove(); // Change dialog buttons $('#' + dialogId).dialog('option', 'buttons', { 'Close':function(){ $(this).dialog('close'); } }); var priority = $(this).find('input[name="priority"]').val(); var user = $(this).find('input[name="username"]').val(); var password = $(this).find('input[name="password"]').val(); var maxVM = $(this).find('input[name="maxvm"]').val(); // Verify inputs are provided if (!user || !password || !maxVM) { var warn = createWarnBar('Please provide a value for each missing field!'); warn.prependTo($(this)); } else { $.ajax( { url : 'lib/cmd.php', dataType : 'json', data : { cmd : 'webrun', tgt : '', args : 'updateuser;' + priority + ';' + user + ';' + password + ';' + maxVM, msg : dialogId }, success : updatePanel }); // Update highest priority topPriority = priority; } }, "Cancel": function(){ $(this).dialog('close'); } } }); } /** * Update dialog * * @param data HTTP request data */ function updatePanel(data) { var dialogId = data.msg; var infoMsg; // Create info message if (jQuery.isArray(data.rsp)) { infoMsg = ''; for (var i in data.rsp) { infoMsg += data.rsp[i] + '
    '; } } else { infoMsg = data.rsp; } // Create info bar with close button var infoBar = $('
    ').css('margin', '5px 0px'); var icon = $('').css({ 'display': 'inline-block', 'margin': '10px 5px' }); // Create close button to close info bar var close = $('').css({ 'display': 'inline-block', 'float': 'right' }).click(function() { $(this).parent().remove(); }); var msg = $('
    ' + infoMsg + '
    ').css({ 'display': 'inline-block', 'width': '85%' }); infoBar.append(icon, msg, close); infoBar.prependTo($('#' + dialogId)); } /** * Open dialog to confirm user delete * * @param users Users to delete */ function openDeleteUserDialog(users) { // Create form to delete disk to pool var dialogId = 'deleteUser'; var deleteForm = $('
    '); // Create info bar var info = createInfoBar('Are you sure you want to delete ' + users.replace(new RegExp(',', 'g'), ', ') + '?'); deleteForm.append(info); // Open dialog to delete user deleteForm.dialog({ title:'Delete user', 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 : 'deleteuser;' + users, msg : dialogId }, success : updatePanel }); }, "Cancel": function() { $(this).dialog( "close" ); } } }); } /** * 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(['', '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(''); // Add row table.add(cols); } } // Append datatable to tab $('#' + panelId).append(table.object()); // Turn into datatable $('#' + tableId).dataTable({ 'iDisplayLength': 50, 'bLengthChange': false, "sScrollX": "100%", "bAutoWidth": true }); // Create action bar var actionBar = $('
    '); // Create a profile var createLnk = $('Create'); createLnk.click(function() { imageDialog(); }); // Edit a profile var editLnk = $('Edit'); 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 = $('Delete'); deleteLnk.click(function() { var images = getNodesChecked(tableId); if (images) { deleteImageDialog(images); } }); // Refresh profiles table var refreshLnk = $('Refresh'); refreshLnk.click(function() { queryImages(panelId); }); // Create an action menu var actionsMenu = createMenu([createLnk, editLnk, deleteLnk, refreshLnk]); 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 = $(''); $('#' + 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 = $('
    '); // 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 = $('
    '); var selectable = $('
    '); var imageType = $('
    '); var architecture = $('
    '); var osName = $('
    '); var osVersion = $('
    '); var profile = $('
    '); var provisionMethod = $('
    '); var provisionSelect = $(''); provisionMethod.append(provisionSelect); var comments = $('
    '); imageForm.append(imageName, selectable, imageType, architecture, osName, osVersion, profile, provisionMethod, comments); // 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) { // Create form to add profile var dialogId = 'editImage'; var imageForm = $('
    '); // 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 = $('
    '); var selectable = $('
    '); var imageType = $('
    '); var architecture = $('
    '); var osName = $('
    '); var osVersion = $('
    '); var profile = $('
    '); var provisionMethod = $('
    '); var provisionSelect = $(''); provisionMethod.append(provisionSelect); var comments = $('
    '); 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'); // 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 = $('
    '); // 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(['', 'Name', 'Selectable', 'IP', 'Hostname', 'Network', '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); } // Save network if (tmp[j].indexOf('network:') > -1) { network = tmp[j].replace('network:', ''); network = jQuery.trim(network); } // 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, network, desc); // Add remove button where id = user name cols.unshift(''); // Add row table.add(cols); } // Append datatable to tab $('#' + panelId).append(table.object()); // Turn into datatable $('#' + tableId).dataTable({ 'iDisplayLength': 50, 'bLengthChange': false, "sScrollX": "100%", "bAutoWidth": true }); // Create action bar var actionBar = $('
    '); // Create a group var createLnk = $('Create'); createLnk.click(function() { groupDialog(); }); // Edit a group var editLnk = $('Edit'); 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 network = cols.eq(5).text(); var description = cols.eq(6).text(); editGroupDialog(group, selectable, ip, hostnames, network, description); } } }); // Delete a profile var deleteLnk = $('Delete'); deleteLnk.click(function() { var groups = getNodesChecked(tableId); if (groups) { deleteGroupDialog(groups); } }); // Refresh profiles table var refreshLnk = $('Refresh'); refreshLnk.click(function() { queryGroups(panelId); }); // Create an action menu var actionsMenu = createMenu([createLnk, editLnk, deleteLnk, refreshLnk]); 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 = $(''); $('#' + 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 = $('
    '); // Create info bar var info = createInfoBar('Provide the following attributes for the group.'); groupForm.append(info); var group = $('
    '); var selectable = $('
    '); var ip = $('
    '); var hostnames = $('
    '); var network = $('
    '); var comments = $('
    '); groupForm.append(group, selectable, ip, hostnames, network, comments); // Open dialog to add image groupForm.dialog({ title:'Create group', modal: true, close: function(){ $(this).remove(); }, width: 400, 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 network = $(this).find('input[name="network"]'); var comments = $(this).find('input[name="comments"]'); // Check that group attributes are provided before continuing var ready = 1; var inputs = new Array(group, ip, hostnames, network); 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");} }); // 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() + "|network:" + network.val() + "|selectable:yes"; else args += "'description:" + comments.val() + "|network:" + network.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 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 iNetwork Group network, e.g. 10.1.2.0/24 * @param iComments Group description */ function editGroupDialog(iGroup, iSelectable, iIp, iHostnames, iNetwork, iComments) { // Create form to add profile var dialogId = 'createGroup'; var groupForm = $('
    '); // Create info bar var info = createInfoBar('Provide the following attributes for the group.'); groupForm.append(info); var group = $('
    '); var selectable = $('
    '); var ip = $('
    '); var hostnames = $('
    '); var network = $('
    '); var comments = $('
    '); groupForm.append(group, selectable, ip, hostnames, network, comments); // 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="network"]').val(iNetwork); groupForm.find('input[name="comments"]').val(iComments); if (iSelectable == "yes") groupForm.find('input[name="selectable"]').attr('checked', 'checked'); // Open dialog to add image groupForm.dialog({ title:'Edit group', modal: true, close: function(){ $(this).remove(); }, width: 400, 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 network = $(this).find('input[name="network"]'); var comments = $(this).find('input[name="comments"]'); // Check that group attributes are provided before continuing var ready = 1; var inputs = new Array(group, ip, hostnames, network); 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");} }); // 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() + "|network:" + network.val() + "|selectable:yes"; else args += "'description:" + comments.val() + "|network:" + network.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 group delete * * @param groups Groups to delete */ function deleteGroupDialog(groups) { // Create form to delete disk to pool var dialogId = 'deleteImage'; var deleteForm = $('
    '); // 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" ); } } }); }