");
+ }
+ // Show the status bar with a message and loading gif
+ $('#'+'zProvisionStatBar'+inst).find('div').append("Loading zhcp information... ");
+ $('#'+'zProvisionStatBar'+inst).find('div').append(" ");
+ $('#'+'zProvisionStatBar'+inst).show();
+
+ // list of calls after the zhcp is verified. Used to determine when in progress gif is to be removed.
+ var ajaxCalls = {"diskpoolnames":1, "zfcppoolnames":1, "userprofilenames":1};
+ var zhcpToCheck = $(this).val();
+ var zhcpField = $(this);
+ var provisionStatusBar = $('#'+'zProvisionStatBar'+inst);
+
+ // Make sure border is set back to black
+ zhcpField.css('border', 'solid #BDBDBD 1px');
+
+ if ($(this).val()) {
+ // Check if this is a valid node by making network names call.
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'lsvm',
+ tgt : zhcpToCheck,
+ args : '--getnetworknames',
+ msg : zhcpToCheck
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ if (data.rsp.length && (data.rsp[0].indexOf("Failed") > -1 || data.rsp[0].indexOf("Invalid") > -1 || data.rsp[0].indexOf("Error") > -1 ) ) {
+ // Remove the progress gif, since bailing out
+ removeProvisionLoadingGif(provisionStatusBar);
+
+ // Create warning dialog
+ var warning = createWarnBar('Failure getting network data for hardware control point ' + zhcpToCheck + ' The hcp field must be a xCAT node name.');
+ var warnDialog = $('
').append(warning);
+
+ // highlight the hcp field
+ zhcpField.css('border', 'solid #FF0000 1px');
+
+ // Open warning dialog
+ warnDialog.dialog({
+ title:'Warning',
+ modal: true,
+ close: function(){
+ $(this).remove();
+ },
+ width: 400,
+ buttons: {
+ "Ok": function() {
+ $(this).dialog("close");
+ }
+ }
+ });
+
+ } else {
+ // Node is good, now set some cookies from network, then check/set other cookies
+ setNetworkCookies(data);
+
+ // Get the HCP name from the hcp node name
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'lsdef',
+ tgt : '',
+ args : zhcpToCheck,
+ msg : 'zhcpFullName'
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ if (data.rsp.length && (data.rsp[0].indexOf("Failed") > -1 || data.rsp[0].indexOf("Invalid") > -1) ) {
+ // Remove the progress gif, since bailing out
+ removeProvisionLoadingGif(provisionStatusBar);
+
+ // Create warning dialog
+ var warning = createWarnBar('Failure getting hcp data from hardware control point ' + zhcpToCheck + ' The hcp field must be a valid xCAT node name.');
+ var warnDialog = $('
').append(warning);
+
+ // highlight the hcp field
+ zhcpField.css('border', 'solid #FF0000 1px');
+
+ // Open warning dialog
+ warnDialog.dialog({
+ title:'Warning',
+ modal: true,
+ close: function(){
+ $(this).remove();
+ },
+ width: 400,
+ buttons: {
+ "Ok": function() {
+ $(this).dialog("close");
+ }
+ }
+ });
+ } else {
+ // Now set the hidden hcp field with the full name
+ // Clear hash table containing definable node attributes
+ nodeAttrs = new Array();
+
+ // Get definable attributes
+ // Data returned
+ var rsp = data.rsp;
+ // Group name
+ var group = data.msg;
+ // Hash of node attributes
+ var attrs = new Object();
+
+ // Go through each attribute
+ var node, args;
+ for (var i in rsp) {
+ // Get node name, skip processing
+ if (rsp[i].indexOf('Object name:') > -1) {
+ i++;
+ }
+
+ // Get key and value
+ args = rsp[i].split('=', 2);
+ var key = jQuery.trim(args[0]);
+ var val = jQuery.trim(rsp[i].substring(rsp[i].indexOf('=') + 1, rsp[i].length));
+
+ // If this is zhcp key then save full name in hidden field
+ if (key == "hcp") {
+ hcpHiddenInput.val(val);
+ }
+
+ }
+
+ }
+ }
+ });
+
+ if (typeof console == "object"){
+ console.log("Looking for cookies from <" + zhcpToCheck + ">");
+ }
+
+ if (!$.cookie('xcat_' + zhcpToCheck + 'diskpools')) {
+ // Get disk pools
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'lsvm',
+ tgt : zhcpToCheck,
+ args : '--diskpoolnames',
+ msg : zhcpToCheck
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ setDiskPoolCookies(data);
+ },
+ complete : function() {
+ checkProvisionCallsDone(provisionStatusBar, ajaxCalls, "diskpoolnames");
+ }
+ });
+ } else {
+ checkProvisionCallsDone(provisionStatusBar, ajaxCalls, "diskpoolnames");
+ }
+
+ if (!$.cookie('xcat_' + zhcpToCheck + 'zfcppools')) {
+ // Get zFCP pools
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'lsvm',
+ tgt : zhcpToCheck,
+ args : '--zfcppoolnames',
+ msg : zhcpToCheck
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ setZfcpPoolCookies(data);
+ },
+ complete : function() {
+ checkProvisionCallsDone(provisionStatusBar, ajaxCalls, "zfcppoolnames");
+ }
+ });
+ } else {
+ checkProvisionCallsDone(provisionStatusBar, ajaxCalls, "zfcppoolnames");
+ }
+
+ if (!$.cookie('xcat_' + zhcpToCheck + 'userprofiles')) {
+ // Get zFCP pools
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ async: false,
+ data : {
+ cmd : 'lsvm',
+ tgt : zhcpToCheck,
+ args : '--userprofilenames',
+ msg : zhcpToCheck
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ setUserProfilesCookies(data);
+ },
+ complete : function() {
+ checkProvisionCallsDone(provisionStatusBar, ajaxCalls, "userprofilenames");
+ }
+ });
+ } else {
+ checkProvisionCallsDone(provisionStatusBar, ajaxCalls, "userprofilenames");
+ }
+
+ // Reset user profile and network drop down box
+ var thisTabId = zhcpField.parents('.tab').attr('id');
+ var thisUserProfile = $('#' + thisTabId + ' select[name=userProfile]');
+ thisUserProfile.children().remove();
+
+ var definedUserProfiles = $.cookie('xcat_' + zhcpToCheck + 'userprofiles').split(',');
+ for (var i in definedUserProfiles) {
+ if( !definedUserProfiles[i] || 0 === definedUserProfiles[i].length) continue;
+ thisUserProfile.append('' + definedUserProfiles[i] + ' ');
+ }
+
+ var thisNetwork = $('#' + thisTabId + ' select[name=network]');
+ thisNetwork.children().remove();
+ thisNetwork.append(' '); // No profile option
+ var definedNetworks = $.cookie('xcat_' + zhcpToCheck + 'networks').split(',');
+ for (var i in definedNetworks) {
+ if( !definedNetworks[i] || 0 === definedNetworks[i].length) continue;
+ if (!jQuery.trim(definedNetworks[i]))
+ continue;
+
+ var directoryEntry, interfaceName;
+
+ // Generate directory entry statement for vSwitch, hipersocket, and guest LAN
+ if (definedNetworks[i].indexOf('VSWITCH ') != -1) {
+ interfaceName = jQuery.trim(definedNetworks[i].replace('VSWITCH ', ''));
+ directoryEntry = "TYPE QDIO LAN " + interfaceName;
+ } else if (definedNetworks[i].indexOf('LAN:HIPERS ') != -1) {
+ interfaceName = jQuery.trim(definedNetworks[i].replace('LAN:HIPERS ', ''));
+ directoryEntry = "TYPE HIPERSOCKETS LAN " + interfaceName;
+ } else {
+ interfaceName = jQuery.trim(definedNetworks[i].replace('LAN:QDIO ', ''));
+ directoryEntry = "TYPE QDIO LAN " + interfaceName;
+ }
+
+ thisNetwork.append('' + definedNetworks[i] + ' ');
+ }
+
+ // Update user entry on change
+ thisNetwork.change(function() {
+ updateUserEntry(thisTabId);
+ });
+
+ thisUserProfile.change(function() {
+ updateUserEntry(thisTabId);
+ });
+ }
+ }
+ });
+ }
+ });
+ hcpDiv.append(hcpNodeLabel);
+ hcpDiv.append(hcpNodeInput);
+ hcpDiv.append(hcpHiddenInput);
+ vmAttr.append(hcpDiv);
+
+ // Create an advanced link to set IP address and hostname
+ var advancedLnk = $('');
+ vmAttr.append(advancedLnk);
+ var advanced = $('
').hide();
+ vmAttr.append(advanced);
+
+ var ip = $('IP address:
');
+ advanced.append(ip);
+ var hostname = $('Hostname:
');
+ advanced.append(hostname);
+
+ // Show IP address and hostname inputs on-click
+ advancedLnk.click(function() {
+ advanced.toggle();
+ });
+
+ // Create operating system image input
+ var os = $('
');
+ var osLabel = $('Operating system image: ');
+ var osSelect = $(' ');
+ osSelect.append($(' '));
+
+ var imageNames = $.cookie('xcat_imagenames').split(',');
+ if (imageNames) {
+ imageNames.sort();
+ for (var i in imageNames) {
+ if( !imageNames[i] || 0 === imageNames[i].length) continue;
+ osSelect.append($('' + imageNames[i] + ' '));
+ }
+ }
+ os.append(osLabel);
+ os.append(osSelect);
+ osAttr.append(os);
+
+ // Create user entry input
+ var defaultChkbox = $(' ').click(function() {
+ // Remove any warning messages
+ $(this).parents('.form').find('.ui-state-error').remove();
+
+ // Get tab Id
+ var thisTabId = $(this).parents('.ui-tabs-panel').parents('.ui-tabs-panel').attr('id');
+
+ // Get objects for HCP, user ID, and OS
+ var userId = $('#' + thisTabId + ' input[name=userId]');
+ var os = $('#' + thisTabId + ' select[name=os]');
+
+ // Get default user entry when clicked
+ if ($(this).attr('checked')) {
+ if (!os.val() || !userId.val()) {
+ // Show warning message
+ var warn = createWarnBar('Please specify the operating system and user ID before checking this box');
+ warn.prependTo($(this).parents('.form'));
+
+ // Highlight empty fields
+ jQuery.each([os, userId], function() {
+ if (!$(this).val()) {
+ $(this).css('border', 'solid #FF0000 1px');
+ }
+ });
+ } else {
+ // Un-highlight empty fields
+ jQuery.each([os, userId], function() {
+ $(this).css('border', 'solid #BDBDBD 1px');
+ });
+
+ // Get profile name
+ var tmp = os.val().split('-');
+ var profile = tmp[3];
+
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'getdefaultuserentry;' + profile,
+ msg : thisTabId
+ },
+
+ success :function(data) {
+ data = decodeRsp(data);
+ // Populate user entry
+ var tabId = data.msg;
+ var entry = new String(data.rsp);
+ var userId = $('#' + tabId + ' input[name=userId]').val();
+ entry = entry.replace(new RegExp('LXUSR', 'g'), userId);
+ $('#' + tabId + ' textarea:visible').val(entry);
+ }
+ });
+ }
+ } else {
+ $('#' + thisTabId + ' textarea:visible').val('');
+
+ // Un-highlight empty fields
+ jQuery.each([os, userId], function() {
+ $(this).css('border', 'solid #BDBDBD 1px');
+ });
+ }
+ });
+ var userEntry = $('Directory entry:
');
+ userEntry.append($(' ').append(defaultChkbox, 'Use default'));
+
+ // Add division on basic tab for specifying: memory, # of CPUs, privilege, user profile, and network.
+ var basicConfig = $('
');
+ var userProfile = $('z/VM profile: ' +
+ 'Select a hardware control point ' +
+ '
');
+ var cpuSelect = $('' +
+ '1 ' +
+ '2 ' +
+ '3 ' +
+ '4 ' +
+ '5 ' +
+ '6 ' +
+ '7 ' +
+ '8 ' +
+ ' ').change(function() {
+ updateUserEntry('zvmProvisionTab' + inst);
+ });
+ var cpuCount = $('CPU count:
').append(cpuSelect);
+ var memorySlider = $('
');
+ var memorySize = $(' ');
+ var memory = $('Memory size:
').append(memorySlider, memorySize);
+ var acceptableMemorySize = ['512M', '1024M', '2G', '3G', '4G', '5G', '6G', '7G', '8G'];
+ memorySlider.slider({
+ value: 0,
+ min: 0,
+ max: 8,
+ step: 1,
+ slide: function(event, ui) {
+ $('#basicConfig' + inst + ' input[name=memory]').val(acceptableMemorySize[ui.value]);
+
+ // Update user entry on change
+ updateUserEntry('zvmProvisionTab' + inst);
+ }
+ });
+
+ // Initialize storage size
+ memorySize.val(acceptableMemorySize[0]);
+
+ var privilege = $('');
+ privilege.find('input').change(function() {
+ updateUserEntry('zvmProvisionTab' + inst);
+ });
+
+ var network = $('Network interface: ' +
+ 'Select a hardware control point ' +
+ '
');
+
+ var vswitchvlan = $(' Vswitch GRANT details. Porttype: ' +
+ 'default ' +'ACCESS ' + 'TRUNK ' + ' ' +
+ 'VLAN id: ' +
+ '
');
+ vswitchvlan.find('input').change(function() {
+ updateUserEntry('zvmProvisionTab' + inst);
+ });
+ vswitchvlan.find('select').change(function() {
+ updateUserEntry('zvmProvisionTab' + inst);
+ });
+
+ vswitchvlan.hide();
+ basicConfig.append(userProfile, cpuCount, memory, privilege, network, vswitchvlan);
+ hwTab.add('basicConfig' + inst, 'Basic', basicConfig, false);
+
+ // Add division on advanced tab for specifying user directory entry
+ hwTab.add('advancedConfig' + inst, 'Advanced', userEntry, false);
+
+ // Create disk table
+ var diskDiv = $('
');
+ var diskLabel = $('Disks: ');
+ var diskTable = $('');
+ var diskHeader = $('');
+ // Adjust header width
+ diskHeader.find('th').css( {
+ 'width' : '80px'
+ });
+ diskHeader.find('th').eq(0).css( {
+ 'width' : '20px'
+ });
+ var diskBody = $(' ');
+ var diskFooter = $(' ');
+
+ /**
+ * Add disks
+ */
+ var addDiskLink = $('Add disk ');
+ addDiskLink.bind('click', function(event) {
+ // Get list of disk pools
+ var thisTabId = $(this).parents('.tab').attr('id');
+ var thisHcp = $('#' + thisTabId + ' input[name=hcp]').val();
+ var definedPools = null;
+ if (thisHcp) {
+ // Get node without domain name
+ var temp = thisHcp.split('.');
+ definedPools = $.cookie('xcat_' + temp[0] + 'diskpools').split(',');
+ } else {
+ var warning = createWarnBar('You must fill in a hardware control point before adding a disk.');
+ var warnDialog = $('
').append(warning);
+
+ // Open dialog
+ warnDialog.dialog({
+ title:'Warning',
+ modal: true,
+ close: function(){
+ $(this).remove();
+ },
+ width: 400,
+ buttons: {
+ "Ok": function() {
+ $(this).dialog("close");
+ }
+ }
+ });
+ return false;
+ }
+
+ // Create a row
+ var diskRow = $(' ');
+
+ // Add remove button
+ var removeBtn = $(' ');
+ var col = $(' ').append(removeBtn);
+ removeBtn.bind('click', function(event) {
+ diskRow.remove();
+ });
+ diskRow.append(col);
+
+ // Create disk type drop down
+ var diskType = $(' ');
+ var diskTypeSelect = $(' ');
+ diskTypeSelect.append('3390 '
+ + '9336 '
+ );
+ diskType.append(diskTypeSelect);
+ diskRow.append(diskType);
+
+ // Create disk address input
+ var diskAddr = $(' ');
+ diskRow.append(diskAddr);
+
+ // Create disk size input
+ var diskSize = $(' ');
+ diskRow.append(diskSize);
+
+ // Create disk mode input
+ var diskMode = $(' ');
+ var diskModeSelect = $(' ');
+ diskModeSelect.append('R '
+ + 'RR '
+ + 'W '
+ + 'WR '
+ + 'M '
+ + 'MR '
+ + 'MW '
+ );
+ diskMode.append(diskModeSelect);
+ diskRow.append(diskMode);
+
+ // Create disk pool drop down
+ var diskPool = $(' ');
+ var diskPoolSelect = $(' ');
+ for (var i in definedPools) {
+ diskPoolSelect.append('' + definedPools[i] + ' ');
+ }
+ diskPool.append(diskPoolSelect);
+ diskRow.append(diskPool);
+
+ // Create disk password input
+ var diskPw = $(' ');
+ diskRow.append(diskPw);
+
+ // Create IPL checkbox
+ //var diskIpl = $(' ');
+ var diskIpl = $(' ');
+ diskRow.append(diskIpl);
+ diskIpl.find('input').change(function() {
+ updateUserEntry(thisTabId);
+ });
+
+ diskBody.append(diskRow);
+
+ // Generate tooltips
+ diskBody.find('td input[title],select[title]').tooltip({
+ position: "top right",
+ offset: [-4, 4],
+ effect: "fade",
+ opacity: 0.7,
+ predelay: 800,
+ events: {
+ def: "mouseover,mouseout",
+ input: "mouseover,mouseout",
+ widget: "focus mouseover,blur mouseout",
+ tooltip: "mouseover,mouseout"
+ }
+ });
+ });
+
+ // Create disk table
+ diskFooter.append(addDiskLink);
+ diskTable.append(diskHeader);
+ diskTable.append(diskBody);
+ diskTable.append(diskFooter);
+
+ diskDiv.append(diskLabel);
+ diskDiv.append(diskTable);
+ hwAttr.append(diskDiv);
+
+ // Create zFCP table
+ var zfcpDiv = $('
');
+ var zfcpLabel = $('zFCP: ');
+ var zfcpTable = $('');
+ var zfcpHeader = $('');
+ // Adjust header width
+ zfcpHeader.find('th').css({
+ 'width' : '80px'
+ });
+ zfcpHeader.find('th').eq(0).css({
+ 'width' : '20px'
+ });
+ var zfcpBody = $(' ');
+ var zfcpFooter = $(' ');
+
+ /**
+ * Add zFCP devices
+ */
+ var addZfcpLink = $('Add zFCP ');
+ addZfcpLink.bind('click', function(event) {
+ // Get list of disk pools
+ var thisTabId = $(this).parents('.tab').attr('id');
+ var thisHcp = $('#' + thisTabId + ' input[name=hcp]').val();
+ var definedPools = null;
+ if (thisHcp) {
+ // Get node without domain name
+ var temp = thisHcp.split('.');
+ definedPools = $.cookie('xcat_' + temp[0] + 'zfcppools').split(',');
+ } else {
+ var warning = createWarnBar('You must fill in a hardware control point before adding a zFCP.');
+ var warnDialog = $('
').append(warning);
+
+ // Open dialog
+ warnDialog.dialog({
+ title:'Warning',
+ modal: true,
+ close: function(){
+ $(this).remove();
+ },
+ width: 400,
+ buttons: {
+ "Ok": function() {
+ $(this).dialog("close");
+ }
+ }
+ });
+
+ }
+
+ // Create a row
+ var zfcpRow = $(' ');
+
+ // Add remove button
+ var removeBtn = $(' ');
+ var col = $(' ').append(removeBtn);
+ removeBtn.bind('click', function(event) {
+ zfcpRow.remove();
+ });
+ zfcpRow.append(col);
+
+ // Create disk address input
+ var zfcpAddr = $(' ');
+ zfcpRow.append(zfcpAddr);
+
+ // Create disk size input
+ var zfcpSize = $(' ');
+ zfcpRow.append(zfcpSize);
+
+ // Create zFCP pool drop down
+ var zfcpPool = $(' ');
+ var zfcpPoolSelect = $(' ');
+ for (var i in definedPools) {
+ zfcpPoolSelect.append('' + definedPools[i] + ' ');
+ }
+ zfcpPool.append(zfcpPoolSelect);
+ zfcpRow.append(zfcpPool);
+
+ // Create disk tag
+ var zfcpTag = $(' ');
+ zfcpRow.append(zfcpTag);
+
+ // Create device port name
+ var zfcpPortName = $(' ');
+ zfcpRow.append(zfcpPortName);
+
+ // Create device unit number
+ var zfcpUnitNo = $(' ');
+ zfcpRow.append(zfcpUnitNo);
+
+ // Create LOADDEV radio button
+ var zfcpLoaddev = $(' ');
+ zfcpRow.append(zfcpLoaddev);
+
+ zfcpBody.append(zfcpRow);
+
+ // Generate tooltips
+ zfcpBody.find('td input[title],select[title]').tooltip({
+ position: "top right",
+ offset: [-4, 4],
+ effect: "fade",
+ opacity: 0.7,
+ predelay: 800,
+ events: {
+ def: "mouseover,mouseout",
+ input: "mouseover,mouseout",
+ widget: "focus mouseover,blur mouseout",
+ tooltip: "mouseover,mouseout"
+ }
+ });
+ });
+
+ zfcpFooter.append(addZfcpLink);
+ zfcpTable.append(zfcpHeader);
+ zfcpTable.append(zfcpBody);
+ zfcpTable.append(zfcpFooter);
+
+ zfcpDiv.append(zfcpLabel);
+ zfcpDiv.append(zfcpTable);
+ hwAttr.append(zfcpDiv);
+
+ // Generate tooltips
+ provNew.find('div input[title],select[title],textarea[title]').tooltip({
+ position: "center right",
+ offset: [-2, 10],
+ effect: "fade",
+ opacity: 0.7,
+ predelay: 800,
+ events: {
+ def: "mouseover,mouseout",
+ input: "mouseover,mouseout",
+ widget: "focus mouseover,blur mouseout",
+ tooltip: "mouseover,mouseout"
+ }
+ });
+
+ // Disable IPL column if advanced tab is selected
+ hwTab.object().tabs({
+ select: function(event, ui) {
+ // Get provision tab instance
+ var thisTabId = $(this).parents('.ui-tabs-panel').attr('id');
+ var inst = thisTabId.replace('zvmProvisionTab', '');
+
+ // Disable and de-select IPL device
+ if (ui.index == 1) {
+ $('#' + thisTabId + ' table:eq(0):visible tbody tr td:nth-child(8) input').attr('disabled','disabled');
+ } else {
+ $('#' + thisTabId + ' table:eq(0):visible tbody tr td:nth-child(8) input').removeAttr('disabled');
+ }
+
+ $('#' + thisTabId + ' table:eq(0):visible tbody tr td:nth-child(8) input').removeAttr('checked');
+ }
+ });
+
+ /**
+ * Provision new
+ */
+ var provisionBtn = createButton('Provision');
+ provisionBtn.bind('click', function(event) {
+ // Remove any warning messages
+ $(this).parent().parent().find('.ui-state-error').remove();
+
+ var ready = true;
+ var errMsg = '';
+
+ // Get tab ID
+ var thisTabId = $(this).parents('.ui-tabs-panel').attr('id');
+ // Get provision tab instance
+ var inst = thisTabId.replace('zvmProvisionTab', '');
+
+ // Get the selected hardware configuration tab
+ // Basic tab index = 0 & advanced tab index = 1
+ var hwTabIndex = $("#hwConfig" + inst).tabs('option', 'selected');
+
+ // Check node name, userId, hardware control point, and group
+ // Check disks and zFCP devices
+ var inputs = $('#' + thisTabId + ' input:visible');
+ for (var i = 0; i < inputs.length; i++) {
+ // Do not check some inputs
+ if (inputs.eq(i).attr('name') == 'memory') {
+ // There should always be a value for memory
+ // Do not change the border
+ continue;
+ } else if (!inputs.eq(i).val()
+ && inputs.eq(i).attr('type') != 'password'
+ && inputs.eq(i).attr('name') != 'zfcpTag'
+ && inputs.eq(i).attr('name') != 'zfcpPortName'
+ && inputs.eq(i).attr('name') != 'zfcpUnitNo') {
+ inputs.eq(i).css('border', 'solid #FF0000 1px');
+ ready = false;
+ } else {
+ inputs.eq(i).css('border', 'solid #BDBDBD 1px');
+ }
+ }
+
+ var selects = $('#' + thisTabId + ' select:visible');
+ for (var i = 0; i < selects.length; i++) {
+ if (!selects.eq(i).val() && selects.eq(i).attr('name') != 'os' && selects.eq(i).attr('name') != 'userProfile' && selects.eq(i).attr('name') != 'network') {
+ selects.eq(i).css('border', 'solid #FF0000 1px');
+ ready = false;
+ } else {
+ selects.eq(i).css('border', 'solid #BDBDBD 1px');
+ }
+ }
+
+ if (hwTabIndex == 1) {
+ // Check user entry
+ var thisUserEntry = $('#' + thisTabId + ' textarea:visible');
+ thisUserEntry.val(thisUserEntry.val().toUpperCase());
+ if (!thisUserEntry.val()) {
+ thisUserEntry.css('border', 'solid #FF0000 1px');
+ ready = false;
+ } else {
+ thisUserEntry.css('border', 'solid #BDBDBD 1px');
+ }
+
+ // Check if user entry contains user ID
+ var thisUserId = $('#' + thisTabId + ' input[name=userId]:visible');
+ var pos = thisUserEntry.val().indexOf('USER ' + thisUserId.val().toUpperCase());
+ if (pos < 0) {
+
+ pos = thisUserEntry.val().indexOf('IDENTITY ' + thisUserId.val().toUpperCase());
+ if (pos < 0) {
+ errMsg = errMsg + 'The directory entry does not contain the correct user/identity ID. ';
+ ready = false;
+ }
+ }
+ }
+ var hostnameCheck = $('#' + thisTabId + ' input[name=hostname]').val();
+ if (hostnameCheck.length > 70) {
+ errMsg = errMsg + 'The host name cannot be longer than 70 characters. ';
+ $('#' + thisTabId + ' input[name=hostname]').css('border', 'solid #FF0000 1px');
+ ready = false;
+ }
+
+ // Show error message for missing inputs
+ if (!ready) {
+ errMsg = errMsg + 'Please provide a value for each missing field. ';
+ }
+
+ // If no operating system is specified, create only user entry
+ os = $('#' + thisTabId + ' select[name=os]:visible');
+
+ // Check number of disks
+ var diskRows = $('#' + thisTabId + ' table tr');
+ // If an OS is given, disks are needed
+ if (os.val() && (diskRows.length < 1)) {
+ errMsg = errMsg + 'You need to add at some disks. ';
+ ready = false;
+ }
+
+ // If this is basic mode, check for a disk with IPL radio button and zFCP with LOADDEV button
+ // Cannot have both. (In advanced mode they create the directory entries.)
+ if (hwTabIndex == 0) {
+ // Find a device to be IPLed?
+ var ECKD_FBA_diskRows = $('#' + thisTabId + ' table:eq(0):visible tbody tr');
+ var iplSet = 0;
+ for (var i = 0; i < ECKD_FBA_diskRows.length; i++) {
+ var diskArgs = ECKD_FBA_diskRows.eq(i).find('td');
+ if (diskArgs.eq(7).find('input').attr("checked") === true) {
+ iplSet = 1;
+ break;
+ }
+ }
+
+ // Check if zFCP loaddev checked
+ var zfcpRows = $('#' + thisTabId + ' table:eq(1):visible tbody tr');
+ if (zfcpRows.length > 0) {
+ for ( var i = 0; i < zfcpRows.length; i++) {
+ var diskArgs = zfcpRows.eq(i).find('td');
+ // This is either true or false
+ var loaddev = diskArgs.eq(7).find('input').attr('checked');
+ if (loaddev && iplSet) {
+ errMsg = errMsg + 'You cannot have both disk IPL and zFCP LOADDEV, can only IPL one device. ';
+ ready = false;
+ }
+ }
+ }
+ }
+
+ // If inputs are valid, ready to provision
+ if (ready) {
+ // Generate user directory entry if basic tab is selected
+ if (hwTabIndex == 0) {
+ updateUserEntry(thisTabId);
+ }
+
+ if (!os.val()) {
+ // If no OS is given, create a virtual server
+ var msg = '';
+ if (diskRows.length > 0) {
+ msg = 'Do you want to create a virtual server without an operating system?';
+ } else {
+ // If no disks are given, create a virtual server (no disk)
+ msg = 'Do you want to create a virtual server without an operating system or disks?';
+ }
+
+ // Open dialog to confirm
+ var confirmDialog = $('');
+ confirmDialog.dialog({
+ title:'Confirm',
+ modal: true,
+ close: function(){
+ $(this).remove();
+ },
+ width: 400,
+ buttons: {
+ "Ok": function(){
+ // Disable provision button
+ provisionBtn.attr('disabled', 'true');
+
+ // Show loader
+ $('#zProvisionStatBar' + inst).show();
+ $('#zProvisionLoader' + inst).show();
+
+ // Disable add disk button
+ addDiskLink.attr('disabled', 'true');
+
+ // Disable close button on disk table
+ $('#' + thisTabId + ' table span').unbind('click');
+
+ // Disable all inputs
+ var inputs = $('#' + thisTabId + ' input');
+ inputs.attr('disabled', 'disabled');
+
+ // Disable all selects
+ var selects = $('#' + thisTabId + ' select');
+ selects.attr('disabled', 'disabled');
+
+ // Add a new line at the end of the user entry
+ var textarea = $('#' + thisTabId + ' textarea');
+ var tmp = jQuery.trim(textarea.val());
+ textarea.val(tmp + '\n');
+ textarea.attr('readonly', 'readonly');
+ textarea.css( {
+ 'background-color' : '#F2F2F2'
+ });
+
+ // Get node name
+ var node = $('#' + thisTabId + ' input[name=nodeName]').val();
+ // Get userId
+ var userId = $('#' + thisTabId + ' input[name=userId]').val();
+ // Get hardware control point
+ var hcp = $('#' + thisTabId + ' input[name=hcp]').val();
+ // Get group
+ var group = $('#' + thisTabId + ' input[name=group]').val();
+ // Get IP address and hostname
+ var ip = $('#' + thisTabId + ' input[name=ip]').val();
+ var hostname = $('#' + thisTabId + ' input[name=hostname]').val();
+
+ // Generate arguments to sent
+ var args = node + ';zvm.hcp=' + hcp
+ + ';zvm.userid=' + userId
+ + ';nodehm.mgt=zvm'
+ + ';groups=' + group;
+ if (ip)
+ args += ';hosts.ip=' + ip;
+
+ if (hostname)
+ args += ';hosts.hostnames=' + hostname;
+
+ /**
+ * (1) Define node
+ */
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'nodeadd',
+ tgt : '',
+ args : args,
+ msg : 'cmd=nodeadd;out=' + inst
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ updateZProvisionNewStatus(data);
+ }
+ });
+
+ $(this).dialog("close");
+ },
+ "Cancel": function() {
+ $(this).dialog("close");
+ }
+ }
+ });
+ } else {
+ /**
+ * Create a virtual server and install OS
+ */
+
+ // Disable provision button
+ $(this).attr('disabled', 'true');
+
+ // Show loader
+ $('#zProvisionStatBar' + inst).show();
+ $('#zProvisionLoader' + inst).show();
+
+ // Disable add disk button
+ addDiskLink.attr('disabled', 'true');
+
+ // Disable close button on disk table
+ $('#' + thisTabId + ' table span').unbind('click');
+
+ // Disable all inputs
+ var inputs = $('#' + thisTabId + ' input');
+ inputs.attr('disabled', 'disabled');
+ inputs.css( {
+ 'background-color' : '#F2F2F2'
+ });
+
+ // Disable all selects
+ var selects = $('#' + thisTabId + ' select');
+ selects.attr('disabled', 'disabled');
+ selects.css( {
+ 'background-color' : '#F2F2F2'
+ });
+
+ // Add a new line at the end of the user entry
+ var textarea = $('#' + thisTabId + ' textarea');
+ var tmp = jQuery.trim(textarea.val());
+ textarea.val(tmp + '\n');
+ textarea.attr('readonly', 'readonly');
+ textarea.css( {
+ 'background-color' : '#F2F2F2'
+ });
+
+ // Get node name
+ var node = $('#' + thisTabId + ' input[name=nodeName]').val();
+ // Get userId
+ var userId = $('#' + thisTabId + ' input[name=userId]').val();
+ // Get hardware control point
+ var hcp = $('#' + thisTabId + ' input[name=hcp]').val();
+ // Get group
+ var group = $('#' + thisTabId + ' input[name=group]').val();
+ // Get IP address and hostname
+ var ip = $('#' + thisTabId + ' input[name=ip]').val();
+ var hostname = $('#' + thisTabId + ' input[name=hostname]').val();
+
+ // Generate arguments to sent
+ var args = node + ';zvm.hcp=' + hcp
+ + ';zvm.userid=' + userId
+ + ';nodehm.mgt=zvm'
+ + ';groups=' + group;
+ if (ip)
+ args += ';hosts.ip=' + ip;
+
+ if (hostname)
+ args += ';hosts.hostnames=' + hostname;
+
+ /**
+ * (1) Define node
+ */
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'nodeadd',
+ tgt : '',
+ args : args,
+ msg : 'cmd=nodeadd;out=' + inst
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ updateZProvisionNewStatus(data);
+ }
+ });
+ }
+ } else {
+ // Show warning message
+ var warn = createWarnBar(errMsg);
+ warn.prependTo($(this).parent().parent());
+ }
+ });
+ provNew.append(provisionBtn);
+
+ return provNew;
+}
+/**
+ * Remove zprovision loading gif for zhcp and message
+ *
+ * @param division holding the gif and message
+ */
+function removeProvisionLoadingGif(provisionStatBar) {
+
+ // Only remove the status bar message and gif we added, then hide the status bar
+ var items = provisionStatBar.find('div').children();
+ for (var i = 0; i< items.length; i++) {
+ var nname = items[i].nodeName;
+ var myid = items[i].id;
+ if (nname == "B" && myid == "loadzhcp") {
+ items[i].remove()
+ } else if (nname == "IMG" && myid == "loadingpic") {
+ items[i].remove();
+ }
+ }
+ provisionStatBar.hide();
+}
+
+/**
+ * Set hash entry to 0 and check if all are 0. If so call
+ * removeProvisionLoadingGif
+ *
+ * @param division holding the gif and message, and hash, and
+ * key
+ */
+function checkProvisionCallsDone(provisionStatBar, table, finishedKey) {
+
+ table[finishedKey] = 0;
+
+ for (var key in table) {
+ if (table[key] == 1) {
+ return; // More to do
+ }
+ }
+
+ removeProvisionLoadingGif(provisionStatBar);
+}
+
+/**
+ * Load zVMs into column (service page)
+ *
+ * @param col Table column where OS images will be placed
+ */
+function loadzVMs(col) {
+ // Get group names and description and append to group column
+ if (!$.cookie('xcat_zvms')) {
+ var infoBar = createInfoBar('No selectable z/VM available');
+ col.append(infoBar);
+ return;
+ }
+
+ var zNames = $.cookie('xcat_zvms').split(',');
+
+ var radio, zBlock, args, zvm, hcp;
+ for (var i in zNames) {
+ if( !zNames[i] || 0 === zNames[i].length) continue;
+ args = zNames[i].split(':');
+ zvm = args[0];
+ hcp = args[1];
+
+ // Create block for each group
+ zBlock = $('
').css({
+ 'border': '1px solid',
+ 'max-width': '200px',
+ 'margin': '5px auto',
+ 'padding': '5px',
+ 'display': 'block',
+ 'vertical-align': 'middle',
+ 'cursor': 'pointer',
+ 'white-space': 'normal'
+ }).click(function(){
+ $(this).children('input:radio').attr('checked', 'checked');
+ $(this).parents('td').find('div').attr('class', 'ui-state-default');
+ $(this).attr('class', 'ui-state-active');
+ });
+ radio = $(' ').css('display', 'none');
+ zBlock.append(radio, $('' + zvm + ' managed by ' + hcp + ' '));
+ zBlock.children('span').css({
+ 'display': 'block',
+ 'margin': '5px',
+ 'text-align': 'left'
+ });
+ col.append(zBlock);
+ }
+}
+
+/**
+ * Load groups into column
+ *
+ * @param col Table column where OS images will be placed
+ */
+function loadSrvGroups(col) {
+ // Get group names and description and append to group column
+ if (!$.cookie('xcat_srv_groups')) {
+ var infoBar = createInfoBar('No selectable group available');
+ col.append(infoBar);
+ return;
+ }
+
+ var groupNames = $.cookie('xcat_srv_groups').split(',');
+
+ var groupBlock, radio, args, name, ip, hostname, desc;
+ for (var i in groupNames) {
+ if( !groupNames[i] || 0 === groupNames[i].length) continue;
+ args = groupNames[i].split(':');
+ name = args[0];
+ ip = args[1];
+ hostname = args[2];
+ desc = args[3];
+
+ // Create block for each group
+ groupBlock = $('
').css({
+ 'border': '1px solid',
+ 'max-width': '200px',
+ 'margin': '5px auto',
+ 'padding': '5px',
+ 'display': 'block',
+ 'vertical-align': 'middle',
+ 'cursor': 'pointer',
+ 'white-space': 'normal'
+ }).click(function(){
+ $(this).children('input:radio').attr('checked', 'checked');
+ $(this).parents('td').find('div').attr('class', 'ui-state-default');
+ $(this).attr('class', 'ui-state-active');
+ });
+ radio = $(' ').css('display', 'none');
+ groupBlock.append(radio, $('' + name + ' : ' + desc + ' '));
+ groupBlock.children('span').css({
+ 'display': 'block',
+ 'margin': '5px',
+ 'text-align': 'left'
+ });
+ col.append(groupBlock);
+ }
+}
+
+/**
+ * Load OS images into column
+ *
+ * @param col Table column where OS images will be placed
+ */
+function loadOSImages(col) {
+ // Get group names and description and append to group column
+ if (!$.cookie('xcat_srv_imagenames')) {
+ var infoBar = createInfoBar('No selectable image available');
+ col.append(infoBar);
+ return;
+ }
+
+ var imgNames = $.cookie('xcat_srv_imagenames').split(',');
+
+ var imgBlock, radio, args, name, desc;
+ for (var i in imgNames) {
+ if( !imgNames[i] || 0 === imgNames[i].length) continue;
+ args = imgNames[i].split(':');
+ name = args[0];
+ desc = args[1];
+
+ // Create block for each image
+ imgBlock = $('
').css({
+ 'border': '1px solid',
+ 'max-width': '200px',
+ 'margin': '5px auto',
+ 'padding': '5px',
+ 'display': 'block',
+ 'vertical-align': 'middle',
+ 'cursor': 'pointer',
+ 'white-space': 'normal'
+ }).click(function(){
+ $(this).children('input:radio').attr('checked', 'checked');
+ $(this).parents('td').find('div').attr('class', 'ui-state-default');
+ $(this).attr('class', 'ui-state-active');
+
+ $('#select-table tbody tr:eq(0) td:eq(3) input[name="master"]').attr('checked', '');
+ $('#select-table tbody tr:eq(0) td:eq(3) input[name="master"]').parents('td').find('div').attr('class', 'ui-state-default');
+ });
+ radio = $(' ').css('display', 'none');
+ imgBlock.append(radio, $('' + name + ' : ' + desc + ' '));
+ imgBlock.children('span').css({
+ 'display': 'block',
+ 'margin': '5px',
+ 'text-align': 'left'
+ });
+ col.append(imgBlock);
+ }
+}
+
+/**
+ * Load golden images into column
+ *
+ * @param col Table column where master copies will be placed
+ */
+function loadGoldenImages(col) {
+ // Get group names and description and append to group column
+ if (!$.cookie('xcat_srv_goldenimages')) {
+ var infoBar = createInfoBar('No selectable master copies available');
+ col.append(infoBar);
+ return;
+ }
+
+ var imgNames = $.cookie('xcat_srv_goldenimages').split(',');
+
+ var imgBlock, radio, args, name, desc;
+ for (var i in imgNames) {
+ if( !imgNames[i] || 0 === imgNames[i].length) continue;
+ args = imgNames[i].split(':');
+ name = args[0];
+ desc = args[1];
+
+ // Create block for each image
+ imgBlock = $('
').css({
+ 'border': '1px solid',
+ 'max-width': '200px',
+ 'margin': '5px auto',
+ 'padding': '5px',
+ 'display': 'block',
+ 'vertical-align': 'middle',
+ 'cursor': 'pointer',
+ 'white-space': 'normal'
+ }).click(function(){
+ $(this).children('input:radio').attr('checked', 'checked');
+ $(this).parents('td').find('div').attr('class', 'ui-state-default');
+ $(this).attr('class', 'ui-state-active');
+
+ // Un-select zVM and image
+ $('#select-table tbody tr:eq(0) td:eq(2) input[name="image"]').attr('checked', '');
+ $('#select-table tbody tr:eq(0) td:eq(2) input[name="image"]').parents('td').find('div').attr('class', 'ui-state-default');
+
+ $('#select-table tbody tr:eq(0) td:eq(0) input[name="hcp"]').attr('checked', '');
+ $('#select-table tbody tr:eq(0) td:eq(0) input[name="hcp"]').parents('td').find('div').attr('class', 'ui-state-default');
+ });
+ radio = $(' ').css('display', 'none');
+ imgBlock.append(radio, $('' + name + ' : ' + desc + ' '));
+ imgBlock.children('span').css({
+ 'display': 'block',
+ 'margin': '5px',
+ 'text-align': 'left'
+ });
+ col.append(imgBlock);
+ }
+}
+
+/**
+ * Set a cookie for zVM host names (service page)
+ *
+ * @param data Data from HTTP request
+ */
+function setzVMCookies(data) {
+ if (data.rsp.length && data.rsp[0].indexOf("Failed") == -1 && data.rsp[0].indexOf("Error") == -1 ) {
+ var zvms = new Array();
+ var hosts = data.rsp[0].split("\n");
+ for ( var i = 0; i < hosts.length; i++) {
+ if (hosts[i] != null && hosts[i] != "") {
+ zvms.push(hosts[i]);
+ if (typeof console == "object"){
+ console.log("Setting a zVM cookie:<"+hosts[i]+">");
+ }
+ }
+ }
+
+ // Set cookie to expire in 60 minutes
+ var exDate = new Date();
+ exDate.setTime(exDate.getTime() + (60 * 60 * 1000));
+ $.cookie('xcat_zvms', zvms, { expires: exDate, path: '/xcat', secure:true });
+ }
+}
+
+/**
+ * Set a cookie for master copies (service page)
+ *
+ * @param data Data from HTTP request
+ */
+function setGoldenImagesCookies(data) {
+ if (data.rsp.length && data.rsp[0].indexOf("Failed") == -1 && data.rsp[0].indexOf("Error") == -1) {
+ var copies = new Array();
+ var tmp = data.rsp[0].split(",");
+ for ( var i = 0; i < tmp.length; i++) {
+ if (tmp[i] != null && tmp[i] != "") {
+ copies.push(tmp[i]);
+ }
+ }
+
+ // Set cookie to expire in 60 minutes
+ var exDate = new Date();
+ exDate.setTime(exDate.getTime() + (60 * 60 * 1000));
+ $.cookie('xcat_srv_goldenimages', copies, { expires: exDate, path: '/xcat', secure:true });
+ }
+}
+
+/**
+ * Set a cookie for disk pool names of a given node
+ *
+ * @param data Data from HTTP request
+ */
+function setDiskPoolCookies(data) {
+ if (data.rsp.length && data.rsp[0].indexOf("Failed") == -1 && data.rsp[0].indexOf("Error") == -1 ) {
+ var node = data.msg;
+ var pools = data.rsp[0].split(node + ": ");
+ var pools2 = [];
+ for (var j in pools) {
+ if (pools[j] != "") {
+ pools2.push(jQuery.trim(pools[j]));
+ }
+ }
+
+ // Set cookie to expire in 60 minutes
+ var exDate = new Date();
+ exDate.setTime(exDate.getTime() + (60 * 60 * 1000));
+ $.cookie('xcat_' + node + 'diskpools', pools2, { expires: exDate, path: '/xcat', secure:true });
+ }
+}
+
+/**
+ * Set a cookie for zFCP pool names of a given node
+ *
+ * @param data Data from HTTP request
+ */
+function setZfcpPoolCookies(data) {
+ if (data.rsp.length && data.rsp[0].indexOf("Failed") == -1 && data.rsp[0].indexOf("Error") == -1 ) {
+ var node = data.msg;
+ var pools = data.rsp[0].split(node + ': ');
+ var pools2 = [];
+ for (var j in pools) {
+ if (pools[j] != "") {
+ pools2.push(jQuery.trim(pools[j]));
+ }
+ }
+
+ // Set cookie to expire in 60 minutes
+ var exDate = new Date();
+ exDate.setTime(exDate.getTime() + (60 * 60 * 1000));
+ $.cookie('xcat_' + node + 'zfcppools', pools2, { expires: exDate, path: '/xcat', secure:true });
+ }
+}
+
+/**
+ * Set a cookie for zHCP host names
+ *
+ * @param zhcps List of zHCPs known
+ */
+function setzHcpCookies(zhcps) {
+ if (zhcps.length) {
+ // Set cookie to expire in 60 minutes
+ var exDate = new Date();
+ exDate.setTime(exDate.getTime() + (60 * 60 * 1000));
+ $.cookie('xcat_zhcps', zhcps, { expires: exDate, path: '/xcat', secure:true });
+ }
+}
+
+/**
+ * Set a cookie for z/VM user profile names of a given node
+ *
+ * @param data Data from HTTP request
+ */
+function setUserProfilesCookies(data) {
+ if (data.rsp.length && data.rsp[0].indexOf("Failed") == -1 && data.rsp[0].indexOf("Error") == -1 ) {
+ var node = data.msg;
+ var profiles = data.rsp[0].split(node + ': ');
+ var profiles2 = [];
+ for (var j in profiles) {
+ if (profiles[j] != "") {
+ profiles2.push(jQuery.trim(profiles[j]));
+ }
+ }
+
+ // Set cookie to expire in 60 minutes
+ var exDate = new Date();
+ exDate.setTime(exDate.getTime() + (60 * 60 * 1000));
+ $.cookie('xcat_' + node + 'userprofiles', profiles2, { expires: exDate, path: '/xcat', secure:true });
+ }
+}
+
+/**
+ * Create virtual machine (service page)
+ *
+ * @param tabId Tab ID
+ * @param group Group
+ * @param hcp Hardware control point
+ * @param img OS image
+ */
+function createzVM(tabId, group, hcp, img, owner) {
+ // Submit request to create VM
+ // webportal provzlinux [group] [hcp] [image] [owner]
+ var iframe = createIFrame('lib/srv_cmd.php?cmd=webportal&tgt=&args=provzlinux;' + group + ';' + hcp + ';' + img + ';' + owner + '&msg=&opts=flush');
+ iframe.prependTo($('#' + tabId));
+}
+
+/**
+ * Query the profiles that exists
+ *
+ * @param panelId Panel ID
+ */
+function queryProfiles(panelId) {
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'tabdump',
+ tgt : '',
+ args : 'osimage',
+ msg : panelId
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ var panelId = data.msg;
+ setOSImageCookies(data);
+ configProfilePanel(panelId);
+ }
+ });
+}
+
+/**
+ * Panel to configure directory entries and disks for a profile
+ *
+ * @param panelId Panel ID
+ */
+function configProfilePanel(panelId) {
+ // Wipe panel clean
+ $('#' + panelId).empty();
+
+ // Add info bar
+ $('#' + panelId).append(createInfoBar('Create, edit, and delete profiles for the self-service portal. It is important to note the default z/VM user ID for any profile should be LXUSR.'));
+
+ // Create table
+ var tableId = 'zvmProfileTable';
+ var table = new DataTable(tableId);
+ table.init([' ', 'Profile', 'Disk pool', 'Disk size', 'Directory entry']);
+
+ // Insert profiles into table
+ var profiles = $.cookie('xcat_profiles').split(',');
+ profiles.push('default'); // Add default profile
+ for (var i in profiles) {
+ if (profiles[i]) {
+ // Columns are: profile, selectable, description, disk pool, disk size, and directory entry
+ var cols = new Array(profiles[i], '', '', '');
+
+ // 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,
+ "bScrollCollapse": true,
+ "sScrollY": "400px",
+ "sScrollX": "110%",
+ "bAutoWidth": true,
+ "oLanguage": {
+ "oPaginate": {
+ "sNext": "",
+ "sPrevious": ""
+ }
+ }
+ });
+
+ // Create action bar
+ var actionBar = $('
').css("width", "450px");
+
+ // Create a profile
+ var createLnk = $('Create ');
+ createLnk.click(function() {
+ profileDialog();
+ });
+
+ // Edit a profile
+ var editLnk = $('Edit ');
+ editLnk.click(function() {
+ var profiles = $('#' + tableId + ' input[type=checkbox]:checked');
+ for (var i in profiles) {
+ var profile = profiles.eq(i).attr('name');
+ if (profile) {
+ // Column order is: profile, selectable, disk pool, disk size, and directory entry
+ var cols = profiles.eq(i).parents('tr').find('td');
+ var pool = cols.eq(2).text();
+ var size = cols.eq(3).text();
+ var entry = cols.eq(4).html().replace(new RegExp(' ', 'g'), '\n');
+
+ editProfileDialog(profile, pool, size, entry);
+ }
+ }
+ });
+
+ // Delete a profile
+ var deleteLnk = $('Delete ');
+ deleteLnk.click(function() {
+ var profiles = getNodesChecked(tableId);
+ if (profiles) {
+ deleteProfileDialog(profiles);
+ }
+ });
+
+ // Refresh profiles table
+ var refreshLnk = $('Refresh ');
+ refreshLnk.click(function() {
+ queryProfiles(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 = $('');
+ $('#' + tableId + '_wrapper').prepend(menuDiv);
+ menuDiv.append(actionBar);
+ $('#' + tableId + '_filter').appendTo(menuDiv);
+
+ // Resize accordion
+ $('#' + tableId).parents('.ui-accordion').accordion('resize');
+
+ // Query directory entries and disk pool/size for each profile
+ for (var i in profiles) {
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'getdefaultuserentry;' + profiles[i],
+ msg : 'out=' + panelId + ';profile=' + profiles[i]
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ insertDirectoryEntry(data);
+ }
+ });
+
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'getzdiskinfo;' + profiles[i],
+ msg : 'out=' + panelId + ';profile=' + profiles[i]
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ insertDiskInfo(data);
+ }
+ });
+ }
+}
+
+/**
+ * Insert the directory entry into the profile table
+ *
+ * @param data Data from HTTP request
+ */
+function insertDirectoryEntry(data) {
+ var tableId = 'zvmProfileTable';
+ var args = data.msg.split(';');
+
+ var profile = args[1].replace('profile=', '');
+
+ // Do not continue if there is nothing
+ if (!data.rsp.length)
+ return;
+
+ var entry = data.rsp[0].replace(new RegExp('\n', 'g'), ' ');
+
+ // Get the row containing the profile
+ var rowPos = findRow(profile, '#' + tableId, 1);
+ if (rowPos < 0)
+ return;
+
+ // Update the directory entry column
+ var dTable = $('#' + tableId).dataTable();
+ dTable.fnUpdate(entry, rowPos, 4, false);
+
+ // Adjust table styling
+ $('#' + tableId + ' td:nth-child(5)').css({
+ 'text-align': 'left'
+ });
+ adjustColumnSize(tableId);
+}
+
+/**
+ * Insert the disk info into the profile table
+ *
+ * @param data Data from HTTP request
+ */
+function insertDiskInfo(data) {
+ var tableId = 'zvmProfileTable';
+ var args = data.msg.split(';');
+
+ var profile = args[1].replace('profile=', '');
+
+ // Do not continue if there is nothing
+ if (!data.rsp.length)
+ return;
+
+ // Get the row containing the profile
+ var rowPos = findRow(profile, '#' + tableId, 1);
+ if (rowPos < 0)
+ return;
+
+ // Update the disk info columns
+ var dTable = $('#' + tableId).dataTable();
+
+ var tmp = "";
+ var pool = "";
+ var eckdSize = 0;
+ var info = data.rsp[0].split('\n');
+ for (var i in info) {
+ if (info[i].indexOf('diskpool') > -1) {
+ tmp = info[i].split('=');
+ pool = jQuery.trim(tmp[1]);
+
+ dTable.fnUpdate(pool, rowPos, 2, false);
+ } if (info[i].indexOf('eckd_size') > -1) {
+ tmp = info[i].split('=');
+ eckdSize = jQuery.trim(tmp[1]);
+
+ dTable.fnUpdate(eckdSize, rowPos, 3, false);
+ }
+ }
+
+ // Adjust table styling
+ adjustColumnSize(tableId);
+}
+
+/**
+ * Open profile dialog
+ */
+function profileDialog() {
+ // Create form to add profile
+ var dialogId = 'zvmCreateProfile';
+ var profileForm = $('
');
+
+ // Create info bar
+ var info = createInfoBar('Configure the default settings for a profile');
+ profileForm.append(info);
+
+ // Insert profiles into select
+ var profileSelect = $(' ');
+ var profiles = $.cookie('xcat_profiles').split(',');
+ profiles.push('default'); // Add default profile
+ for (var i in profiles) {
+ if (profiles[i]) {
+ profileSelect.append($('' + profiles[i] + ' '));
+ }
+ }
+
+ profileForm.append($('Profile:
').append(profileSelect));
+ profileForm.append('Disk pool:
');
+ profileForm.append('Disk size (ECKD):
');
+ profileForm.append('Directory entry:
');
+
+ // Generate tooltips
+ profileForm.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 processor
+ profileForm.dialog({
+ title:'Configure profile',
+ modal: true,
+ close: function(){
+ $(this).remove();
+ },
+ width: 600,
+ buttons: {
+ "Ok": function(){
+ // Remove any warning messages
+ $(this).find('.ui-state-error').remove();
+
+ // Find profile attributes
+ var profile = $(this).find('select[name=profile]').val();
+ var pool = $(this).find('input[name=disk_pool]').val();
+ var size = $(this).find('input[name=disk_size_eckd]').val();
+ var entry = $(this).find('textarea[name=directory_entry]').val();
+
+ // If inputs are not complete, show warning message
+ if (!profile || !pool || !size || !entry) {
+ var warn = createWarnBar('Please provide a value for each missing field.');
+ warn.prependTo($(this));
+ } else {
+ // Change dialog buttons
+ $('#' + dialogId).dialog('option', 'buttons', {
+ 'Close':function(){
+ $(this).dialog('destroy').remove();
+ }
+ });
+
+ // Write file to /var/tmp
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'write',
+ tgt : '/var/tmp/' + profile + '.direct',
+ args : '',
+ cont : entry,
+ msg : dialogId + ';' + profile + ';' + pool + ';' + size
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ var args = data.msg.split(';');
+
+ // Create profile in xCAT
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'mkzprofile;' + args[1] + ';' + args[2] + ';' + args[3],
+ msg : args[0]
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ updatePanel(data);
+ }
+ });
+ }
+ });
+ }
+ },
+ "Cancel": function() {
+ $(this).dialog( "close" );
+ }
+ }
+ });
+}
+
+/**
+ * Open dialog to confirm profile delete
+ *
+ * @param profiles Profiles to delete
+ */
+function deleteProfileDialog(profiles) {
+ // Create form to delete disk to pool
+ var dialogId = 'zvmDeleteProfile';
+ var deleteForm = $('
');
+
+ // Create info bar
+ var info = createInfoBar('Are you sure you want to delete ' + profiles.replace(new RegExp(',', 'g'), ', ') + '?');
+ deleteForm.append(info);
+
+ // Open dialog to delete user
+ deleteForm.dialog({
+ title:'Delete profile',
+ 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 : 'rmzprofile;' + profiles,
+ msg : dialogId
+ },
+ success : function(data) {
+ data = decodeRsp(data);
+ updatePanel(data);
+ }
+ });
+ },
+ "Cancel": function() {
+ $(this).dialog( "close" );
+ }
+ }
+ });
+}
+
+/**
+ * Open dialog to edit profile
+ *
+ * @param profile Profile to edit
+ * @param pool Disk pool
+ * @param size Disk size
+ * @param entry Directory entry
+ */
+function editProfileDialog(profile, pool, size, entry) {
+ // Create form to add profile
+ var dialogId = 'zvmEditProfile_' + profile;
+ var profileForm = $('
');
+
+ // Create info bar
+ var info = createInfoBar('Configure the default settings for a profile');
+ profileForm.append(info);
+
+ // Insert profiles into select
+ var profileSelect = $(' ');
+ var profiles = $.cookie('xcat_profiles').split(',');
+ profiles.push('default'); // Add default profile
+ for (var i in profiles) {
+ if (profiles[i]) {
+ profileSelect.append($('' + profiles[i] + ' '));
+ }
+ }
+
+ profileForm.append($('Profile:
').append(profileSelect));
+ profileForm.append('Disk pool:
');
+ profileForm.append('Disk size (ECKD):
');
+ profileForm.append('Directory entry:
');
+
+ // Insert profile values
+ profileSelect.val(profile);
+ profileForm.find('input[name=disk_pool]').val(pool);
+ profileForm.find('input[name=disk_size_eckd]').val(size);
+ profileForm.find('textarea[name=directory_entry]').val(entry);
+
+ // Generate tooltips
+ profileForm.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 processor
+ profileForm.dialog({
+ title:'Configure profile',
+ modal: true,
+ close: function(){
+ $(this).remove();
+ },
+ width: 600,
+ buttons: {
+ "Ok": function(){
+ // Remove any warning messages
+ $(this).find('.ui-state-error').remove();
+
+ // Find profile attributes
+ var profile = $(this).find('select[name=profile]').val();
+ var pool = $(this).find('input[name=disk_pool]').val();
+ var size = $(this).find('input[name=disk_size_eckd]').val();
+ var entry = $(this).find('textarea[name=directory_entry]').val();
+
+ // If inputs are not complete, show warning message
+ if (!profile || !pool || !size || !entry) {
+ var warn = createWarnBar('Please provide a value for each missing field.');
+ warn.prependTo($(this));
+ } else {
+ // Change dialog buttons
+ $('#' + dialogId).dialog('option', 'buttons', {
+ 'Close':function(){
+ $(this).dialog('destroy').remove();
+ }
+ });
+
+ // A newline at the end of directory entry is needed
+ entry = entry.replace(/^\s+|\s+$/g, '');
+ entry += '\n';
+
+ // Write file to /var/tmp
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'write',
+ tgt : '/var/tmp/' + profile + '.direct',
+ args : '',
+ cont : entry,
+ msg : dialogId + ';' + profile + ';' + pool + ';' + size
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ var args = data.msg.split(';');
+
+ // Create profile in xCAT
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'mkzprofile;' + args[1] + ';' + args[2] + ';' + args[3],
+ msg : args[0]
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ updatePanel(data);
+ }
+ });
+ }
+ });
+ }
+ },
+ "Cancel": function() {
+ $(this).dialog( "close" );
+ }
+ }
+ });
+}
+
+/**
+ * Get a hash map containing the zHCP to z/VM system mapping
+ *
+ * @returns Hash map containing the zHCP to z/VM system mapping
+ */
+function getHcpZvmHash() {
+ // Get zVM host names
+ if (!$.cookie('xcat_zvms')) {
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ async: false,
+ data : {
+ cmd : 'webportal',
+ tgt : '',
+ args : 'lszvm',
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ setzVMCookies(data);
+ }
+ });
+ }
+
+ var zvms = $.cookie('xcat_zvms').split(',');
+ var hcp2zvm = new Object();
+ var args, zvm, iHcp, tmp;
+ for (var i in zvms) {
+ if( !zvms[i] || 0 === zvms[i].length) continue;
+ args = zvms[i].split(':');
+ zvm = args[0].toLowerCase();
+
+ if (args[1].indexOf('.') != -1) {
+ tmp = args[1].split('.');
+ iHcp = tmp[0];
+ } else {
+ iHcp = args[1];
+ }
+
+ hcp2zvm[iHcp] = zvm;
+ }
+
+ return hcp2zvm;
+}
+
+/**
+ * Update the user entry text area on a given tab
+ *
+ * @param tabId Tab Id where user entry text area is contained
+ */
+function updateUserEntry(tabId) {
+ var userId = $('#' + tabId + ' input[name=userId]').val().toUpperCase();
+ var profile = $('#' + tabId + ' select[name=userProfile]').val();
+ var cpuCount = parseInt($('#' + tabId + ' select[name=cpuCount]').val());
+ var memory = $('#' + tabId + ' input[name=memory]').val();
+ var network = $('#' + tabId + ' select[name=network]').val();
+ var networktext = $('#' + tabId + ' select[name=network]').find('option:selected').text();
+ networktext = jQuery.trim(networktext);
+ var hcp = $('#' + tabId + ' input[name=hcp]').val();
+ var hcpNode = $('#' + tabId + ' input[name=hcpNode]').val();
+ var hashtable = getselectedNetworkHash();
+ if (typeof console == "object"){
+ console.log("Entering updateUserEntry for tab id:"+tabId);
+ }
+
+ if (!hashtable) {
+ hashtable = [[]];
+ setselectedNetworkHash(hashtable);
+
+ if (typeof console == "object") {
+ console.log("updateUserEntry. creating new hash[[]] table!!");
+ }
+ }
+
+ if (networktext.indexOf('VSWITCH') > -1) {
+ var nettokens = networktext.split(' '); // Get tokens for vswitch, system, name
+ var hashid = tabId + '_' + nettokens[2];
+ var requestStarted = 0;
+
+ // Did we already get the network details?
+ if (typeof hashtable[hashid] === 'undefined') {
+ if (typeof console == "object") {
+ console.log("updateUserEntry. calling getNetworkDetails since no hashid defined:" + hashid);
+ }
+ requestStarted = 1;
+ getNetworkDetails(hcpNode, nettokens[2], hashid, tabId);
+ } else if (typeof hashtable[hashid]['vlan_awareness'] === 'undefined') { // May not hit this condition
+ if (typeof console == "object") {
+ console.log("updateUserEntry. calling getNetworkDetails since no vlan_awareness was found in hashid:" + hashid);
+ }
+ requestStarted = 1;
+ getNetworkDetails(hcpNode, nettokens[2], hashid, tabId);
+ }
+
+ // If a request is started, then do the ajax stop path
+ if (requestStarted == 1) {
+ // Make sure that the request to get network details is finished before
+ // calling generateUserEntry
+ $(document).ajaxStop(function() {
+ if (typeof console == "object") {
+ console.log("updateUserEntry. In ajaxstop");
+ }
+ requestStarted = 0;
+ var privilege = [];
+ $('#' + tabId + ' input[name=privilege]:checked').each(function () {
+ privilege.push($(this).val());
+ });
+ privilege = privilege.join('');
+
+ // Find device to be IPL
+ var diskRows = $('#' + tabId + ' table:eq(0):visible tbody tr');
+ var ipl;
+ for (var i = 0; i < diskRows.length; i++) {
+ var diskArgs = diskRows.eq(i).find('td');
+ var address = diskArgs.eq(2).find('input').val();
+ if (diskArgs.eq(7).find('input').attr("checked") === true) {
+ ipl = address;
+ break;
+ }
+ }
+
+ // Check if zFCP loaddev checked, if so ipl the fcp card
+ var zfcpRows = $('#' + tabId + ' table:eq(1):visible tbody tr');
+ if (zfcpRows.length > 0) {
+ for ( var i = 0; i < zfcpRows.length; i++) {
+ var diskArgs = zfcpRows.eq(i).find('td');
+ var address = diskArgs.eq(1).find('input').val();
+ // This is either true or false
+ var loaddev = diskArgs.eq(7).find('input').attr('checked');
+ if (loaddev) {
+ ipl = address;
+ }
+ }
+ }
+
+
+ // Only update directory entry if the basic tab is selected
+ var inst = tabId.replace('zvmProvisionTab', '');
+ var hwTabIndex = $("#hwConfig" + inst).tabs('option', 'selected');
+ var showvlan = $('#' + tabId).find('#vlandiv'); // Vlan information only for basic tab if vswitch is vlan aware
+
+ if (hwTabIndex == 0) {
+ if ((typeof hashtable[hashid] !== 'undefined') &&
+ (hashtable[hashid]["vlan_awareness"] == "AWARE")) {
+ if (typeof console == "object"){
+ console.log("VLAN AWARE hashid:"+hashid);
+ }
+ showvlan.find('input[name=vswitchvlanid]').val(hashtable[hashid]["vlan_id"]);
+ showvlan.find('select[name=vswitchporttype]').val(hashtable[hashid]["port_type"]);
+ showvlan.show();
+ } else {
+ showvlan.find('input[name=vswitchvlanid]').val("default");
+ showvlan.find('select[name=vswitchporttype]').val("default");
+ showvlan.hide();
+ }
+ var userDirectoryEntry = generateUserEntry(userId, "XCAT", memory, privilege, profile, cpuCount, network, ipl, hcp, networktext, tabId, hashid);
+ $('#' + tabId + ' textarea').val(userDirectoryEntry);
+ }
+ });
+
+ } else {
+ var privilege = [];
+ $('#' + tabId + ' input[name=privilege]:checked').each(function () {
+ privilege.push($(this).val());
+ });
+ privilege = privilege.join('');
+
+ // Find device to be IPL
+ var diskRows = $('#' + tabId + ' table:eq(0):visible tbody tr');
+ var ipl;
+ for (var i = 0; i < diskRows.length; i++) {
+ var diskArgs = diskRows.eq(i).find('td');
+ var address = diskArgs.eq(2).find('input').val();
+ if (diskArgs.eq(7).find('input').attr("checked") === true) {
+ ipl = address;
+ break;
+ }
+ }
+
+ // Check if zFCP loaddev checked, if so ipl the fcp card
+ var zfcpRows = $('#' + tabId + ' table:eq(1):visible tbody tr');
+ if (zfcpRows.length > 0) {
+ for ( var i = 0; i < zfcpRows.length; i++) {
+ var diskArgs = zfcpRows.eq(i).find('td');
+ var address = diskArgs.eq(1).find('input').val();
+ // This is either true or false
+ var loaddev = diskArgs.eq(7).find('input').attr('checked');
+ if (loaddev) {
+ ipl = address;
+ }
+ }
+ }
+
+ // Only update directory entry if the basic tab is selected
+ var inst = tabId.replace('zvmProvisionTab', '');
+ var hwTabIndex = $("#hwConfig" + inst).tabs('option', 'selected');
+ var showvlan = $('#' + tabId).find('#vlandiv'); // Vlan information only for basic tab if vswitch is vlan aware
+
+ if (hwTabIndex == 0) {
+ if (hashtable[hashid]["vlan_awareness"] == "AWARE") {
+ if (typeof console == "object"){
+ console.log("VLAN AWARE hashid:"+hashid);
+ }
+ showvlan.find('input[name=vswitchvlanid]').val(hashtable[hashid]["vlan_id"]);
+ showvlan.find('select[name=vswitchporttype]').val(hashtable[hashid]["port_type"]);
+ showvlan.show();
+ } else {
+ showvlan.find('input[name=vswitchvlanid]').val("default");
+ showvlan.find('select[name=vswitchporttype]').val("default");
+ showvlan.hide();
+ }
+ var userDirectoryEntry = generateUserEntry(userId, "XCAT", memory, privilege, profile, cpuCount, network, ipl, hcp, networktext, tabId, hashid);
+ $('#' + tabId + ' textarea').val(userDirectoryEntry);
+ }
+ }
+
+ } else {
+ var hashid = '';
+ var privilege = [];
+ $('#' + tabId + ' input[name=privilege]:checked').each(function () {
+ privilege.push($(this).val());
+ });
+ privilege = privilege.join('');
+
+ // Find device to be IPL
+ var diskRows = $('#' + tabId + ' table:eq(0):visible tbody tr');
+ var ipl;
+ for (var i = 0; i < diskRows.length; i++) {
+ var diskArgs = diskRows.eq(i).find('td');
+ var address = diskArgs.eq(2).find('input').val();
+ if (diskArgs.eq(7).find('input').attr("checked") === true) {
+ ipl = address;
+ break;
+ }
+ }
+
+ // Check if zFCP loaddev checked, if so ipl the fcp card
+ var zfcpRows = $('#' + tabId + ' table:eq(1):visible tbody tr');
+ if (zfcpRows.length > 0) {
+ for ( var i = 0; i < zfcpRows.length; i++) {
+ var diskArgs = zfcpRows.eq(i).find('td');
+ var address = diskArgs.eq(1).find('input').val();
+ // This is either true or false
+ var loaddev = diskArgs.eq(7).find('input').attr('checked');
+ if (loaddev) {
+ ipl = address;
+ }
+ }
+ }
+
+ // Only update directory entry if the basic tab is selected
+ var inst = tabId.replace('zvmProvisionTab', '');
+ var hwTabIndex = $("#hwConfig" + inst).tabs('option', 'selected');
+ if (hwTabIndex == 0) {
+ var userDirectoryEntry = generateUserEntry(userId, "XCAT", memory, privilege, profile, cpuCount, network, ipl, hcp, networktext, tabId, hashid);
+ $('#' + tabId + ' textarea').val(userDirectoryEntry);
+ }
+ }
+
+}
+
+/**
+ * Generate a user directory entry
+ *
+ * @param userId User Id
+ * @param password User password
+ * @param memory Memory to assign to virtual machine
+ * @param privilege User privilege class
+ * @param profile User profile
+ * @param cpuCount Number of CPU to assign to virtual machine
+ * @param network Network interface used by virtual machine
+ * @param ipl The device to be IPL
+ * @param hcp The hcp for this user
+ * @param networktext string containing network info
+ * @param tabId The current tab identifier
+ * @param hashid If a vswitch, then the hash index, else empty
+ * string
+ *
+ * @returns User directory entry
+ */
+function generateUserEntry(userId, password, memory, privilege, profile, cpuCount, network, ipl, hcp, networktext, tabId, hashid) {
+ var userDirectoryEntry = "USER " + userId + " XCAT " + memory + " " + memory + " " + privilege + "\n";
+ var hashtable = getselectedNetworkHash();
+
+ // Include user profile if there is one
+ if (profile) {
+ userDirectoryEntry += "INCLUDE " + profile + "\n";
+ }
+
+ // Only up to 8 CPU can be assigned
+ for (var i = 0; i < cpuCount; i++) {
+ userDirectoryEntry += "CPU 0" + i + "\n";
+ }
+
+ // Set device IPL
+ if (ipl) {
+ userDirectoryEntry += "IPL " + ipl + "\n";
+ }
+
+ if (typeof console == "object"){
+ console.log("Entering generateUserEntry. userid "+userId +" network: " + network + " tabid "+tabId);
+ }
+
+ userDirectoryEntry += "MACHINE ESA\n"; // Simulate s390 architecture
+
+ // Include network vswitch grant command if given, must be before NICDEF (or other devices)
+ if (network.length > 0) {
+ // Check for VSWITCH and vlan value
+ if (networktext.indexOf('VSWITCH') > -1) {
+ var tokens = networktext.split(' ');
+ var dirmcmd = "COMMAND SET VSWITCH "+tokens[2]+ " GRANT "+ userId;
+ if ((typeof hashtable[hashid] !== 'undefined') &&
+ ("vlan_awareness" in hashtable[hashid])) {
+ var vlanaware = hashtable[hashid]["vlan_awareness"];
+ if (vlanaware == 'AWARE') {
+
+ // Did they pick a port type and vlanid?
+ var uiport = $('#' + tabId + ' select[name=vswitchporttype]').val();
+ var uilanid = $('#' + tabId + ' input[name=vswitchvlanid]').val();
+
+ if (uiport.length > 0 && uiport != "default") {
+ dirmcmd += " PORTTYPE " + uiport;
+ }
+ if (uilanid.length > 0 && uilanid != "default") {
+ dirmcmd += " VLAN " + uilanid;
+ }
+ }
+ } else {
+ if (typeof console == "object"){
+ console.log("**** NO VSWITCH info found in hash or the hashtable with key "+hashid + " is undefined.");
+ }
+ }
+ userDirectoryEntry += dirmcmd +"\n";
+ }
+ }
+ userDirectoryEntry += "CONSOLE 0009 3215 T\n";
+ if (network.length > 0) {
+ userDirectoryEntry += "NICDEF 0A00 " + network + "\n";
+ }
+
+ userDirectoryEntry += "SPOOL 000C 2540 READER *\n";
+ userDirectoryEntry += "SPOOL 000D 2540 PUNCH A\n";
+ userDirectoryEntry += "SPOOL 000E 1403 A\n";
+
+ if (typeof console == "object"){
+ console.log("Exiting generateUserEntry. Directory created:"+userDirectoryEntry);
+ }
+
+ return userDirectoryEntry;
+}
+
+/**
+ * Convert a string (e.g. 1024M) into GB
+ *
+ * @param size The string containing the size
+ * @return Size in GB
+ */
+function convertString2Gb(size) {
+ var sizeGb = 0;
+ if (size.indexOf('G') != -1) {
+ sizeGb = parseInt(size);
+ } else if (size.indexOf('M') != -1) {
+ sizeGb = parseInt(size)*1024;
+ }
+
+ return sizeGb;
+}
+
+/**
+ * Convert a given number of cylinders into GB
+ *
+ * @param cylinders Number of cylinders
+ * @return Size in GB
+ */
+function convertCylinders2Gb(cylinders) {
+ var bytes = cylinders * 737280;
+ var sizeGb = bytes/(1024*1024*1024);
+ sizeGb = Math.round(sizeGb * 10)/10; // Round to 1 decimal place
+
+ return sizeGb;
+}
+
+/**
+ * Convert a given number of blocks into GB
+ *
+ * @param blocks Number of blocks
+ * @return Size in GB
+ */
+function convertBlocks2Gb(blocks) {
+ var sizeGb = blocks/(2048*1024);
+ sizeGb = Math.round(sizeGb * 10)/10; // Round to 1 decimal place
+
+ return sizeGb;
+}
+
+/**
+ * Get the network Vswitch details in a hash table
+ *
+ * @param hcp The hardware ccontrol point for this vswitch
+ * @param vswitch name from "VSWITCH SYSTEM switchname"
+ * @param hash id key
+ * @parma table id or ''
+ *
+ * @returns nothing (sets global variable
+ * selectedNetworkHash[tabId]
+ */
+function getNetworkDetails(hcpNode, vswitchname, hashId, tabId) {
+ if (typeof console == "object") {
+ console.log("Entering getNetworkDetails. HashId:" + hashId + " tabId<" + tabId + ">");
+ }
+
+ // Get network details
+ $.ajax( {
+ url: 'lib/cmd.php',
+ dataType: 'json',
+ data: {
+ cmd: 'lsvm',
+ tgt: hcpNode,
+ args: '--getnetwork;' + vswitchname + ';VSWITCH',
+ msg: 'hcp=' + hcpNode + ';type=VSWITCH' + ';network=' + vswitchname + ';hashindex=' + hashId
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+
+ var vlanid = "";
+ var vlanaware = "";
+ var args = data.msg.split(';');
+ var hcp = args[0].replace('hcp=', '');
+ var type = args[1].replace('type=', '');
+ var name = jQuery.trim(args[2].replace('network=', ''));
+ var hashindex = jQuery.trim(args[3].replace('hashindex=', ''));
+ var hashtable = getselectedNetworkHash();
+ var foundInvalid = 0;
+ // The SMAPI code can return "Invalid" for spg_scope so we need to skip this condition
+ if (data.rsp.length && (data.rsp[0].indexOf("Invalid") > -1) ) {
+ foundInvalid = 1;
+ if (data.rsp[0].indexOf("spg_scope: Invalid"> -1) ) {
+ foundInvalid = 0;
+ }
+ }
+ if (!hashtable) {
+ hashtable = [[]];
+ setselectedNetworkHash(hashtable);
+
+ if (typeof console == "object") {
+ console.log("getNetworkDetails. creating new hash[[]] table!!" + "hashindex<" + hashindex + ">" );
+ }
+ }
+ if (data.rsp.length && (data.rsp[0].indexOf("Failed") > -1 || (foundInvalid == 1) || data.rsp[0].indexOf("Error") > -1 ) ) {
+ if (typeof console == "object") {
+ console.log("getNetworkDetails. failure getting the network data for " + hcpNode + " network "+ vswitchname);
+ }
+ // Create warning dialog
+ var warning = createWarnBar('Failure getting network data for hardware control point ' + hcpNode + ' The hcp field must be a xCAT node name.');
+ var warnDialog = $('
').append(warning);
+
+ // highlight the hcp field
+ if (tabId.length >0) {
+ $('#' + tabId).find('input[name=hcpNode]').css('border', 'solid #FF0000 1px');
+ }
+
+ // Open warning dialog
+ warnDialog.dialog({
+ title:'Warning',
+ modal: true,
+ close: function(){
+ $(this).remove();
+ },
+ width: 400,
+ buttons: {
+ "Ok": function() {
+ $(this).dialog("close");
+ }
+ }
+ });
+ }
+ var tmp = data.rsp[0].split(hcp + ': ');
+ for (var i = 1; i < tmp.length; i++) {
+ var dataline = tmp[i];
+ var keyval;
+ if (dataline.indexOf(':') > -1) {
+ keyval = dataline.split(':');
+ } else {
+ keyval = dataline.split(' ');
+ }
+ keyval[0] = jQuery.trim(keyval[0]);
+ keyval[1] = jQuery.trim(keyval[1]);
+ if (typeof hashtable[hashindex] === 'undefined') {
+ hashtable[hashindex] = [];
+ }
+
+ hashtable[hashindex][keyval[0]] = keyval[1];
+ }
+ }
+ });
+ return;
+}
+
+
+/**
+ * Set a cookie for the zhcp node name for a specific node
+ *
+ * @param data Data from HTTP request
+ */
+function setNodeZhcpNodename(data) {
+ if (data.rsp.length && data.rsp[0].indexOf("Failed") == -1 && data.rsp[0].indexOf("Error") == -1 ) {
+ var savedTokens = data.msg.split(';');
+ var node = savedTokens[0];
+ var hcphostname = savedTokens[1];
+ var nodename;
+ var hostname;
+
+ for (var i in data.rsp) {
+ nodename = data.rsp[i][0];
+ hostname = data.rsp[i][1];
+ if (hostname == hcphostname) {
+ if (typeof console == "object"){
+ console.log("SetNodeZhcpNodename cookie set for node "+node+" using zhcp nodename "+nodename);
+ }
+ // Set cookie to expire in 60 minutes
+ var exDate = new Date();
+ exDate.setTime(exDate.getTime() + (60 * 60 * 1000));
+ $.cookie('xcat_' + node+'_hcpnodename', nodename, { expires: exDate, path: '/xcat', secure:true });
+ }
+ }
+ }
+}
diff --git a/xCAT-UI/js/help/help.js b/xCAT-UI/js/help/help.js
index 95d77b677..aee8f7149 100644
--- a/xCAT-UI/js/help/help.js
+++ b/xCAT-UI/js/help/help.js
@@ -1,924 +1,927 @@
-/**
- * Global variables
- */
-var helpTab; // Help tabs
-var ivpChoices = new Array;
-var ivpChoiceValues = new Array;
-var selectInfo = new Object();
-var xcatVerTabId = '';
-
-
-/**
- * Load the help page and create the tabs.
- */
-function loadHelpPage(){
- createHelpTab();
- createVerifyXCATTab();
-}
-
-/**
- * Create the Help Tab
- *
- * @return Tab object
- */
-function createHelpTab(){
- // Create help tab
- var tab = new Tab();
- setHelpTab(tab);
- tab.init();
- $('#content').append(tab.object());
-
- var helpForm = $('
');
- helpForm.append(
- '' +
- 'Quick Start ' +
- '' +
- '' +
- '1. View defined nodes View node definitions by groups in a table. ' +
- '2. Manage operating system images View operating system images defined in xCAT. Copy operating system ISOs into xCAT. ' +
- '3. Provision nodes Create virtual machines. Install an operating system onto virtual machines. ' +
- '4. Manage and provision storage and networks Create network devices. Define storage for systems. ' +
- ' ' +
- ' ' +
- '' +
- 'Settings ' +
- '' +
- '' +
- 'a. Manage and control user access ' +
- 'b. Edit the xCAT database tables ' +
- ' ' +
- ' ');
- tab.add('helpTab', 'Help', helpForm, false);
-}
-
-
-/**
- * Create the Verify xCAT Tab
- *
- * @return Tab object
- */
-function createVerifyXCATTab() {
- var comments = 'Name of the IVP run';
- var ivpEnabled = 'checked';
- var ivpDisabled = '';
-
- // Get the tab
- var tab = getHelpTab();
- var fs, legend;
-
- // Generate new tab ID
- var instance = 0;
- xcatVerTabId = 'verifyXCATTab' + instance;
-
- // Build the list of IVPs in the table
- readIvpTable( 'NEW' );
-
- // Create info bar and status bar
- var introBarId = 'verifyXCATIntroBar' + instance;
- var introBar = createStatusBar(introBarId);
- introBar.find('div').append(
- ' ' +
- 'Run, schedule or remove Installation Verification Procedures. ' +
- '' +
- 'The IVP consists of a basic IVP and a full IVP. ' +
- 'The basic IVP validates the xCAT and SMAPI environments with tests that include ' +
- 'checking for access to the ZHCP agents and verifying disk space. ' +
- 'The full IVP validates the OpenStack compute node in addition to the xCAT ' +
- 'and SMAPI environments. ' +
- '
' +
- 'The IVP is composed of multiple components which can take additional parameters '+
- 'depending on the type of IVP. ' +
- 'The parameters shown on this panel will vary based on the type of IVP that is chosen. ' +
- '
' +
- '- The orchestrator, xCAT verifynode command, coordinates the functions of the IVP. ' +
- 'For a full IVP, the orchestrator transmits an analysis script known as the ' +
- 'preparation script for an OpenStack compute node, invokes it and obtains ' +
- 'the output of the script. ' +
- '
' +
- '- The IVP preparation script analyzes an OpenStack compute node and its OpenStack ' +
- 'configuration files as they related to z/VM. ' +
- 'The preparation script produces a driver script that is used to ' +
- 'continue IVP processing with information gathered during the analysis. ' +
- 'The preparations scripts are located in the /opt/xcat/share/xcat/tools/zvm/ ' +
- 'directory on the CMA system that is running xCAT. ' +
- 'The name of the script begins with \'prep_zxcatIVP_\' and ends with \'.pl\'. ' +
- 'The middle part of the name is the human readable identifier of the OpenStack release, ' +
- 'eg. prep_zxcatIVP_NEWTON.pl for the OpenStack Newton release. ' +
- '
' +
- '- The main IVP script, zxcatIVP.pl, handles the analysis of the xCAT environment. ' +
- 'When invoked as part of a basic IVP, it verifies the xCAT environment as it relates ' +
- 'to the xCAT Management Node, the ZHCP agent, z/VM SMAPI and CP. ' +
- 'When invoked as part of a full IVP, it is invoked by the driver script and uses the ' +
- 'OpenStack configuration options to verify the environment. This is similar to the tests ' +
- 'performed by the basic IVP but the tests relate to the OpenStack compute node, ' +
- 'the related z/VM and the ZHCP agent for that z/VM hypervisor ' +
- 'instead of running tests for all ZHCP agents and disk pools. ' +
- 'A full IVP drives a number of additional tests that are not part of the basic IVP. ' +
- '
' +
- 'Three buttons at the bottom of the panel drive the tasks: ' +
- '\'Run...\' button immediately starts an IVP with the parameters specified on the panel. ' +
- '\'Save...\' button schedules an IVP to be run or modifies the settings of an existing scheduled IVP. ' +
- '\'Remove...\' button removes the indicated scheduled IVP. ' +
- 'Note: xCAT creates default IVPs when it detects that no IVPs are defined. ' +
- 'For this reason, you do not want to remove all IVPs unless you want xCAT to recreate the ' +
- 'default IVPs the next hour that it checks for IVPs to run.' +
- '
' +
- 'ID of Run: ' +
- 'Begin by selecting the either \'New\' or the Id of an existing run. ' +
- 'Information about the run will be ' +
- 'be filled in from the details in the xCAT zvmivp table, if it exists.' +
- '
' +
- 'Type of IVP Run: ' +
- 'Select the type of run based on whether a basic IVP of the xCAT MN and all of its ' +
- 'ZHCP agents or a full IVP related to OpenStack and the xCAT MN, and the ZHCP related to ' +
- 'the compute node. ' +
- '
' +
- 'Orchestrator Parameters: ' +
- 'The most often used orchestrator operand is the --ignore operand to inform ' +
- 'verifynode that it should ignore a specific warning. ' +
- 'This prevents you from being notified by the IVP about a known condition that you ' +
- 'do not consider an error. ' +
- '' +
- 'Preparation Script Parameters: ' +
- 'The preparation script supports the --ignore operand to ' +
- 'ignore the specified messages. ' +
- 'Sometimes your environment may have a configuration which you consider valid ' +
- 'that would produce a warning message. By using this operand, you instruct ' +
- 'the preparation script that the warning should not be considered a problem. ' +
- 'This avoids false warnings. ' +
- 'For more information on possible preparation script operands, invoke the ' +
- 'script that is for your level of OpenStack with the --help operand. '+
- '' +
- 'If you are running CMA as an OpenStack controller then no additional parameters ' +
- 'required to verify the controller\'s environment. If wish to verify an OpenStack ' +
- 'compute node on another system then some additional parameters will be required. ' +
- '
' +
- 'OpenStack System IP Address: ' +
- 'You need to provide the IP address of the compute node that you would like to test. ' +
- '
' +
- 'OpenStack User: ' +
- 'The user name that is allowed to access the OpenStack configuration files. ' +
- 'The IVP uses that information to send the preparation script and run it on the ' +
- 'compute node. ' +
- '
' +
- 'Main IVP Script Parameters: ' +
- 'As with the orchestrator and preparation script, a field exists to provide ' +
- 'tailoring to the main IVP script. ' +
- 'The most commonly used operand is the --ignore operand to ' +
- 'ignore the listed messages. ' +
- 'For more information on possible main IVP script operands, invoke the ' +
- 'script as follows: /opt/xcat/bin/zxcatIVP.pl --help '+
- '' +
- 'Scheduling related parameters: ' +
- 'If you are going to schedule an IVP run then some additional operands are of interest ' +
- 'to you.' +
- '
' +
- 'Schedule: ' +
- 'The schedule operand indicates when the IVP should be run. ' +
- 'You can select it to be run every hour of the day or specify the hours. ' +
- '
' +
- 'Name: ' +
- 'The name operand allows you to associate a descriptive name with the run. ' +
- 'This allows you to easily recognize a specific run in the \'ID or Run\' field. ' +
- '
' +
- 'Disable: ' +
- 'The disable checkbox allows you to temporarily disable an IVP from running. '
- );
-
- var statBarId = 'verifyXCATStatusBar' + instance;
- var statBar = createStatusBar(statBarId).hide();
- var loader = createLoader( '' );
- statBar.find('div').append( loader );
-
- // Create the verify form and put info and status bars on the form.
- var verifyXCATForm = $( '
' );
- verifyXCATForm.append( introBar, statBar );
-
- // Create 'Create a Verify xCAT' fieldset
- fs = $( ' ' );
- fs.append( $( 'Verify: ' ));
- fs.append( $( 'ID of Run: '
- + ''
- + ' '
- + '
' ));
- fs.append( $(''
- + 'Type of IVP Run: '
- + ' Basic IVP: xCAT MN/ZHCP Verification '
- + ' Full IVP: xCAT MN/ZHCP and OpenStack Verification'
- + '
' ));
- fs.append( $(''
- + 'Run Parameters: '
- + 'Orchestrator Script Parameters: '
- + 'Main IVP Script Parameters: '
- + '
' ));
- divFullParms = xcatVerTabId + "_divFullParms";
- fs.append( $(''
- + 'OpenStack System IP Address: '
- + 'OpenStack user: '
- + 'Preparation Script Parameters: '
- + '
' ));
- fs.append( $(''
- + '
Automation Parameters: '
- +
- '
'
- + '
'
- + 'Name: '
- + ' Disable this run'
- +
- '
'));
- verifyXCATForm.append( fs );
- verifyXCATForm.find('#' + divFullParms).hide();
-
- //************************************************************************
- // Function: Show appropriate division based on the runType.
- //************************************************************************
- verifyXCATForm.change(function(){
- var runType = $(this).parent().find('input[name="runType"]:checked').val();
- if ( runType == 'verifyBasic' ) {
- verifyXCATForm.find('#' + divFullParms).hide();
- } else if ( runType == 'verifyOpenStack' ) {
- verifyXCATForm.find('#' + divFullParms).show();
- } else {
- verifyXCATForm.find('#' + divFullParms).hide();
- }
- });
-
- //************************************************************************
- // Function: Run immediately button.
- //************************************************************************
- var verifyBtn = createButton( 'Run this IVP Now' );
- verifyBtn.click(function() {
- var driveFunction = 1;
- var argList = '';
-
- // Remove any warning messages
- $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
-
- var runType = $(this).parent().find('input[name="runType"]:checked').val();
- if ( runType == 'verifyBasic' ) {
- argList += '||--basicivp';
- } else if ( runType == 'verifyOpenStack' ) {
- argList += '||--fullivp';
- var openstackIP = $(this).parent().find('input[name=openstackIP]').val();
- if ( openstackIP != '' ) {
- argList += '||--openstackip ' + openstackIP;
- } else {
- // Show an information message.
- $('#' + statBarId).find('div').append(
- 'You did not specify the IP address of the OpenStack system. The IVP ' +
- 'will use the IP address of the system running the xCAT management node as ' +
- 'the OpenStack IP address. ');
- }
- var openstackUser = $(this).parent().find('input[name=openstackUser]').val();
- if ( openstackUser != '' ) {
- argList += '||--openstackuser ' + hexEncode( openstackUser );
- }
- var prepParms = $(this).parent().find('input[name=prepParms]').val();
- if ( prepParms != '' ) {
- argList += '||--prepparms ' + hexEncode( prepParms );
- }
- } else {
- // Show warning message
- var warn = createWarnBar('You did not select a basic or full IVP.');
- warn.prependTo($(this).parents('.ui-tabs-panel'));
- driveFunction = 0;
- }
- var orchParms = $(this).parent().find('input[name=orchParms]').val();
- if ( orchParms != '' ) {
- argList += '||--orchparms ' + hexEncode( orchParms );
- }
- var mainParms = $(this).parent().find('input[name=mainParms]').val();
- if ( mainParms != '' ) {
- argList += '||--zxcatparms ' + hexEncode( mainParms );
- }
- argList += '||end';
-
- if ( driveFunction == 1 ) {
- $('#' + statBarId).find('div').append( 'Invoking verifynode to run the IVP. ' );
- $('#' + statBarId).find('img').show();
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'verifynode '+ argList,
- msg : 'out=' + statBarId + ';cmd=verifynode'
- },
- success : updateStatusBar
- });
-
- // Show status bar
- statBar.show();
- }
- });
- verifyXCATForm.append( verifyBtn );
-
- //************************************************************************
- // Function: Save an IVP button.
- //************************************************************************
- var scheduleBtn = createButton( 'Save this IVP Run' );
- scheduleBtn.click(function() {
- var driveFunction = 1;
- var argList = '';
-
- // Remove any warning messages
- $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
-
- var ivpId = $(this).parent().find('select[name=ivpId]').val();
- if ( ivpId != 'NEW' ) {
- argList += '||--id ' + ivpId;
- }
- var runType = $(this).parent().find('input[name="runType"]:checked').val();
- if ( runType == 'verifyBasic' ) {
- argList += '||--type basicivp';
- } else if ( runType == 'verifyOpenStack' ) {
- argList += '||--type fullivp';
- var openstackIP = $(this).parent().find('input[name=openstackIP]').val();
- if ( openstackIP != '' ) {
- argList = argList + '||--openstackip ' + openstackIP;
- } else {
- // Show an information message.
- $('#' + statBarId).find('div').append(
- 'You did not specify the IP address of the OpenStack system. The IVP ' +
- 'will use the IP address of the system running the xCAT management node as ' +
- 'the OpenStack IP address. ');
- }
- var openstackUser = $(this).parent().find('input[name=openstackUser]').val();
- if ( openstackUser != '' ) {
- argList += '||--openstackuser ' + hexEncode( openstackUser );
- } else {
- argList += '||--openstackuser \'\'';
- }
- var prepParms = $(this).parent().find('input[name=prepParms]').val();
- if ( prepParms != '' ) {
- argList += '||--prepparms ' + hexEncode( prepParms );
- } else {
- argList += '||--prepparms \'\'';
- }
- } else {
- // Show warning message
- var warn = createWarnBar('You did not select a basic or full IVP.');
- warn.prependTo($(this).parents('.ui-tabs-panel'));
- driveFunction = 0;
- }
- var ivpSchedule = "";
- var checkboxes = $(this).parent().find('input[name="ivpSchedule"]:checked');
- var everyHourChecked = $(this).parent().find('input[name="ivpSchedule"][value=24]').is(':checked')
- if ( everyHourChecked ) {
- ivpSchedule = '0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23';
- } else {
- for ( var i=0, n=checkboxes.length; i' );
- $('#' + statBarId).find('img').show();
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'verifynode '+ argList,
- msg : 'out=' + statBarId + ';cmd=verifynode;ivpId=' + ivpId
- },
- success : function(data) {
- updateStatusBar(data);
- var args = data.msg.split(';');
- var ivpId = '';
- for ( var i=0; i < args.length; i++ ) {
- if ( args[i].match('^ivpId=') ) {
- ivpId = args[i].replace('ivpId=', '');
- }
- }
- readIvpTable( 'NEW' );
- }
- });
-
- // Show status bar
- statBar.show();
- }
- });
- verifyXCATForm.append( scheduleBtn );
-
- //************************************************************************
- // Function: Remove an IVP button.
- //************************************************************************
- var removeBtn = createButton( 'Remove this IVP Run' );
- removeBtn.click(function() {
- var driveFunction = 1;
- var argList = '';
-
- // Remove any warning messages
- $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
-
- var ivpId = $(this).parent().find('select[name=ivpId]').val();
- if ( ivpId != 'NEW' ) {
- argList = '||--remove' + '||--id ' + ivpId + '||end';
- } else {
- // Show warning message
- var warn = createWarnBar('You did not select the ID of an existing run.');
- warn.prependTo($(this).parents('.ui-tabs-panel'));
- driveFunction = 0;
- }
-
- if ( driveFunction == 1 ) {
- $('#' + statBarId).find('div').append( 'Invoking verifynode to remove the IVP. ' );
- $('#' + statBarId).find('img').show();
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'verifynode '+ argList,
- msg : 'out=' + statBarId + ';cmd=verifynode'
- },
- success : function(data) {
- updateStatusBar(data);
- readIvpTable( 'NEW' );
- }
- });
-
- // Show status bar
- statBar.show();
- }
- });
- verifyXCATForm.append( removeBtn );
-
- tab.add( xcatVerTabId, 'Verify xCAT', verifyXCATForm, false );
-}
-
-
-/**
- * Check each hour checkbox when the "Every Hour" checkbox is checked.
- *
- * @param cb checkbox object that was checked or unchecked.
- */
-function everyHourClick( cb ) {
- if ( cb.checked ) {
- for (var i = 0; i <= 23; i++){
- var thisField = $( '#' + xcatVerTabId + ' input[name=ivpSchedule][value='+i+']' );
- thisField.attr( 'checked', true );
- }
- }
-}
-
-
-/**
- * Get node tab
- *
- * @return Tab object
- */
-function getHelpTab() {
- return helpTab;
-}
-
-
-/**
- * Decodes a printable hex string back into the javascript
- * unicode string that it represents.
- *
- * @param hexVal Printable hex string to convert
- * back into its original javascript string form.
- */
-hexDecode = function( hexVal ){
- var result = "";
-
- if ( hexVal.match("^HexEncoded:") ) {
- hexVal = hexVal.replace( 'HexEncoded:', '' );
- var hexes = hexVal.match(/.{1,4}/g) || [];
- for( var i = 0; i < hexes.length; i++ ) {
- result += String.fromCharCode( parseInt( hexes[i], 16 ) );
- }
- } else {
- result = hexVal;
- }
-
- return result;
-}
-
-
-/**
- * Encode a string into printable hex. This avoids
- * an issues with escaping quotes or handling unicode.
- *
- * @param str String to encode into printable hex.
- */
-function hexEncode( str ){
- var hex;
-
- var result = 'HexEncoded:';
- for (var i=0; i < str.length; i++) {
- hex = str.charCodeAt(i).toString(16);
- result += ("000"+hex).slice(-4);
- }
-
- return result;
-}
-
-
-/**
- * Handle click of an hour checkbox to uncheck the 24 hour checkbox, if this
- * was an uncheck of the hour.
- *
- * @param cb checkbox object that was checked or unchecked.
- */
-function hourClick( cb ) {
- if ( ! cb.checked ) {
- var thisField = $( '#' + xcatVerTabId + ' input[name=ivpSchedule][value="24"]' );
- thisField.attr( 'checked', false );
- }
-}
-
-
-/**
- * Drive the tabdump API to obtain the scheduled IVP information.
- *
- * @param ivpId - Id of the IVP for which we should setup the panel fields
- * after the read. Currently, it is required to be 'NEW'.
- */
-function readIvpTable( ivpId ) {
- if ( typeof console == "object" ) {
- console.log( "Entering readIvpTable(" + ivpId + ")" );
-}
-
- // Get IVP information
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'tabdump',
- tgt : '',
- args : 'zvmivp',
- msg : 'ivpId=' + ivpId
- },
-
- success : function( data ) {
- setArrays( data );
- var ivpId = data.msg.replace('ivpId=', '');
- setVarsForId( ivpId );
- }
- });
-}
-
-
-/**
- * Setup the arrays/hashes with the data from the zvmivp table
- *
- * @param data Data from HTTP request
- */
-function setArrays(data) {
- if ( typeof console == "object" ) {
- console.log( "Entering setArrays(" + data.rsp + ")" );
- }
-
- // Get response
- var rsp = data.rsp;
-
- // Clear the list of IVP information.
- ivpChoices = new Array();
- ivpChoiceValues = new Array();
- selectInfo = new Object();
-
- // Get column value
- var idPos = 0;
- var ipPos = 0;
- var schedulePos = 0;
- var lrPos = 0;
- var torPos = 0;
- var aUserPos = 0;
- var oParmsPos = 0;
- var pParmsPos = 0;
- var mainParmsPos = 0;
- var cmntPos = 0;
-
- var colNameArray = rsp[0].substr(1).split(',');
- for ( var i in colNameArray ) {
- switch ( colNameArray[i] ) {
- case 'id':
- idPos = i;
- break;
- case 'ip':
- ipPos = i;
- break;
- case 'schedule':
- schedulePos = i;
- break;
- case 'last_run':
- lrPos = i;
- break;
- case 'type_of_run':
- typeOfRunPos = i;
- break;
- case 'access_user':
- aUserPos = i;
- break;
- case 'orch_parms':
- oParmsPos = i;
- break;
- case 'prep_parms':
- pParmsPos = i;
- break;
- case 'main_ivp_parms':
- mainParmsPos = i;
- break;
- case 'comments':
- cmntPos = i;
- break;
- case 'disable':
- disablePos = i;
- break;
- default :
- break;
- }
- }
-
- // Get IVP information from the table data.
- for (var i = 1; i < rsp.length; i++) {
- var cols = rsp[i].split(',');
- var id = cols[idPos].replace(new RegExp('"', 'g'), '');
- var ip = cols[ipPos].replace(new RegExp('"', 'g'), '');
- var schedule = cols[schedulePos].replace(new RegExp('"', 'g'), '');
- var typeOfRun = cols[typeOfRunPos].replace(new RegExp('"', 'g'), '');
- var openstackUser = cols[aUserPos].replace(new RegExp('"', 'g'), '');
- var orchParms = cols[oParmsPos].replace(new RegExp('"', 'g'), '');
- var prepParms = cols[pParmsPos].replace(new RegExp('"', 'g'), '');
- var mainParms = cols[mainParmsPos].replace(new RegExp('"', 'g'), '');
- var comments = cols[cmntPos].replace(new RegExp('"', 'g'), '');
- var disable = cols[disablePos].replace(new RegExp('"', 'g'), '');
-
- ivpChoiceValues.push( id );
- selectInfo[id] = new Object();
- selectInfo[id]['id'] = id;
- selectInfo[id]['ip'] = ip;
- selectInfo[id]['schedule'] = schedule;
- selectInfo[id]['typeOfRun'] = typeOfRun.toLowerCase();
- selectInfo[id]['openstackUser'] = hexDecode( openstackUser );
- selectInfo[id]['orchParms'] = hexDecode( orchParms );
- selectInfo[id]['prepParms'] = hexDecode( prepParms );
- selectInfo[id]['mainParms'] = hexDecode( mainParms );
- selectInfo[id]['comments'] = hexDecode(comments);
- selectInfo[id]['disable'] = disable.toLowerCase();
- }
-
- // Sort the choices so we get a pretty list and build the choice strings.
- ivpChoiceValues.sort( function(a, b) {
- if ( ! isNaN(a) && ! isNaN(b) ) {
- // Both are numbers, do a numeric compare
- return a-b;
- } else if ( isNaN(a) && isNaN(b) ) {
- // Both are strings, do a string compare
- return a.localeCompare( b );
- } else if ( isNaN(a) ) {
- // Strings go after numbers
- return 1;
- } else {
- // Numbers go before strings
- return -1;
- }
- } );
- ivpChoiceValues.forEach( function( id ) {
- var idComments;
- if ( selectInfo[id]['comments'] != '' ) {
- idComments = id + ': ' + selectInfo[id]['comments'];
- } else {
- idComments = id + ': A comment was not specified.';
- }
- ivpChoices.push( idComments );
- }, this);
-
- // Clear out a hash element for the 'NEW' choice.
- selectInfo['NEW'] = new Object();
- selectInfo['NEW']['id'] = '';
- selectInfo['NEW']['ip'] = '';
- selectInfo['NEW']['schedule'] = '';
- selectInfo['NEW']['typeOfRun'] = '';
- selectInfo['NEW']['openstackUser'] = '';
- selectInfo['NEW']['orchParms'] = '';
- selectInfo['NEW']['prepParms'] = '';
- selectInfo['NEW']['mainParms'] = '';
- selectInfo['NEW']['comments'] = '';
- selectInfo['NEW']['disable'] = '';
-
- // Add in the NEW option at the top of the array.
- ivpChoices.unshift( "NEW: New IVP" );
- ivpChoiceValues.unshift( "NEW" );
-
- // Construct the new Select option choices
- var ivpChoicesLen = ivpChoices.length;
- var selectIdOptions = '';
- for ( var i = 0; i < ivpChoicesLen; i++ ) {
- selectIdOptions += '' + ivpChoices[i] + ' ';
- }
-
- // Find the division containing the select and replace its contents
- var thisIvpSelect = $( '#' + xcatVerTabId + ' select[name=ivpId]' );
- thisIvpSelect.children().remove();
- thisIvpSelect.append( selectIdOptions );
-}
-
-
-/**
- * Set node tab
- *
- * @param tab
- * Tab object
- * @return Nothing
- */
-function setHelpTab(tab) {
- helpTab = tab;
-}
-
-
-/**
- * Set IVP variables based on the chosen Id
- *
- * @param data Data from HTTP request
- */
-function setVarsForId( id ) {
- if ( typeof console == "object" ) {
- console.log( "Entering setVarsForId(" + id + ")" );
- }
-
- var thisField = $( '#' + xcatVerTabId + ' input[name="runType"]' );
- if ( selectInfo[id]['typeOfRun'] == 'basicivp' ) {
- thisField.val(['verifyBasic']);
- } else if ( selectInfo[id]['typeOfRun'] == 'fullivp' ) {
- thisField.val(['verifyOpenStack']);
- } else {
- thisField.val([]);
- }
-
- thisField = $( '#' + xcatVerTabId + ' input[name=orchParms]' );
- thisField.val( selectInfo[id]['orchParms'] );
-
- thisField = $( '#' + xcatVerTabId + ' input[name=prepParms]' );
- thisField.val( selectInfo[id]['prepParms'] );
-
- var thisfield = $( '#' + xcatVerTabId + ' input[name=mainParms]' );
- thisfield.val( selectInfo[id]['mainParms'] );
-
- thisField = $( '#' + xcatVerTabId + ' input[name=openstackIP]' );
- thisField.val( selectInfo[id]['ip'] );
-
- thisField = $( '#' + xcatVerTabId + ' input[name=openstackUser]' );
- thisField.val( selectInfo[id]['openstackUser'] );
-
- var hours = new Object();
- var fullDay = 1;
- var hour = selectInfo[id]['schedule'].split(' ');
- for ( var j = 0; j < hour.length; j++ ) {
- hours[hour[j]] = 1;
- }
-
- for (var i = 0; i <= 23; i++) {
- thisField = $( '#' + xcatVerTabId + ' input[name=ivpSchedule][value='+i+']' );
- if ( hours[i] == 1 ) {
- thisField.attr( 'checked', true );
- } else {
- fullDay = 0;
- thisField.attr( 'checked', false );
- }
- }
- if ( fullDay == 1 ) {
- thisField = $( '#' + xcatVerTabId + ' input[name=ivpSchedule][value=24]' );
- thisField.attr( 'checked', true );
- } else {
- thisField = $( '#' + xcatVerTabId + " input[name=ivpSchedule][value=24]" );
- thisField.attr( 'checked', false );
- }
-
- thisField = $( '#' + xcatVerTabId + ' input[name=comments]' );
- thisField.val( selectInfo[id]['comments'] );
-
- thisField = $( '#' + xcatVerTabId + ' input[name=disableRun][value=disabled]' );
- if ( selectInfo[id]['disable'] == 1 || selectInfo[id]['disable'] == 'yes' ) {
- thisField.attr( 'checked', true );
- } else {
- thisField.attr( 'checked', false );
- }
-}
-
-
-/**
- * Update status bar of a given tab
- *
- * @param data Data returned from HTTP request
- */
-function updateStatusBar(data) {
- if ( typeof console == "object" ) {
- console.log( "Entering updateStatusBar(\nmsg: " + data.msg + "\nrsp: " + data.rsp + ")" );
- }
-
- // Get ajax response
- var rsp = data.rsp;
- var args = data.msg.split(';');
- var statBarId = '';
- var cmd = '';
- for ( var i=0; i < args.length; i++ ) {
- if ( args[i].match('^cmd=') ) {
- cmd = args[i].replace('cmd=', '');
- } else if ( args[i].match('^out=') ) {
- statBarId = args[i].replace('out=', '');
- }
- }
-
- if (cmd == 'verifynode') {
- // Hide loader
- $('#' + statBarId).find('img').hide();
-
- // Write ajax response to status bar
- var prg = writeRsp(rsp, '');
- $('#' + statBarId).find('div').append(prg);
-
- // Put a check box after the response.
- var icon = $(' ').css({
- 'vertical-align': 'top'
- });
- $('#' + statBarId).find( 'div' ).append(icon);
- $('#' + statBarId).find( 'div' ).append( ' ' );
- } else {
- // Hide loader
- $('#' + statBarId).find('img').hide();
-
- // Write ajax response to status bar
- var prg = writeRsp(rsp, '');
- $('#' + statBarId).find('div').append(prg);
- }
-}
+/**
+ * Global variables
+ */
+var helpTab; // Help tabs
+var ivpChoices = new Array;
+var ivpChoiceValues = new Array;
+var selectInfo = new Object();
+var xcatVerTabId = '';
+
+
+/**
+ * Load the help page and create the tabs.
+ */
+function loadHelpPage(){
+ createHelpTab();
+ createVerifyXCATTab();
+}
+
+/**
+ * Create the Help Tab
+ *
+ * @return Tab object
+ */
+function createHelpTab() {
+ // Create help tab
+ var tab = new Tab();
+ setHelpTab(tab);
+ tab.init();
+ $('#content').append(tab.object());
+
+ var helpForm = $('
');
+ helpForm.append(
+ '' +
+ 'Quick Start ' +
+ '' +
+ '' +
+ '1. View defined nodes View node definitions by groups in a table. ' +
+ '2. Manage operating system images View operating system images defined in xCAT. Copy operating system ISOs into xCAT. ' +
+ '3. Provision nodes Create virtual machines. Install an operating system onto virtual machines. ' +
+ '4. Manage and provision storage and networks Create network devices. Define storage for systems. ' +
+ ' ' +
+ ' ' +
+ '' +
+ 'Settings ' +
+ '' +
+ '' +
+ 'a. Manage and control user access ' +
+ 'b. Edit the xCAT database tables ' +
+ ' ' +
+ ' ');
+ tab.add('helpTab', 'Help', helpForm, false);
+}
+
+
+/**
+ * Create the Verify xCAT Tab
+ *
+ * @return Tab object
+ */
+function createVerifyXCATTab() {
+ var comments = 'Name of the IVP run';
+ var ivpEnabled = 'checked';
+ var ivpDisabled = '';
+
+ // Get the tab
+ var tab = getHelpTab();
+ var fs, legend;
+
+ // Generate new tab ID
+ var instance = 0;
+ xcatVerTabId = 'verifyXCATTab' + instance;
+
+ // Build the list of IVPs in the table
+ readIvpTable( 'NEW' );
+
+ // Create info bar and status bar
+ var introBarId = 'verifyXCATIntroBar' + instance;
+ var introBar = createStatusBar(introBarId);
+ introBar.find('div').append(
+ ' ' +
+ 'Run, schedule or remove Installation Verification Procedures. ' +
+ '' +
+ 'The IVP consists of a basic IVP and a full IVP. ' +
+ 'The basic IVP validates the xCAT and SMAPI environments with tests that include ' +
+ 'checking for access to the ZHCP agents and verifying disk space. ' +
+ 'The full IVP validates the OpenStack compute node in addition to the xCAT ' +
+ 'and SMAPI environments. ' +
+ '
' +
+ 'The IVP is composed of multiple components which can take additional parameters '+
+ 'depending on the type of IVP. ' +
+ 'The parameters shown on this panel will vary based on the type of IVP that is chosen. ' +
+ '
' +
+ '- The orchestrator, xCAT verifynode command, coordinates the functions of the IVP. ' +
+ 'For a full IVP, the orchestrator transmits an analysis script known as the ' +
+ 'preparation script for an OpenStack compute node, invokes it and obtains ' +
+ 'the output of the script. ' +
+ '
' +
+ '- The IVP preparation script analyzes an OpenStack compute node and its OpenStack ' +
+ 'configuration files as they related to z/VM. ' +
+ 'The preparation script produces a driver script that is used to ' +
+ 'continue IVP processing with information gathered during the analysis. ' +
+ 'The preparations scripts are located in the /opt/xcat/share/xcat/tools/zvm/ ' +
+ 'directory on the CMA system that is running xCAT. ' +
+ 'The name of the script begins with \'prep_zxcatIVP_\' and ends with \'.pl\'. ' +
+ 'The middle part of the name is the human readable identifier of the OpenStack release, ' +
+ 'eg. prep_zxcatIVP_NEWTON.pl for the OpenStack Newton release. ' +
+ '
' +
+ '- The main IVP script, zxcatIVP.pl, handles the analysis of the xCAT environment. ' +
+ 'When invoked as part of a basic IVP, it verifies the xCAT environment as it relates ' +
+ 'to the xCAT Management Node, the ZHCP agent, z/VM SMAPI and CP. ' +
+ 'When invoked as part of a full IVP, it is invoked by the driver script and uses the ' +
+ 'OpenStack configuration options to verify the environment. This is similar to the tests ' +
+ 'performed by the basic IVP but the tests relate to the OpenStack compute node, ' +
+ 'the related z/VM and the ZHCP agent for that z/VM hypervisor ' +
+ 'instead of running tests for all ZHCP agents and disk pools. ' +
+ 'A full IVP drives a number of additional tests that are not part of the basic IVP. ' +
+ '
' +
+ 'Three buttons at the bottom of the panel drive the tasks: ' +
+ '\'Run...\' button immediately starts an IVP with the parameters specified on the panel. ' +
+ '\'Save...\' button schedules an IVP to be run or modifies the settings of an existing scheduled IVP. ' +
+ '\'Remove...\' button removes the indicated scheduled IVP. ' +
+ 'Note: xCAT creates default IVPs when it detects that no IVPs are defined. ' +
+ 'For this reason, you do not want to remove all IVPs unless you want xCAT to recreate the ' +
+ 'default IVPs the next hour that it checks for IVPs to run.' +
+ '
' +
+ 'ID of Run: ' +
+ 'Begin by selecting the either \'New\' or the Id of an existing run. ' +
+ 'Information about the run will be ' +
+ 'be filled in from the details in the xCAT zvmivp table, if it exists.' +
+ '
' +
+ 'Type of IVP Run: ' +
+ 'Select the type of run based on whether a basic IVP of the xCAT MN and all of its ' +
+ 'ZHCP agents or a full IVP related to OpenStack and the xCAT MN, and the ZHCP related to ' +
+ 'the compute node. ' +
+ '
' +
+ 'Orchestrator Parameters: ' +
+ 'The most often used orchestrator operand is the --ignore operand to inform ' +
+ 'verifynode that it should ignore a specific warning. ' +
+ 'This prevents you from being notified by the IVP about a known condition that you ' +
+ 'do not consider an error. ' +
+ '' +
+ 'Preparation Script Parameters: ' +
+ 'The preparation script supports the --ignore operand to ' +
+ 'ignore the specified messages. ' +
+ 'Sometimes your environment may have a configuration which you consider valid ' +
+ 'that would produce a warning message. By using this operand, you instruct ' +
+ 'the preparation script that the warning should not be considered a problem. ' +
+ 'This avoids false warnings. ' +
+ 'For more information on possible preparation script operands, invoke the ' +
+ 'script that is for your level of OpenStack with the --help operand. '+
+ '' +
+ 'If you are running CMA as an OpenStack controller then no additional parameters ' +
+ 'required to verify the controller\'s environment. If wish to verify an OpenStack ' +
+ 'compute node on another system then some additional parameters will be required. ' +
+ '
' +
+ 'OpenStack System IP Address: ' +
+ 'You need to provide the IP address of the compute node that you would like to test. ' +
+ '
' +
+ 'OpenStack User: ' +
+ 'The user name that is allowed to access the OpenStack configuration files. ' +
+ 'The IVP uses that information to send the preparation script and run it on the ' +
+ 'compute node. ' +
+ '
' +
+ 'Main IVP Script Parameters: ' +
+ 'As with the orchestrator and preparation script, a field exists to provide ' +
+ 'tailoring to the main IVP script. ' +
+ 'The most commonly used operand is the --ignore operand to ' +
+ 'ignore the listed messages. ' +
+ 'For more information on possible main IVP script operands, invoke the ' +
+ 'script as follows: /opt/xcat/bin/zxcatIVP.pl --help '+
+ '' +
+ 'Scheduling related parameters: ' +
+ 'If you are going to schedule an IVP run then some additional operands are of interest ' +
+ 'to you.' +
+ '
' +
+ 'Schedule: ' +
+ 'The schedule operand indicates when the IVP should be run. ' +
+ 'You can select it to be run every hour of the day or specify the hours. ' +
+ '
' +
+ 'Name: ' +
+ 'The name operand allows you to associate a descriptive name with the run. ' +
+ 'This allows you to easily recognize a specific run in the \'ID or Run\' field. ' +
+ '
' +
+ 'Disable: ' +
+ 'The disable checkbox allows you to temporarily disable an IVP from running. '
+ );
+
+ var statBarId = 'verifyXCATStatusBar' + instance;
+ var statBar = createStatusBar(statBarId).hide();
+ var loader = createLoader( '' );
+ statBar.find('div').append( loader );
+
+ // Create the verify form and put info and status bars on the form.
+ var verifyXCATForm = $( '
' );
+ verifyXCATForm.append( introBar, statBar );
+
+ // Create 'Create a Verify xCAT' fieldset
+ fs = $( ' ' );
+ fs.append( $( 'Verify: ' ));
+ fs.append( $( 'ID of Run: '
+ + ''
+ + ' '
+ + '
' ));
+ fs.append( $(''
+ + 'Type of IVP Run: '
+ + ' Basic IVP: xCAT MN/ZHCP Verification '
+ + ' Full IVP: xCAT MN/ZHCP and OpenStack Verification'
+ + '
' ));
+ fs.append( $(''
+ + 'Run Parameters: '
+ + 'Orchestrator Script Parameters: '
+ + 'Main IVP Script Parameters: '
+ + '
' ));
+ divFullParms = xcatVerTabId + "_divFullParms";
+ fs.append( $(''
+ + 'OpenStack System IP Address: '
+ + 'OpenStack user: '
+ + 'Preparation Script Parameters: '
+ + '
' ));
+ fs.append( $(''
+ + '
Automation Parameters: '
+ + '
'
+ + '
'
+ + 'Name: '
+ + ' Disable this run'
+ + '
'));
+ verifyXCATForm.append( fs );
+ verifyXCATForm.find('#' + divFullParms).hide();
+
+ //************************************************************************
+ // Function: Show appropriate division based on the runType.
+ //************************************************************************
+ verifyXCATForm.change(function(){
+ var runType = $(this).parent().find('input[name="runType"]:checked').val();
+ if ( runType == 'verifyBasic' ) {
+ verifyXCATForm.find('#' + divFullParms).hide();
+ } else if ( runType == 'verifyOpenStack' ) {
+ verifyXCATForm.find('#' + divFullParms).show();
+ } else {
+ verifyXCATForm.find('#' + divFullParms).hide();
+ }
+ });
+
+ //************************************************************************
+ // Function: Run immediately button.
+ //************************************************************************
+ var verifyBtn = createButton( 'Run this IVP Now' );
+ verifyBtn.click(function() {
+ var driveFunction = 1;
+ var argList = '';
+
+ // Remove any warning messages
+ $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
+
+ var runType = $(this).parent().find('input[name="runType"]:checked').val();
+ if ( runType == 'verifyBasic' ) {
+ argList += '||--basicivp';
+ } else if ( runType == 'verifyOpenStack' ) {
+ argList += '||--fullivp';
+ var openstackIP = $(this).parent().find('input[name=openstackIP]').val();
+ if ( openstackIP != '' ) {
+ argList += '||--openstackip ' + openstackIP;
+ } else {
+ // Show an information message.
+ $('#' + statBarId).find('div').append(
+ 'You did not specify the IP address of the OpenStack system. The IVP ' +
+ 'will use the IP address of the system running the xCAT management node as ' +
+ 'the OpenStack IP address. ');
+ }
+ var openstackUser = $(this).parent().find('input[name=openstackUser]').val();
+ if ( openstackUser != '' ) {
+ argList += '||--openstackuser ' + hexEncode( openstackUser );
+ }
+ var prepParms = $(this).parent().find('input[name=prepParms]').val();
+ if ( prepParms != '' ) {
+ argList += '||--prepparms ' + hexEncode( prepParms );
+ }
+ } else {
+ // Show warning message
+ var warn = createWarnBar('You did not select a basic or full IVP.');
+ warn.prependTo($(this).parents('.ui-tabs-panel'));
+ driveFunction = 0;
+ }
+ var orchParms = $(this).parent().find('input[name=orchParms]').val();
+ if ( orchParms != '' ) {
+ argList += '||--orchparms ' + hexEncode( orchParms );
+ }
+ var mainParms = $(this).parent().find('input[name=mainParms]').val();
+ if ( mainParms != '' ) {
+ argList += '||--zxcatparms ' + hexEncode( mainParms );
+ }
+ argList += '||end';
+
+ if ( driveFunction == 1 ) {
+ $('#' + statBarId).find('div').append( 'Invoking verifynode to run the IVP. ' );
+ $('#' + statBarId).find('img').show();
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'verifynode '+ argList,
+ msg : 'out=' + statBarId + ';cmd=verifynode'
+ },
+ success : function(data) {
+ data = decodeRsp(data);
+ updateStatusBar(data);
+ }
+ });
+
+ // Show status bar
+ statBar.show();
+ }
+ });
+ verifyXCATForm.append( verifyBtn );
+
+ //************************************************************************
+ // Function: Save an IVP button.
+ //************************************************************************
+ var scheduleBtn = createButton( 'Save this IVP Run' );
+ scheduleBtn.click(function() {
+ var driveFunction = 1;
+ var argList = '';
+
+ // Remove any warning messages
+ $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
+
+ var ivpId = $(this).parent().find('select[name=ivpId]').val();
+ if ( ivpId != 'NEW' ) {
+ argList += '||--id ' + ivpId;
+ }
+ var runType = $(this).parent().find('input[name="runType"]:checked').val();
+ if ( runType == 'verifyBasic' ) {
+ argList += '||--type basicivp';
+ } else if ( runType == 'verifyOpenStack' ) {
+ argList += '||--type fullivp';
+ var openstackIP = $(this).parent().find('input[name=openstackIP]').val();
+ if ( openstackIP != '' ) {
+ argList = argList + '||--openstackip ' + openstackIP;
+ } else {
+ // Show an information message.
+ $('#' + statBarId).find('div').append(
+ 'You did not specify the IP address of the OpenStack system. The IVP ' +
+ 'will use the IP address of the system running the xCAT management node as ' +
+ 'the OpenStack IP address. ');
+ }
+ var openstackUser = $(this).parent().find('input[name=openstackUser]').val();
+ if ( openstackUser != '' ) {
+ argList += '||--openstackuser ' + hexEncode( openstackUser );
+ } else {
+ argList += '||--openstackuser \'\'';
+ }
+ var prepParms = $(this).parent().find('input[name=prepParms]').val();
+ if ( prepParms != '' ) {
+ argList += '||--prepparms ' + hexEncode( prepParms );
+ } else {
+ argList += '||--prepparms \'\'';
+ }
+ } else {
+ // Show warning message
+ var warn = createWarnBar('You did not select a basic or full IVP.');
+ warn.prependTo($(this).parents('.ui-tabs-panel'));
+ driveFunction = 0;
+ }
+ var ivpSchedule = "";
+ var checkboxes = $(this).parent().find('input[name="ivpSchedule"]:checked');
+ var everyHourChecked = $(this).parent().find('input[name="ivpSchedule"][value=24]').is(':checked')
+ if ( everyHourChecked ) {
+ ivpSchedule = '0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23';
+ } else {
+ for ( var i=0, n=checkboxes.length; i' );
+ $('#' + statBarId).find('img').show();
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'verifynode '+ argList,
+ msg : 'out=' + statBarId + ';cmd=verifynode;ivpId=' + ivpId
+ },
+ success : function( data ) {
+ data = decodeRsp(data);
+ updateStatusBar( data );
+ var args = data.msg.split(';');
+ var ivpId = '';
+ for ( var i=0; i < args.length; i++ ) {
+ if ( args[i].match('^ivpId=') ) {
+ ivpId = args[i].replace('ivpId=', '');
+ }
+ }
+ readIvpTable( 'NEW' );
+ }
+ });
+
+ // Show status bar
+ statBar.show();
+ }
+ });
+ verifyXCATForm.append( scheduleBtn );
+
+ //************************************************************************
+ // Function: Remove an IVP button.
+ //************************************************************************
+ var removeBtn = createButton( 'Remove this IVP Run' );
+ removeBtn.click(function() {
+ var driveFunction = 1;
+ var argList = '';
+
+ // Remove any warning messages
+ $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
+
+ var ivpId = $(this).parent().find('select[name=ivpId]').val();
+ if ( ivpId != 'NEW' ) {
+ argList = '||--remove' + '||--id ' + ivpId + '||end';
+ } else {
+ // Show warning message
+ var warn = createWarnBar('You did not select the ID of an existing run.');
+ warn.prependTo($(this).parents('.ui-tabs-panel'));
+ driveFunction = 0;
+ }
+
+ if ( driveFunction == 1 ) {
+ $('#' + statBarId).find('div').append( 'Invoking verifynode to remove the IVP. ' );
+ $('#' + statBarId).find('img').show();
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'verifynode '+ argList,
+ msg : 'out=' + statBarId + ';cmd=verifynode'
+ },
+ success : function( data ) {
+ data = decodeRsp(data);
+ updateStatusBar( data );
+ readIvpTable( 'NEW' );
+ }
+ });
+
+ // Show status bar
+ statBar.show();
+ }
+ });
+ verifyXCATForm.append( removeBtn );
+
+ tab.add( xcatVerTabId, 'Verify xCAT', verifyXCATForm, false );
+
+}
+
+
+/**
+ * Check each hour checkbox when the "Every Hour" checkbox is checked.
+ *
+ * @param cb checkbox object that was checked or unchecked.
+ */
+function everyHourClick( cb ) {
+ if ( cb.checked ) {
+ for (var i = 0; i <= 23; i++) {
+ var thisField = $( '#' + xcatVerTabId + ' input[name=ivpSchedule][value='+i+']' );
+ thisField.attr( 'checked', true );
+ }
+ }
+}
+
+
+/**
+ * Get node tab
+ *
+ * @return Tab object
+ */
+function getHelpTab() {
+ return helpTab;
+}
+
+
+/**
+ * Decodes a printable hex string back into the javascript
+ * unicode string that it represents.
+ *
+ * @param hexVal Printable hex string to convert
+ * back into its original javascript string form.
+ */
+hexDecode = function( hexVal ){
+ var result = "";
+
+ if ( hexVal.match("^HexEncoded:") ) {
+ hexVal = hexVal.replace( 'HexEncoded:', '' );
+ var hexes = hexVal.match(/.{1,4}/g) || [];
+ for( var i = 0; i < hexes.length; i++ ) {
+ result += String.fromCharCode( parseInt( hexes[i], 16 ) );
+ }
+ } else {
+ result = hexVal;
+ }
+
+ return result;
+}
+
+
+/**
+ * Encode a string into printable hex. This avoids
+ * an issues with escaping quotes or handling unicode.
+ *
+ * @param str String to encode into printable hex.
+ */
+function hexEncode( str ){
+ var hex;
+
+ var result = 'HexEncoded:';
+ for (var i=0; i < str.length; i++) {
+ hex = str.charCodeAt(i).toString(16);
+ result += ("000"+hex).slice(-4);
+ }
+
+ return result;
+}
+
+
+/**
+ * Handle click of an hour checkbox to uncheck the 24 hour checkbox, if this
+ * was an uncheck of the hour.
+ *
+ * @param cb checkbox object that was checked or unchecked.
+ */
+function hourClick( cb ) {
+ if ( ! cb.checked ) {
+ var thisField = $( '#' + xcatVerTabId + ' input[name=ivpSchedule][value="24"]' );
+ thisField.attr( 'checked', false );
+ }
+}
+
+
+/**
+ * Drive the tabdump API to obtain the scheduled IVP information.
+ *
+ * @param ivpId - Id of the IVP for which we should setup the panel fields
+ * after the read. Currently, it is required to be 'NEW'.
+ */
+function readIvpTable( ivpId ) {
+ if ( typeof console == "object" ) {
+ console.log( "Entering readIvpTable(" + ivpId + ")" );
+ }
+
+ // Get IVP information
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'tabdump',
+ tgt : '',
+ args : 'zvmivp',
+ msg : 'ivpId=' + ivpId
+ },
+
+ success : function( data ) {
+ data = decodeRsp(data);
+ setArrays( data );
+ var ivpId = data.msg.replace('ivpId=', '');
+ setVarsForId( ivpId );
+ }
+ });
+}
+
+
+/**
+ * Setup the arrays/hashes with the data from the zvmivp table
+ *
+ * @param data Data from HTTP request
+ */
+function setArrays( data ) {
+ if ( typeof console == "object" ){
+ console.log( "Entering setArrays(" + data.rsp + ")" );
+ }
+
+ // Get response
+ var rsp = data.rsp;
+
+ // Clear the list of IVP information.
+ ivpChoices = new Array();
+ ivpChoiceValues = new Array();
+ selectInfo = new Object();
+
+ // Get column value
+ var idPos = 0;
+ var ipPos = 0;
+ var schedulePos = 0;
+ var lrPos = 0;
+ var torPos = 0;
+ var aUserPos = 0;
+ var oParmsPos = 0;
+ var pParmsPos = 0;
+ var mainParmsPos = 0;
+ var cmntPos = 0;
+
+ var colNameArray = rsp[0].substr(1).split(',');
+ for ( var i in colNameArray ) {
+ switch ( colNameArray[i] ) {
+ case 'id':
+ idPos = i;
+ break;
+ case 'ip':
+ ipPos = i;
+ break;
+ case 'schedule':
+ schedulePos = i;
+ break;
+ case 'last_run':
+ lrPos = i;
+ break;
+ case 'type_of_run':
+ typeOfRunPos = i;
+ break;
+ case 'access_user':
+ aUserPos = i;
+ break;
+ case 'orch_parms':
+ oParmsPos = i;
+ break;
+ case 'prep_parms':
+ pParmsPos = i;
+ break;
+ case 'main_ivp_parms':
+ mainParmsPos = i;
+ break;
+ case 'comments':
+ cmntPos = i;
+ break;
+ case 'disable':
+ disablePos = i;
+ break;
+ default :
+ break;
+ }
+ }
+
+ // Get IVP information from the table data.
+ for (var i = 1; i < rsp.length; i++) {
+ var cols = rsp[i].split(',');
+ var id = cols[idPos].replace(new RegExp('"', 'g'), '');
+ var ip = cols[ipPos].replace(new RegExp('"', 'g'), '');
+ var schedule = cols[schedulePos].replace(new RegExp('"', 'g'), '');
+ var typeOfRun = cols[typeOfRunPos].replace(new RegExp('"', 'g'), '');
+ var openstackUser = cols[aUserPos].replace(new RegExp('"', 'g'), '');
+ var orchParms = cols[oParmsPos].replace(new RegExp('"', 'g'), '');
+ var prepParms = cols[pParmsPos].replace(new RegExp('"', 'g'), '');
+ var mainParms = cols[mainParmsPos].replace(new RegExp('"', 'g'), '');
+ var comments = cols[cmntPos].replace(new RegExp('"', 'g'), '');
+ var disable = cols[disablePos].replace(new RegExp('"', 'g'), '');
+
+ ivpChoiceValues.push( id );
+ selectInfo[id] = new Object();
+ selectInfo[id]['id'] = id;
+ selectInfo[id]['ip'] = ip;
+ selectInfo[id]['schedule'] = schedule;
+ selectInfo[id]['typeOfRun'] = typeOfRun.toLowerCase();
+ selectInfo[id]['openstackUser'] = hexDecode( openstackUser );
+ selectInfo[id]['orchParms'] = hexDecode( orchParms );
+ selectInfo[id]['prepParms'] = hexDecode( prepParms );
+ selectInfo[id]['mainParms'] = hexDecode( mainParms );
+ selectInfo[id]['comments'] = hexDecode(comments);
+ selectInfo[id]['disable'] = disable.toLowerCase();
+ }
+
+ // Sort the choices so we get a pretty list and build the choice strings.
+ ivpChoiceValues.sort( function(a, b) {
+ if ( ! isNaN(a) && ! isNaN(b) ) {
+ // Both are numbers, do a numeric compare
+ return a-b;
+ } else if ( isNaN(a) && isNaN(b) ) {
+ // Both are strings, do a string compare
+ return a.localeCompare( b );
+ } else if ( isNaN(a) ) {
+ // Strings go after numbers
+ return 1;
+ } else {
+ // Numbers go before strings
+ return -1;
+ }
+ } );
+ ivpChoiceValues.forEach( function( id ) {
+ var idComments;
+ if ( selectInfo[id]['comments'] != '' ) {
+ idComments = id + ': ' + selectInfo[id]['comments'];
+ } else {
+ idComments = id + ': A comment was not specified.';
+ }
+ ivpChoices.push( idComments );
+ }, this);
+
+ // Clear out a hash element for the 'NEW' choice.
+ selectInfo['NEW'] = new Object();
+ selectInfo['NEW']['id'] = '';
+ selectInfo['NEW']['ip'] = '';
+ selectInfo['NEW']['schedule'] = '';
+ selectInfo['NEW']['typeOfRun'] = '';
+ selectInfo['NEW']['openstackUser'] = '';
+ selectInfo['NEW']['orchParms'] = '';
+ selectInfo['NEW']['prepParms'] = '';
+ selectInfo['NEW']['mainParms'] = '';
+ selectInfo['NEW']['comments'] = '';
+ selectInfo['NEW']['disable'] = '';
+
+ // Add in the NEW option at the top of the array.
+ ivpChoices.unshift( "NEW: New IVP" );
+ ivpChoiceValues.unshift( "NEW" );
+
+ // Construct the new Select option choices
+ var ivpChoicesLen = ivpChoices.length;
+ var selectIdOptions = '';
+ for ( var i = 0; i < ivpChoicesLen; i++ ) {
+ selectIdOptions += '' + ivpChoices[i] + ' ';
+ }
+
+ // Find the division containing the select and replace its contents
+ var thisIvpSelect = $( '#' + xcatVerTabId + ' select[name=ivpId]' );
+ thisIvpSelect.children().remove();
+ thisIvpSelect.append( selectIdOptions );
+}
+
+
+/**
+ * Set node tab
+ *
+ * @param tab
+ * Tab object
+ * @return Nothing
+ */
+function setHelpTab(tab) {
+ helpTab = tab;
+}
+
+
+/**
+ * Set IVP variables based on the chosen Id
+ *
+ * @param data Data from HTTP request
+ */
+function setVarsForId( id ) {
+ if ( typeof console == "object" ) {
+ console.log( "Entering setVarsForId(" + id + ")" );
+ }
+
+ var thisField = $( '#' + xcatVerTabId + ' input[name="runType"]' );
+ if ( selectInfo[id]['typeOfRun'] == 'basicivp' ) {
+ thisField.val(['verifyBasic']);
+ } else if ( selectInfo[id]['typeOfRun'] == 'fullivp' ) {
+ thisField.val(['verifyOpenStack']);
+ } else {
+ thisField.val([]);
+ }
+
+ thisField = $( '#' + xcatVerTabId + ' input[name=orchParms]' );
+ thisField.val( selectInfo[id]['orchParms'] );
+
+ thisField = $( '#' + xcatVerTabId + ' input[name=prepParms]' );
+ thisField.val( selectInfo[id]['prepParms'] );
+
+ var thisfield = $( '#' + xcatVerTabId + ' input[name=mainParms]' );
+ thisfield.val( selectInfo[id]['mainParms'] );
+
+ thisField = $( '#' + xcatVerTabId + ' input[name=openstackIP]' );
+ thisField.val( selectInfo[id]['ip'] );
+
+ thisField = $( '#' + xcatVerTabId + ' input[name=openstackUser]' );
+ thisField.val( selectInfo[id]['openstackUser'] );
+
+ var hours = new Object();
+ var fullDay = 1;
+ var hour = selectInfo[id]['schedule'].split(' ');
+ for ( var j = 0; j < hour.length; j++ ) {
+ hours[hour[j]] = 1;
+ }
+
+ for (var i = 0; i <= 23; i++) {
+ thisField = $( '#' + xcatVerTabId + ' input[name=ivpSchedule][value='+i+']' );
+ if ( hours[i] == 1 ) {
+ thisField.attr( 'checked', true );
+ } else {
+ fullDay = 0;
+ thisField.attr( 'checked', false );
+ }
+ }
+ if ( fullDay == 1 ) {
+ thisField = $( '#' + xcatVerTabId + ' input[name=ivpSchedule][value=24]' );
+ thisField.attr( 'checked', true );
+ } else {
+ thisField = $( '#' + xcatVerTabId + " input[name=ivpSchedule][value=24]" );
+ thisField.attr( 'checked', false );
+ }
+
+ thisField = $( '#' + xcatVerTabId + ' input[name=comments]' );
+ thisField.val( selectInfo[id]['comments'] );
+
+ thisField = $( '#' + xcatVerTabId + ' input[name=disableRun][value=disabled]' );
+ if ( selectInfo[id]['disable'] == 1 || selectInfo[id]['disable'] == 'yes' ) {
+ thisField.attr( 'checked', true );
+ } else {
+ thisField.attr( 'checked', false );
+ }
+}
+
+
+/**
+ * Update status bar of a given tab
+ *
+ * @param data Data returned from HTTP request
+ */
+function updateStatusBar(data) {
+ if ( typeof console == "object" ) {
+ console.log( "Entering updateStatusBar(\nmsg: " + data.msg + "\nrsp: " + data.rsp + ")" );
+ }
+
+ // Get ajax response
+ var rsp = data.rsp;
+ var args = data.msg.split(';');
+ var statBarId = '';
+ var cmd = '';
+ for ( var i=0; i < args.length; i++ ) {
+ if ( args[i].match('^cmd=') ) {
+ cmd = args[i].replace('cmd=', '');
+ } else if ( args[i].match('^out=') ) {
+ statBarId = args[i].replace('out=', '');
+ }
+ }
+
+ if (cmd == 'verifynode') {
+ // Hide loader
+ $('#' + statBarId).find('img').hide();
+
+ // Write ajax response to status bar
+ var prg = writeRsp(rsp, '');
+ $('#' + statBarId).find('div').append(prg);
+
+ // Put a check box after the response.
+ var icon = $(' ').css({
+ 'vertical-align': 'top'
+ });
+ $('#' + statBarId).find( 'div' ).append(icon);
+ $('#' + statBarId).find( 'div' ).append( ' ' );
+ } else {
+ // Hide loader
+ $('#' + statBarId).find('img').hide();
+
+ // Write ajax response to status bar
+ var prg = writeRsp(rsp, '');
+ $('#' + statBarId).find('div').append(prg);
+ }
+}
\ No newline at end of file
diff --git a/xCAT-UI/js/monitor/gangliamon.js b/xCAT-UI/js/monitor/gangliamon.js
index 411d6a382..7aadafbab 100644
--- a/xCAT-UI/js/monitor/gangliamon.js
+++ b/xCAT-UI/js/monitor/gangliamon.js
@@ -1,1046 +1,1058 @@
-/**
- * Global variables
- */
-
-// Save grid summary data, update every one minute
-var gridData;
-
-// Save nodes path, used for getting detail from rrd file
-var nodePath = new Object();
-
-// Save nodes current status,
-// unknown = -2, error = -1, warning = 0, normal = 1 are used for sorting
-var nodeStatus = new Object();
-
-// Update timer
-var gangliaTimer;
-
-// Global frame hash
-var framehash;
-// Global cec hash
-var cechash;
-// Global blade hash
-var bladehash;
-// Global x rack hash
-var rackhash;
-// Global other type node hash
-var otherhash;
-
-/**
- * Load Ganglia monitoring tool
- *
- * @return Nothing
- */
-function loadGangliaMon() {
- $('#gangliamon').append(createInfoBar('Checking RPMs'));
-
- // Get groups and set cookie
- if (!$.cookie('xcat_groups')) {
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'extnoderange',
- tgt : '/.*',
- args : 'subgroups',
- msg : ''
- },
-
- success : setGroupsCookies
- });
- }
-
- // Check whether Ganglia RPMs are installed on the xCAT MN
- $.ajax({
- url : 'lib/systemcmd.php',
- dataType : 'json',
- data : {
- cmd : 'rpm -q rrdtool ganglia-gmetad ganglia-gmond'
- },
-
- success : checkGangliaRPMs
- });
- return;
-}
-
-/**
- * Check whether Ganglia RPMs are installed
- *
- * @param data Data returned from HTTP request
- */
-function checkGangliaRPMs(data) {
- var gangliaTab = $('#gangliamon');
- gangliaTab.empty();
-
- // Get the list of Ganglia RPMs installed
- var status = data.rsp.split(/\n/);
- var gangliaRPMs = ["rrdtool", "ganglia-gmetad", "ganglia-gmond"];
- var warningMsg = 'Before continuing, please install the following packages: ';
- var missingRPMs = false;
- for (var i in status) {
- if (status[i].indexOf("not installed") > -1) {
- warningMsg += gangliaRPMs[i] + ' ';
- missingRPMs = true;
- }
- }
-
- // Append Ganglia PDF
- if (missingRPMs) {
- var warningBar = createWarnBar(warningMsg);
- warningBar.css('margin-bottom', '10px');
- warningBar.prependTo(gangliaTab);
- } else {
- gangliaTab.append(createInfoBar('Checking running status'));
-
- // Check if ganglia is running on the xCAT MN
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'monls',
- tgt : '',
- args : 'gangliamon',
- msg : ''
- },
-
- success : checkGangliaRunning
- });
- }
-
- return;
-}
-
-/**
- * Check whether Ganglia is running
- *
- * @param data Data returned from HTTP request
- */
-function checkGangliaRunning(data) {
- var gangliaTab = $('#gangliamon');
- gangliaTab.empty();
-
- // If Ganglia is not started
- if (data.rsp[0].indexOf("not-monitored") > -1) {
- // Create link to start Ganglia
- var startLnk = $('Click here ');
- startLnk.css({
- 'color' : 'blue',
- 'text-decoration' : 'none'
- });
- startLnk.click(function() {
- // Turn on Ganglia for all nodes
- monitorNode('', 'on');
- });
-
- // Create warning bar
- var warningBar = $('
');
- var msg = $('
').css({
- 'display': 'inline-block',
- 'width': '90%'
- });
- var icon = $(' ').css({
- 'display': 'inline-block',
- 'margin': '10px 5px'
- });
- warningBar.append(icon);
- msg.append('Please start Ganglia on xCAT. ');
- msg.append(startLnk);
- msg.append(' to start Ganglia.');
- warningBar.append(msg);
- warningBar.css('margin-bottom', '10px');
-
- // If there are any warning messages, append this warning after it
- var curWarnings = $('#gangliamon').find('.ui-state-error');
-
- if (curWarnings.length) {
- curWarnings.after(warningBar);
- } else {
- warningBar.prependTo(gangliaTab);
- }
-
- return;
- }
-
- // Legend for node status
- var legend = '' +
- ' Normal ' +
- ' Heavy Load ' +
- ' Error ' +
- ' Unknown ' +
- '
';
-
- // Gganglia grid overview
- var showStr = '
Grid Overview ' +
- '[Hide]
' +
- '
' +
- '
Current Nodes Status ' + legend + '
' +
- 'All Nodes
' +
- '
';
- gangliaTab.append(showStr);
-
- // Get summary data and draw on page
- $('#gangliaGridSummary').append('Getting grid summary data ');
- sendGridSummaryAjax();
-
- // Get all nodes location data which can support the zoom monitor
- $('#gangliaNodes').append('Getting all nodes status ');
- sendLocationAjax();
-
- // Bind the hide/show button event
- $('#gangliamon #hidesup').bind('click', function(){
- if ('[Hide]' == $(this).text()) {
- $(this).html('[Show]');
- } else {
- $(this).html('[Hide]');
- }
-
- $('#gangliaGridSummary').toggle();
- });
-}
-
-/**
- * Send AJAX request to get all nodes parent and position to create hardware hierarchy hash
- */
-function sendLocationAjax() {
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'graph',
- msg : ''
- },
-
- success: function(data){
- if (!data.rsp[0]) {
- return;
- }
-
- extractLocationlData(data.rsp[0]);
- // Get nodes current status and draw on the page
- sendNodeCurrentAjax();
-
- // Start the timer to update page per minute
- gangliaTimer = window.setTimeout('updateGangliaPage()', 60000);
- }
- });
-}
-
-/**
- * Extract the location query data and saved in global variable
- */
-function extractLocationlData(locationData) {
- framehash = new Object();
- cechash = new Object();
- bladehash = new Object();
- rackhash = new Object();
-
- // Linux nodes which has no parent
- linuxArray = new Array();
-
- // Other unknown nodes only have one parent, use number 1 as there parent
- otherhash = new Object();
- otherhash[1] = new Array();
-
- var allnodearray = locationData.split(';');
- var temparray;
- var parent = '';
- var name = '';
- for (var i in allnodearray) {
- temparray = allnodearray[i].split(':');
- name = temparray[0];
-
- // If there is not parent (or mpa, or rack) information
- parent = temparray[2];
- if (!parent) {
- // Go to next node
- otherhash[1].push(name);
- continue;
- }
-
- switch (temparray[1].toLowerCase()) {
- case 'blade': {
- if (!bladehash[parent]) {
- bladehash[parent] = new Array();
- }
-
- bladehash[parent].push(name);
- }
- break;
-
- case 'systemx': {
- if (!rackhash[parent]) {
- rackhash[parent] = new Array();
- }
-
- rackhash[parent].push(name);
- }
- break;
-
- case 'frame': {
- if (!framehash[name]) {
- framehash[name] = new Array();
- }
- }
- break;
-
- case 'cec': {
- if (!framehash[parent]) {
- framehash[parent] = new Array();
- }
-
- framehash[parent].push(name);
- }
- break;
-
- case 'lpar':
- case 'lpar,osi':
- case 'osi,lpar': {
- if (!cechash[parent]) {
- cechash[parent] = new Array();
- }
-
- cechash[parent].push(name);
- }
-
- break;
- default: {
- otherhash[1].push(name);
- }
- break;
- }
- }
-}
-
-/**
- * Send AJAX request to get grid summary information
- */
-function sendGridSummaryAjax() {
- // Get the summary data
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'gangliashow;_grid_;hour;_summary_',
- msg : ''
- },
-
- success: function(data) {
- createGridSummaryData(data.rsp[0]);
- drawGridSummary();
- }
- });
-}
-
-/**
- * Send AJAX request to get nodes current load information
- */
-function sendNodeCurrentAjax() {
-
- // Get all nodes current status
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'gangliacurrent;node;',
- msg : ''
- },
-
- success: function(data){
- createNodeStatusData(data.rsp[0]);
- drawGangliaNodesArea($('#gangliaorder').val());
- }
- });
-}
-
-/**
- * Send AJAX request to get grid current summary information to update the page
- */
-function sendGridCurrentAjax(){
- // Get the summary data
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'gangliacurrent;grid',
- msg : ''
- },
-
- success: function(data){
- updateGridSummaryData(data.rsp[0]);
- drawGridSummary();
- }
- });
-}
-
-/**
- * Save the grid summary data to local global variable
- */
-function createGridSummaryData(summaryString){
- // Empty the global data
- // The data structure looks like: metric1:time11,val11,time12,val12,...;metric2:time21,val21,time22,val22,...;....
- gridData = new Object();
-
- var metricArray = summaryString.split(';');
- var metricname = '';
- var valueArray = '';
- var position = 0;
- var tempLength = 0;
- for (var index = 0; index < metricArray.length; index++) {
- position = metricArray[index].indexOf(':');
-
- // Get the metric name and init its global array to save timestamp and value pair
- metricname = metricArray[index].substr(0, position);
- gridData[metricname] = new Array();
- valueArray = metricArray[index].substr(position + 1).split(',');
- tempLength = valueArray.length;
-
- // Save timestamp and value into global array
- for (var i = 0; i < tempLength; i++) {
- gridData[metricname].push(Number(valueArray[i]));
- }
- }
-}
-
-/**
- * Update the grid summary data to local global variable
- */
-function updateGridSummaryData(currentString){
- // The data structure looks like: metric1:time11,val11,time12,val12,...;metric2:time21,val21,time22,val22,...;....
- var metricArray = currentString.split(';');
- var metricname = '';
- var position = 0;
- var tempLength = 0;
- var index = 0;
- var tempArray;
-
- tempLength = metricArray.length;
- for (index = 0; index < tempLength; index++) {
- position = metricArray[index].indexOf(':');
- metricname = metricArray[index].substr(0, position);
- tempArray = metricArray[index].substr(position + 1).split(',');
- if (gridData[metricname]) {
- gridData[metricname].shift();
- gridData[metricname].shift();
- gridData[metricname].push(Number(tempArray[0]));
- gridData[metricname].push(Number(tempArray[1]));
- }
- }
-}
-
-/**
- * Draw the grid summay area by global data
- */
-function drawGridSummary() {
- var gridDrawArea = $('#gangliaGridSummary');
- var showStr = '';
- var tempStr = $('#gangliamon').attr('class');
-
- // jqflot only draws on the visible area
- // If the tab is hide, return directly
- if (tempStr.indexOf('hide') != -1) {
- return;
- }
-
- if ($('#gangliamon #hidesup').text() == '[Show]') {
- return;
- }
-
- gridDrawArea.empty();
- showStr = '
' +
- '
' +
- '
' +
- '
' +
- '
' +
- '
';
- gridDrawArea.append(showStr);
- drawLoadFlot('gangliasummaryload', 'Grid', gridData['load_one'], gridData['cpu_num']);
- drawCpuFlot('gangliasummarycpu', 'Grid', gridData['cpu_idle']);
- drawMemFlot('gangliasummarymem', 'Grid', gridData['mem_free'], gridData['mem_total']);
- drawDiskFlot('gangliasummarydisk', 'Grid', gridData['disk_free'], gridData['disk_total']);
- drawNetworkFlot('gangliasummarynetwork', 'Grid', gridData['bytes_in'], gridData['bytes_out']);
-}
-
-/**
- * Draw the load flot by data (summary data or one node data)
- *
- * @param areaid Which DIV draw this flot
- * @param loadpair The load timestamp and value pair
- * @param cpupair The CPU number and value pair
- */
-function drawLoadFlot(areaid, titleprefix, loadpair, cpupair) {
- var load = new Array();
- var cpunum = new Array();
- var index = 0;
- var yaxismax = 0;
- var interval = 1;
-
- $('#' + areaid).empty();
- // Parse load pair, the timestamp must mutiply 1000, javascript time stamp is millisecond
- for (index = 0; index < loadpair.length; index += 2) {
- load.push([loadpair[index] * 1000, loadpair[index + 1]]);
- if (loadpair[index + 1] > yaxismax) {
- yaxismax = loadpair[index + 1];
- }
- }
-
- // Parse cpu pair
- for (index = 0; index < cpupair.length; index += 2) {
- cpunum.push([cpupair[index] * 1000, cpupair[index + 1]]);
- if (cpupair[index + 1] > yaxismax) {
- yaxismax = cpupair[index + 1];
- }
- }
-
- interval = parseInt(yaxismax / 3);
- if (interval < 1) {
- interval = 1;
- }
-
- $.jqplot(areaid, [load, cpunum], {
- title: titleprefix + ' Loads/Procs Last Hour',
- axes:{
- xaxis:{
- renderer : $.jqplot.DateAxisRenderer,
- numberTicks: 4,
- tickOptions : {
- formatString : '%R',
- show : true
- }
- },
- yaxis: {
- min : 0,
- tickInterval : interval
- }
- },
- legend : {
- show: true,
- location: 'nw'
- },
- series:[{label:'Load'}, {label: 'CPU Number'}],
- seriesDefaults : {showMarker: false}
- });
-}
-
-/**
- * Draw the CPU usage flot by data (maybe summary data or one node data)
- *
- * @param areaid Which DIV draw this flot
- * @param titleprefix Title used name
- * @param cpupair The CPU timestamp and value pair
- */
-function drawCpuFlot(areaid, titleprefix, cpupair) {
- var cpu = new Array();
- var index = 0;
-
- $('#' + areaid).empty();
-
- // Time stamp should be mutiplied by 1000
- // We get the CPU idle from server
- for (index = 0; index < cpupair.length; index +=2) {
- cpu.push([(cpupair[index] * 1000), (100 - cpupair[index + 1])]);
- }
-
- $.jqplot(areaid, [cpu],{
- title: titleprefix + ' Cpu Use Last Hour',
- axes:{
- xaxis:{
- renderer : $.jqplot.DateAxisRenderer,
- numberTicks: 4,
- tickOptions : {
- formatString : '%R',
- show : true
- }
- },
- yaxis: {
- min : 0,
- max : 100,
- tickOptions:{formatString : '%d\%'}
- }
- },
- seriesDefaults : {showMarker: false}
- });
-}
-
-/**
- * Draw the memory usage flot by data (summary data or one node data)
- *
- * @param areaid Which DIV draw this flot
- * @param titleprefix Title used name
- * @param cpupair The CPU timestamp and value pair
- */
-function drawMemFlot(areaid, titleprefix, freepair, totalpair){
- var use = new Array();
- var total = new Array();
- var tempsize = 0;
- var index = 0;
-
- $('#' + areaid).empty();
- if (freepair.length < totalpair.length) {
- tempsize = freepair.length;
- } else {
- tempsize = freepair.length;
- }
-
- for (index = 0; index < tempsize; index += 2) {
- var temptotal = totalpair[index + 1];
- var tempuse = temptotal - freepair[index + 1];
- temptotal = temptotal / 1000000;
- tempuse = tempuse / 1000000;
- total.push([totalpair[index] * 1000, temptotal]);
- use.push([freepair[index] * 1000, tempuse]);
- }
-
- $.jqplot(areaid, [use, total], {
- title: titleprefix + ' Memory Use Last Hour',
- axes:{
- xaxis:{
- renderer : $.jqplot.DateAxisRenderer,
- numberTicks: 4,
- tickOptions : {
- formatString : '%R',
- show : true
- }
- },
- yaxis: {
- min : 0,
- tickOptions:{formatString : '%.2fG'}
- }
- },
- legend : {
- show: true,
- location: 'nw'
- },
- series:[{label:'Used'}, {label: 'Total'}],
- seriesDefaults : {showMarker: false}
- });
-}
-
-/**
- * Draw the disk usage flot by data (summary data or one node's data)
- *
- * @param areaid Which div draw this flot
- * @param titleprefix Title used name
- * @param freepair The free disk number, Ganglia only logs the free data
- * @param totalpair The total disk number
- */
-function drawDiskFlot(areaid, titleprefix, freepair, totalpair) {
- var use = new Array();
- var total = new Array();
- var tempsize = 0;
- var index = 0;
-
- $('#' + areaid).empty();
- if (freepair.length < totalpair.length) {
- tempsize = freepair.length;
- } else{
- tempsize = freepair.length;
- }
-
- for (index = 0; index < tempsize; index += 2) {
- var temptotal = totalpair[index + 1];
- var tempuse = temptotal - freepair[index + 1];
- total.push([totalpair[index] * 1000, temptotal]);
- use.push([freepair[index] * 1000, tempuse]);
- }
-
- $.jqplot(areaid, [use, total], {
- title: titleprefix + ' Disk Use Last Hour',
- axes:{
- xaxis:{
- renderer : $.jqplot.DateAxisRenderer,
- numberTicks: 4,
- tickOptions : {
- formatString : '%R',
- show : true
- }
- },
- yaxis: {
- min : 0,
- tickOptions:{formatString : '%.2fG'}
- }
- },
- legend : {
- show: true,
- location: 'nw'
- },
- series:[{label:'Used'}, {label: 'Total'}],
- seriesDefaults : {showMarker: false}
- });
-}
-
-/**
- * Draw the network load flot by data (summary data or one node data)
- *
- * @param areaid Which div draw this flot
- * @param titleprefix Title used name
- * @param inpair The timestamp and value pair for download
- * @param outpair The timestamp and value pair for upload
- */
-function drawNetworkFlot(areaid, titleprefix, inpair, outpair) {
- var inArray = new Array();
- var outArray = new Array();
- var index = 0;
- var maxvalue = 0;
- var unitname = 'B';
- var divisor = 1;
-
- for (index = 0; index < inpair.length; index += 2) {
- if (inpair[index + 1] > maxvalue) {
- maxvalue = inpair[index + 1];
- }
- }
-
- for (index = 0; index < outpair.length; index += 2) {
- if (outpair[index + 1] > maxvalue) {
- maxvalue = outpair[index + 1];
- }
- }
-
- if (maxvalue > 3000000) {
- divisor = 1000000;
- unitname = 'GB';
- } else if (maxvalue >= 3000) {
- divisor = 1000;
- unitname = 'MB';
- } else {
- // Do nothing
- }
-
- for (index = 0; index < inpair.length; index += 2) {
- inArray.push([(inpair[index] * 1000), (inpair[index + 1] / divisor)]);
- }
-
- for (index = 0; index < outpair.length; index += 2) {
- outArray.push([(outpair[index] * 1000), (outpair[index + 1] / divisor)]);
- }
-
- $.jqplot(areaid, [inArray, outArray], {
- title: titleprefix + ' Network Last Hour',
- axes:{
- xaxis:{
- renderer : $.jqplot.DateAxisRenderer,
- numberTicks: 4,
- tickOptions : {
- formatString : '%R',
- show : true
- }
- },
- yaxis: {
- min : 0,
- tickOptions:{formatString : '%d' + unitname}
- }
- },
- legend : {
- show: true,
- location: 'nw'
- },
- series:[{label:'In'}, {label: 'Out'}],
- seriesDefaults : {showMarker: false}
- });
-}
-
-/**
- * Create node status data
- *
- * @param nodesStatus Node status
- */
-function createNodeStatusData(nodesStatus) {
- var nodesArray = nodesStatus.split(';');
- var position = 0;
- var nodename = '';
- var index = 0;
- var tempArray;
- var tempStr = '';
-
- for (index in nodePath) {
- delete(nodePath[index]);
- }
-
- for (index in nodeStatus) {
- delete(nodeStatus[index]);
- }
-
- for (index = 0; index < nodesArray.length; index++) {
- tempStr = nodesArray[index];
- position = tempStr.indexOf(':');
- nodename = tempStr.substring(0, position);
- tempArray = tempStr.substring(position + 1).split(',');
- nodeStatus[nodename] = tempArray[0];
- if (('WARNING' == tempArray[0]) || ('NORMAL' == tempArray[0])){
- nodePath[nodename] = tempArray[1];
- }
- }
-}
-
-/**
- * Draw nodes current status
- */
-function drawGangliaNodesArea() {
- var position = 0;
-
- // Find out the last child's type and name
- var currentobj = $('#zoomDiv span:last');
- var type = currentobj.attr('name').toLowerCase();
- var name = currentobj.text();
- position = name.indexOf('(');
-
- if (position > -1) {
- name = name.substr(3, position - 3);
- }
- $('#gangliaNodes').empty();
-
- switch (type) {
- // Draw the node current status
- case 'blade':
- case 'cec':
- case 'rack':
- case 'other': {
- drawGangliaNodesAreaPic(type, name);
- }
- break;
-
- // Draw a summary table
- case 'all':
- case 'frame': {
- drawGangliaNodesAreaTable(type, name);
- }
- break;
- default:
- break;
- }
-}
-
-function drawGangliaNodesAreaPic(type, name) {
- var index = 0;
- var arraypoint = '';
- var templength = 0;
- var showStr = '';
- var nodename = '';
- var temparray;
-
- switch(type) {
- case 'blade': {
- arraypoint = bladehash[name];
- }
- break;
- case 'cec': {
- arraypoint = cechash[name];
- }
- break;
- case 'rack': {
- arraypoint = rackhash[name];
- }
- break;
- case 'other': {
- arraypoint = otherhash[1];
- }
- default:
- break;
- }
- $('#gangliaNodes').html('');
-
- temparray = arraypoint.sort();
- templength = arraypoint.length;
-
- for (index = 0; index < templength; index++) {
- nodename = temparray[index];
- switch (nodeStatus[nodename]) {
- case 'ERROR':
- showStr = ' ';
- break;
- case 'WARNING':
- showStr = ' ';
- break;
- case 'NORMAL':
- showStr = ' ';
- break;
- default:
- showStr = ' ';
- break;
- }
- $('#gangliaNodes ul').append(showStr);
- }
-
- // Bind all normal and warning nodes click event
- $('.monitor-normal,.monitorwarning').bind('click', function() {
- var nodename = $(this).attr('title');
- window.open('ganglianode.php?n=' + nodename + '&p=' + nodePath[nodename],
- 'nodedetail','height=430,width=950,scrollbars=yes,status =no');
- });
-}
-
-function drawGangliaNodesAreaTable(type, name) {
- var table = $('');
- var row = '';
- var usedCec = new Object();
-
- var header = $('');
- table.append(header);
-
- if (type == 'all') {
- for (var i in framehash) {
- var framename = i;
- row = '' + framename + ' Frame ' +
- monitorStatAgg('frame', framehash[i]) + ' ';
- table.append(row);
- for(var j in framehash[i]){
- usedCec[framehash[i][j]] = 1;
- }
- }
-
- for (var i in cechash) {
- if (usedCec[i]) {
- continue;
- }
- var cecname = i;
- row = '' + cecname + ' CEC ' +
- monitorStatAgg('cec', cechash[i]) + ' ';
- table.append(row);
- }
-
- for (var i in bladehash) {
- var bladename = i;
- row = '' + bladename + ' Blade ' +
- monitorStatAgg('blade', bladehash[i]) + ' ';
- table.append(row);
- }
-
- for (var i in rackhash) {
- var rackname = i;
- row = '' + rackname + ' Rack ' +
- monitorStatAgg('rack', rackhash[i]) + ' ';
- table.append(row);
- }
-
- if (otherhash[1].length > 0) {
- row = 'Other Other ' +
- monitorStatAgg('other', otherhash[1]) + ' ';
- table.append(row);
- }
- } else {
- for (var i in framehash[name]) {
- var cecname = framehash[name][i];
- row = '' + cecname + ' ' +
- 'CEC ' + monitorStatAgg('cec', cechash[cecname]) + ' ';
- table.append(row);
- }
- }
-
- $('#gangliaNodes').append(table);
-}
-
-/**
- * Update all tab per minute
- */
-function monitorStatAgg(type, inputarray) {
- var normalnum = 0;
- var warningnum = 0;
- var errornum = 0;
- var nuknownnum = 0;
- var tempArray;
- var tempname;
-
- switch (type) {
- case 'blade':
- case 'cec':
- case 'rack':
- case 'other': {
- tempArray = inputarray;
- }
- break;
- case 'frame': {
- tempArray = new Array();
- for (var i in inputarray){
- tempname = inputarray[i];
- for (var j in cechash[tempname]) {
- tempArray.push(cechash[tempname][j]);
- }
- }
- }
- break;
- default:
- return;
- break;
- }
-
- for (var i in tempArray) {
- tempname = tempArray[i];
- switch(nodeStatus[tempname]) {
- case 'NORMAL':
- normalnum++;
- break;
- case 'WARNING':
- warningnum++;
- break;
- case 'ERROR':
- errornum++;
- break;
- default:
- nuknownnum++;
- break;
- }
- }
-
- normalnum = normalnum?normalnum:'-';
- warningnum = warningnum?warningnum:'-';
- errornum = errornum?errornum:'-';
- nuknownnum = nuknownnum?nuknownnum:'-';
-
- return ('' + normalnum + ' ' + warningnum + ' ' + errornum + ' ' + nuknownnum + ' ');
-}
-
-/**
- * Update all tab per minute
- */
-function updateGangliaPage() {
- if ($('#gangliaNodes').size() < 1) {
- return;
- }
-
- sendGridCurrentAjax();
- sendNodeCurrentAjax();
-
- gangliaTimer = window.setTimeout('updateGangliaPage()', 60000);
-}
-
-/**
- * Change the zoom area when clicked
- */
-function updateZoom(obj) {
- var type=$(obj).attr('name');
- while ($('#zoomDiv span:last').attr('name') != type) {
- $('#zoomDiv span:last').remove();
- }
- $(obj).removeClass('monitor-zoom-link');
- $(obj).unbind('click');
-
- drawGangliaNodesArea();
-}
-
-/**
- * Add the zoom level when clicked
- */
-function addZoomDiv(obj) {
- var name = $(obj).text();
- var type = $(obj).attr('name');
-
- var lastzoomobj = $('#zoomDiv span:last');
- lastzoomobj.addClass('monitor-zoom-link');
- lastzoomobj.bind('click', function() {
- updateZoom(this);
- });
-
- var newcontent = ' > ' + name + '(' + type.toUpperCase() + ')';
- var newli = '' + newcontent + ' ';
- $('#zoomDiv').append(newli);
-
- drawGangliaNodesArea();
+/**
+ * Global variables
+ */
+
+// Save grid summary data, update every one minute
+var gridData;
+
+// Save nodes path, used for getting detail from rrd file
+var nodePath = new Object();
+
+// Save nodes current status,
+// unknown = -2, error = -1, warning = 0, normal = 1 are used for sorting
+var nodeStatus = new Object();
+
+// Update timer
+var gangliaTimer;
+
+// Global frame hash
+var framehash;
+// Global cec hash
+var cechash;
+// Global blade hash
+var bladehash;
+// Global x rack hash
+var rackhash;
+// Global other type node hash
+var otherhash;
+
+/**
+ * Load Ganglia monitoring tool
+ *
+ * @return Nothing
+ */
+function loadGangliaMon() {
+ $('#gangliamon').append(createInfoBar('Checking RPMs'));
+
+ // Get groups and set cookie
+ if (!$.cookie('xcat_groups')) {
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'extnoderange',
+ tgt : '/.*',
+ args : 'subgroups',
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ setGroupsCookies(data);
+ }
+ });
+ }
+
+ // Check whether Ganglia RPMs are installed on the xCAT MN
+ $.ajax({
+ url : 'lib/systemcmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'rpm -q rrdtool ganglia-gmetad ganglia-gmond'
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ checkGangliaRPMs(data);
+ }
+ });
+ return;
+}
+
+/**
+ * Check whether Ganglia RPMs are installed
+ *
+ * @param data Data returned from HTTP request
+ */
+function checkGangliaRPMs(data) {
+ var gangliaTab = $('#gangliamon');
+ gangliaTab.empty();
+
+ // Get the list of Ganglia RPMs installed
+ var status = data.rsp.split(/\n/);
+ var gangliaRPMs = ["rrdtool", "ganglia-gmetad", "ganglia-gmond"];
+ var warningMsg = 'Before continuing, please install the following packages: ';
+ var missingRPMs = false;
+ for (var i in status) {
+ if (status[i].indexOf("not installed") > -1) {
+ warningMsg += gangliaRPMs[i] + ' ';
+ missingRPMs = true;
+ }
+ }
+
+ // Append Ganglia PDF
+ if (missingRPMs) {
+ var warningBar = createWarnBar(warningMsg);
+ warningBar.css('margin-bottom', '10px');
+ warningBar.prependTo(gangliaTab);
+ } else {
+ gangliaTab.append(createInfoBar('Checking running status'));
+
+ // Check if ganglia is running on the xCAT MN
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'monls',
+ tgt : '',
+ args : 'gangliamon',
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ checkGangliaRunning(data);
+ }
+ });
+ }
+
+ return;
+}
+
+/**
+ * Check whether Ganglia is running
+ *
+ * @param data Data returned from HTTP request
+ */
+function checkGangliaRunning(data) {
+ var gangliaTab = $('#gangliamon');
+ gangliaTab.empty();
+
+ // If Ganglia is not started
+ if (data.rsp[0].indexOf("not-monitored") > -1) {
+ // Create link to start Ganglia
+ var startLnk = $('Click here ');
+ startLnk.css({
+ 'color' : 'blue',
+ 'text-decoration' : 'none'
+ });
+ startLnk.click(function() {
+ // Turn on Ganglia for all nodes
+ monitorNode('', 'on');
+ });
+
+ // Create warning bar
+ var warningBar = $('
');
+ var msg = $('
').css({
+ 'display': 'inline-block',
+ 'width': '90%'
+ });
+ var icon = $(' ').css({
+ 'display': 'inline-block',
+ 'margin': '10px 5px'
+ });
+ warningBar.append(icon);
+ msg.append('Please start Ganglia on xCAT. ');
+ msg.append(startLnk);
+ msg.append(' to start Ganglia.');
+ warningBar.append(msg);
+ warningBar.css('margin-bottom', '10px');
+
+ // If there are any warning messages, append this warning after it
+ var curWarnings = $('#gangliamon').find('.ui-state-error');
+
+ if (curWarnings.length) {
+ curWarnings.after(warningBar);
+ } else {
+ warningBar.prependTo(gangliaTab);
+ }
+
+ return;
+ }
+
+ // Legend for node status
+ var legend = '' +
+ ' Normal ' +
+ ' Heavy Load ' +
+ ' Error ' +
+ ' Unknown ' +
+ '
';
+
+ // Gganglia grid overview
+ var showStr = '
Grid Overview ' +
+ '[Hide]
' +
+ '
' +
+ '
Current Nodes Status ' + legend + '
' +
+ 'All Nodes
' +
+ '
';
+ gangliaTab.append(showStr);
+
+ // Get summary data and draw on page
+ $('#gangliaGridSummary').append('Getting grid summary data ');
+ sendGridSummaryAjax();
+
+ // Get all nodes location data which can support the zoom monitor
+ $('#gangliaNodes').append('Getting all nodes status ');
+ sendLocationAjax();
+
+ // Bind the hide/show button event
+ $('#gangliamon #hidesup').bind('click', function(){
+ if ('[Hide]' == $(this).text()) {
+ $(this).html('[Show]');
+ } else {
+ $(this).html('[Hide]');
+ }
+
+ $('#gangliaGridSummary').toggle();
+ });
+}
+
+/**
+ * Send AJAX request to get all nodes parent and position to create hardware hierarchy hash
+ */
+function sendLocationAjax() {
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'graph',
+ msg : ''
+ },
+
+ success: function(data){
+ data = decodeRsp(data);
+ if (!data.rsp[0]) {
+ return;
+ }
+
+ extractLocationlData(data.rsp[0]);
+ // Get nodes current status and draw on the page
+ sendNodeCurrentAjax();
+
+ // Start the timer to update page per minute
+ gangliaTimer = window.setTimeout('updateGangliaPage()', 60000);
+ }
+ });
+}
+
+/**
+ * Extract the location query data and saved in global variable
+ */
+function extractLocationlData(locationData) {
+ framehash = new Object();
+ cechash = new Object();
+ bladehash = new Object();
+ rackhash = new Object();
+
+ // Linux nodes which has no parent
+ linuxArray = new Array();
+
+ // Other unknown nodes only have one parent, use number 1 as there parent
+ otherhash = new Object();
+ otherhash[1] = new Array();
+
+ var allnodearray = locationData.split(';');
+ var temparray;
+ var parent = '';
+ var name = '';
+ for (var i in allnodearray) {
+ temparray = allnodearray[i].split(':');
+ name = temparray[0];
+
+ // If there is not parent (or mpa, or rack) information
+ parent = temparray[2];
+ if (!parent) {
+ // Go to next node
+ otherhash[1].push(name);
+ continue;
+ }
+
+ switch (temparray[1].toLowerCase()) {
+ case 'blade': {
+ if (!bladehash[parent]) {
+ bladehash[parent] = new Array();
+ }
+
+ bladehash[parent].push(name);
+ }
+ break;
+
+ case 'systemx': {
+ if (!rackhash[parent]) {
+ rackhash[parent] = new Array();
+ }
+
+ rackhash[parent].push(name);
+ }
+ break;
+
+ case 'frame': {
+ if (!framehash[name]) {
+ framehash[name] = new Array();
+ }
+ }
+ break;
+
+ case 'cec': {
+ if (!framehash[parent]) {
+ framehash[parent] = new Array();
+ }
+
+ framehash[parent].push(name);
+ }
+ break;
+
+ case 'lpar':
+ case 'lpar,osi':
+ case 'osi,lpar': {
+ if (!cechash[parent]) {
+ cechash[parent] = new Array();
+ }
+
+ cechash[parent].push(name);
+ }
+
+ break;
+ default: {
+ otherhash[1].push(name);
+ }
+ break;
+ }
+ }
+}
+
+/**
+ * Send AJAX request to get grid summary information
+ */
+function sendGridSummaryAjax() {
+ // Get the summary data
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'gangliashow;_grid_;hour;_summary_',
+ msg : ''
+ },
+
+ success: function(data) {
+ data = decodeRsp(data);
+ createGridSummaryData(data.rsp[0]);
+ drawGridSummary();
+ }
+ });
+}
+
+/**
+ * Send AJAX request to get nodes current load information
+ */
+function sendNodeCurrentAjax() {
+
+ // Get all nodes current status
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'gangliacurrent;node;',
+ msg : ''
+ },
+
+ success: function(data){
+ createNodeStatusData(data.rsp[0]);
+ drawGangliaNodesArea($('#gangliaorder').val());
+ }
+ });
+}
+
+/**
+ * Send AJAX request to get grid current summary information to update the page
+ */
+function sendGridCurrentAjax(){
+ // Get the summary data
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'gangliacurrent;grid',
+ msg : ''
+ },
+
+ success: function(data){
+ data = decodeRsp(data);
+ updateGridSummaryData(data.rsp[0]);
+ drawGridSummary();
+ }
+ });
+}
+
+/**
+ * Save the grid summary data to local global variable
+ */
+function createGridSummaryData(summaryString){
+ // Empty the global data
+ // The data structure looks like: metric1:time11,val11,time12,val12,...;metric2:time21,val21,time22,val22,...;....
+ gridData = new Object();
+
+ var metricArray = summaryString.split(';');
+ var metricname = '';
+ var valueArray = '';
+ var position = 0;
+ var tempLength = 0;
+ for (var index = 0; index < metricArray.length; index++) {
+ position = metricArray[index].indexOf(':');
+
+ // Get the metric name and init its global array to save timestamp and value pair
+ metricname = metricArray[index].substr(0, position);
+ gridData[metricname] = new Array();
+ valueArray = metricArray[index].substr(position + 1).split(',');
+ tempLength = valueArray.length;
+
+ // Save timestamp and value into global array
+ for (var i = 0; i < tempLength; i++) {
+ gridData[metricname].push(Number(valueArray[i]));
+ }
+ }
+}
+
+/**
+ * Update the grid summary data to local global variable
+ */
+function updateGridSummaryData(currentString){
+ // The data structure looks like: metric1:time11,val11,time12,val12,...;metric2:time21,val21,time22,val22,...;....
+ var metricArray = currentString.split(';');
+ var metricname = '';
+ var position = 0;
+ var tempLength = 0;
+ var index = 0;
+ var tempArray;
+
+ tempLength = metricArray.length;
+ for (index = 0; index < tempLength; index++) {
+ position = metricArray[index].indexOf(':');
+ metricname = metricArray[index].substr(0, position);
+ tempArray = metricArray[index].substr(position + 1).split(',');
+ if (gridData[metricname]) {
+ gridData[metricname].shift();
+ gridData[metricname].shift();
+ gridData[metricname].push(Number(tempArray[0]));
+ gridData[metricname].push(Number(tempArray[1]));
+ }
+ }
+}
+
+/**
+ * Draw the grid summay area by global data
+ */
+function drawGridSummary() {
+ var gridDrawArea = $('#gangliaGridSummary');
+ var showStr = '';
+ var tempStr = $('#gangliamon').attr('class');
+
+ // jqflot only draws on the visible area
+ // If the tab is hide, return directly
+ if (tempStr.indexOf('hide') != -1) {
+ return;
+ }
+
+ if ($('#gangliamon #hidesup').text() == '[Show]') {
+ return;
+ }
+
+ gridDrawArea.empty();
+ showStr = '
' +
+ '
' +
+ '
' +
+ '
' +
+ '
' +
+ '
';
+ gridDrawArea.append(showStr);
+ drawLoadFlot('gangliasummaryload', 'Grid', gridData['load_one'], gridData['cpu_num']);
+ drawCpuFlot('gangliasummarycpu', 'Grid', gridData['cpu_idle']);
+ drawMemFlot('gangliasummarymem', 'Grid', gridData['mem_free'], gridData['mem_total']);
+ drawDiskFlot('gangliasummarydisk', 'Grid', gridData['disk_free'], gridData['disk_total']);
+ drawNetworkFlot('gangliasummarynetwork', 'Grid', gridData['bytes_in'], gridData['bytes_out']);
+}
+
+/**
+ * Draw the load flot by data (summary data or one node data)
+ *
+ * @param areaid Which DIV draw this flot
+ * @param loadpair The load timestamp and value pair
+ * @param cpupair The CPU number and value pair
+ */
+function drawLoadFlot(areaid, titleprefix, loadpair, cpupair) {
+ var load = new Array();
+ var cpunum = new Array();
+ var index = 0;
+ var yaxismax = 0;
+ var interval = 1;
+
+ $('#' + areaid).empty();
+ // Parse load pair, the timestamp must mutiply 1000, javascript time stamp is millisecond
+ for (index = 0; index < loadpair.length; index += 2) {
+ load.push([loadpair[index] * 1000, loadpair[index + 1]]);
+ if (loadpair[index + 1] > yaxismax) {
+ yaxismax = loadpair[index + 1];
+ }
+ }
+
+ // Parse cpu pair
+ for (index = 0; index < cpupair.length; index += 2) {
+ cpunum.push([cpupair[index] * 1000, cpupair[index + 1]]);
+ if (cpupair[index + 1] > yaxismax) {
+ yaxismax = cpupair[index + 1];
+ }
+ }
+
+ interval = parseInt(yaxismax / 3);
+ if (interval < 1) {
+ interval = 1;
+ }
+
+ $.jqplot(areaid, [load, cpunum], {
+ title: titleprefix + ' Loads/Procs Last Hour',
+ axes:{
+ xaxis:{
+ renderer : $.jqplot.DateAxisRenderer,
+ numberTicks: 4,
+ tickOptions : {
+ formatString : '%R',
+ show : true
+ }
+ },
+ yaxis: {
+ min : 0,
+ tickInterval : interval
+ }
+ },
+ legend : {
+ show: true,
+ location: 'nw'
+ },
+ series:[{label:'Load'}, {label: 'CPU Number'}],
+ seriesDefaults : {showMarker: false}
+ });
+}
+
+/**
+ * Draw the CPU usage flot by data (maybe summary data or one node data)
+ *
+ * @param areaid Which DIV draw this flot
+ * @param titleprefix Title used name
+ * @param cpupair The CPU timestamp and value pair
+ */
+function drawCpuFlot(areaid, titleprefix, cpupair) {
+ var cpu = new Array();
+ var index = 0;
+
+ $('#' + areaid).empty();
+
+ // Time stamp should be mutiplied by 1000
+ // We get the CPU idle from server
+ for (index = 0; index < cpupair.length; index +=2) {
+ cpu.push([(cpupair[index] * 1000), (100 - cpupair[index + 1])]);
+ }
+
+ $.jqplot(areaid, [cpu],{
+ title: titleprefix + ' Cpu Use Last Hour',
+ axes:{
+ xaxis:{
+ renderer : $.jqplot.DateAxisRenderer,
+ numberTicks: 4,
+ tickOptions : {
+ formatString : '%R',
+ show : true
+ }
+ },
+ yaxis: {
+ min : 0,
+ max : 100,
+ tickOptions:{formatString : '%d\%'}
+ }
+ },
+ seriesDefaults : {showMarker: false}
+ });
+}
+
+/**
+ * Draw the memory usage flot by data (summary data or one node data)
+ *
+ * @param areaid Which DIV draw this flot
+ * @param titleprefix Title used name
+ * @param cpupair The CPU timestamp and value pair
+ */
+function drawMemFlot(areaid, titleprefix, freepair, totalpair){
+ var use = new Array();
+ var total = new Array();
+ var tempsize = 0;
+ var index = 0;
+
+ $('#' + areaid).empty();
+ if (freepair.length < totalpair.length) {
+ tempsize = freepair.length;
+ } else {
+ tempsize = freepair.length;
+ }
+
+ for (index = 0; index < tempsize; index += 2) {
+ var temptotal = totalpair[index + 1];
+ var tempuse = temptotal - freepair[index + 1];
+ temptotal = temptotal / 1000000;
+ tempuse = tempuse / 1000000;
+ total.push([totalpair[index] * 1000, temptotal]);
+ use.push([freepair[index] * 1000, tempuse]);
+ }
+
+ $.jqplot(areaid, [use, total], {
+ title: titleprefix + ' Memory Use Last Hour',
+ axes:{
+ xaxis:{
+ renderer : $.jqplot.DateAxisRenderer,
+ numberTicks: 4,
+ tickOptions : {
+ formatString : '%R',
+ show : true
+ }
+ },
+ yaxis: {
+ min : 0,
+ tickOptions:{formatString : '%.2fG'}
+ }
+ },
+ legend : {
+ show: true,
+ location: 'nw'
+ },
+ series:[{label:'Used'}, {label: 'Total'}],
+ seriesDefaults : {showMarker: false}
+ });
+}
+
+/**
+ * Draw the disk usage flot by data (summary data or one node's data)
+ *
+ * @param areaid Which div draw this flot
+ * @param titleprefix Title used name
+ * @param freepair The free disk number, Ganglia only logs the free data
+ * @param totalpair The total disk number
+ */
+function drawDiskFlot(areaid, titleprefix, freepair, totalpair) {
+ var use = new Array();
+ var total = new Array();
+ var tempsize = 0;
+ var index = 0;
+
+ $('#' + areaid).empty();
+ if (freepair.length < totalpair.length) {
+ tempsize = freepair.length;
+ } else{
+ tempsize = freepair.length;
+ }
+
+ for (index = 0; index < tempsize; index += 2) {
+ var temptotal = totalpair[index + 1];
+ var tempuse = temptotal - freepair[index + 1];
+ total.push([totalpair[index] * 1000, temptotal]);
+ use.push([freepair[index] * 1000, tempuse]);
+ }
+
+ $.jqplot(areaid, [use, total], {
+ title: titleprefix + ' Disk Use Last Hour',
+ axes:{
+ xaxis:{
+ renderer : $.jqplot.DateAxisRenderer,
+ numberTicks: 4,
+ tickOptions : {
+ formatString : '%R',
+ show : true
+ }
+ },
+ yaxis: {
+ min : 0,
+ tickOptions:{formatString : '%.2fG'}
+ }
+ },
+ legend : {
+ show: true,
+ location: 'nw'
+ },
+ series:[{label:'Used'}, {label: 'Total'}],
+ seriesDefaults : {showMarker: false}
+ });
+}
+
+/**
+ * Draw the network load flot by data (summary data or one node data)
+ *
+ * @param areaid Which div draw this flot
+ * @param titleprefix Title used name
+ * @param inpair The timestamp and value pair for download
+ * @param outpair The timestamp and value pair for upload
+ */
+function drawNetworkFlot(areaid, titleprefix, inpair, outpair) {
+ var inArray = new Array();
+ var outArray = new Array();
+ var index = 0;
+ var maxvalue = 0;
+ var unitname = 'B';
+ var divisor = 1;
+
+ for (index = 0; index < inpair.length; index += 2) {
+ if (inpair[index + 1] > maxvalue) {
+ maxvalue = inpair[index + 1];
+ }
+ }
+
+ for (index = 0; index < outpair.length; index += 2) {
+ if (outpair[index + 1] > maxvalue) {
+ maxvalue = outpair[index + 1];
+ }
+ }
+
+ if (maxvalue > 3000000) {
+ divisor = 1000000;
+ unitname = 'GB';
+ } else if (maxvalue >= 3000) {
+ divisor = 1000;
+ unitname = 'MB';
+ } else {
+ // Do nothing
+ }
+
+ for (index = 0; index < inpair.length; index += 2) {
+ inArray.push([(inpair[index] * 1000), (inpair[index + 1] / divisor)]);
+ }
+
+ for (index = 0; index < outpair.length; index += 2) {
+ outArray.push([(outpair[index] * 1000), (outpair[index + 1] / divisor)]);
+ }
+
+ $.jqplot(areaid, [inArray, outArray], {
+ title: titleprefix + ' Network Last Hour',
+ axes:{
+ xaxis:{
+ renderer : $.jqplot.DateAxisRenderer,
+ numberTicks: 4,
+ tickOptions : {
+ formatString : '%R',
+ show : true
+ }
+ },
+ yaxis: {
+ min : 0,
+ tickOptions:{formatString : '%d' + unitname}
+ }
+ },
+ legend : {
+ show: true,
+ location: 'nw'
+ },
+ series:[{label:'In'}, {label: 'Out'}],
+ seriesDefaults : {showMarker: false}
+ });
+}
+
+/**
+ * Create node status data
+ *
+ * @param nodesStatus Node status
+ */
+function createNodeStatusData(nodesStatus) {
+ var nodesArray = nodesStatus.split(';');
+ var position = 0;
+ var nodename = '';
+ var index = 0;
+ var tempArray;
+ var tempStr = '';
+
+ for (index in nodePath) {
+ delete(nodePath[index]);
+ }
+
+ for (index in nodeStatus) {
+ delete(nodeStatus[index]);
+ }
+
+ for (index = 0; index < nodesArray.length; index++) {
+ tempStr = nodesArray[index];
+ position = tempStr.indexOf(':');
+ nodename = tempStr.substring(0, position);
+ tempArray = tempStr.substring(position + 1).split(',');
+ nodeStatus[nodename] = tempArray[0];
+ if (('WARNING' == tempArray[0]) || ('NORMAL' == tempArray[0])){
+ nodePath[nodename] = tempArray[1];
+ }
+ }
+}
+
+/**
+ * Draw nodes current status
+ */
+function drawGangliaNodesArea() {
+ var position = 0;
+
+ // Find out the last child's type and name
+ var currentobj = $('#zoomDiv span:last');
+ var type = currentobj.attr('name').toLowerCase();
+ var name = currentobj.text();
+ position = name.indexOf('(');
+
+ if (position > -1) {
+ name = name.substr(3, position - 3);
+ }
+ $('#gangliaNodes').empty();
+
+ switch (type) {
+ // Draw the node current status
+ case 'blade':
+ case 'cec':
+ case 'rack':
+ case 'other': {
+ drawGangliaNodesAreaPic(type, name);
+ }
+ break;
+
+ // Draw a summary table
+ case 'all':
+ case 'frame': {
+ drawGangliaNodesAreaTable(type, name);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+function drawGangliaNodesAreaPic(type, name) {
+ var index = 0;
+ var arraypoint = '';
+ var templength = 0;
+ var showStr = '';
+ var nodename = '';
+ var temparray;
+
+ switch(type) {
+ case 'blade': {
+ arraypoint = bladehash[name];
+ }
+ break;
+ case 'cec': {
+ arraypoint = cechash[name];
+ }
+ break;
+ case 'rack': {
+ arraypoint = rackhash[name];
+ }
+ break;
+ case 'other': {
+ arraypoint = otherhash[1];
+ }
+ default:
+ break;
+ }
+ $('#gangliaNodes').html('');
+
+ temparray = arraypoint.sort();
+ templength = arraypoint.length;
+
+ for (index = 0; index < templength; index++) {
+ nodename = temparray[index];
+ switch (nodeStatus[nodename]) {
+ case 'ERROR':
+ showStr = ' ';
+ break;
+ case 'WARNING':
+ showStr = ' ';
+ break;
+ case 'NORMAL':
+ showStr = ' ';
+ break;
+ default:
+ showStr = ' ';
+ break;
+ }
+ $('#gangliaNodes ul').append(showStr);
+ }
+
+ // Bind all normal and warning nodes click event
+ $('.monitor-normal,.monitorwarning').bind('click', function() {
+ var nodename = $(this).attr('title');
+ window.open('ganglianode.php?n=' + nodename + '&p=' + nodePath[nodename],
+ 'nodedetail','height=430,width=950,scrollbars=yes,status =no');
+ });
+}
+
+function drawGangliaNodesAreaTable(type, name) {
+ var table = $('');
+ var row = '';
+ var usedCec = new Object();
+
+ var header = $('');
+ table.append(header);
+
+ if (type == 'all') {
+ for (var i in framehash) {
+ var framename = i;
+ row = '' + framename + ' Frame ' +
+ monitorStatAgg('frame', framehash[i]) + ' ';
+ table.append(row);
+ for(var j in framehash[i]){
+ usedCec[framehash[i][j]] = 1;
+ }
+ }
+
+ for (var i in cechash) {
+ if (usedCec[i]) {
+ continue;
+ }
+ var cecname = i;
+ row = '' + cecname + ' CEC ' +
+ monitorStatAgg('cec', cechash[i]) + ' ';
+ table.append(row);
+ }
+
+ for (var i in bladehash) {
+ var bladename = i;
+ row = '' + bladename + ' Blade ' +
+ monitorStatAgg('blade', bladehash[i]) + ' ';
+ table.append(row);
+ }
+
+ for (var i in rackhash) {
+ var rackname = i;
+ row = '' + rackname + ' Rack ' +
+ monitorStatAgg('rack', rackhash[i]) + ' ';
+ table.append(row);
+ }
+
+ if (otherhash[1].length > 0) {
+ row = 'Other Other ' +
+ monitorStatAgg('other', otherhash[1]) + ' ';
+ table.append(row);
+ }
+ } else {
+ for (var i in framehash[name]) {
+ var cecname = framehash[name][i];
+ row = '' + cecname + ' ' +
+ 'CEC ' + monitorStatAgg('cec', cechash[cecname]) + ' ';
+ table.append(row);
+ }
+ }
+
+ $('#gangliaNodes').append(table);
+}
+
+/**
+ * Update all tab per minute
+ */
+function monitorStatAgg(type, inputarray) {
+ var normalnum = 0;
+ var warningnum = 0;
+ var errornum = 0;
+ var nuknownnum = 0;
+ var tempArray;
+ var tempname;
+
+ switch (type) {
+ case 'blade':
+ case 'cec':
+ case 'rack':
+ case 'other': {
+ tempArray = inputarray;
+ }
+ break;
+ case 'frame': {
+ tempArray = new Array();
+ for (var i in inputarray){
+ tempname = inputarray[i];
+ for (var j in cechash[tempname]) {
+ tempArray.push(cechash[tempname][j]);
+ }
+ }
+ }
+ break;
+ default:
+ return;
+ break;
+ }
+
+ for (var i in tempArray) {
+ tempname = tempArray[i];
+ switch(nodeStatus[tempname]) {
+ case 'NORMAL':
+ normalnum++;
+ break;
+ case 'WARNING':
+ warningnum++;
+ break;
+ case 'ERROR':
+ errornum++;
+ break;
+ default:
+ nuknownnum++;
+ break;
+ }
+ }
+
+ normalnum = normalnum?normalnum:'-';
+ warningnum = warningnum?warningnum:'-';
+ errornum = errornum?errornum:'-';
+ nuknownnum = nuknownnum?nuknownnum:'-';
+
+ return ('' + normalnum + ' ' + warningnum + ' ' + errornum + ' ' + nuknownnum + ' ');
+}
+
+/**
+ * Update all tab per minute
+ */
+function updateGangliaPage() {
+ if ($('#gangliaNodes').size() < 1) {
+ return;
+ }
+
+ sendGridCurrentAjax();
+ sendNodeCurrentAjax();
+
+ gangliaTimer = window.setTimeout('updateGangliaPage()', 60000);
+}
+
+/**
+ * Change the zoom area when clicked
+ */
+function updateZoom(obj) {
+ var type=$(obj).attr('name');
+ while ($('#zoomDiv span:last').attr('name') != type) {
+ $('#zoomDiv span:last').remove();
+ }
+ $(obj).removeClass('monitor-zoom-link');
+ $(obj).unbind('click');
+
+ drawGangliaNodesArea();
+}
+
+/**
+ * Add the zoom level when clicked
+ */
+function addZoomDiv(obj) {
+ var name = $(obj).text();
+ var type = $(obj).attr('name');
+
+ var lastzoomobj = $('#zoomDiv span:last');
+ lastzoomobj.addClass('monitor-zoom-link');
+ lastzoomobj.bind('click', function() {
+ updateZoom(this);
+ });
+
+ var newcontent = ' > ' + name + '(' + type.toUpperCase() + ')';
+ var newli = '' + newcontent + ' ';
+ $('#zoomDiv').append(newli);
+
+ drawGangliaNodesArea();
}
\ No newline at end of file
diff --git a/xCAT-UI/js/monitor/monitor.js b/xCAT-UI/js/monitor/monitor.js
index 5f1eeedaa..d55341cf5 100644
--- a/xCAT-UI/js/monitor/monitor.js
+++ b/xCAT-UI/js/monitor/monitor.js
@@ -1,276 +1,281 @@
-/**
- * Global variables
- */
-var monitorTabs; // Monitor tabs
-
-/**
- * Set the monitor tab
- *
- * @param o
- * Tab object
- * @return Nothing
- */
-function setMonitorTab(o) {
- monitorTabs = o;
-}
-
-/**
- * Get the monitor tab
- *
- * @return Tab object
- */
-function getMonitorTab() {
- return monitorTabs;
-}
-
-/**
- * Load the monitor page
- */
-function loadMonitorPage() {
- // If the page is already loaded
- if ($('#monitor_page').children().length) {
- // Do not reload the monitor page
- return;
- }
-
- // Create monitor tab
- var tab = new Tab();
- setMonitorTab(tab);
- tab.init();
- $('#content').append(tab.object());
-
- var monitorForm = $('
');
- monitorForm.append('Getting monitoring status ').append(createLoader());
- tab.add('monitorTab', 'Monitor', monitorForm, false);
-
- // Get monitoring status of each tool
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'monls',
- msg : ''
- },
-
- /**
- * Load monitoring status
- *
- * @param data Data returned from HTTP request
- */
- success : function(data){
- // Initialize status for each tool
- var statusHash = new Object();
- statusHash['xcatmon'] = 'Off';
- statusHash['rmcmon'] = 'Off';
- statusHash['rmcevent'] = 'Off';
- statusHash['gangliamon'] = 'Off';
- if (data.rsp[0]) {
- var tempArray = data.rsp[0].split(';');
- var position = 0;
- var name = '';
- var status = '';
- for ( var i in tempArray) {
- position = tempArray[i].indexOf(':');
- if (position == -1) {
- continue;
- }
-
- name = tempArray[i].substr(0, position);
- status = tempArray[i].substr(position + 1);
- statusHash[name] = status;
- }
- }
-
- // Create a status buttonset for each monitoring tool
- var statusButtonHash = new Object();
- for ( var name in statusHash) {
- var statusButton = $('
').css({
- 'width': '100px',
- 'text-align': 'center'
- });
- statusButtonHash[name] = statusButton;
-
- // Set button to correct status
- if (statusHash[name] == 'On') {
- statusButton.append($('On '));
- statusButton.append($('Off '));
- } else {
- statusButton.append($('On '));
- statusButton.append($('Off '));
- }
-
- statusButton.find('label').css({
- 'margin': '0px',
- 'padding': '0px',
- 'font-size': '10px',
- 'width': 'auto'
- });
- statusButton.buttonset();
-
- // Turn on or off monitoring tool when clicked
- statusButton.find('input["' + name + '"]:radio').change(toggleMonitor);
- }
-
- var monTable = $('');
- monTable.append($(''));
-
- var monTableBody = $(' ');
- monTable.append(monTableBody);
-
- var xcatMon = $(' ');
- xcatMon.append($('xCAT '));
- xcatMon.append($(' ').append(statusButtonHash['xcatmon']));
- xcatMon.append($('xCAT provides node status monitoring using fping on AIX and nmapon Linux. It also provides application status monitoring. The status and the appstatus columns of the nodelist table will be updated periodically with the latest status values for the nodes. '));
- monTableBody.append(xcatMon);
-
- var rmcMon = $(' ');
- rmcMon.append($('RMC '));
- rmcMon.append($(' ').append(statusButtonHash['rmcmon']));
- rmcMon.append($('Resource Monitoring and Control (RMC) is a generalized framework for managing, monitoring and manipulating resources, such as physical or logical system entities. RMC is utilized as a communication mechanism for reporting service events to the Hardware Management Console (HMC). '));
- monTableBody.append(rmcMon);
-
- var rmcEvent = $(' ');
- rmcEvent.append($('RMC Event '));
- rmcEvent.append($(' ').append(statusButtonHash['rmcevent']));
- rmcEvent.append($('Shows a list of events recorded by the RSCT Event Response resource manager in the audit log. '));
- monTableBody.append(rmcEvent);
-
- var gangliaMon = $(' ');
- gangliaMon.append($('Ganglia '));
- gangliaMon.append($(' ').append(statusButtonHash['gangliamon']));
- gangliaMon.append($('Ganglia is a scalable distributed monitoring system for high-performance computing systems such as clusters and Grids. '));
- monTableBody.append(gangliaMon);
-
- // Do not word wrap
- monTableBody.find('td:nth-child(1)').css('white-space', 'nowrap');
- monTableBody.find('td:nth-child(3)').css({
- 'white-space': 'normal',
- 'text-align': 'left'
- });
-
- // Append info bar
- $('#monitorTab div').empty().append(createInfoBar('Select a monitoring tool to use'));
- $('#monitorTab .form').append(monTable);
-
- // Open monitoring tool onclick
- $('#monitorTab .form a').bind('click', function() {
- loadMonitorTab($(this).attr('name'));
- });
- }
- });
-}
-
-/**
- * Load monitoring tool in a new tab
- *
- * @param name Name of monitoring tool
- */
-function loadMonitorTab(name) {
- // If the tab exist, then we only need to select it
- var tab = getMonitorTab();
- if ($("#" + name).length) {
- tab.select(name);
- return;
- }
-
- switch (name) {
- case 'xcatmon':
- tab.add(name, 'xCAT', '', true);
- loadXcatMon();
- break;
- case 'rmcmon':
- tab.add(name, 'RMC Monitor', '', true);
- loadRmcMon();
- break;
- case 'gangliamon':
- tab.add(name, 'Ganglia', '', true);
- loadGangliaMon();
- break;
- case 'rmcevent':
- tab.add(name, 'RMC Event', '', true);
- loadRmcEvent();
- break;
- }
-
- tab.select(name);
-}
-
-/**
- * Load tab showing 'Under contruction'
- *
- * @param monitorName Name of monitoring tool
- * @param tab Tab area
- */
-function loadUnfinish(monitorName, tab) {
- var unfinishPage = $('
');
- unfinishPage.append(createInfoBar('Not yet supported'));
- tab.add(monitorName, 'Unfinished', unfinishPage, true);
-}
-
-/**
- * Turn on or off monitoring tool
- *
- * @return Nothing
- */
-function toggleMonitor() {
- // Get the name of the monitoring tool
- var name = $(this).attr('name');
- // Get the status to toggle to, either on or off
- var status = $(this).val();
-
- // Start or stop monitoring plugin
- var command = 'monstart';
- if (status == 'Off') {
- command = 'monstop' ;
- }
-
- // Start or stop monitoring on xCAT
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : command,
- tgt : '',
- args : name + '',
- msg : ''
- },
- success : function(data) {
- // Start or stop monitoring on remote nodes
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : command,
- tgt : '',
- args : name + ';-r',
- msg : name + ' switched ' + status
- },
- success : updateMonStatus
- });
- }
- });
-}
-
-/**
- * Update the monitoring status on Monitor tab
- *
- * @param data Data returned from HTTP request
- */
-function updateMonStatus(data) {
- var rsp = data.rsp[data.rsp.length-1];
- var msg = data.msg;
-
- // Create appropriate info or warning bar
- var bar = '';
- if (rsp.indexOf('started') > -1 || rsp.indexOf('stopped') > -1) {
- bar = createInfoBar(msg);
- } else {
- bar = createWarnBar('Failed to ' + msg + '. ' + rsp);
- }
-
- // Prepend info or warning bar to tab
- bar.prependTo($('#monitorTab .form'));
- bar.delay(4000).slideUp();
+/**
+ * Global variables
+ */
+var monitorTabs; // Monitor tabs
+
+/**
+ * Set the monitor tab
+ *
+ * @param o
+ * Tab object
+ * @return Nothing
+ */
+function setMonitorTab(o) {
+ monitorTabs = o;
+}
+
+/**
+ * Get the monitor tab
+ *
+ * @return Tab object
+ */
+function getMonitorTab() {
+ return monitorTabs;
+}
+
+/**
+ * Load the monitor page
+ */
+function loadMonitorPage() {
+ // If the page is already loaded
+ if ($('#monitor_page').children().length) {
+ // Do not reload the monitor page
+ return;
+ }
+
+ // Create monitor tab
+ var tab = new Tab();
+ setMonitorTab(tab);
+ tab.init();
+ $('#content').append(tab.object());
+
+ var monitorForm = $('
');
+ monitorForm.append('Getting monitoring status ').append(createLoader());
+ tab.add('monitorTab', 'Monitor', monitorForm, false);
+
+ // Get monitoring status of each tool
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'monls',
+ msg : ''
+ },
+
+ /**
+ * Load monitoring status
+ *
+ * @param data Data returned from HTTP request
+ */
+ success : function(data){
+ data = decodeRsp(data);
+ // Initialize status for each tool
+ var statusHash = new Object();
+ statusHash['xcatmon'] = 'Off';
+ statusHash['rmcmon'] = 'Off';
+ statusHash['rmcevent'] = 'Off';
+ statusHash['gangliamon'] = 'Off';
+ if (data.rsp[0]) {
+ var tempArray = data.rsp[0].split(';');
+ var position = 0;
+ var name = '';
+ var status = '';
+ for ( var i in tempArray) {
+ position = tempArray[i].indexOf(':');
+ if (position == -1) {
+ continue;
+ }
+
+ name = tempArray[i].substr(0, position);
+ status = tempArray[i].substr(position + 1);
+ statusHash[name] = status;
+ }
+ }
+
+ // Create a status buttonset for each monitoring tool
+ var statusButtonHash = new Object();
+ for ( var name in statusHash) {
+ var statusButton = $('
').css({
+ 'width': '100px',
+ 'text-align': 'center'
+ });
+ statusButtonHash[name] = statusButton;
+
+ // Set button to correct status
+ if (statusHash[name] == 'On') {
+ statusButton.append($('On '));
+ statusButton.append($('Off '));
+ } else {
+ statusButton.append($('On '));
+ statusButton.append($('Off '));
+ }
+
+ statusButton.find('label').css({
+ 'margin': '0px',
+ 'padding': '0px',
+ 'font-size': '10px',
+ 'width': 'auto'
+ });
+ statusButton.buttonset();
+
+ // Turn on or off monitoring tool when clicked
+ statusButton.find('input["' + name + '"]:radio').change(toggleMonitor);
+ }
+
+ var monTable = $('');
+ monTable.append($(''));
+
+ var monTableBody = $(' ');
+ monTable.append(monTableBody);
+
+ var xcatMon = $(' ');
+ xcatMon.append($('xCAT '));
+ xcatMon.append($(' ').append(statusButtonHash['xcatmon']));
+ xcatMon.append($('xCAT provides node status monitoring using fping on AIX and nmapon Linux. It also provides application status monitoring. The status and the appstatus columns of the nodelist table will be updated periodically with the latest status values for the nodes. '));
+ monTableBody.append(xcatMon);
+
+ var rmcMon = $(' ');
+ rmcMon.append($('RMC '));
+ rmcMon.append($(' ').append(statusButtonHash['rmcmon']));
+ rmcMon.append($('Resource Monitoring and Control (RMC) is a generalized framework for managing, monitoring and manipulating resources, such as physical or logical system entities. RMC is utilized as a communication mechanism for reporting service events to the Hardware Management Console (HMC). '));
+ monTableBody.append(rmcMon);
+
+ var rmcEvent = $(' ');
+ rmcEvent.append($('RMC Event '));
+ rmcEvent.append($(' ').append(statusButtonHash['rmcevent']));
+ rmcEvent.append($('Shows a list of events recorded by the RSCT Event Response resource manager in the audit log. '));
+ monTableBody.append(rmcEvent);
+
+ var gangliaMon = $(' ');
+ gangliaMon.append($('Ganglia '));
+ gangliaMon.append($(' ').append(statusButtonHash['gangliamon']));
+ gangliaMon.append($('Ganglia is a scalable distributed monitoring system for high-performance computing systems such as clusters and Grids. '));
+ monTableBody.append(gangliaMon);
+
+ // Do not word wrap
+ monTableBody.find('td:nth-child(1)').css('white-space', 'nowrap');
+ monTableBody.find('td:nth-child(3)').css({
+ 'white-space': 'normal',
+ 'text-align': 'left'
+ });
+
+ // Append info bar
+ $('#monitorTab div').empty().append(createInfoBar('Select a monitoring tool to use'));
+ $('#monitorTab .form').append(monTable);
+
+ // Open monitoring tool onclick
+ $('#monitorTab .form a').bind('click', function() {
+ loadMonitorTab($(this).attr('name'));
+ });
+ }
+ });
+}
+
+/**
+ * Load monitoring tool in a new tab
+ *
+ * @param name Name of monitoring tool
+ */
+function loadMonitorTab(name) {
+ // If the tab exist, then we only need to select it
+ var tab = getMonitorTab();
+ if ($("#" + name).length) {
+ tab.select(name);
+ return;
+ }
+
+ switch (name) {
+ case 'xcatmon':
+ tab.add(name, 'xCAT', '', true);
+ loadXcatMon();
+ break;
+ case 'rmcmon':
+ tab.add(name, 'RMC Monitor', '', true);
+ loadRmcMon();
+ break;
+ case 'gangliamon':
+ tab.add(name, 'Ganglia', '', true);
+ loadGangliaMon();
+ break;
+ case 'rmcevent':
+ tab.add(name, 'RMC Event', '', true);
+ loadRmcEvent();
+ break;
+ }
+
+ tab.select(name);
+}
+
+/**
+ * Load tab showing 'Under contruction'
+ *
+ * @param monitorName Name of monitoring tool
+ * @param tab Tab area
+ */
+function loadUnfinish(monitorName, tab) {
+ var unfinishPage = $('
');
+ unfinishPage.append(createInfoBar('Not yet supported'));
+ tab.add(monitorName, 'Unfinished', unfinishPage, true);
+}
+
+/**
+ * Turn on or off monitoring tool
+ *
+ * @return Nothing
+ */
+function toggleMonitor() {
+ // Get the name of the monitoring tool
+ var name = $(this).attr('name');
+ // Get the status to toggle to, either on or off
+ var status = $(this).val();
+
+ // Start or stop monitoring plugin
+ var command = 'monstart';
+ if (status == 'Off') {
+ command = 'monstop' ;
+ }
+
+ // Start or stop monitoring on xCAT
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : command,
+ tgt : '',
+ args : name + '',
+ msg : ''
+ },
+ success : function(data) {
+ data = decodeRsp(data);
+ // Start or stop monitoring on remote nodes
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : command,
+ tgt : '',
+ args : name + ';-r',
+ msg : name + ' switched ' + status
+ },
+ success : function(data) {
+ data = decodeRsp(data);
+ updateMonStatus(data);
+ }
+ });
+ }
+ });
+}
+
+/**
+ * Update the monitoring status on Monitor tab
+ *
+ * @param data Data returned from HTTP request
+ */
+function updateMonStatus(data) {
+ var rsp = data.rsp[data.rsp.length-1];
+ var msg = data.msg;
+
+ // Create appropriate info or warning bar
+ var bar = '';
+ if (rsp.indexOf('started') > -1 || rsp.indexOf('stopped') > -1) {
+ bar = createInfoBar(msg);
+ } else {
+ bar = createWarnBar('Failed to ' + msg + '. ' + rsp);
+ }
+
+ // Prepend info or warning bar to tab
+ bar.prependTo($('#monitorTab .form'));
+ bar.delay(4000).slideUp();
}
\ No newline at end of file
diff --git a/xCAT-UI/js/monitor/rmcmon.js b/xCAT-UI/js/monitor/rmcmon.js
index 6b5aaa517..31ef0906f 100644
--- a/xCAT-UI/js/monitor/rmcmon.js
+++ b/xCAT-UI/js/monitor/rmcmon.js
@@ -1,1189 +1,1212 @@
-var globalNodesDetail = new Object();
-var globalAllNodesNum = 0;
-var globalFinishNodesNum = 0;
-var globalTimeStamp;
-var globalCondition = '';
-var globalResponse = new Object();
-
-function loadRmcMon() {
- // Find the rmcmon tab
- var rmcMonTab = $('#rmcmon');
-
- // Add the stauts bar first. id = 'rmcMonStatus'
- var rmcStatusBar = createStatusBar('rmcMonStatus');
- rmcStatusBar.find('div').append(createLoader());
- rmcMonTab.append(rmcStatusBar);
-
- // Add the configure button
- var configButton = createButton('Configure');
- configButton.hide();
- configButton.click(function() {
- if ($('#rmcMonConfig').is(':hidden')) {
- $('#rmcMonConfig').show();
- } else {
- $('#rmcMonConfig').hide();
- }
- });
- rmcMonTab.append(configButton);
-
- // Add configure div
- rmcMonTab.append("
");
- $('#rmcMonConfig').hide();
-
- // Load the configure div's content
- loadRmcMonConfigure();
-
- // Add the content of the rmcmon
- rmcMonTab
- .append("");
- $('#nodeDetail').hide();
-
- // Check the software work status by platform (Linux and AIX)
- $.ajax({
- url : 'lib/systemcmd.php',
- dataType : 'json',
- data : {
- cmd : 'ostype'
- },
-
- success : rsctRpmCheck
- });
-}
-
-function loadRmcMonConfigure() {
- // Get the configure div and clean its content
- var rmcmonCfgDiv = $('#rmcMonConfig');
- rmcmonCfgDiv.empty();
-
- // Add the start button
- var startButton = createButton('Start');
- rmcmonCfgDiv.append(startButton);
- startButton.click(function() {
- $('#rmcMonStatus div').empty().append(createLoader());
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'rmcstart;compute',
- msg : ''
- },
-
- success : function(data) {
- $('#rmcMonStatus div').empty().append(data.rsp[0]);
- }
- });
- });
-
- // Add the stop button
- var stopButton = createButton('Stop');
- rmcmonCfgDiv.append(stopButton);
- stopButton.click(function() {
- $('#rmcMonStatus div').empty().append(createLoader());
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'monstop',
- tgt : '',
- args : 'rmcmon',
- msg : ''
- },
-
- success : function(data) {
- $('#rmcMonStatus div').empty().append(data.rsp[0]);
- }
- });
- });
-
- // Add the cancel button
- var cancelButton = createButton('Cancel');
- rmcmonCfgDiv.append(cancelButton);
- cancelButton.click(function() {
- $('#rmcMonConfig').hide();
- });
-}
-
-function rsctRpmCheck(data) {
- // Linux has to check the rscp first
- if ('aix' != data.rsp) {
- $.ajax({
- url : 'lib/systemcmd.php',
- dataType : 'json',
- data : {
- cmd : 'rpm -q rsct.core'
- },
-
- success : function(data) {
- if (-1 != data.rsp.indexOf("not")) {
- $('#rmcMonStatus div')
- .empty()
- .append(
- 'Please install the RSCT first. '
- + 'You can find more support from xCAT2-Monitoring.pdf ');
- } else {
- xcatrmcRpmCheck();
- }
- }
- });
- } else {
- xcatrmcRpmCheck();
- }
-}
-
-function xcatrmcRpmCheck() {
- $.ajax({
- url : 'lib/systemcmd.php',
- dataType : 'json',
- data : {
- cmd : 'rpm -q xCAT-rmc rrdtool'
- },
-
- success : function(data) {
- var softInstallStatus = data.rsp.split(/\n/);
- var needHelp = false;
- $('#rmcMonStatus div').empty();
- // Check the xcat-rmc
- if (-1 != softInstallStatus[0].indexOf("not")) {
- needHelp = true;
- $('#rmcMonStatus div')
- .append(
- 'Please install the xCAT-rmc first. ');
- }
-
- // Check the rrdtool
- if (-1 != softInstallStatus[1].indexOf("not")) {
- needHelp = true;
- $('#rmcMonStatus div')
- .append(
- 'Please install the RRD-tool first. ');
- }
-
- // Add help info or load the rmc show
- if (needHelp) {
- $('#rmcMonStatus div')
- .append(
- 'You can find more support form xCAT2-Monitoring.pdf ');
- } else {
- rmcWorkingCheck();
- }
- }
- });
-}
-
-function rmcWorkingCheck() {
- $('#rmcMonStatus div').empty().append("Checking RMC working status");
- $('#rmcMonStatus div').append(createLoader());
- $('#rmcmon button:first').show();
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'monls',
- tgt : '',
- args : 'rmcmon',
- msg : ''
- },
-
- success : function(data) {
- if (-1 != data.rsp[0].indexOf("not-monitored")) {
- $('#rmcMonStatus div').empty().append(
- "Please start the RMC Monitoring first");
- return;
- }
- loadRmcMonShow();
- }
- });
-}
-
-function removeStatusBar() {
- if (globalAllNodesNum == globalFinishNodesNum) {
- $('#rmcMonStatus').remove();
- }
-
- $('#rmcmonDetail [title]').tooltip({
- position : [ 'center', 'right' ]
- });
-}
-
-function loadRmcMonShow() {
- $('#rmcMonStatus div').empty().append("Getting summary data");
- $('#rmcMonStatus div').append(createLoader());
-
- // Load the rmc status summary
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'rmcshow;summary;PctTotalTimeIdle,PctRealMemFree',
- msg : ''
- },
-
- success : function(data) {
- showRmcSummary(data.rsp[0]);
- }
- });
-}
-
-function showRmcSummary(returnData) {
- var attributes = returnData.split(';');
- var attr;
- var attrName;
- var attrValues;
- var attrDiv;
- var summaryTable = $('');
- var summaryRow;
- globalTimeStamp = new Array();
-
- // Update the rmc status area
- $('#rmcMonStatus div').empty().append("Getting nodes data").append(
- createLoader());
- // Load each nodes' status
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'rmcshow;compute;PctTotalTimeIdle,PctRealMemFree',
- msg : ''
- },
-
- success : function(data) {
- parseRmcData(data.rsp);
- }
- });
-
- // Create the timestamp, the flot only use the UTC time, so had to change the value, to show the right time
- var tempDate = new Date();
- var tempOffset = tempDate.getTimezoneOffset();
- var tempTime = tempDate.getTime() - 3600000;
- for (var i = 0; i < 60; i++) {
- tempDate.setTime(tempTime + i * 60000);
- globalTimeStamp.push(tempDate.getTime());
- }
-
- // Show the summary data
- $('#rmcmonSummary').empty().append('Overview ');
- $('#rmcmonSummary').append(summaryTable);
-
- for (attr in attributes) {
- var tempTd = $(' ');
- var tempArray = [];
- var temp = attributes[attr].indexOf(':');
- attrName = attributes[attr].substr(0, temp);
- attrValues = attributes[attr].substr(temp + 1).split(',');
-
- if (0 == (attr % 3)) {
- summaryRow = $(' ');
- summaryTable.append(summaryRow);
- }
- summaryRow.append(tempTd);
- attrDiv = $('
');
- tempTd.append(attrDiv);
- for (var i in attrValues) {
- tempArray.push([ globalTimeStamp[i], Number(attrValues[i]) ]);
- }
-
- $.jqplot('monitor-sum-div' + attr, [ tempArray ], {
- series : [ {
- showMarker : false
- } ],
- axes : {
- xaxis : {
- label : attrName,
- renderer : $.jqplot.DateAxisRenderer,
- numberTicks : 5,
- tickOptions : {
- formatString : '%R',
- show : true,
- fontSize : '10px'
- }
- },
- yaxis : {
- tickOptions : {
- formatString : '%.2f',
- fontSize : '10px'
- }
- }
- }
- });
- }
-}
-
-function parseRmcData(returnData) {
- var nodeName;
- var nodeStatus;
-
- $('#rmcmonDetail').empty().append('Detail ');
-
- // Add the table for show nodes
- var detailUl = $('');
- // Update the table area
- $('#rmcmonDetail ul').remove();
- $('#rmcmonDetail').append(detailUl);
-
- globalAllNodesNum = returnData.length;
- globalFinishNodesNum = 0;
- for (var i in returnData) {
- var temp = returnData[i].indexOf(':');
- ;
- nodeName = returnData[i].substr(0, temp);
- nodeStatus = returnData[i].substr(temp + 1).replace(/(^\s*)|(\s*$)/g,
- '');
-
- if ('OK' != nodeStatus) {
- globalFinishNodesNum++;
- detailUl.append(createUnkownNode(nodeName));
- removeStatusBar();
- continue;
- }
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'rmcshow;' + nodeName
- + ';PctTotalTimeIdle,PctRealMemFree',
- msg : nodeName
- },
-
- success : function(data) {
- showRmcNodes(data.rsp, data.msg);
- }
- });
- }
-}
-
-function createUnkownNode(nodeName) {
- var tempLi = ' Unknown">';
- return tempLi;
-}
-
-function createErrorNode(nodeName) {
- var tempLi = ' Error">';
-}
-
-function showRmcNodes(data, nodename) {
- var attrname = '';
- var values = '';
- var position = 0;
- var index = 0;
- var classname = '';
- var tempObj = {};
-
- for (index in data) {
- position = data[index].indexOf(':');
- attrname = data[index].substr(0, position);
- values = data[index].substr(position + 1);
- // Error node, cannot get the last hour's data
- if (!values) {
- $('#rmcmonDetail ul').append(createErrorNode(nodename));
- if (globalNodesDetail[nodename]) {
- delete (globalNodesDetail[nodename]);
- }
- return;
- }
-
- // Normal node, save the values
- tempObj[attrname] = values;
- }
-
- globalNodesDetail[nodename] = tempObj;
-
- // Get each average
- var cpuAvg = 0;
- var memAvg = 0;
- var tempSum = 0;
- var tempArray = globalNodesDetail[nodename]['PctTotalTimeIdle'].split(',');
- for (index = 0; index < tempArray.length; index++) {
- tempSum += Number(tempArray[index]);
- }
- cpuAvg = parseInt(tempSum / index);
-
- tempArray = globalNodesDetail[nodename]['PctRealMemFree'].split(',');
- tempSum = 0;
- for (index = 0; index < tempArray.length; index++) {
- tempSum += Number(tempArray[index]);
- }
- memAvg = parseInt(tempSum / index);
-
- if (cpuAvg >= 10 && memAvg <= 90) {
- classname = 'monitor-normal';
- } else {
- classname = 'mornitor-warning';
- }
-
- var normalLi = $(' ');
-
- $('#rmcmonDetail ul').append(normalLi);
- normalLi.bind('click', function() {
- showNode($(this).attr('id'));
- });
-
- // Check if the process finished
- globalFinishNodesNum++;
- removeStatusBar();
-}
-
-function showNode(nodeName) {
- var nodeTable = $('');
- var backButton = createButton('Go back to all nodes');
- var nodeRow;
- var parseNum = 0;
-
- $('#rmcmonDetail').hide();
- $('#nodeDetail').empty().show();
- $('#nodeDetail').append('' + nodeName + ' Detail ');
- $('#nodeDetail').append(backButton);
- backButton.bind('click', function() {
- $('#nodeDetail').hide();
- $('#rmcmonDetail').show();
- });
-
- $('#nodeDetail').append(nodeTable);
-
- for (var attr in globalNodesDetail[nodeName]) {
- var tempTd = $(' ');
- var attrChat = $('
');
- if (0 == parseNum % 4) {
- nodeRow = $(' ');
- nodeTable.append(nodeRow);
- }
- nodeRow.append(tempTd);
- parseNum++;
-
- tempTd.append(attrChat);
- var tempData = globalNodesDetail[nodeName][attr].split(',');
- var tempArray = [];
- for (var i in tempData) {
- tempArray.push([ globalTimeStamp[i], Number(tempData[i]) ]);
- }
-
- $.jqplot('monitor-node-div' + nodeName + attr, [ tempArray ], {
- series : [ {
- showMarker : false
- } ],
- axes : {
- xaxis : {
- label : attr,
- renderer : $.jqplot.DateAxisRenderer,
- numberTicks : 5,
- tickOptions : {
- formatString : '%R',
- show : true,
- fontSize : '10px'
- }
- },
- yaxis : {
- tickOptions : {
- formatString : '%.2f',
- fontSize : '10px'
- }
- }
- }
- });
- }
-}
-
-/**
- * Load the rmc event tab
- */
-function loadRmcEvent() {
- // Find the rmcevent tab
-
- // Add the stauts bar first
- var rmcStatusBar = createStatusBar('rmcEventStatus');
- rmcStatusBar.find('div').append(createLoader());
- $('#rmcevent').append(rmcStatusBar);
- $('#rmcevent').append('
');
-
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'lsevent;-O;1000',
- msg : ''
- },
-
- success : showEventLog
- });
-}
-
-/**
- * Get all conditions
- */
-function getConditions() {
- if (!globalCondition) {
- $('#rmcEventStatus div').empty()
- .append('Getting predefined conditions').append(createLoader());
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'lscondition',
- msg : ''
- },
-
- success : function(data) {
- $('#rmcEventStatus div').empty();
- $('#rmcEventButtons').show();
- globalCondition = data.rsp[0];
- }
- });
- } else {
- $('#rmcEventButtons').show();
- }
-}
-
-/**
- * Get all response
- */
-function getResponse() {
- var tempFlag = false;
- // Get all response first
- for (var i in globalResponse) {
- tempFlag = true;
- break;
- }
-
- if (!tempFlag) {
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'lsresponse',
- msg : ''
- },
-
- success : function(data) {
- var resps = data.rsp[0].split(';');
- for (var i in resps) {
- var name = resps[i];
- name = name.substr(1, (name.length - 2));
- globalResponse[name] = 1;
- }
- }
- });
- }
-}
-
-/**
- * Show all the event in the rmc event tab
- *
- * @param data Response from the xcat server
- */
-function showEventLog(data) {
- $('#rmcEventStatus div').empty();
- // rsct not installed
- if (data.rsp[0] && (-1 != data.rsp[0].indexOf('lsevent'))) {
- $('#rmcEventStatus div').append('Please install RSCT first!');
- return;
- }
- var eventDiv = $('#rmcEventDiv');
- eventDiv.empty();
-
- // Get conditions and responses, save in the global
- getConditions();
- getResponse();
-
- var eventTable = new DataTable('lsEventTable');
- eventTable.init([ 'Time', 'Type', 'Content' ]);
-
- for (var i in data.rsp) {
- var row = data.rsp[i].split(';');
- eventTable.add(row);
- }
-
- eventDiv.append(eventTable.object());
- $('#lsEventTable').dataTable({
- 'iDisplayLength': 50,
- 'bLengthChange': false,
- "bScrollCollapse": true,
- "sScrollY": "400px",
- "sScrollX": "110%",
- "bAutoWidth": true,
- "oLanguage": {
- "oPaginate": {
- "sNext": "",
- "sPrevious": ""
- }
- }
- });
-
- // Add the configure button
- loadRmcEventConfig();
-
- // Unsort on the content column
- $('#lsEventTable thead tr th').eq(2).unbind('click');
-}
-
-/**
- * Add the configure button into rmc event tab
- */
-function loadRmcEventConfig() {
- // Create action bar
- var actionBar = $('
');
- var chCondScopeLnk = $('Change condition scope ');
- chCondScopeLnk.bind('click', function() {
- chCondScopeDia();
- });
-
- var mkCondRespLnk = $('Make/remove associatione ');
- mkCondRespLnk.bind('click', function() {
- mkCondRespDia();
- });
-
- var startCondRespLnk = $('Start/stop association ');
- startCondRespLnk.bind('click', function() {
- startStopCondRespDia();
- });
-
- // Actions
- var actionsLnk = 'Actions ';
- var actsMenu = createMenu([ chCondScopeLnk, mkCondRespLnk, startCondRespLnk ]);
-
- // Create an action menu
- var actionsMenu = createMenu([ [ actionsLnk, actsMenu ] ]);
- actionsMenu.superfish();
- actionsMenu.css('display', 'inline-block');
- actionBar.append(actionsMenu);
-
- // Create a division to hold actions menu
- var menuDiv = $('');
- $('#lsEventTable_wrapper').prepend(menuDiv);
- menuDiv.append(actionBar);
- $('#lsEventTable_filter').appendTo(menuDiv);
-}
-
-/**
- * Show the make association dialogue
- */
-function mkCondRespDia() {
- var diaDiv = $('
');
- var mkAssociationTable = 'Condition Name Response Name ';
- mkAssociationTable += '';
- // Add the conditions into fieldset
- if (!globalCondition) {
- mkAssociationTable += 'Getting predefined conditions, open this dislogue later';
- } else {
- mkAssociationTable += createConditionTd(globalCondition);
- }
-
- mkAssociationTable += ' Please select condition first
';
- diaDiv.append(mkAssociationTable);
- diaDiv.append('');
- // Change the response field when click the condition
- diaDiv.find('input:radio').bind('click',
- function() {
- diaDiv.find('#mkAssResp').empty().append('Getting response').append(createLoader());
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'lscondresp;"'
- + $(this).attr('value') + '"',
- msg : ''
- },
-
- success : function(data) {
- var tempHash = new Object();
- var oldSelectedResp = '';
- var showStr = '';
- if (data.rsp[0]) {
- var names = data.rsp[0].split(';');
- for (var i in names) {
- var name = names[i];
- name = name.substr(1,
- name.length - 2);
- tempHash[name] = 1;
- }
- }
-
- for (var name in globalResponse) {
- if (tempHash[name]) {
- showStr += '
'
- + name
- + '
';
- oldSelectedResp += ';' + name;
- } else {
- showStr += '
'
- + name
- + '
';
- }
- }
-
- diaDiv.find('#mkAssResp').empty()
- .append(showStr);
- diaDiv.find('#selectedResp').empty()
- .append(oldSelectedResp);
- }
- });
- });
-
- diaDiv.dialog({
- modal : true,
- width : 620,
- height : 600,
- close : function(event, ui) {
- $(this).remove();
- },
- buttons : {
- 'Ok' : function() {
- var newResp = new Object();
- var oldResp = new Object();
- var oldString = '';
- var newString = '';
-
- // Get the old seelected responses
- var conditionName = $(this).find('#mkAssCond :checked').attr(
- 'value');
- if (!conditionName) {
- return;
- }
- var temp = $(this).find('#selectedResp').html();
- if (!temp) {
- return;
- }
- var tempArray = temp.substr(1).split(';');
- for (var i in tempArray) {
- oldResp[tempArray[i]] = 1;
- }
-
- // Get the new selected responses
- $(this).find('#mkAssResp input:checked').each(function() {
- var respName = $(this).attr('value');
- newResp[respName] = 1;
- });
-
- for (var i in newResp) {
- if (oldResp[i]) {
- delete oldResp[i];
- delete newResp[i];
- }
- }
-
- // Add the response which are delete
- for (var i in oldResp) {
- oldString += ',"' + i + '"';
- }
- if ('' != oldString) {
- oldString = oldString.substr(1);
- }
-
- // Add the response which are new add
- for (var i in newResp) {
- newString += ',"' + i + '"';
- }
- if ('' != newString) {
- newString = newString.substr(1);
- }
-
- if (('' != oldString) || ('' != newString)) {
- $('#rmcEventStatus div').empty().append(
- 'Create/remove associations ').append(
- createLoader());
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'mkcondresp;"' + conditionName + '";+'
- + newString + ':-' + oldString,
- msg : ''
- },
-
- success : function(data) {
- $('#rmcEventStatus div').empty()
- .append(data.rsp[0]);
- ;
- }
- });
- }
- $(this).dialog('destroy').remove();
- },
- 'Cancel' : function() {
- $(this).dialog('destroy').remove();
- }
- }
- });
-}
-
-/**
- * Show the make condition dialogue
- */
-function chCondScopeDia() {
- var diaDiv = $('
');
- var tableContent = '
';
- diaDiv.append(tableContent);
- // Fieldset to show status
- diaDiv.append('
');
- // Create the dislogue
- diaDiv.dialog({
- modal : true,
- width : 500,
- height : 600,
- close : function(event, ui) {
- $(this).remove();
- },
- buttons : {
- 'Ok' : function() {
- $('#changeStatus').empty().append('
Status ');
- var conditionName = $('#changePreCond :checked').attr('value');
- var groupName = '';
- $('#changeGroup :checked').each(function() {
- if ('' == groupName) {
- groupName += $(this).attr('value');
- } else {
- groupName += ',' + $(this).attr('value');
- }
- });
-
- if (undefined == conditionName) {
- $('#changeStatus').append('Please select conditon');
- return;
- }
-
- if ('' == groupName) {
- $('#changeStatus').append('Please select group');
- return;
- }
-
- $('#changeStatus').append(createLoader());
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'mkcondition;change;' + conditionName + ';'
- + groupName,
- msg : ''
- },
-
- success : function(data) {
- $('#changeStatus img').remove();
- if (-1 != data.rsp[0].indexOf('Error')) {
- $('#changeStatus').append(data.rsp[0]);
- } else {
- $('#rmcEventStatus div').empty()
- .append(data.rsp[0]);
- $('#chScopeDiaDiv').remove();
- }
- }
- });
- },
- 'Cancel' : function() {
- $(this).dialog('destroy').remove();
- }
- }
- });
-}
-
-/**
- * Show the make response dialogue
- */
-function mkResponseDia() {
- var diaDiv = $('
');
- diaDiv.append('Not yet supported.');
-
- diaDiv.dialog({
- modal : true,
- width : 400,
- close : function(event, ui) {
- $(this).remove();
- },
- buttons : {
- 'Ok' : function() {
- $(this).dialog('destroy').remove();
- },
- 'Cancel' : function() {
- $(this).dialog('destroy').remove();
- }
- }
- });
-}
-
-/**
- * Start the condition and response associations
- */
-function startStopCondRespDia() {
- var diaDiv = $('
');
- diaDiv.append('Getting conditions').append(createLoader());
-
- if (!globalCondition) {
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'lscondition',
- msg : ''
- },
-
- success : function(data) {
- if (data.rsp[0]) {
- globalcondition = data.rsp[0];
- $('#divStartStopAss').empty().append(
- createAssociationTable(globalCondition));
- $('#divStartStopAss')
- .dialog("option", "position", 'center');
- } else {
- $('#divStartStopAss').empty().append(
- 'There are no conditions');
- }
- }
- });
- } else {
- diaDiv.empty().append(createAssociationTable(globalCondition));
- }
-
- diaDiv.dialog({
- modal : true,
- width : 570,
- height : 600,
- close : function(event, ui) {
- $(this).remove();
- },
- buttons : {
- 'Close' : function() {
- $(this).dialog('destroy').remove();
- }
- }
- });
-
- $('#divStartStopAss button').bind(
- 'click',
- function() {
- var operationType = '';
- var conditionName = $(this).attr('name');
- if ('Start' == $(this).html()) {
- operationType = 'start';
- } else {
- operationType = 'stop';
- }
-
- $(this).parent().prev().empty().append(createLoader());
- $('#divStartStopAss').dialog('option', 'disabled', true);
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : operationType + 'condresp;' + conditionName,
- msg : operationType + ';' + conditionName
- },
-
- success : function(data) {
- var conditionName = '';
- var newOperationType = '';
- var associationStatus = '';
- var backgroudColor = '';
- if ('start' == data.msg.substr(0, 5)) {
- newOperationType = 'Stop';
- conditionName = data.msg.substr(6);
- associationStatus = 'Monitored';
- backgroudColor = '#ffffff';
- } else {
- newOperationType = 'Start';
- conditionName = data.msg.substr(5);
- associationStatus = 'Not Monitored';
- backgroudColor = '#fffacd';
- }
-
- var button = $('#divStartStopAss button[name="'
- + conditionName + '"]');
- if (data.rsp[0]) {
- $('#rmcEventStatus div').empty().append(
- 'Getting associations\' status').append(
- createLoader());
- $('#rmcEventButtons').hide();
- button.html(newOperationType);
- button.parent().prev().html(associationStatus);
- button.parent().parent().css('background-color',
- backgroudColor);
- globalCondition = '';
- getConditions();
- } else {
- button.html('Error');
- }
-
- $('#divStartStopAss').dialog('option', 'disabled',
- false);
- }
- });
- });
-}
-
-/**
- * Stop the condition and response associations
- */
-function stopCondRespDia() {
- var diaDiv = $('
');
- diaDiv.append('Getting conditions').append(createLoader());
-
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'lscondition;-m',
- msg : ''
- },
-
- success : function(data) {
- if (data.rsp[0]) {
- $('#stopAss').empty().append(
- createConditionTable(data.rsp[0]));
- $('#stopAss').dialog("option", "position", 'center');
- } else {
- $('#stopAss').empty().append(
- 'There is not monitored condition.');
- }
- }
- });
-
- diaDiv.dialog({
- modal : true,
- width : 570,
- close : function(event, ui) {
- $(this).remove();
- },
- buttons : {
- 'Stop' : function() {
- var conditionName = $('#stopAss :checked').attr('value');
- if (!conditionName) {
- alert('Select condition name please.');
- return;
- }
- $('#rmcEventStatus div').empty().append(
- 'Stoping monitor on ' + conditionName).append(
- createLoader());
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'stopcondresp;' + conditionName,
- msg : ''
- },
-
- success : function(data) {
- $('#rmcEventStatus div').empty().append(data.rsp[0]);
- }
- });
- $(this).dialog('destroy').remove();
- },
- 'Cancel' : function() {
- $(this).dialog('destroy').remove();
- }
- }
- });
-}
-
-/**
- * Create the condition table for dialogue
- *
- * @param cond Condition
- */
-function createConditionTd(cond) {
- var conditions = cond.split(';');
- var name = '';
- var showStr = '';
- for (var i in conditions) {
- name = conditions[i];
- // Because there is status and quotation marks in name,
- // we must delete the status and quotation marks
- name = name.substr(1, name.length - 6);
- showStr += '
' + name + '
';
- }
-
- return showStr;
-}
-
-/**
- * Create the association table for dialogue, which show the status and start/stop associations
- *
- * @param cond Condition
- */
-function createAssociationTable(cond) {
- var conditions = cond.split(';');
- var name = '';
- var tempLength = '';
- var tempStatus = '';
- var showStr = '
Condition Name Status Start/Stop ';
- showStr += '';
-
- for (var i in conditions) {
- name = conditions[i];
- tempLength = name.length;
- tempStatus = name.substr(tempLength - 3);
- name = name.substr(1, tempLength - 6);
-
- if ('Not' == tempStatus) {
- showStr += '' + name
- + ' Not Monitored ';
- showStr += 'Start ';
- } else {
- showStr += '' + name + ' Monitored ';
- showStr += 'Stop ';
- }
- showStr += ' ';
- }
-
- showStr += '
';
-
- return showStr;
+var globalNodesDetail = new Object();
+var globalAllNodesNum = 0;
+var globalFinishNodesNum = 0;
+var globalTimeStamp;
+var globalCondition = '';
+var globalResponse = new Object();
+
+function loadRmcMon() {
+ // Find the rmcmon tab
+ var rmcMonTab = $('#rmcmon');
+
+ // Add the stauts bar first. id = 'rmcMonStatus'
+ var rmcStatusBar = createStatusBar('rmcMonStatus');
+ rmcStatusBar.find('div').append(createLoader());
+ rmcMonTab.append(rmcStatusBar);
+
+ // Add the configure button
+ var configButton = createButton('Configure');
+ configButton.hide();
+ configButton.click(function() {
+ if ($('#rmcMonConfig').is(':hidden')) {
+ $('#rmcMonConfig').show();
+ } else {
+ $('#rmcMonConfig').hide();
+ }
+ });
+ rmcMonTab.append(configButton);
+
+ // Add configure div
+ rmcMonTab.append("
");
+ $('#rmcMonConfig').hide();
+
+ // Load the configure div's content
+ loadRmcMonConfigure();
+
+ // Add the content of the rmcmon
+ rmcMonTab
+ .append("
");
+ $('#nodeDetail').hide();
+
+ // Check the software work status by platform (Linux and AIX)
+ $.ajax({
+ url : 'lib/systemcmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'ostype'
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ rsctRpmCheck(data);
+ }
+ });
+}
+
+function loadRmcMonConfigure() {
+ // Get the configure div and clean its content
+ var rmcmonCfgDiv = $('#rmcMonConfig');
+ rmcmonCfgDiv.empty();
+
+ // Add the start button
+ var startButton = createButton('Start');
+ rmcmonCfgDiv.append(startButton);
+ startButton.click(function() {
+ $('#rmcMonStatus div').empty().append(createLoader());
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'rmcstart;compute',
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ $('#rmcMonStatus div').empty().append(data.rsp[0]);
+ }
+ });
+ });
+
+ // Add the stop button
+ var stopButton = createButton('Stop');
+ rmcmonCfgDiv.append(stopButton);
+ stopButton.click(function() {
+ $('#rmcMonStatus div').empty().append(createLoader());
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'monstop',
+ tgt : '',
+ args : 'rmcmon',
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ $('#rmcMonStatus div').empty().append(data.rsp[0]);
+ }
+ });
+ });
+
+ // Add the cancel button
+ var cancelButton = createButton('Cancel');
+ rmcmonCfgDiv.append(cancelButton);
+ cancelButton.click(function() {
+ $('#rmcMonConfig').hide();
+ });
+}
+
+function rsctRpmCheck(data) {
+ // Linux has to check the rscp first
+ if ('aix' != data.rsp) {
+ $.ajax({
+ url : 'lib/systemcmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'rpm -q rsct.core'
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ if (-1 != data.rsp.indexOf("not")) {
+ $('#rmcMonStatus div')
+ .empty()
+ .append(
+ 'Please install the
RSCT first.
'
+ + 'You can find more support from
xCAT2-Monitoring.pdf ');
+ } else {
+ xcatrmcRpmCheck();
+ }
+ }
+ });
+ } else {
+ xcatrmcRpmCheck();
+ }
+}
+
+function xcatrmcRpmCheck() {
+ $.ajax({
+ url : 'lib/systemcmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'rpm -q xCAT-rmc rrdtool'
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ var softInstallStatus = data.rsp.split(/\n/);
+ var needHelp = false;
+ $('#rmcMonStatus div').empty();
+ // Check the xcat-rmc
+ if (-1 != softInstallStatus[0].indexOf("not")) {
+ needHelp = true;
+ $('#rmcMonStatus div')
+ .append(
+ 'Please install the
xCAT-rmc first.
');
+ }
+
+ // Check the rrdtool
+ if (-1 != softInstallStatus[1].indexOf("not")) {
+ needHelp = true;
+ $('#rmcMonStatus div')
+ .append(
+ 'Please install the
RRD-tool first.
');
+ }
+
+ // Add help info or load the rmc show
+ if (needHelp) {
+ $('#rmcMonStatus div')
+ .append(
+ 'You can find more support form
xCAT2-Monitoring.pdf ');
+ } else {
+ rmcWorkingCheck();
+ }
+ }
+ });
+}
+
+function rmcWorkingCheck() {
+ $('#rmcMonStatus div').empty().append("Checking RMC working status");
+ $('#rmcMonStatus div').append(createLoader());
+ $('#rmcmon button:first').show();
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'monls',
+ tgt : '',
+ args : 'rmcmon',
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ if (-1 != data.rsp[0].indexOf("not-monitored")) {
+ $('#rmcMonStatus div').empty().append(
+ "Please start the RMC Monitoring first");
+ return;
+ }
+ loadRmcMonShow();
+ }
+ });
+}
+
+function removeStatusBar() {
+ if (globalAllNodesNum == globalFinishNodesNum) {
+ $('#rmcMonStatus').remove();
+ }
+
+ $('#rmcmonDetail [title]').tooltip({
+ position : [ 'center', 'right' ]
+ });
+}
+
+function loadRmcMonShow() {
+ $('#rmcMonStatus div').empty().append("Getting summary data");
+ $('#rmcMonStatus div').append(createLoader());
+
+ // Load the rmc status summary
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'rmcshow;summary;PctTotalTimeIdle,PctRealMemFree',
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ showRmcSummary(data.rsp[0]);
+ }
+ });
+}
+
+function showRmcSummary(returnData) {
+ var attributes = returnData.split(';');
+ var attr;
+ var attrName;
+ var attrValues;
+ var attrDiv;
+ var summaryTable = $('
');
+ var summaryRow;
+ globalTimeStamp = new Array();
+
+ // Update the rmc status area
+ $('#rmcMonStatus div').empty().append("Getting nodes data").append(
+ createLoader());
+ // Load each nodes' status
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'rmcshow;compute;PctTotalTimeIdle,PctRealMemFree',
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ parseRmcData(data.rsp);
+ }
+ });
+
+ // Create the timestamp, the flot only use the UTC time, so had to change the value, to show the right time
+ var tempDate = new Date();
+ var tempOffset = tempDate.getTimezoneOffset();
+ var tempTime = tempDate.getTime() - 3600000;
+ for (var i = 0; i < 60; i++) {
+ tempDate.setTime(tempTime + i * 60000);
+ globalTimeStamp.push(tempDate.getTime());
+ }
+
+ // Show the summary data
+ $('#rmcmonSummary').empty().append('
Overview ');
+ $('#rmcmonSummary').append(summaryTable);
+
+ for (attr in attributes) {
+ var tempTd = $('
');
+ var tempArray = [];
+ var temp = attributes[attr].indexOf(':');
+ attrName = attributes[attr].substr(0, temp);
+ attrValues = attributes[attr].substr(temp + 1).split(',');
+
+ if (0 == (attr % 3)) {
+ summaryRow = $('
');
+ summaryTable.append(summaryRow);
+ }
+ summaryRow.append(tempTd);
+ attrDiv = $('
');
+ tempTd.append(attrDiv);
+ for (var i in attrValues) {
+ tempArray.push([ globalTimeStamp[i], Number(attrValues[i]) ]);
+ }
+
+ $.jqplot('monitor-sum-div' + attr, [ tempArray ], {
+ series : [ {
+ showMarker : false
+ } ],
+ axes : {
+ xaxis : {
+ label : attrName,
+ renderer : $.jqplot.DateAxisRenderer,
+ numberTicks : 5,
+ tickOptions : {
+ formatString : '%R',
+ show : true,
+ fontSize : '10px'
+ }
+ },
+ yaxis : {
+ tickOptions : {
+ formatString : '%.2f',
+ fontSize : '10px'
+ }
+ }
+ }
+ });
+ }
+}
+
+function parseRmcData(returnData) {
+ var nodeName;
+ var nodeStatus;
+
+ $('#rmcmonDetail').empty().append('
Detail ');
+
+ // Add the table for show nodes
+ var detailUl = $('
');
+ // Update the table area
+ $('#rmcmonDetail ul').remove();
+ $('#rmcmonDetail').append(detailUl);
+
+ globalAllNodesNum = returnData.length;
+ globalFinishNodesNum = 0;
+ for (var i in returnData) {
+ var temp = returnData[i].indexOf(':');
+ ;
+ nodeName = returnData[i].substr(0, temp);
+ nodeStatus = returnData[i].substr(temp + 1).replace(/(^\s*)|(\s*$)/g,
+ '');
+
+ if ('OK' != nodeStatus) {
+ globalFinishNodesNum++;
+ detailUl.append(createUnkownNode(nodeName));
+ removeStatusBar();
+ continue;
+ }
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'rmcshow;' + nodeName
+ + ';PctTotalTimeIdle,PctRealMemFree',
+ msg : nodeName
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ showRmcNodes(data.rsp, data.msg);
+ }
+ });
+ }
+}
+
+function createUnkownNode(nodeName) {
+ var tempLi = '
Unknown">';
+ return tempLi;
+}
+
+function createErrorNode(nodeName) {
+ var tempLi = '
Error">';
+}
+
+function showRmcNodes(data, nodename) {
+ var attrname = '';
+ var values = '';
+ var position = 0;
+ var index = 0;
+ var classname = '';
+ var tempObj = {};
+
+ for (index in data) {
+ position = data[index].indexOf(':');
+ attrname = data[index].substr(0, position);
+ values = data[index].substr(position + 1);
+ // Error node, cannot get the last hour's data
+ if (!values) {
+ $('#rmcmonDetail ul').append(createErrorNode(nodename));
+ if (globalNodesDetail[nodename]) {
+ delete (globalNodesDetail[nodename]);
+ }
+ return;
+ }
+
+ // Normal node, save the values
+ tempObj[attrname] = values;
+ }
+
+ globalNodesDetail[nodename] = tempObj;
+
+ // Get each average
+ var cpuAvg = 0;
+ var memAvg = 0;
+ var tempSum = 0;
+ var tempArray = globalNodesDetail[nodename]['PctTotalTimeIdle'].split(',');
+ for (index = 0; index < tempArray.length; index++) {
+ tempSum += Number(tempArray[index]);
+ }
+ cpuAvg = parseInt(tempSum / index);
+
+ tempArray = globalNodesDetail[nodename]['PctRealMemFree'].split(',');
+ tempSum = 0;
+ for (index = 0; index < tempArray.length; index++) {
+ tempSum += Number(tempArray[index]);
+ }
+ memAvg = parseInt(tempSum / index);
+
+ if (cpuAvg >= 10 && memAvg <= 90) {
+ classname = 'monitor-normal';
+ } else {
+ classname = 'mornitor-warning';
+ }
+
+ var normalLi = $('
');
+
+ $('#rmcmonDetail ul').append(normalLi);
+ normalLi.bind('click', function() {
+ showNode($(this).attr('id'));
+ });
+
+ // Check if the process finished
+ globalFinishNodesNum++;
+ removeStatusBar();
+}
+
+function showNode(nodeName) {
+ var nodeTable = $('
');
+ var backButton = createButton('Go back to all nodes');
+ var nodeRow;
+ var parseNum = 0;
+
+ $('#rmcmonDetail').hide();
+ $('#nodeDetail').empty().show();
+ $('#nodeDetail').append('
' + nodeName + ' Detail ');
+ $('#nodeDetail').append(backButton);
+ backButton.bind('click', function() {
+ $('#nodeDetail').hide();
+ $('#rmcmonDetail').show();
+ });
+
+ $('#nodeDetail').append(nodeTable);
+
+ for (var attr in globalNodesDetail[nodeName]) {
+ var tempTd = $('
');
+ var attrChat = $('
');
+ if (0 == parseNum % 4) {
+ nodeRow = $('
');
+ nodeTable.append(nodeRow);
+ }
+ nodeRow.append(tempTd);
+ parseNum++;
+
+ tempTd.append(attrChat);
+ var tempData = globalNodesDetail[nodeName][attr].split(',');
+ var tempArray = [];
+ for (var i in tempData) {
+ tempArray.push([ globalTimeStamp[i], Number(tempData[i]) ]);
+ }
+
+ $.jqplot('monitor-node-div' + nodeName + attr, [ tempArray ], {
+ series : [ {
+ showMarker : false
+ } ],
+ axes : {
+ xaxis : {
+ label : attr,
+ renderer : $.jqplot.DateAxisRenderer,
+ numberTicks : 5,
+ tickOptions : {
+ formatString : '%R',
+ show : true,
+ fontSize : '10px'
+ }
+ },
+ yaxis : {
+ tickOptions : {
+ formatString : '%.2f',
+ fontSize : '10px'
+ }
+ }
+ }
+ });
+ }
+}
+
+/**
+ * Load the rmc event tab
+ */
+function loadRmcEvent() {
+ // Find the rmcevent tab
+
+ // Add the stauts bar first
+ var rmcStatusBar = createStatusBar('rmcEventStatus');
+ rmcStatusBar.find('div').append(createLoader());
+ $('#rmcevent').append(rmcStatusBar);
+ $('#rmcevent').append('
');
+
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'lsevent;-O;1000',
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ showEventLog(data);
+ }
+ });
+}
+
+/**
+ * Get all conditions
+ */
+function getConditions() {
+ if (!globalCondition) {
+ $('#rmcEventStatus div').empty()
+ .append('Getting predefined conditions').append(createLoader());
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'lscondition',
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ $('#rmcEventStatus div').empty();
+ $('#rmcEventButtons').show();
+ globalCondition = data.rsp[0];
+ }
+ });
+ } else {
+ $('#rmcEventButtons').show();
+ }
+}
+
+/**
+ * Get all response
+ */
+function getResponse() {
+ var tempFlag = false;
+ // Get all response first
+ for (var i in globalResponse) {
+ tempFlag = true;
+ break;
+ }
+
+ if (!tempFlag) {
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'lsresponse',
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ var resps = data.rsp[0].split(';');
+ for (var i in resps) {
+ var name = resps[i];
+ name = name.substr(1, (name.length - 2));
+ globalResponse[name] = 1;
+ }
+ }
+ });
+ }
+}
+
+/**
+ * Show all the event in the rmc event tab
+ *
+ * @param data Response from the xcat server
+ */
+function showEventLog(data) {
+ $('#rmcEventStatus div').empty();
+ // rsct not installed
+ if (data.rsp[0] && (-1 != data.rsp[0].indexOf('lsevent'))) {
+ $('#rmcEventStatus div').append('Please install RSCT first!');
+ return;
+ }
+ var eventDiv = $('#rmcEventDiv');
+ eventDiv.empty();
+
+ // Get conditions and responses, save in the global
+ getConditions();
+ getResponse();
+
+ var eventTable = new DataTable('lsEventTable');
+ eventTable.init([ 'Time', 'Type', 'Content' ]);
+
+ for (var i in data.rsp) {
+ var row = data.rsp[i].split(';');
+ eventTable.add(row);
+ }
+
+ eventDiv.append(eventTable.object());
+ $('#lsEventTable').dataTable({
+ 'iDisplayLength': 50,
+ 'bLengthChange': false,
+ "bScrollCollapse": true,
+ "sScrollY": "400px",
+ "sScrollX": "110%",
+ "bAutoWidth": true,
+ "oLanguage": {
+ "oPaginate": {
+ "sNext": "",
+ "sPrevious": ""
+ }
+ }
+ });
+
+ // Add the configure button
+ loadRmcEventConfig();
+
+ // Unsort on the content column
+ $('#lsEventTable thead tr th').eq(2).unbind('click');
+}
+
+/**
+ * Add the configure button into rmc event tab
+ */
+function loadRmcEventConfig() {
+ // Create action bar
+ var actionBar = $('
');
+ var chCondScopeLnk = $('
Change condition scope ');
+ chCondScopeLnk.bind('click', function() {
+ chCondScopeDia();
+ });
+
+ var mkCondRespLnk = $('
Make/remove associatione ');
+ mkCondRespLnk.bind('click', function() {
+ mkCondRespDia();
+ });
+
+ var startCondRespLnk = $('
Start/stop association ');
+ startCondRespLnk.bind('click', function() {
+ startStopCondRespDia();
+ });
+
+ // Actions
+ var actionsLnk = '
Actions ';
+ var actsMenu = createMenu([ chCondScopeLnk, mkCondRespLnk, startCondRespLnk ]);
+
+ // Create an action menu
+ var actionsMenu = createMenu([ [ actionsLnk, actsMenu ] ]);
+ actionsMenu.superfish();
+ actionsMenu.css('display', 'inline-block');
+ actionBar.append(actionsMenu);
+
+ // Create a division to hold actions menu
+ var menuDiv = $('');
+ $('#lsEventTable_wrapper').prepend(menuDiv);
+ menuDiv.append(actionBar);
+ $('#lsEventTable_filter').appendTo(menuDiv);
+}
+
+/**
+ * Show the make association dialogue
+ */
+function mkCondRespDia() {
+ var diaDiv = $('
');
+ var mkAssociationTable = '
Condition Name Response Name ';
+ mkAssociationTable += '';
+ // Add the conditions into fieldset
+ if (!globalCondition) {
+ mkAssociationTable += 'Getting predefined conditions, open this dislogue later';
+ } else {
+ mkAssociationTable += createConditionTd(globalCondition);
+ }
+
+ mkAssociationTable += ' Please select condition first
';
+ diaDiv.append(mkAssociationTable);
+ diaDiv.append('
');
+ // Change the response field when click the condition
+ diaDiv.find('input:radio').bind('click',
+ function() {
+ diaDiv.find('#mkAssResp').empty().append('Getting response').append(createLoader());
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'lscondresp;"'
+ + $(this).attr('value') + '"',
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ var tempHash = new Object();
+ var oldSelectedResp = '';
+ var showStr = '';
+ if (data.rsp[0]) {
+ var names = data.rsp[0].split(';');
+ for (var i in names) {
+ var name = names[i];
+ name = name.substr(1,
+ name.length - 2);
+ tempHash[name] = 1;
+ }
+ }
+
+ for (var name in globalResponse) {
+ if (tempHash[name]) {
+ showStr += '
'
+ + name
+ + '
';
+ oldSelectedResp += ';' + name;
+ } else {
+ showStr += '
'
+ + name
+ + '
';
+ }
+ }
+
+ diaDiv.find('#mkAssResp').empty()
+ .append(showStr);
+ diaDiv.find('#selectedResp').empty()
+ .append(oldSelectedResp);
+ }
+ });
+ });
+
+ diaDiv.dialog({
+ modal : true,
+ width : 620,
+ height : 600,
+ close : function(event, ui) {
+ $(this).remove();
+ },
+ buttons : {
+ 'Ok' : function() {
+ var newResp = new Object();
+ var oldResp = new Object();
+ var oldString = '';
+ var newString = '';
+
+ // Get the old seelected responses
+ var conditionName = $(this).find('#mkAssCond :checked').attr(
+ 'value');
+ if (!conditionName) {
+ return;
+ }
+ var temp = $(this).find('#selectedResp').html();
+ if (!temp) {
+ return;
+ }
+ var tempArray = temp.substr(1).split(';');
+ for (var i in tempArray) {
+ oldResp[tempArray[i]] = 1;
+ }
+
+ // Get the new selected responses
+ $(this).find('#mkAssResp input:checked').each(function() {
+ var respName = $(this).attr('value');
+ newResp[respName] = 1;
+ });
+
+ for (var i in newResp) {
+ if (oldResp[i]) {
+ delete oldResp[i];
+ delete newResp[i];
+ }
+ }
+
+ // Add the response which are delete
+ for (var i in oldResp) {
+ oldString += ',"' + i + '"';
+ }
+ if ('' != oldString) {
+ oldString = oldString.substr(1);
+ }
+
+ // Add the response which are new add
+ for (var i in newResp) {
+ newString += ',"' + i + '"';
+ }
+ if ('' != newString) {
+ newString = newString.substr(1);
+ }
+
+ if (('' != oldString) || ('' != newString)) {
+ $('#rmcEventStatus div').empty().append(
+ 'Create/remove associations ').append(
+ createLoader());
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'mkcondresp;"' + conditionName + '";+'
+ + newString + ':-' + oldString,
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ $('#rmcEventStatus div').empty()
+ .append(data.rsp[0]);
+ ;
+ }
+ });
+ }
+ $(this).dialog('destroy').remove();
+ },
+ 'Cancel' : function() {
+ $(this).dialog('destroy').remove();
+ }
+ }
+ });
+}
+
+/**
+ * Show the make condition dialogue
+ */
+function chCondScopeDia() {
+ var diaDiv = $('
');
+ var tableContent = '
';
+ diaDiv.append(tableContent);
+ // Fieldset to show status
+ diaDiv.append('
');
+ // Create the dislogue
+ diaDiv.dialog({
+ modal : true,
+ width : 500,
+ height : 600,
+ close : function(event, ui) {
+ $(this).remove();
+ },
+ buttons : {
+ 'Ok' : function() {
+ $('#changeStatus').empty().append('
Status ');
+ var conditionName = $('#changePreCond :checked').attr('value');
+ var groupName = '';
+ $('#changeGroup :checked').each(function() {
+ if ('' == groupName) {
+ groupName += $(this).attr('value');
+ } else {
+ groupName += ',' + $(this).attr('value');
+ }
+ });
+
+ if (undefined == conditionName) {
+ $('#changeStatus').append('Please select conditon');
+ return;
+ }
+
+ if ('' == groupName) {
+ $('#changeStatus').append('Please select group');
+ return;
+ }
+
+ $('#changeStatus').append(createLoader());
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'mkcondition;change;' + conditionName + ';'
+ + groupName,
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ $('#changeStatus img').remove();
+ if (-1 != data.rsp[0].indexOf('Error')) {
+ $('#changeStatus').append(data.rsp[0]);
+ } else {
+ $('#rmcEventStatus div').empty()
+ .append(data.rsp[0]);
+ $('#chScopeDiaDiv').remove();
+ }
+ }
+ });
+ },
+ 'Cancel' : function() {
+ $(this).dialog('destroy').remove();
+ }
+ }
+ });
+}
+
+/**
+ * Show the make response dialogue
+ */
+function mkResponseDia() {
+ var diaDiv = $('
');
+ diaDiv.append('Not yet supported.');
+
+ diaDiv.dialog({
+ modal : true,
+ width : 400,
+ close : function(event, ui) {
+ $(this).remove();
+ },
+ buttons : {
+ 'Ok' : function() {
+ $(this).dialog('destroy').remove();
+ },
+ 'Cancel' : function() {
+ $(this).dialog('destroy').remove();
+ }
+ }
+ });
+}
+
+/**
+ * Start the condition and response associations
+ */
+function startStopCondRespDia() {
+ var diaDiv = $('
');
+ diaDiv.append('Getting conditions').append(createLoader());
+
+ if (!globalCondition) {
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'lscondition',
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ if (data.rsp[0]) {
+ globalcondition = data.rsp[0];
+ $('#divStartStopAss').empty().append(
+ createAssociationTable(globalCondition));
+ $('#divStartStopAss')
+ .dialog("option", "position", 'center');
+ } else {
+ $('#divStartStopAss').empty().append(
+ 'There are no conditions');
+ }
+ }
+ });
+ } else {
+ diaDiv.empty().append(createAssociationTable(globalCondition));
+ }
+
+ diaDiv.dialog({
+ modal : true,
+ width : 570,
+ height : 600,
+ close : function(event, ui) {
+ $(this).remove();
+ },
+ buttons : {
+ 'Close' : function() {
+ $(this).dialog('destroy').remove();
+ }
+ }
+ });
+
+ $('#divStartStopAss button').bind(
+ 'click',
+ function() {
+ var operationType = '';
+ var conditionName = $(this).attr('name');
+ if ('Start' == $(this).html()) {
+ operationType = 'start';
+ } else {
+ operationType = 'stop';
+ }
+
+ $(this).parent().prev().empty().append(createLoader());
+ $('#divStartStopAss').dialog('option', 'disabled', true);
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : operationType + 'condresp;' + conditionName,
+ msg : operationType + ';' + conditionName
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ var conditionName = '';
+ var newOperationType = '';
+ var associationStatus = '';
+ var backgroudColor = '';
+ if ('start' == data.msg.substr(0, 5)) {
+ newOperationType = 'Stop';
+ conditionName = data.msg.substr(6);
+ associationStatus = 'Monitored';
+ backgroudColor = '#ffffff';
+ } else {
+ newOperationType = 'Start';
+ conditionName = data.msg.substr(5);
+ associationStatus = 'Not Monitored';
+ backgroudColor = '#fffacd';
+ }
+
+ var button = $('#divStartStopAss button[name="'
+ + conditionName + '"]');
+ if (data.rsp[0]) {
+ $('#rmcEventStatus div').empty().append(
+ 'Getting associations\' status').append(
+ createLoader());
+ $('#rmcEventButtons').hide();
+ button.html(newOperationType);
+ button.parent().prev().html(associationStatus);
+ button.parent().parent().css('background-color',
+ backgroudColor);
+ globalCondition = '';
+ getConditions();
+ } else {
+ button.html('Error');
+ }
+
+ $('#divStartStopAss').dialog('option', 'disabled',
+ false);
+ }
+ });
+ });
+}
+
+/**
+ * Stop the condition and response associations
+ */
+function stopCondRespDia() {
+ var diaDiv = $('
');
+ diaDiv.append('Getting conditions').append(createLoader());
+
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'lscondition;-m',
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ if (data.rsp[0]) {
+ $('#stopAss').empty().append(
+ createConditionTable(data.rsp[0]));
+ $('#stopAss').dialog("option", "position", 'center');
+ } else {
+ $('#stopAss').empty().append(
+ 'There is not monitored condition.');
+ }
+ }
+ });
+
+ diaDiv.dialog({
+ modal : true,
+ width : 570,
+ close : function(event, ui) {
+ $(this).remove();
+ },
+ buttons : {
+ 'Stop' : function() {
+ var conditionName = $('#stopAss :checked').attr('value');
+ if (!conditionName) {
+ alert('Select condition name please.');
+ return;
+ }
+ $('#rmcEventStatus div').empty().append(
+ 'Stoping monitor on ' + conditionName).append(
+ createLoader());
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'stopcondresp;' + conditionName,
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ $('#rmcEventStatus div').empty().append(data.rsp[0]);
+ }
+ });
+ $(this).dialog('destroy').remove();
+ },
+ 'Cancel' : function() {
+ $(this).dialog('destroy').remove();
+ }
+ }
+ });
+}
+
+/**
+ * Create the condition table for dialogue
+ *
+ * @param cond Condition
+ */
+function createConditionTd(cond) {
+ var conditions = cond.split(';');
+ var name = '';
+ var showStr = '';
+ for (var i in conditions) {
+ name = conditions[i];
+ // Because there is status and quotation marks in name,
+ // we must delete the status and quotation marks
+ name = name.substr(1, name.length - 6);
+ showStr += '
' + name + '
';
+ }
+
+ return showStr;
+}
+
+/**
+ * Create the association table for dialogue, which show the status and start/stop associations
+ *
+ * @param cond Condition
+ */
+function createAssociationTable(cond) {
+ var conditions = cond.split(';');
+ var name = '';
+ var tempLength = '';
+ var tempStatus = '';
+ var showStr = '
Condition Name Status Start/Stop ';
+ showStr += '';
+
+ for (var i in conditions) {
+ name = conditions[i];
+ tempLength = name.length;
+ tempStatus = name.substr(tempLength - 3);
+ name = name.substr(1, tempLength - 6);
+
+ if ('Not' == tempStatus) {
+ showStr += '' + name
+ + ' Not Monitored ';
+ showStr += 'Start ';
+ } else {
+ showStr += '' + name + ' Monitored ';
+ showStr += 'Stop ';
+ }
+ showStr += ' ';
+ }
+
+ showStr += '
';
+
+ return showStr;
}
\ No newline at end of file
diff --git a/xCAT-UI/js/monitor/xcatmon.js b/xCAT-UI/js/monitor/xcatmon.js
index 8458b393c..9eb8a9a5d 100644
--- a/xCAT-UI/js/monitor/xcatmon.js
+++ b/xCAT-UI/js/monitor/xcatmon.js
@@ -1,419 +1,423 @@
-/**
- * Global variables
- */
-var xcatMonTableId = "xcatMonSettingTable";
-
-/**
- * Load xCAT monitoring
- */
-function loadXcatMon() {
- // Find xCAT monitoring tab
- var xcatMonTab = $('#xcatmon');
- xcatMonTab.append("
");
-
- // Show content of monsetting table
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'tabdump',
- tgt : '',
- args : 'monsetting',
- msg : ''
- },
- success : loadXcatMonSetting
- });
-}
-
-function loadXcatMonSetting(data) {
- var apps = ""; // Contains the xcatmon config
- var rsp = data.rsp;
- if (!rsp.length)
- return;
-
- var apps_flag = 0;
- var ping; // xcatmon ping interval
- var ping_flag = 0;
-
- // Create an info bar
- var infoBar = createInfoBar('Click on a cell to edit. Click outside the table to write to the cell. Once you are finished configuring the xCAT monitor, click on Apply.');
- $('#xcatmonTable').append(infoBar);
-
- // Create xcatmon table
- var xcatmonTable = new DataTable(xcatMonTableId);
-
- // Create datatable
- var dTable;
-
- // Create table header
- var header = rsp[0].split(",");
- header.splice(3, 2);
- header.splice(0, 1);
- header[0] = "App Name";
- header[1] = "Configure";
- header.push('
');
- header.unshift('');
- xcatmonTable.init(header);
-
- // Create container for original table contents
- var origCont = new Array();
- origCont[0] = header; // Table headers
-
- // Create container for new contents to use later updating monsetting table
- var newCont = new Object();
- newCont[0] = rsp[0].split(","); // Table headers
-
- // Create container for other monsetting lines
- var otherCont = new Array();
-
- $('#xcatmonTable').append(xcatmonTable.object());
- var m = 1; // Count for origCont
- var n = 0;
- for ( var i = 1; i < rsp.length; i++) {
- var pos = rsp[i].indexOf("xcatmon"); // Only check xcatmon setting
- if (pos == 1) {
- if ((rsp[i].indexOf("apps") == -1) && (rsp[i].indexOf("ping") == -1)) {
- var cols = rsp[i].split(',');
- for ( var j = 0; j < cols.length; j++) {
- if (cols[j].count('"') % 2 == 1) {
- while (cols[j].count('"') % 2 == 1) {
- cols[j] = cols[j] + "," + cols[j + 1];
- cols.splice(j + 1, 1);
- }
- }
- cols[j] = cols[j].replace(new RegExp('"', 'g'), '');
- }
-
- cols.splice(3, 2);
- cols.splice(0, 1);
- cols.push('
');
- cols.unshift('
');
-
- // Add column to table
- xcatmonTable.add(cols);
- origCont[m++] = cols;
- } else {
- if (!apps_flag) { // Check the apps setting
- if (rsp[i].indexOf("apps") > -1) {
- apps = rsp[i].split(',');
-
- for ( var j = 0; j < apps.length; j++) {
- if (apps[j].count('"') % 2 == 1) {
- while (apps[j].count('"') % 2 == 1) {
- apps[j] = apps[j] + "," + apps[j + 1];
- apps.splice(j + 1, 1);
- }
- }
- apps[j] = apps[j].replace(new RegExp('"', 'g'), '');
- }
-
- apps_flag = 1; // Set the flag to 1 to avoid this subroute
- }
- }
-
- // Get into the ping settings
- if (!ping_flag) {
- // Check the ping interval
- if (rsp[i].indexOf("ping-interval") > -1) {
- ping = rsp[i].split(',');
- for ( var j = 0; j < ping.length; j++) {
- if (ping[j].count('"') % 2 == 1) {
- while (ping[j].count('"') % 2 == 1) {
- ping[j] = ping[j] + "," + ping[j + 1];
- ping.splice(j + 1, 1);
- }
- }
- ping[j] = ping[j].replace((new RegExp('"', 'g')),
- '');
- }
- ping_flag = 1;
- }
- }
- }
- } else if (pos != 1) {
- // The other monitor in the monsetting table
- var otherCols = rsp[i].split(',');
- for ( var k = 0; k < otherCols.length; k++) {
- if (otherCols[k].count('"') % 2 == 1) {
- while (otherCols[k].count('"') % 2 == 1) {
- otherCols[k] = otherCols[k] + "," + otherCols[k + 1];
- otherCols.splice(k + 1, 1);
- }
- }
- otherCols[k] = otherCols[k].replace(new RegExp('"', 'g'), '');
- }
-
- otherCont[n++] = otherCols;
-
- }
- }
- // If app is not in the monsetting table, then create default apps row
- if (!apps_flag) {
- apps = rsp[0].split(',');
- apps[0] = "xcatmon";
- apps[1] = "apps";
- apps[2] = "";
- apps[3] = "";
- apps[4] = "";
- }
-
- // If the ping interval is not in the monsetting table, then create the
- // default ping-interval
- if (!ping_flag) {
- ping = rsp[0].split(',');
- ping[0] = "xcatmon";
- ping[1] = "ping-interval";
-
- // Set default ping-interval setting to 5
- ping[2] = "5";
- ping[3] = "";
- ping[4] = "";
- }
-
- // Set checkbox to be true
- var checked = apps[2].split(',');
- for ( var i = 0; i < checked.length; i++) {
- $("input:checkbox[name=" + checked[i] + "]").attr('checked', true);
- for ( var j = 0; j < origCont.length; j++) {
- if (origCont[j][1] == checked[i]) {
- origCont[j].splice(3, 1);
- origCont[j].push('
');
- }
- }
-
- }
- $(":checkbox").tooltip();
-
- // Make the table editable
- $('#' + xcatMonTableId + ' td:not(td:nth-child(1),td:last-child)').editable(function(value, settings) {
- var colPos = this.cellIndex;
- var rowPos = dTable.fnGetPosition(this.parentNode);
- dTable.fnUpdate(value, rowPos, colPos);
- return (value);
- }, {
- onblur : 'submit',
- type : 'textarea',
- placeholder : ' ',
- height : '30px'
- });
-
- // Save datatable
- dTable = $('#' + xcatMonTableId).dataTable({
- 'iDisplayLength': 50,
- 'bLengthChange': false,
- "bScrollCollapse": true,
- "sScrollY": "400px",
- "sScrollX": "110%",
- "bAutoWidth": true,
- "oLanguage": {
- "oPaginate": {
- "sNext": "",
- "sPrevious": ""
- }
- }
- });
-
- // Create action bar
- var actionBar = $('
');
- var addRowLnk = $('
Add row ');
- addRowLnk.bind('click', function(event) {
- // Create container for new row
- var row = new Array();
-
- // Add delete button to row
- row.push('
');
- for ( var i = 0; i < header.length - 2; i++)
- row.push('');
-
- // Add checkbox
- row.push('
');
- // Get the datatable of the table
- var dTable = $('#' + xcatMonTableId).dataTable();
- // Add the new row to the datatable
- dTable.fnAddData(row);
-
- // make the datatable editable
- $(":checkbox[title]").tooltip();
- $('#' + xcatMonTableId + ' td:not(td:nth-child(1),td:last-child)').editable(function(value, settings) {
- var colPos = this.cellIndex;
- var rowPos = dTable
- .fnGetPosition(this.parentNode);
- dTable.fnUpdate(value, rowPos,
- colPos);
- return (value);
- }, {
- onblur : 'submit',
- type : 'textarea',
- placeholder : ' ',
- height : '30px'
- });
- });
-
- // Create apply button to store the contents of the table to the monsetting table
- var applyLnk = $('
Apply ');
- applyLnk.bind('click', function(event) {
- // Get the datatable
- var dTable = $('#' + xcatMonTableId).dataTable();
- // Get datatable rows
- var dRows = dTable.fnGetNodes();
- var count = 0;
-
- // Create a new container for the apps value
- var appValue = '';
- var tableName = 'monsetting';
- var closeBtn = createButton('close');
-
- // Get the row contents
- for ( var i = 0; i < dRows.length; i++) {
- if (dRows[i]) {
- // Get the row columns
- var cols = dRows[i].childNodes;
- // Create a container for the new columns
- var vals = new Array();
-
- for ( var j = 1; j < cols.length - 1; j++) {
- var val = cols.item(j).firstChild.nodeValue;
- if (val == ' ')
- vals[j - 1] = '';
- else
- vals[j - 1] = val;
- }
-
- var vals_orig = new Array();
- // Copy data from vals to vals_orig
- for ( var p = 0; p < 2; p++) {
- var val = vals[p];
- vals_orig[p] = val;
- }
-
- vals.push('');
- vals.push('');
- vals.unshift('xcatmon');
-
- // Stored new column to newCont
- newCont[i + 1] = vals;
-
- if (cols.item(cols.length - 1).firstChild.checked) {
- vals_orig.push('
');
- } else {
- vals_orig.push('
');
- }
-
- // Add delete button to row
- vals_orig.unshift('
');
- // Add row to origCont
- origCont[i + 1] = vals_orig;
- count = i + 1;
-
- // Check checkbox for every row when merging the app name with the apps values
- if (cols.item(cols.length - 1).firstChild.checked)
- appValue = appValue.concat(cols.item(2).firstChild.nodeValue + ",");
- }
- }
-
- count++;
-
- // Delete the last comma of the apps value
- appValue = appValue.substring(0, (appValue.length - 1));
- apps[2] = appValue;
-
- newCont[count++] = apps;
- newCont[count++] = ping;
-
- // Add to other monitor settings
- for ( var j = 0; j < otherCont.length; j++) {
- newCont[count++] = otherCont[j];
- }
-
- // Create save dialog
- var dialogSave = $('
Saving configuration
');
- dialogSave.append(createLoader());
-
- $('#xcatmon').append(dialogSave);
- $("#saveDialog").dialog({
- modal : true
- });
-
- $('.ui-dialog-titlebar-close').hide();
- $.ajax({
- type : 'POST',
- url : 'lib/tabRestore.php',
- dataType : 'json',
- data : {
- table : tableName,
- cont : newCont
- },
- success : function(data) {
- // empty the dialog.add the close button
- $("#saveDialog").empty().append('
Configuration saved!
');
- $("#saveDialog").append(closeBtn);
- }
- });
-
- // Close button
- closeBtn.bind('click', function(event) {
- $("#saveDialog").dialog("destroy");
- $("#saveDialog").remove();
- });
-
- // Clear the newCont
- newCont = null;
- newCont = new Object();
- newCont[0] = rsp[0].split(",");
- });
-
- var cancelLnk = $('
Cancel ');
- cancelLnk.bind('click', function(event) {
- // Get the datatable for the page
- var dTable = $('#' + xcatMonTableId).dataTable();
-
- // Clear the datatable
- dTable.fnClearTable();
-
- // Add the contents of origCont to the datatable
- for ( var i = 1; i < origCont.length; i++)
- dTable.fnAddData(origCont[i], true);
-
- $(":checkbox[title]").tooltip();
- $('#' + xcatMonTableId + ' td:not(td:nth-child(1),td:last-child)').editable(function(value, settings) {
- var colPos = this.cellIndex;
- var rowPos = dTable.fnGetPosition(this.parentNode);
- dTable.fnUpdate(value, rowPos, colPos);
- return (value);
- }, {
- onblur : 'submit',
- type : 'textarea',
- placeholder : ' ',
- height : '30px'
- });
- });
-
- // Create actions menu
- var actionsLnk = '
Actions ';
- var actsMenu = createMenu([ addRowLnk, applyLnk, cancelLnk ]);
- var actionsMenu = createMenu([ [ actionsLnk, actsMenu ] ]);
- actionsMenu.superfish();
- actionsMenu.css('display', 'inline-block');
- actionBar.append(actionsMenu);
-
- // Create a division to hold actions menu
- var menuDiv = $('');
- $('#' + xcatMonTableId + '_wrapper').prepend(menuDiv);
- menuDiv.append(actionBar);
- $('#' + xcatMonTableId + '_filter').appendTo(menuDiv);
-}
-
-/**
- * Delete a row from the table
- */
-function deleteXcatMonRow(obj) {
- var dTable = $('#' + xcatMonTableId).dataTable();
- var rows = dTable.fnGetNodes();
- var tgtRow = $(obj).parent().parent().get(0);
- for ( var i in rows) {
- if (rows[i] == tgtRow) {
- dTable.fnDeleteRow(i, null, true);
- break;
- }
- }
+/**
+ * Global variables
+ */
+var xcatMonTableId = "xcatMonSettingTable";
+
+/**
+ * Load xCAT monitoring
+ */
+function loadXcatMon() {
+ // Find xCAT monitoring tab
+ var xcatMonTab = $('#xcatmon');
+ xcatMonTab.append("
");
+
+ // Show content of monsetting table
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'tabdump',
+ tgt : '',
+ args : 'monsetting',
+ msg : ''
+ },
+ success : function(data) {
+ data = decodeRsp(data);
+ loadXcatMonSetting(data);
+ }
+ });
+}
+
+function loadXcatMonSetting(data) {
+ var apps = ""; // Contains the xcatmon config
+ var rsp = data.rsp;
+ if (!rsp.length)
+ return;
+
+ var apps_flag = 0;
+ var ping; // xcatmon ping interval
+ var ping_flag = 0;
+
+ // Create an info bar
+ var infoBar = createInfoBar('Click on a cell to edit. Click outside the table to write to the cell. Once you are finished configuring the xCAT monitor, click on Apply.');
+ $('#xcatmonTable').append(infoBar);
+
+ // Create xcatmon table
+ var xcatmonTable = new DataTable(xcatMonTableId);
+
+ // Create datatable
+ var dTable;
+
+ // Create table header
+ var header = rsp[0].split(",");
+ header.splice(3, 2);
+ header.splice(0, 1);
+ header[0] = "App Name";
+ header[1] = "Configure";
+ header.push('
');
+ header.unshift('');
+ xcatmonTable.init(header);
+
+ // Create container for original table contents
+ var origCont = new Array();
+ origCont[0] = header; // Table headers
+
+ // Create container for new contents to use later updating monsetting table
+ var newCont = new Object();
+ newCont[0] = rsp[0].split(","); // Table headers
+
+ // Create container for other monsetting lines
+ var otherCont = new Array();
+
+ $('#xcatmonTable').append(xcatmonTable.object());
+ var m = 1; // Count for origCont
+ var n = 0;
+ for ( var i = 1; i < rsp.length; i++) {
+ var pos = rsp[i].indexOf("xcatmon"); // Only check xcatmon setting
+ if (pos == 1) {
+ if ((rsp[i].indexOf("apps") == -1) && (rsp[i].indexOf("ping") == -1)) {
+ var cols = rsp[i].split(',');
+ for ( var j = 0; j < cols.length; j++) {
+ if (cols[j].count('"') % 2 == 1) {
+ while (cols[j].count('"') % 2 == 1) {
+ cols[j] = cols[j] + "," + cols[j + 1];
+ cols.splice(j + 1, 1);
+ }
+ }
+ cols[j] = cols[j].replace(new RegExp('"', 'g'), '');
+ }
+
+ cols.splice(3, 2);
+ cols.splice(0, 1);
+ cols.push('
');
+ cols.unshift('
');
+
+ // Add column to table
+ xcatmonTable.add(cols);
+ origCont[m++] = cols;
+ } else {
+ if (!apps_flag) { // Check the apps setting
+ if (rsp[i].indexOf("apps") > -1) {
+ apps = rsp[i].split(',');
+
+ for ( var j = 0; j < apps.length; j++) {
+ if (apps[j].count('"') % 2 == 1) {
+ while (apps[j].count('"') % 2 == 1) {
+ apps[j] = apps[j] + "," + apps[j + 1];
+ apps.splice(j + 1, 1);
+ }
+ }
+ apps[j] = apps[j].replace(new RegExp('"', 'g'), '');
+ }
+
+ apps_flag = 1; // Set the flag to 1 to avoid this subroute
+ }
+ }
+
+ // Get into the ping settings
+ if (!ping_flag) {
+ // Check the ping interval
+ if (rsp[i].indexOf("ping-interval") > -1) {
+ ping = rsp[i].split(',');
+ for ( var j = 0; j < ping.length; j++) {
+ if (ping[j].count('"') % 2 == 1) {
+ while (ping[j].count('"') % 2 == 1) {
+ ping[j] = ping[j] + "," + ping[j + 1];
+ ping.splice(j + 1, 1);
+ }
+ }
+ ping[j] = ping[j].replace((new RegExp('"', 'g')),
+ '');
+ }
+ ping_flag = 1;
+ }
+ }
+ }
+ } else if (pos != 1) {
+ // The other monitor in the monsetting table
+ var otherCols = rsp[i].split(',');
+ for ( var k = 0; k < otherCols.length; k++) {
+ if (otherCols[k].count('"') % 2 == 1) {
+ while (otherCols[k].count('"') % 2 == 1) {
+ otherCols[k] = otherCols[k] + "," + otherCols[k + 1];
+ otherCols.splice(k + 1, 1);
+ }
+ }
+ otherCols[k] = otherCols[k].replace(new RegExp('"', 'g'), '');
+ }
+
+ otherCont[n++] = otherCols;
+
+ }
+ }
+ // If app is not in the monsetting table, then create default apps row
+ if (!apps_flag) {
+ apps = rsp[0].split(',');
+ apps[0] = "xcatmon";
+ apps[1] = "apps";
+ apps[2] = "";
+ apps[3] = "";
+ apps[4] = "";
+ }
+
+ // If the ping interval is not in the monsetting table, then create the
+ // default ping-interval
+ if (!ping_flag) {
+ ping = rsp[0].split(',');
+ ping[0] = "xcatmon";
+ ping[1] = "ping-interval";
+
+ // Set default ping-interval setting to 5
+ ping[2] = "5";
+ ping[3] = "";
+ ping[4] = "";
+ }
+
+ // Set checkbox to be true
+ var checked = apps[2].split(',');
+ for ( var i = 0; i < checked.length; i++) {
+ $("input:checkbox[name=" + checked[i] + "]").attr('checked', true);
+ for ( var j = 0; j < origCont.length; j++) {
+ if (origCont[j][1] == checked[i]) {
+ origCont[j].splice(3, 1);
+ origCont[j].push('
');
+ }
+ }
+
+ }
+ $(":checkbox").tooltip();
+
+ // Make the table editable
+ $('#' + xcatMonTableId + ' td:not(td:nth-child(1),td:last-child)').editable(function(value, settings) {
+ var colPos = this.cellIndex;
+ var rowPos = dTable.fnGetPosition(this.parentNode);
+ dTable.fnUpdate(value, rowPos, colPos);
+ return (value);
+ }, {
+ onblur : 'submit',
+ type : 'textarea',
+ placeholder : ' ',
+ height : '30px'
+ });
+
+ // Save datatable
+ dTable = $('#' + xcatMonTableId).dataTable({
+ 'iDisplayLength': 50,
+ 'bLengthChange': false,
+ "bScrollCollapse": true,
+ "sScrollY": "400px",
+ "sScrollX": "110%",
+ "bAutoWidth": true,
+ "oLanguage": {
+ "oPaginate": {
+ "sNext": "",
+ "sPrevious": ""
+ }
+ }
+ });
+
+ // Create action bar
+ var actionBar = $('
');
+ var addRowLnk = $('
Add row ');
+ addRowLnk.bind('click', function(event) {
+ // Create container for new row
+ var row = new Array();
+
+ // Add delete button to row
+ row.push('
');
+ for ( var i = 0; i < header.length - 2; i++)
+ row.push('');
+
+ // Add checkbox
+ row.push('
');
+ // Get the datatable of the table
+ var dTable = $('#' + xcatMonTableId).dataTable();
+ // Add the new row to the datatable
+ dTable.fnAddData(row);
+
+ // make the datatable editable
+ $(":checkbox[title]").tooltip();
+ $('#' + xcatMonTableId + ' td:not(td:nth-child(1),td:last-child)').editable(function(value, settings) {
+ var colPos = this.cellIndex;
+ var rowPos = dTable
+ .fnGetPosition(this.parentNode);
+ dTable.fnUpdate(value, rowPos,
+ colPos);
+ return (value);
+ }, {
+ onblur : 'submit',
+ type : 'textarea',
+ placeholder : ' ',
+ height : '30px'
+ });
+ });
+
+ // Create apply button to store the contents of the table to the monsetting table
+ var applyLnk = $('
Apply ');
+ applyLnk.bind('click', function(event) {
+ // Get the datatable
+ var dTable = $('#' + xcatMonTableId).dataTable();
+ // Get datatable rows
+ var dRows = dTable.fnGetNodes();
+ var count = 0;
+
+ // Create a new container for the apps value
+ var appValue = '';
+ var tableName = 'monsetting';
+ var closeBtn = createButton('close');
+
+ // Get the row contents
+ for ( var i = 0; i < dRows.length; i++) {
+ if (dRows[i]) {
+ // Get the row columns
+ var cols = dRows[i].childNodes;
+ // Create a container for the new columns
+ var vals = new Array();
+
+ for ( var j = 1; j < cols.length - 1; j++) {
+ var val = cols.item(j).firstChild.nodeValue;
+ if (val == ' ')
+ vals[j - 1] = '';
+ else
+ vals[j - 1] = val;
+ }
+
+ var vals_orig = new Array();
+ // Copy data from vals to vals_orig
+ for ( var p = 0; p < 2; p++) {
+ var val = vals[p];
+ vals_orig[p] = val;
+ }
+
+ vals.push('');
+ vals.push('');
+ vals.unshift('xcatmon');
+
+ // Stored new column to newCont
+ newCont[i + 1] = vals;
+
+ if (cols.item(cols.length - 1).firstChild.checked) {
+ vals_orig.push('
');
+ } else {
+ vals_orig.push('
');
+ }
+
+ // Add delete button to row
+ vals_orig.unshift('
');
+ // Add row to origCont
+ origCont[i + 1] = vals_orig;
+ count = i + 1;
+
+ // Check checkbox for every row when merging the app name with the apps values
+ if (cols.item(cols.length - 1).firstChild.checked)
+ appValue = appValue.concat(cols.item(2).firstChild.nodeValue + ",");
+ }
+ }
+
+ count++;
+
+ // Delete the last comma of the apps value
+ appValue = appValue.substring(0, (appValue.length - 1));
+ apps[2] = appValue;
+
+ newCont[count++] = apps;
+ newCont[count++] = ping;
+
+ // Add to other monitor settings
+ for ( var j = 0; j < otherCont.length; j++) {
+ newCont[count++] = otherCont[j];
+ }
+
+ // Create save dialog
+ var dialogSave = $('
Saving configuration
');
+ dialogSave.append(createLoader());
+
+ $('#xcatmon').append(dialogSave);
+ $("#saveDialog").dialog({
+ modal : true
+ });
+
+ $('.ui-dialog-titlebar-close').hide();
+ $.ajax({
+ type : 'POST',
+ url : 'lib/tabRestore.php',
+ dataType : 'json',
+ data : {
+ table : tableName,
+ cont : newCont
+ },
+ success : function(data) {
+ // do not put in until tabRestore.php has been updated: data = decodeRsp(data);
+ // empty the dialog.add the close button
+ $("#saveDialog").empty().append('
Configuration saved!
');
+ $("#saveDialog").append(closeBtn);
+ }
+ });
+
+ // Close button
+ closeBtn.bind('click', function(event) {
+ $("#saveDialog").dialog("destroy");
+ $("#saveDialog").remove();
+ });
+
+ // Clear the newCont
+ newCont = null;
+ newCont = new Object();
+ newCont[0] = rsp[0].split(",");
+ });
+
+ var cancelLnk = $('
Cancel ');
+ cancelLnk.bind('click', function(event) {
+ // Get the datatable for the page
+ var dTable = $('#' + xcatMonTableId).dataTable();
+
+ // Clear the datatable
+ dTable.fnClearTable();
+
+ // Add the contents of origCont to the datatable
+ for ( var i = 1; i < origCont.length; i++)
+ dTable.fnAddData(origCont[i], true);
+
+ $(":checkbox[title]").tooltip();
+ $('#' + xcatMonTableId + ' td:not(td:nth-child(1),td:last-child)').editable(function(value, settings) {
+ var colPos = this.cellIndex;
+ var rowPos = dTable.fnGetPosition(this.parentNode);
+ dTable.fnUpdate(value, rowPos, colPos);
+ return (value);
+ }, {
+ onblur : 'submit',
+ type : 'textarea',
+ placeholder : ' ',
+ height : '30px'
+ });
+ });
+
+ // Create actions menu
+ var actionsLnk = '
Actions ';
+ var actsMenu = createMenu([ addRowLnk, applyLnk, cancelLnk ]);
+ var actionsMenu = createMenu([ [ actionsLnk, actsMenu ] ]);
+ actionsMenu.superfish();
+ actionsMenu.css('display', 'inline-block');
+ actionBar.append(actionsMenu);
+
+ // Create a division to hold actions menu
+ var menuDiv = $('');
+ $('#' + xcatMonTableId + '_wrapper').prepend(menuDiv);
+ menuDiv.append(actionBar);
+ $('#' + xcatMonTableId + '_filter').appendTo(menuDiv);
+}
+
+/**
+ * Delete a row from the table
+ */
+function deleteXcatMonRow(obj) {
+ var dTable = $('#' + xcatMonTableId).dataTable();
+ var rows = dTable.fnGetNodes();
+ var tgtRow = $(obj).parent().parent().get(0);
+ for ( var i in rows) {
+ if (rows[i] == tgtRow) {
+ dTable.fnDeleteRow(i, null, true);
+ break;
+ }
+ }
}
\ No newline at end of file
diff --git a/xCAT-UI/js/nodes/nodes.js b/xCAT-UI/js/nodes/nodes.js
index 769aa5e87..b9c970500 100644
--- a/xCAT-UI/js/nodes/nodes.js
+++ b/xCAT-UI/js/nodes/nodes.js
@@ -1,4329 +1,4419 @@
-/**
- * Global variables
- */
-var nodesTab; // Nodes tabs
-var origAttrs = new Object(); // Original node attributes
-var nodeAttrs; // Node attributes
-var nodesList; // Node list
-var nodesTableId = 'nodesDatatable'; // Nodes datatable ID
-var nodesTabInfoBar;
-var builtInXCAT = 1; // 1 means xCAT shipped with zVM
-
-/**
- * Set node tab
- *
- * @param tab
- * Tab object
- * @return Nothing
- */
-function setNodesTab(tab) {
- nodesTab = tab;
-}
-
-/**
- * Get node tab
- *
- * @return Tab object
- */
-function getNodesTab() {
- return nodesTab;
-}
-
-/**
- * Set node tab info bar. Used by zvmUtils.js
- *
- * @param tab
- * infobar object
- * @return Nothing
- */
-function setNodesTabInfoBar(tabinfo) {
- nodesTabInfoBar = tabinfo;
-}
-
-/**
- * Get node tab info bar
- *
- * @return Tab info bar object
- */
-function getNodesTabInfoBar() {
- return nodesTabInfoBar;
-}
-
-/**
- * Get node list
- *
- * @return Node list
- */
-function getNodesList() {
- return nodesList;
-}
-
-/**
- * Get nodes table ID
- *
- * @return Nodes table ID
- */
-function getNodesTableId() {
- return nodesTableId;
-}
-
-/**
- * Load nodes page
- */
-function loadNodesPage() {
- // If groups are not already loaded
- if (!$('#groups').length) {
- // Create a groups division
- var groups = $('
');
- var nodes = $('
');
- $('#content').append(groups);
- $('#content').append(nodes);
-
- // Create loader and info bar
- groups.append(createLoader());
-
- // Get groups
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'extnoderange',
- tgt : '/.*',
- args : 'subgroups',
- msg : ''
- },
-
- // Load groups
- success : function(data){
- loadGroups(data);
-
- var cookieGroup = $.cookie('xcat_selectgrouponnodes');
- if (cookieGroup) {
- $('#groups .groupdiv div').each(function(){
- if ($(this).text() == cookieGroup){
- $(this).trigger('click');
- return false;
- }
- });
- } else {
- // Trigger the first group click event
- $('#groups .groupdiv div').eq(0).trigger('click');
- }
- }
- });
- }
-}
-
-/**
- * Show cluster summary in pie charts
- *
- * @param groupName Group name
- */
-function loadPieSummary(groupName){
- var summaryTable = '
' +
- '' +
- '
' +
- '
' +
- '
' +
- ' ' +
- '' +
- '
' +
- '
' +
- '
';
- $('#summaryTab').append(summaryTable);
- $('#summaryTab .summarypie').append(createLoader());
-
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'summary;' + groupName,
- msg : ''
- },
-
- success:function(data) {
- for (var i in data.rsp) {
- drawPieSummary(i, data.rsp[i]);
- }
- }
- });
-}
-
-/**
- * Get nodes information and draw pie chart
- *
- * @param index Node index
- * @param valuePair Node information key value pairing
- */
-function drawPieSummary(index, valuePair){
- var position = 0;
- var key = '';
- var val = '';
- var chartTitle = '';
- var dataArray = [];
- var tempArray = [];
- var container = $('#summaryTab .summarypie').eq(index);
-
- position = valuePair.indexOf('=');
- chartTitle = valuePair.substr(0, position);
- tempArray = valuePair.substr(position + 1).split(';');
-
- for (var i in tempArray) {
- position = tempArray[i].indexOf(':');
- key = tempArray[i].substr(0, position);
- val = Number(tempArray[i].substr(position + 1));
- dataArray.push([key,val]);
- }
-
- container.empty();
-
- var plot = $.jqplot(container.attr('id'), [dataArray], {
- title: chartTitle,
- seriesDefaults: {
- renderer: $.jqplot.PieRenderer,
- rendererOptions: {
- padding: 5,
- fill: true,
- shadow: true,
- shadowOffset: 2,
- shadowDepth: 5,
- shadowAlpha: 0.07,
- dataLabels : 'value',
- showDataLabels: true
- }
- },
- legend: {
- show:true,
- location: 'e'
- }
- });
-}
-
-/**
- * Load groups
- *
- * @param data Data returned from HTTP request
- */
-function loadGroups(data) {
- // Remove loader
- $('#groups').find('img').remove();
-
- // Save group in cookie
- var groups = data.rsp;
- setGroupsCookies(data);
-
- // Create a list of groups
- $('#groups').append('
Groups
');
- var grouplist= $('
');
- // Create a link for each group
- for (var i = 0; i < groups.length; i++) {
- grouplist.append('
' + groups[i] + '
');
- }
-
- $('#groups').append(grouplist);
-
- // Bind the click event
- $('#groups .groupdiv div').bind('click', function(){
- var thisGroup = $(this).text();
- $('#groups .groupdiv div').removeClass('selectgroup');
- $(this).addClass('selectgroup');
-
- // Save selected group into cookie
- $.cookie('xcat_selectgrouponnodes', thisGroup, { expires: 7, path: '/xcat', secure:true });
-
- drawNodesArea(thisGroup,'',thisGroup);
- });
-
- // Make a link to add nodes
- $('#groups').append('
');
- $('#groups #adddiv').append(mkAddNodeLink());
-}
-
-/**
- * Empty the nodes area and add three tabs for nodes result
- *
- * @param targetgroup The name range for nodels command
- * @param cmdargs Filter arguments for nodels command
- * @param message The useful information from the HTTP request
- */
-function drawNodesArea(targetgroup, cmdargs, message){
- // Clear nodes division
- $('#nodes').empty();
-
- // Create a tab for this group
- var tab = new Tab('nodesPageTabs');
- setNodesTab(tab);
- tab.init();
- $('#nodes').append(tab.object());
- tab.add('summaryTab', 'Summary', '', false);
- tab.add('nodesTab', 'Nodes', '', false);
- if (builtInXCAT == 0) {
- tab.add('graphTab', 'Graphic', '', false);
- }
-
- // Load nodes table when tab is selected
- $('#nodesPageTabs').bind('tabsselect', function(event, ui) {
- // Load summary when tab is selected
- if (!$('#summaryTab').children().length && ui.index == 0) {
- loadPieSummary(targetgroup);
- }
-
- // Load nodes table when tab is selected
- else if (!$('#nodesTab').children().length && ui.index == 1) {
- // Create loader
- $('#nodesTab').append($('
').append(createLoader()));
-
- // To improve performance, get all nodes within selected group
- // Get node definitions only for first 50 nodes
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'nodels',
- tgt : targetgroup,
- args : cmdargs,
- msg : message
- },
-
- /**
- * Get node definitions for first 50 nodes
- *
- * @param data Data returned from HTTP request
- */
- success : function(data) {
- var rsp = data.rsp;
- var group = data.msg;
-
- // Save nodes in a list so it can be accessed later
- nodesList = new Array();
- for (var i in rsp) {
- if (rsp[i][0]) {
- nodesList.push(rsp[i][0]);
- }
- }
-
- // Sort nodes list
- nodesList.sort();
-
- // Get first 50 nodes
- var nodes = '';
- for (var i = 0; i < nodesList.length; i++) {
- if (i > 49) {
- break;
- }
-
- nodes += nodesList[i] + ',';
- }
-
- // Remove last comma
- nodes = nodes.substring(0, nodes.length-1);
-
- // Get nodes definitions
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'lsdef',
- tgt : '',
- args : nodes,
- msg : targetgroup
- },
-
- success : loadNodes
- });
-
- }
- });
- }
-
- // Load graphical layout when tab is selected
- else if ((builtInXCAT == 0) && (!$('#graphTab').children().length && ui.index == 2)) {
- // For the graphical tab, check the graphical data first
- createPhysicalLayout(nodesList);
- }
- });
-
- // Get last view (if any)
- // This can be summary, nodes, or graphic
- if ($.cookie('xcat_tabindex_history')) {
- var order = $.cookie('xcat_tabindex_history').split(',');
- order[0] = parseInt(order[0]);
- order[1] = parseInt(order[1]);
- if (order[0] == 0 || order[1] == 0) {
- // For some reason, you cannot trigger a select of index 0
- loadPieSummary(targetgroup);
- } else if (order[0] == 1 || order[0] == 2) {
- $('#nodesPageTabs').tabs('select', order[0]);
- } else if (order[1] == 1 || order[1] == 2) {
- $('#nodesPageTabs').tabs('select', order[1]);
- } else {
- loadPieSummary(targetgroup);
- }
- } else {
- loadPieSummary(targetgroup);
- }
-}
-
-/**
- * Make a link to add nodes
- *
- * @returns Link to add nodes
- */
-function mkAddNodeLink() {
- // Create link to add nodes
- var addNodeLink = $('
+ Add node ');
- addNodeLink.click(function() {
- // Create info bar
- var info = createInfoBar('Select the hardware management for the new node range');
-
- // Create form to add node
- var addNodeForm = $('
');
- addNodeForm.append(info);
- if (builtInXCAT == 0) {
- addNodeForm.append('
Hardware management: '
- + ''
- + 'ESX '
- + 'KVM '
- + 'z\/VM '
- + 'iDataPlex '
- + 'BladeCenter '
- + 'System p ' // Documentation refers to 'IBM System p' (where p is NOT capitalized)
- + ' '
- + '
');
- } else {
- addNodeForm.append('
Hardware management: '
- + ''
- + 'z\/VM '
- + ' '
- + '
');
- }
-
- // Create advanced link to set advanced node properties
- var advanced = $('
');
- var advancedLnk = $('
Advanced ').css({
- 'cursor': 'pointer',
- 'color': '#0000FF'
- });
- advancedLnk.click(function() {
- // Get node attributes
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'lsdef',
- tgt : '',
- args : '-t;node;-h',
- msg : ''
- },
-
- /**
- * Set node attributes and open dialog
- *
- * @param data Data returned from HTTP request
- */
- success : function(data) {
- // Save node attributes
- setNodeAttrs(data);
- // Open a dialog to set node attributes
- openSetAttrsDialog();
- }
- });
-
- // Close dialog
- addNodeForm.dialog('destroy').remove();
- });
- advanced.append(advancedLnk);
- addNodeForm.append(advanced);
-
- // Open dialog to add node
- addNodeForm.dialog({
- modal: true,
- width: 400,
- title:'Add node',
- close: function() {$(this).remove();},
- buttons: {
- 'Ok': function() {
- // Get hardware management
- var mgt = $(this).find('select[name=mgt]').val();
-
- var plugin;
- switch(mgt) {
- case "kvm":
- plugin = new kvmPlugin();
- break;
- case "esx":
- plugin = new esxPlugin();
- break;
- case "blade":
- plugin = new bladePlugin();
- break;
- case "hmc":
- plugin = new hmcPlugin();
- break;
- case "ipmi":
- plugin = new ipmiPlugin();
- break;
- case "zvm":
- plugin = new zvmPlugin();
- break;
- }
-
- $(this).dialog('destroy').remove();
- plugin.addNode();
- },
- 'Cancel': function(){
- $(this).dialog('destroy').remove();
- }
- }
- });
-
- });
-
- // Generate tooltips
- addNodeLink.tooltip({
- position: 'center right',
- offset: [-2, 10],
- effect: 'fade',
- opacity: 0.7,
- predelay: 800
- });
-
- return addNodeLink;
-}
-
-/**
- * Load nodes belonging to a given group
- *
- * @param data Data returned from HTTP request
- */
-function loadNodes(data) {
- // Clear the tab before inserting the table
- $('#nodesTab').children().remove();
-
- // Data returned
- var rsp = data.rsp;
- // Group name
- var group = data.msg;
- // Hash of Node attributes
- var attrs = new Object();
- // Node attributes
- var headers = new Object();
-
- // Variable to send command and request node status
- var getNodeStatus = true;
-
- // Clear hash table containing node attributes
- origAttrs = '';
-
- var node, args;
- for (var i in rsp) {
- // Get node name
- if (rsp[i].indexOf('Object name:') > -1) {
- var temp = rsp[i].split(': ');
- node = jQuery.trim(temp[1]);
-
- // Create a hash for the node attributes
- attrs[node] = new Object();
- i++;
- }
-
- // Get key and value
- args = rsp[i].split('=', 2);
- var key = jQuery.trim(args[0]);
- var val = jQuery.trim(rsp[i].substring(rsp[i].indexOf('=') + 1));
-
- // Create a hash table
- attrs[node][key] = val;
- headers[key] = 1;
-
- // If node status is available
- if (key == 'status') {
- // Do not request node status
- getNodeStatus = false;
- }
- }
-
- // Add nodes that are not in data returned
- for (var i in nodesList) {
- if (!attrs[nodesList[i]]) {
- // Create attributes list and save node name
- attrs[nodesList[i]] = new Object();
- attrs[nodesList[i]]['node'] = nodesList[i];
- }
- }
-
- // Save attributes in hash table
- origAttrs = attrs;
-
- // Sort headers
- var sorted = new Array();
- for (var key in headers) {
- // Do not put comments and status in twice
- if (key != 'usercomment' && key != 'status' && key.indexOf('status') < 0) {
- sorted.push(key);
- }
- }
- sorted.sort();
-
- // Add column for check box, node, ping, power, monitor, and comments
- sorted.unshift('
',
- 'node',
- '
status ',
- '
power ',
- '
monitor ',
- 'comments');
-
- // Create a datatable
- var nodesTable = new DataTable(nodesTableId);
- nodesTable.init(sorted);
-
- // Go through each node
- for (var node in attrs) {
- // Create a row
- var row = new Array();
-
- // Create a check box, node link, and get node status
- var checkBx = '
';
- var nodeLink = $('
' + node + ' ').bind('click', loadNode);
-
- // If there is no status attribute for the node, do not try to access hash table
- // else the code will break
- var status = '';
- if (attrs[node]['status']) {
- status = attrs[node]['status'].replace('sshd', 'ping');
- }
-
- // Push in checkbox, node, status, monitor, and power
- row.push(checkBx, nodeLink, status, '', '');
-
- // If the node attributes are known (i.e the group is known)
- if (attrs[node]['groups']) {
- // Put in comments
- var comments = attrs[node]['usercomment'];
- // If no comments exists, show 'No comments' and set icon image source
- var iconSrc;
- if (!comments) {
- comments = 'No comments';
- iconSrc = 'images/nodes/ui-icon-no-comment.png';
- } else {
- iconSrc = 'images/nodes/ui-icon-comment.png';
- }
-
- // Create comments icon
- var tipID = node + 'Tip';
- var icon = $('
').css({
- 'width': '18px',
- 'height': '18px'
- });
-
- // Create tooltip
- var tip = createCommentsToolTip(comments);
- var col = $('
').append(icon);
- col.append(tip);
- row.push(col);
-
- // Generate tooltips
- icon.tooltip({
- position: "center right",
- offset: [-2, 10],
- effect: "fade",
- opacity: 0.8,
- relative: true,
- delay: 500
- });
- } else {
- // Do not put in comments if attributes are not known
- row.push('');
- }
-
- // Go through each header
- for (var i = 6; i < sorted.length; i++) {
- // Add the node attributes to the row
- var key = sorted[i];
-
- // Do not put comments and status in twice
- if (key != 'usercomment' && key != 'status' && key.indexOf('status') < 0) {
- var val = attrs[node][key];
- if (val) {
- row.push(val);
- } else {
- row.push('');
- }
- }
- }
-
- // Add the row to the table
- nodesTable.add(row);
- }
-
- // Clear the tab before inserting the table
- $('#nodesTab').children().remove();
-
- // Create info bar for nodes tab
- var info = createInfoBar('Double-click on a cell to edit a node\'s properties. Click outside the table to save changes. Hit the Escape key to ignore changes.');
- $('#nodesTab').append(info);
- info.id = 'NodesInfoBar';
- setNodesTabInfoBar(info);
-
- // Create action bar
- var actionBar = $('
').css("width", "400px");
-
- /**
- * Create menu for actions to perform against a given node
- */
-
- // Power on
- var powerOnLnk = $('
Power on ');
- powerOnLnk.click(function() {
- var tgtNodes = getNodesChecked(nodesTableId);
- if (tgtNodes) {
- powerNode(tgtNodes, 'on');
- }
- });
-
- // Power off
- var powerOffLnk = $('
Power off ');
- powerOffLnk.click(function() {
- var tgtNodes = getNodesChecked(nodesTableId);
- if (tgtNodes) {
-
- var msg = 'Do you want to power off: ' + tgtNodes + '?';
- // Open dialog to confirm
- var confirmDialog = $('
');
- confirmDialog.dialog({
- title:'Confirm',
- modal: true,
- close: function(){
- $(this).remove();
- },
- width: 400,
- buttons: {
- "Ok": function() {
- powerNode(tgtNodes, 'off');
- $(this).dialog("close");
- },
- "Cancel": function() {
- $(this).dialog("close");
- }
- }
- });
- }
- });
-
- // Power softoff
- var powerSoftoffLnk = $('
Shutdown ');
- powerSoftoffLnk.click(function() {
- var tgtNodes = getNodesChecked(nodesTableId);
- if (tgtNodes) {
- var msg = 'Do you want to shutdown: ' + tgtNodes + '?';
- // Open dialog to confirm
- var confirmDialog = $('
');
- confirmDialog.dialog({
- title:'Confirm',
- modal: true,
- close: function(){
- $(this).remove();
- },
- width: 400,
- buttons: {
- "Ok": function() {
- powerNode(tgtNodes, 'softoff');
- $(this).dialog("close");
- },
- "Cancel": function() {
- $(this).dialog("close");
- }
- }
- });
- }
- });
- if (builtInXCAT == 0) {
- // Turn monitoring on
- var monitorOnLnk = $('
Monitor on ');
- monitorOnLnk.click(function() {
- var tgtNodes = getNodesChecked(nodesTableId);
- if (tgtNodes) {
- monitorNode(tgtNodes, 'on');
- }
- });
-
- // Turn monitoring off
- var monitorOffLnk = $('
Monitor off ');
- monitorOffLnk.click(function() {
- var tgtNodes = getNodesChecked(nodesTableId);
- if (tgtNodes) {
- monitorNode(tgtNodes, 'off');
- }
- });
- }
-
- // Clone
- var cloneLnk = $('
Clone ');
- cloneLnk.click(function() {
- var tgtNodes = getNodesChecked(nodesTableId).split(',');
- for (var i in tgtNodes) {
- var mgt = getNodeAttr(tgtNodes[i], 'mgt');
-
- // Create an instance of the plugin
- var plugin;
- switch(mgt) {
- case "kvm":
- plugin = new kvmPlugin();
- break;
- case "esx":
- plugin = new esxPlugin();
- break;
- case "zvm":
- plugin = new zvmPlugin();
- break;
- }
- if (mgt == "zvm") {
- var nodeOS = getNodeAttr(tgtNodes[i], 'os');
- var nodeArch = getNodeAttr(tgtNodes[i], 'arch');
- plugin.loadClonePage(tgtNodes[i], nodeOS, nodeArch);
- } else {
- plugin.loadClonePage(tgtNodes[i]);
- }
-
- }
- });
-
- // Delete
- var deleteLnk = $('
Delete ');
- deleteLnk.click(function() {
- var tgtNodes = getNodesChecked(nodesTableId);
- if (tgtNodes) {
- loadDeletePage(tgtNodes);
- }
- });
-
- // Unlock Function
- var unlockLnk = $('
Unlock ');
- unlockLnk.click(function() {
-
- // Get the "master" value from the site table.
- var siteMaster;
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'tabdump',
- tgt : '',
- args : 'site',
- msg : 'cmd=tabdump site;'
- },
-
- success : function(data) {
- var outId = $(data.msg);
- var props = data.rsp;
- if ( jQuery.isArray(data.rsp) ) {
- for (var i in data.rsp) {
- if ( data.rsp[i].indexOf('"master"') == 0 ) {
- siteMaster = data.rsp[i].slice( 10, -3 );
- }
- }
- } else {
- if ( data.rsp.indexOf('"master"') == 0 ) {
- siteMaster = data.rsp.slice( 10, -3 );
- }
- }
-
- // Process the nodes that were checked.
- var tgtNodes = getNodesChecked(nodesTableId).split(',');
- var normalNodes = '';
- var mnNode = '';
- for (var i in tgtNodes) {
- var nodeIP = getNodeAttr( tgtNodes[i], 'ip' );
- if ( nodeIP == siteMaster ) {
- if ( mnNode == '' ) {
- // Only one xCAT node will have the same address as
- // the site master IP address and this is the
- // xCAT MN.
- mnNode = tgtNodes[i];
- }
- } else {
- if ( normalNodes == '' ) {
- normalNodes = tgtNodes[i];
- } else {
- normalNodes = normalNodes + "," + tgtNodes[i];
- }
- }
- }
-
- if ( normalNodes != '' ) {
- loadUnlockPage( normalNodes );
- }
- if ( mnNode != '' ) {
- loadUnlockNonNodesPage( mnNode );
- }
- }
- });
- });
-
- // Run script
- var scriptLnk = $('
Run script ');
- scriptLnk.click(function() {
- var tgtNodes = getNodesChecked(nodesTableId);
- if (tgtNodes) {
- loadScriptPage(tgtNodes);
- } else {
- openDialog('warn', "No nodes checked!");
- }
- });
-
- // Migrate VM
- var migrateLnk = $('
Migrate ');
- migrateLnk.click(function() {
- var tgtNodes = getNodesChecked(nodesTableId).split(',');
- var mgt = "", tmp = "";
- var fromhcp = "";
- for (var i in tgtNodes) {
- tmp = getNodeAttr(tgtNodes[i], 'mgt');
- fromhcp += getNodeAttr(tgtNodes[i], 'hcp') + ',';
- if (!mgt) {
- mgt = tmp
- } else {
- if (tmp != mgt) {
- openDialog('warn', "You can pick only one type (mgt) of node to migrate!");
- return;
- }
- }
- }
-
- // Create an instance of the plugin
- var plugin;
- switch(mgt) {
- // Only hypervisors support migration
- case "kvm":
- plugin = new kvmPlugin();
- break;
- case "esx":
- plugin = new esxPlugin();
- break;
- case "zvm":
- plugin = new zvmPlugin();
- break;
- }
- if (mgt == "zvm") {
- plugin.loadMigratePage(tgtNodes, fromhcp);
- } else {
- plugin.loadMigratePage(tgtNodes);
- }
- });
-
- // Update
- var updateLnk = $('
Update ');
- updateLnk.click(function() {
- var tgtNodes = getNodesChecked(nodesTableId);
- if (tgtNodes) {
- loadUpdatenodePage(tgtNodes);
- }
- });
-
- // Set boot state
- var setBootStateLnk = $('
Set boot state ');
- setBootStateLnk.click(function() {
- var tgtNodes = getNodesChecked(nodesTableId);
- if (tgtNodes) {
- loadNodesetPage(tgtNodes);
- }
- });
-
- // Boot to network
- var boot2NetworkLnk = $('
Boot to network ');
- boot2NetworkLnk.click(function() {
- var tgtNodes = getNodesChecked(nodesTableId);
- if (tgtNodes) {
- loadNetbootPage(tgtNodes);
- }
- });
-
- // Provision node
- var provisionLnk = $('
Provision ');
- provisionLnk.click(function() {
- var tgtNodes = getNodesChecked(nodesTableId);
- if (tgtNodes){
- // Jump directly to the provision page
- jump2Provision(tgtNodes);
- }
- });
-
- // Remote console
- var rcons = $('
Open console ');
- rcons.bind('click', function(event){
- var tgtNodes = getNodesChecked(nodesTableId);
- if (tgtNodes) {
- loadRconsPage(tgtNodes);
- }
- });
-
- // Discovery
- var discoverLnk = $('
Discover systems ');
- discoverLnk.bind( 'click', function(event) {
- var tgtNodes = getNodesChecked(nodesTableId).split(',');
- if ( tgtNodes ) {
- var hosts;
- for (var i in tgtNodes) {
- var hostType = getNodeAttr( tgtNodes[i], 'hosttype' );
- if ( hostType == 'zvm' ) {
- if ( hosts ) {
- hosts += "," + tgtNodes[i];
- } else {
- hosts = tgtNodes[i];
- }
-
- } else {
- openDialog('warn', tgtNodes[i] + " does not have a hosttype of 'zvm': " + hostType );
- }
- }
- if ( hosts ) {
- discoverVMNodes( hosts );
- }
- } else {
- openDialog('warn', "No nodes checked!");
- }
- });
-
- // Edit properties
- var editProps = $('
Edit properties ');
- editProps.bind('click', function(event){
- var tgtNodes = getNodesChecked(nodesTableId).split(',');
- for (var i in tgtNodes) {
- editNodeProps(tgtNodes[i]);
- }
- });
-
- // Install Ganglia
- var installMonLnk = $('
Install monitoring ');
- installMonLnk.click(function() {
- var tgtNodes = getNodesChecked(nodesTableId);
- if (tgtNodes) {
- installGanglia(tgtNodes);
- }
- });
-
- // Scan
- var rscanLnk = $('
Scan ');
- rscanLnk.bind('click', function(event){
- var tgtNodes = getNodesChecked(nodesTableId);
- if (tgtNodes) {
- loadRscanPage(tgtNodes);
- }
- });
-
- // Event log
- var logLnk = $('
Event log ');
- logLnk.click(function() {
- var tgtNodes = getNodesChecked(nodesTableId).split(',');
- for (var i in tgtNodes) {
- var mgt = getNodeAttr(tgtNodes[i], 'mgt');
-
- // Create an instance of the plugin
- var plugin;
- switch(mgt) {
- case "kvm":
- plugin = new kvmPlugin();
- break;
- case "esx":
- plugin = new esxPlugin();
- break;
- case "blade":
- plugin = new bladePlugin();
- break;
- case "hmc":
- plugin = new hmcPlugin();
- break;
- case "ipmi":
- plugin = new ipmiPlugin();
- break;
- case "zvm":
- plugin = new zvmPlugin();
- break;
- }
-
- plugin.loadLogPage(tgtNodes[i]);
- }
- });
-
- // Actions
- var actionsLnk = '
Actions ';
- if (builtInXCAT == 0) {
- if (group == 'hosts') {
- var actsMenu = createMenu([deleteLnk]);
- } else {
- var actsMenu = createMenu([cloneLnk, deleteLnk, migrateLnk, monitorOnLnk, monitorOffLnk, powerOnLnk, powerOffLnk, scriptLnk, powerSoftoffLnk]);
- }
- } else {
- if (group == 'hosts') {
- var actsMenu = createMenu([deleteLnk]);
- } else {
- var actsMenu = createMenu([cloneLnk, deleteLnk, migrateLnk, powerOnLnk, powerOffLnk, scriptLnk, powerSoftoffLnk]);
- }
- }
-
- // Configurations
- var configLnk = '
Configuration ';
- if (builtInXCAT == 0) {
- if (group == 'hosts') {
- var configMenu = createMenu([editProps]);
- } else {
- var configMenu = createMenu([editProps, logLnk, installMonLnk, rscanLnk, unlockLnk, updateLnk]);
- }
- } else {
- if (group == 'hosts') {
- var configMenu = createMenu([ discoverLnk, editProps ]);
- } else {
- var configMenu = createMenu([editProps, logLnk, rscanLnk, unlockLnk, updateLnk]);
- }
- }
-
- // Provision
- var provLnk = '
Provision ';
- if (builtInXCAT == 0) {
- var provMenu = createMenu([boot2NetworkLnk, rcons, setBootStateLnk, provisionLnk]);
- } else {
- var provMenu = createMenu([boot2NetworkLnk, setBootStateLnk]);
- }
-
- /**
- * Refresh button
- */
- var refreshBtn = createButton('Refresh');
- refreshBtn.click(function() {
- // Remove any warning messages
- $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
-
- var zhcpsCheck = $.cookie('xcat_zhcps').split(',');
- var zhcpHash = new Object();
- for (var h in zhcpsCheck) {
- if (!zhcpHash[zhcpsCheck[h]]) {
-
- zhcpHash[zhcpsCheck[h]] = 1;
- if (typeof console == "object"){
- console.log("zhcp check for <"+zhcpsCheck[h]+">");
- }
-
- // Check if SMAPI is online
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'lsvm',
- tgt : zhcpsCheck[h],
- args : '',
- msg : 'group=refreshgroups' + ';hcp=' + zhcpsCheck[h]
- },
-
- // Load hardware control point specific info
- // Get disk pools and network names
- success : loadHcpInfo
- });
- }
- }
-
- window.location.reload();
- });
- refreshBtn.css({'width': '80px'});
- refreshBtn.css({'height': '27px'});
- //refreshBtn.css('vertical-align', 'top');
- refreshBtn.css({'align': 'top'});
-
- // Create an action menu
- var actionsMenu;
- if (group == 'hosts') {
- actionsMenu = createMenu([ [ actionsLnk, actsMenu ], [ configLnk, configMenu ] ]);
- } else {
- actionsMenu = createMenu([ [ actionsLnk, actsMenu ], [ configLnk, configMenu ], [ provLnk, provMenu ] ]);
- }
- actionsMenu.superfish();
- actionsMenu.css('display', 'inline-block');
- actionBar.append(actionsMenu);
- actionBar.append(refreshBtn);
-
- // Set correct theme for action menu
- actionsMenu.find('li').hover(function() {
- setMenu2Theme($(this));
- }, function() {
- setMenu2Normal($(this));
- });
-
- // Insert action bar and nodes datatable
- $('#nodesTab').append(nodesTable.object());
-
- // Turn table into a datatable
- var nodesDatatable = $('#' + nodesTableId).dataTable({
- 'iDisplayLength': 50,
- 'bLengthChange': false,
- "bScrollCollapse": true,
- "sScrollY": "400px",
- "sScrollX": "110%",
- "bAutoWidth": true,
- "oLanguage": {
- "oPaginate": {
- "sNext": "",
- "sPrevious": ""
- }
- }
- });
-
- // Filter table when enter key is pressed
- $('#' + nodesTableId + '_filter input').unbind();
- $('#' + nodesTableId + '_filter input').bind('keyup', function(e){
- if (e.keyCode == 13) {
- var table = $('#' + nodesTableId).dataTable();
- table.fnFilter($(this).val());
-
- // If there are nodes found, get the node attributes
- if (!$('#' + nodesTableId + ' .dataTables_empty').length) {
- getNodeAttrs(group);
- }
- }
- });
-
- // Load node definitions when next or previous buttons are clicked
- $('#' + nodesTableId + '_next, #' + nodesTableId + '_previous').click(function() {
- getNodeAttrs(group);
- });
-
- /**
- * Change how datatable behaves
- */
-
- // Do not sort ping, power, and comment column
- var cols = $('#' + nodesTableId + ' thead tr th').click(function() {
- getNodeAttrs(group);
- });
- var checkboxCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(0)');
- var pingCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(2)');
- var powerCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
- var monitorCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)');
- var commentCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(5)');
- checkboxCol.unbind('click');
- pingCol.unbind('click');
- powerCol.unbind('click');
- monitorCol.unbind('click');
- commentCol.unbind('click');
-
- // Create enough space for loader to be displayed
- // Center align power, ping, and comments
- $('#' + nodesTableId + ' td:nth-child(3),td:nth-child(4),td:nth-child(5)').css({
- 'text-align': 'center'
- });
-
- // No minimum width for comments column
- $('#' + nodesTableId + ' tbody tr td:nth-child(6)').css('text-align', 'center');
-
- // Instead refresh the node, power, and monitor status
- pingCol.find('span a').click(function() {
- refreshNodeStatus(group, nodesTableId);
- });
- powerCol.find('span a').click(function() {
- refreshPowerStatus(group, nodesTableId);
- });
- monitorCol.find('span a').click(function() {
- refreshGangliaStatus(group, nodesTableId);
- });
-
- // Create a division to hold actions menu
- var menuDiv = $(''); // # ');
- update.append(createInfoBar('Updating table
'));
-
- update.dialog({
- title: 'Updating',
- modal: true,
- width: 300,
- position: 'center'
- });
- }
-}
-
-/**
- * Add nodes to datatable
- *
- * @param data Data returned from HTTP request
- */
-function addNodes2Table(data) {
- // Data returned
- var rsp = data.rsp;
- // Group name
- var group = data.msg;
- // Hash of node attributes
- var attrs = new Object();
- // Node attributes
- var headers = $('#' + nodesTableId).parents('.dataTables_scroll').find('.dataTables_scrollHead thead tr th');
-
- // Variable to send command and request node status
- var getNodeStatus = true;
-
- // Go through each attribute
- var node, args;
- for (var i in rsp) {
- // Get node name
- if (rsp[i].indexOf('Object name:') > -1) {
- var temp = rsp[i].split(': ');
- node = jQuery.trim(temp[1]);
-
- // Create a hash for node attributes
- attrs[node] = new Object();
- i++;
- }
-
- // Get key and value
- args = rsp[i].split('=', 2);
- var key = jQuery.trim(args[0]);
- var val = jQuery.trim(rsp[i].substring(rsp[i].indexOf('=') + 1, rsp[i].length));
-
- // Create a hash table
- attrs[node][key] = val;
- // Save attributes in original hash table
- origAttrs[node][key] = val;
-
- // If node status is available
- if (key == 'status') {
- // Do not request node status
- getNodeStatus = false;
- }
- }
-
- // Set the first five headers
- var headersCol = new Object();
- headersCol['node'] = 1;
- headersCol['status'] = 2;
- headersCol['power'] = 3;
- headersCol['monitor'] = 4;
- headersCol['comments'] = 5;
-
- // Go through each header
- for (var i = 6; i < headers.length; i++) {
- // Get the column index
- headersCol[headers.eq(i).html()] = i;
- }
-
- // Go through each node
- var datatable = $('#' + nodesTableId).dataTable();
- var rows = datatable.fnGetData();
- for (var node in attrs) {
- // Get row containing node
- var nodeRowPos = 0;
- for (var i in rows) {
- // If column contains node
- if (rows[i][1].indexOf('>' + node + '<') > -1) {
- nodeRowPos = i;
- break;
- }
- }
-
- // Get node status
- var status = '';
- if (attrs[node]['status']){
- status = attrs[node]['status'].replace('sshd', 'ping');
- }
-
- rows[nodeRowPos][headersCol['status']] = status;
-
- // Go through each header
- for (var key in headersCol) {
- // Do not put comments and status in twice
- if (key != 'usercomment' && key != 'status' && key.indexOf('status') < 0) {
- var val = attrs[node][key];
- if (val) {
- rows[nodeRowPos][headersCol[key]] = val;
- }
- }
- }
-
- // Update row
- datatable.fnUpdate(rows[nodeRowPos], parseInt(nodeRowPos), undefined, false);
-
- // Insert node comments
- // This is done after datatable is updated because
- // you cannot insert an object using fnUpdate()
- var comments = attrs[node]['usercomment'];
-
- // If no comments exists, show 'No comments' and
- // set icon image source
- var iconSrc;
- if (!comments) {
- comments = 'No comments';
- iconSrc = 'images/nodes/ui-icon-no-comment.png';
- } else {
- iconSrc = 'images/nodes/ui-icon-comment.png';
- }
-
- // Create icon for node comments
- var tipID = node + 'Tip';
- var commentsCol = $('#' + node).parent().parent().find('td').eq(5);
-
- // Create tooltip
- var icon = $('
').css({
- 'width': '18px',
- 'height': '18px'
- });
-
- var tip = createCommentsToolTip(comments);
- var span = $('
').append(icon);
- span.append(tip);
- commentsCol.append(span);
-
- // Generate tooltips
- icon.tooltip({
- position: "center right",
- offset: [-2, 10],
- effect: "fade",
- opacity: 0.8,
- relative: true,
- delay: 500
- });
- }
-
- // Enable node link
- $('.node').bind('click', loadNode);
-
- // Close dialog for updating table
- $('.ui-dialog-content').dialog('destroy').remove();
-
- /**
- * Enable editable columns
- */
- // Do not make 1st, 2nd, 3rd, 4th, 5th, or 6th column editable
- $('#' + nodesTableId + ' td:not(td:nth-child(1),td:nth-child(2),td:nth-child(3),td:nth-child(4),td:nth-child(5),td:nth-child(6))').editable(
- function(value, settings) {
- // If users did not do changes, return the value directly
- // jeditable save the old value in this.revert
- if ($(this).attr('revert') == value){
- return value;
- }
- // Get column index
- var colPos = this.cellIndex;
-
- // Get row index
- var dTable = $('#' + nodesTableId).dataTable();
- var rowPos = dTable.fnGetPosition(this.parentNode);
-
- // Update datatable
- dTable.fnUpdate(value, rowPos, colPos, false);
-
- // Get table headers
- var headers = $('#' + nodesTableId + ' thead tr th');
-
- // Get node name
- var node = $(this).parent().find('td a.node').text();
- // 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 node attributes
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'chdef',
- tgt : '',
- args : '-t;node;-o;' + node + ';' + args,
- msg : 'out=nodesTab;tgt=' + node
- },
-
- success: showChdefOutput
- });
-
- return value;
- }, {
- onblur : 'submit', // Clicking outside editable area submits changes
- type : 'textarea',
- placeholder: ' ',
- event : 'dblclick',
- height : '30px' // The height of the text area
- });
-
- // If request to get node status is made
- if (getNodeStatus) {
- // Get node status
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'nodestat',
- tgt : group,
- args : '-u',
- msg : ''
- },
-
- success : loadNodeStatus
- });
- } else {
- // Hide status loader
- var statCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(2)');
- statCol.find('img').hide();
- }
-
- /**
- * Additional ajax requests need to be made for zVM
- */
- advancedLoad(group);
- adjustColumnSize(nodesTableId);
-}
-
-/**
- * Load the status of Ganglia for a given group
- *
- * @param data Data returned from HTTP request
- */
-function loadGangliaStatus(data) {
- // Get datatable
- var datatable = $('#' + nodesTableId).dataTable();
- var ganglia = data.rsp;
- var rowNum, node, status;
-
- for ( var i in ganglia) {
- // ganglia[0] = nodeName and ganglia[1] = state
- node = jQuery.trim(ganglia[i][0]);
- status = jQuery.trim(ganglia[i][1]);
-
- if (node) {
- // Get the row containing the node
- rowNum = findRow(node, '#' + nodesTableId, 1);
-
- // Update the power status column
- datatable.fnUpdate(status, rowNum, 4);
- }
- }
-
- // Hide Ganglia loader
- var gangliaCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)');
- gangliaCol.find('img').hide();
- adjustColumnSize(nodesTableId);
-}
-
-/**
- * Refresh the status of Ganglia for each node
- *
- * @param group Group name
- */
-function refreshGangliaStatus(group) {
- // Show ganglia loader
- var gangliaCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)');
- gangliaCol.find('img').show();
-
- // Get power status for nodes shown
- var nodes = getNodesShown(nodesTableId);
-
- // Get the status of Ganglia
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'gangliastatus;' + nodes,
- msg : ''
- },
-
- success : loadGangliaStatus
- });
-}
-
-/**
- * Load power status for each node
- *
- * @param data Data returned from HTTP request
- */
-function loadPowerStatus(data) {
- var dTable = $('#' + nodesTableId).dataTable();
- var power = data.rsp;
- var rowPos, node, status, args;
-
- for (var i in power) {
- // power[0] = nodeName and power[1] = state
- args = power[i].split(':');
- node = jQuery.trim(args[0]);
- status = jQuery.trim(args[1]);
-
- // Get the row containing the node
- rowPos = findRow(node, '#' + nodesTableId, 1);
-
- // Update the power status column
- dTable.fnUpdate(status, rowPos, 3);
- }
-
- // Hide power loader
- var powerCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
- powerCol.find('img').hide();
- adjustColumnSize(nodesTableId);
-}
-
-/**
- * Refresh power status for each node
- *
- * @param group Group name
- * @param tableId Table to update node status
- */
-function refreshPowerStatus(group, tableId) {
- // Show power loader
- var powerCol = $('#' + tableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
- powerCol.find('img').show();
-
- // Get power status for nodes shown
- var nodes = getNodesShown(tableId);
-
- // Get power status
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'rpower',
- tgt : nodes,
- args : 'stat',
- msg : ''
- },
-
- success : loadPowerStatus
- });
-}
-
-/**
- * Load node status for each node
- *
- * @param data Data returned from HTTP request
- */
-function loadNodeStatus(data) {
- var dTable = $('#' + nodesTableId).dataTable();
- var rsp = data.rsp;
- var args, rowPos, node, status;
-
- // Get all nodes within datatable
- for (var i in rsp) {
- args = rsp[i].split(':');
-
- // args[0] = node and args[1] = status
- node = jQuery.trim(args[0]);
- status = jQuery.trim(args[1]).replace('sshd', 'ping');
-
- // Get row containing node
- rowPos = findRow(node, '#' + nodesTableId, 1);
-
- // Update ping status column
- dTable.fnUpdate(status, rowPos, 2, false);
- }
-
- // Hide status loader
- var statCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(2)');
- statCol.find('img').hide();
- adjustColumnSize(nodesTableId);
-}
-
-/**
- * Refresh ping status for each node
- *
- * @param group Group name
- * @param tableId Table to update node status
- */
-function refreshNodeStatus(group, tableId) {
- // Show ping loader
- var pingCol = $('#' + tableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(2)');
- pingCol.find('img').show();
-
- // Get power status for nodes shown
- var nodes = getNodesShown(tableId);
-
- // Get the node status
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'nodestat',
- tgt : nodes,
- args : '-u',
- msg : ''
- },
-
- success : loadNodeStatus
- });
-}
-
-/**
- * Load inventory for given node
- *
- * @param e Windows event
- */
-function loadNode(e) {
- if (!e) {
- e = window.event;
- }
-
- // Get node that was clicked
- var node = (e.target) ? e.target.id : e.srcElement.id;
- var mgt = getNodeAttr(node, 'mgt');
-
- // Create an instance of the plugin
- var plugin;
- switch(mgt) {
- case "kvm":
- plugin = new kvmPlugin();
- break;
- case "esx":
- plugin = new esxPlugin();
- break;
- case "blade":
- plugin = new bladePlugin();
- break;
- case "hmc":
- plugin = new hmcPlugin();
- break;
- case "ipmi":
- plugin = new ipmiPlugin();
- break;
- case "zvm":
- plugin = new zvmPlugin();
- break;
- }
-
- // Get tab area where a new tab will be inserted
- var myTab = getNodesTab();
- var inst = 0;
- var newTabId = 'nodeTab' + inst;
- while ($('#' + newTabId).length) {
- // If one already exists, generate another one
- inst = inst + 1;
- newTabId = 'nodeTab' + inst;
- }
- // Reset node process
- $.cookie('xcat_' + node + 'Processes', 0, { path: '/xcat', secure:true });
-
- // Add new tab, only if one does not exist
- var loader = createLoader(newTabId + 'TabLoader');
- loader = $('
').append(loader);
- myTab.add(newTabId, node, loader, true);
-
- // Get node inventory
- var msg = 'out=' + newTabId + ',node=' + node;
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'rinv',
- tgt : node,
- args : 'all',
- msg : msg
- },
-
- success : plugin.loadInventory
- });
-
- // Select new tab
- myTab.select(newTabId);
-}
-
-/**
- * Unlock a node by setting the ssh keys
- *
- * @param tgtNodes Nodes to unlock
- */
-function loadUnlockPage(tgtNodes) {
- // Get nodes tab
- var tab = getNodesTab();
-
- // Generate new tab ID
- var instance = 0;
- var newTabId = 'unlockTab' + instance;
- while ($('#' + newTabId).length) {
- // If one already exists, generate another one
- instance = instance + 1;
- newTabId = 'unlockTab' + instance;
- }
-
- // Create status bar, hide on load
- var statBarId = 'unlockStatusBar' + instance;
- var statBar = createStatusBar(statBarId).hide();
-
- // Create loader
- var loader = createLoader('');
- statBar.find('div').append(loader);
-
- // Create info bar
- var infoBar = createInfoBar('Give the root password for this node range to setup its SSH keys.');
-
- // Create unlock form
- var unlockForm = $('
');
- unlockForm.append(statBar, infoBar);
-
- // Create VM fieldset
- var vmFS = $('
');
- var vmLegend = $('
Virtual Machine ');
- vmFS.append(vmLegend);
- unlockForm.append(vmFS);
-
- var vmAttr = $('
');
- vmFS.append($('
'));
- vmFS.append(vmAttr);
-
- vmAttr.append('
Target node range:
');
- vmAttr.append('
Password:
');
-
- // Generate tooltips
- unlockForm.find('div input[title]').tooltip({
- position: "center right",
- offset: [-2, 10],
- effect: "fade",
- opacity: 0.7,
- predelay: 800,
- events : {
- def : "mouseover,mouseout",
- input : "mouseover,mouseout",
- widget : "focus mouseover,blur mouseout",
- tooltip : "mouseover,mouseout"
- }
- });
-
- /**
- * Ok
- */
- var unlockBtn = createButton('Unlock');
- unlockBtn.css({
- 'width': '80px',
- 'display': 'block'
- });
- unlockBtn.click(function() {
- // Remove any warning messages
- $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
-
- // If a password is given
- var password = $('#' + newTabId + ' input[name=password]').css('border', 'solid #BDBDBD 1px');
- if (password.val()) {
- // Setup SSH keys
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'unlock;' + tgtNodes + ';' + password.val(),
- msg : 'out=' + statBarId + ';cmd=unlock;tgt=' + tgtNodes
- },
-
- success : updateStatusBar
- });
-
- // Show status bar
- statBar.show();
-
- // Disable all inputs and Ok button
- $('#' + newTabId + ' input').attr('disabled', 'disabled');
- $(this).attr('disabled', 'true');
- } else {
- // Show warning message
- var warn = createWarnBar('You are missing some values!');
- warn.prependTo($(this).parents('.ui-tabs-panel'));
- password.css('border', 'solid #FF0000 1px');
- }
- });
-
- unlockForm.append(unlockBtn);
- tab.add(newTabId, 'Unlock', unlockForm, true);
- tab.select(newTabId);
-}
-
-function loadUnlockNonNodesPage( tgtNodes ) {
-
- // Get nodes tab
- var tab = getNodesTab();
- var fs, legend;
-
- // Generate new tab ID
- var instance = 0;
- var newTabId = 'unlockNonNodesTab' + instance;
- while ($('#' + newTabId).length) {
- // If one already exists, generate another one
- instance = instance + 1;
- newTabId = 'unlockNonNodesTab' + instance;
- }
-
- // Create info bar and status bar
- var infoBar = createInfoBar( 'Unlock systems that have not been defined to xCAT. Either:
' +
- '-Create a script to install the xCAT Management Node\'s public key on the target systems, or
' +
- '-Unlock system(s) directly using their IP address(es) ' +
- '(Specify multiple systems by separating the addresses with a comma),
' +
- '-Show the xCAT Management Node\'s public key to use to unlock the system.' );
-
- var statBarId = 'unlockNonNodesStatusBar' + instance;
- var statBar = createStatusBar(statBarId).hide();
- var loader = createLoader( '' );
- statBar.find('div').append( loader );
-
- // Create unlock form and put info and status bars on the form
- var unlockNonNodesForm = $( '
' );
- unlockNonNodesForm.append( infoBar, statBar );
-
- // Create 'Create an Unlock Script' fieldset
- fs = $( '
' );
- legend = $( '
Create an Unlock Script ' );
- fs.append( legend );
- unlockNonNodesForm.append( fs );
-
- // Create Script bar
- var scriptBarId = 'unlockNonNodesScriptBar' + instance;
- var scriptBar = createStatusBar(scriptBarId).hide();
- unlockNonNodesForm.append( scriptBar );
-
- var createBtn = createButton( 'Create Script' );
- createBtn.css({
- 'width': '200px',
- 'display': 'block'
- });
-
- createBtn.click(function() {
- // Remove any warning messages
- $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
-
- // Get the SSH keys for a non-node
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'unlockshow;' + tgtNodes + ';script;',
- msg : 'out=' + statBarId + ';scriptBar=' + scriptBarId +';cmd=unlock;tgt=' + tgtNodes
- },
-
- success : updateScriptBar
- });
-
- // Show status bar
- statBar.show();
- });
-
- unlockNonNodesForm.append( createBtn );
-
- // Create 'Unlock a system using the root password' Script fieldset
- fs = $( '
' );
- legend = $( '
Unlock a system using the root password ' );
- fs.append( legend );
- unlockNonNodesForm.append( fs );
-
- var vmAttr = $('
' );
- fs.append($('
'));
- fs.append( vmAttr );
-
- vmAttr.append( '
IP Address:
' );
- vmAttr.append( '
Password:
' );
-
- /**
- * Unlock button for non-nodes
- */
- var unlockBtn = createButton('Unlock');
- unlockBtn.css({
- 'width': '80px',
- 'display': 'block'
- });
-
- unlockBtn.click(function() {
- // Remove any warning messages
- $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
-
- // If an ip and password is given
- var ip = $('#' + newTabId + ' input[name=ip]').css('border', 'solid #BDBDBD 1px');
- var password = $( '#' + newTabId + ' input[name=password]').css('border', 'solid #BDBDBD 1px' );
- if ( password.val() && ip.val() ) {
- $('#' + statBarId).find('img').show();
- // Setup SSH keys for a non-node
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'unlockbyip;' + tgtNodes + ';' + password.val() + ";" + ip.val(),
- msg : 'out=' + statBarId + ';cmd=unlock;tgt=' + tgtNodes
- },
-
- success : updateStatusBar
- });
-
- // Show status bar
- statBar.show();
- } else {
- // Show warning message
- var warn = createWarnBar('Both ip address and password must be specified.');
- warn.prependTo($(this).parents('.ui-tabs-panel'));
- password.css('border', 'solid #FF0000 1px');
- }
- });
-
- unlockNonNodesForm.append(unlockBtn);
-
- // Create 'SSH Key' fieldset
- var sshKey = '';
- fs = $( '
' );
- legend = $( '
xCAT Management Node Public Key ' );
- fs.append( legend );
- unlockNonNodesForm.append( fs );
-
- // Create key bar, hide on load
- var keyBarId = 'unlockNonNodesKeyBar' + instance;
- var keyBar = createStatusBar(keyBarId).hide();
- unlockNonNodesForm.append( keyBar );
-
- // Generate tooltips
- unlockNonNodesForm.find('div input[title]').tooltip({
- position: "center right",
- offset: [-2, 10],
- effect: "fade",
- opacity: 0.7,
- predelay: 800,
- events : {
- def : "mouseover,mouseout",
- input : "mouseover,mouseout",
- widget : "focus mouseover,blur mouseout",
- tooltip : "mouseover,mouseout"
- }
- });
-
- /**
- * "Get Key" button
- */
- var getBtn = createButton('Get Key');
- getBtn.css({
- 'width': '80px',
- 'display': 'block'
- });
-
- getBtn.click(function() {
- // Remove any warning messages
- $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
-
- // Get the SSH keys for a non-node
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'unlockshow;' + tgtNodes + ';key;',
- msg : 'out=' + statBarId + ';keyBar=' + keyBarId +';cmd=unlock;tgt=' + tgtNodes
- },
-
- success : updateKeyBar
- });
-
- // Show status bar
- statBar.show();
- });
-
- unlockNonNodesForm.append(getBtn);
-
- tab.add(newTabId, 'Unlock System', unlockNonNodesForm, true);
- tab.select(newTabId);
-}
-
-
-/**
- * Update key and status bar of a given tab
- *
- * @param data Data returned from HTTP request
- */
-function updateKeyBar(data) {
- // Get ajax response
- var rsp = data.rsp;
- var args = data.msg.split(';');
- var statBarId = args[0].replace('out=', '');
- var keyBarId = args[1].replace('keyBar=', '');
- var cmd = args[2].replace('cmd=', '');
- var tgts = args[3].replace('tgt=', '').split(',');
-
- $('#' + statBarId).find('img').hide();
-
- // Extract the key portion and status portions from the response
- var keyRespStart = rsp[0].indexOf("
");
- var keyRespEnd = rsp[0].indexOf(" ");;
- var keyOnly = rsp[0].substring( keyRespStart+9, keyRespEnd );
- var statLines = rsp[0].substring( 0, keyRespStart-1 );
-
- if ( keyOnly.length > 0 ) {
- // Expected response was returned, show it in the key bar.
- var keyLines = keyOnly.split(/\n/);
- for ( var i in keyLines ) {
- $('#' + keyBarId).find( 'div' ).append( keyLines[i] );
- $('#' + keyBarId).find( 'div' ).append( '
' );
- }
- $('#' + keyBarId).show();
-
- // Other lines from the response are shown in the Status bar.
- if ( statLines.length > 0 ) {
- prg = statLines.split(/\n/);
- prg = writeRsp( prg, '' );
- $('#' + statBarId).find( 'div' ).append( prg );
- }
- } else {
- // Did not find the expected response, write the ajax response to status bar.
- var prg = writeRsp(rsp, '');
- $('#' + statBarId).find('div').append(prg);
- }
-
-}
-
-
-/**
- * Update the script and status bar of a given tab
- *
- * @param data Data returned from HTTP request
- */
-function updateScriptBar(data) {
- // Get ajax response
- var rsp = data.rsp;
- var args = data.msg.split(';');
- var statBarId = args[0].replace('out=', '');
- var scriptBarId = args[1].replace('scriptBar=', '');
- var cmd = args[2].replace('cmd=', '');
- var tgts = args[3].replace('tgt=', '').split(',');
-
- $('#' + statBarId).find('img').hide();
-
- // Extract the key portion and status portions from the response
- var scriptRespStart = rsp[0].indexOf("
");
- var scriptRespEnd = rsp[0].indexOf(" ");;
- var scriptOnly = rsp[0].substring( scriptRespStart+12, scriptRespEnd );
- var statLines = rsp[0].substring( 0, scriptRespStart-1 );
-
- if ( scriptOnly.length > 0 ) {
- // Expected response was returned, show it in the script bar along with the rest of the code.
- var scriptLines = scriptOnly.split(/\n/);
- for ( var i in scriptLines ) {
- scriptLines[i] = scriptLines[i].replace(/^\s\s\s\s\s\s\s\s+/gm, ' ');
- scriptLines[i] = scriptLines[i].replace(/^\s\s\s\s\s\s+/gm, ' ');
- scriptLines[i] = scriptLines[i].replace(/^\s\s\s\s+/gm, ' ');
- scriptLines[i] = scriptLines[i].replace(/^\s\s+/gm, ' ');
- $('#' + scriptBarId).find( 'div' ).append( scriptLines[i] + '
' );
- }
- $('#' + scriptBarId).show();
-
- // Other lines from the response are shown in the Status bar.
- if ( statLines.length > 0 ) {
- prg = statLines.split(/\n/);
- prg = writeRsp( prg, '' );
- $('#' + statBarId).find( 'div' ).append( prg );
- }
- } else {
- // Did not find the expected response, write the ajax response to status bar.
- var prg = writeRsp(rsp, '');
- $('#' + statBarId).find('div').append(prg);
- }
-
-}
-
-/**
- * Load script page
- *
- * @param tgtNodes Targets to run script against
- */
-function loadScriptPage(tgtNodes) {
- // Get nodes tab
- var tab = getNodesTab();
-
- // Generate new tab ID
- var inst = 0;
- var newTabId = 'scriptTab' + inst;
- while ($('#' + newTabId).length) {
- // If one already exists, generate another one
- inst = inst + 1;
- newTabId = 'scriptTab' + inst;
- }
-
- // Create remote script form
- var scriptForm = $('
');
-
- // Create status bar
- var barId = 'scriptStatusBar' + inst;
- var statBar = createStatusBar(barId);
- statBar.hide();
- var loader = createLoader('scriptLoader' + inst);
- statBar.find('div').append(loader);
-
- // Create info bar
- var infoBar = createInfoBar('Load a script to run against this node range.');
- scriptForm.append(infoBar, statBar);
-
- // Create VM fieldset
- var vmFS = $('
');
- var vmLegend = $('
Virtual Machine ');
- vmFS.append(vmLegend);
- scriptForm.append(vmFS);
-
- var vmAttr = $('
');
- vmFS.append($('
'));
- vmFS.append(vmAttr);
-
- // Create logs fieldset
- var scriptFS = $('
');
- var scriptLegend = $('
Script ');
- scriptFS.append(scriptLegend);
- scriptForm.append(scriptFS);
-
- var scriptAttr = $('
');
- scriptFS.append($('
'));
- scriptFS.append(scriptAttr);
-
- // Target node or group
- var tgt = $('
Target node range:
');
- vmAttr.append(tgt);
-
- // Upload file
- var upload = $('
');
- var label = $('
Remote file: ');
- var file = $('
');
- var subBtn = createButton('Load');
- upload.append(label, file, subBtn);
- scriptAttr.append(upload);
-
- // Script
- var script = $('
Script: ');
- scriptAttr.append(script);
-
- // Generate tooltips
- scriptForm.find('div input[title],textarea').tooltip({
- position: "center right",
- offset: [-2, 10],
- effect: "fade",
- opacity: 0.7,
- predelay: 800,
- events : {
- def : "mouseover,mouseout",
- input : "mouseover,mouseout",
- widget : "focus mouseover,blur mouseout",
- tooltip : "mouseover,mouseout"
- }
- });
-
- // Ajax form options
- var options = {
- // Output to text area
- target : '#' + newTabId + ' textarea'
- };
- upload.ajaxForm(options);
-
- /**
- * Run
- */
- var runBtn = createButton('Run');
- runBtn.css({
- 'width': '80px'
- });
- runBtn.click(function() {
- // Remove any warning messages
- $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
-
- // Get script to run
- var textarea = $('#' + newTabId + ' textarea').css('border', 'solid #BDBDBD 1px');
-
- // If no inputs are empty
- if (textarea.val()) {
- // Run script
- runScript(inst);
- } else {
- // Show warning message
- var warn = createWarnBar('You are missing some values');
- warn.prependTo($(this).parents('.ui-tabs-panel'));
- textarea.css('border', 'solid #FF0000 1px');
- }
- });
- scriptForm.append(runBtn);
-
- // Append to discover tab
- tab.add(newTabId, 'Script', scriptForm, true);
-
- // Select new tab
- tab.select(newTabId);
-}
-
-/**
- * Sort a list
- *
- * @return Sorted list
- */
-jQuery.fn.sort = function() {
- return this.pushStack([].sort.apply(this, arguments), []);
-};
-
-function sortAlpha(a, b) {
- return a.innerHTML > b.innerHTML ? 1 : -1;
-};
-
-/**
- * Power on a given node
- *
- * @param node Node to power on or off
- * @param power2 Power node to given state
- */
-function powerNode(node, power2) {
- // Show power loader
- var powerCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
- powerCol.find('img').show();
-
- node = node.replace('Power', '');
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'rpower',
- tgt : node,
- args : power2,
- msg : node
- },
-
- success : updatePowerStatus
- });
-}
-
-/**
- * Load delete node page
- *
- * @param tgtNodes Nodes to delete
- */
-function loadDeletePage(tgtNodes) {
- // Get nodes tab
- var myTab = getNodesTab();
-
- // Generate new tab ID
- var inst = 0;
- newTabId = 'deleteTab' + inst;
- while ($('#' + newTabId).length) {
- // If one already exists, generate another one
- inst = inst + 1;
- newTabId = 'deleteTab' + inst;
- }
-
- // Create target nodes string
- var tgtNodesStr = '';
- var nodes = tgtNodes.split(',');
- // Loop through each node
- for (var i in nodes) {
- // If it is the 1st and only node
- if (i == 0 && i == nodes.length - 1) {
- tgtNodesStr += nodes[i];
- }
- // If it is the 1st node of many nodes
- else if (i == 0 && i != nodes.length - 1) {
- // Append a comma to the string
- tgtNodesStr += nodes[i] + ', ';
- } else {
- // If it is the last node
- if (i == nodes.length - 1) {
- // Append nothing to the string
- tgtNodesStr += nodes[i];
- } else {
- // Append a comma to the string
- tgtNodesStr += nodes[i] + ', ';
- }
- }
- }
-
- // Create delete form
- var deleteForm = $('
');
-
- // Create status bar, hide on load
- var statBarId = 'deleteStatusBar' + inst;
- var statBar = createStatusBar(statBarId).hide();
-
- // Create loader
- var loader = createLoader('');
- statBar.find('div').append(loader);
- statBar.hide();
- deleteForm.append(statBar);
-
- // Create confirm fieldset
- var confirmFS = $('
');
- var confirmLegend = $('
Confirm ');
- confirmFS.append(confirmLegend);
- deleteForm.append(confirmFS);
-
- var confirmAttr = $('
');
- confirmFS.append($('
'));
- confirmFS.append(confirmAttr);
-
- // Confirm delete
- var instr = $('
Are you sure you want to delete ' + tgtNodesStr + ' ?
').css('word-wrap', 'break-word');
- var dbOnly = $('
Only delete entries in database
');
- confirmAttr.append(instr);
- confirmAttr.append(dbOnly);
-
- /**
- * Delete
- */
- var deleteBtn = createButton('Delete');
- deleteBtn.click(function() {
- var cmd = "rmvm";
- // Only delete entries in database if checked
- if ($("#" + newTabId + " input[name='db-only']").attr('checked')) {
- cmd = "noderm";
- }
-
- // Delete the virtual server or remove the node.
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : cmd,
- tgt : tgtNodes,
- args : '',
- msg : 'out=' + statBarId + ';cmd=' + cmd + ';tgt=' + tgtNodes
- },
-
- success : updateStatusBar
- });
-
- // Show status bar loader
- statBar.show();
-
- // Disable delete button
- $(this).attr('disabled', 'true');
- });
-
- /**
- * Cancel
- */
- var cancelBtn = createButton('Cancel');
- cancelBtn.bind('click', function(){
- myTab.remove($(this).parent().parent().attr('id'));
- });
-
- deleteForm.append(deleteBtn, cancelBtn);
- myTab.add(newTabId, 'Delete', deleteForm, true);
-
- myTab.select(newTabId);
-}
-
-/**
- * Update status bar of a given tab
- *
- * @param data Data returned from HTTP request
- */
-function updateStatusBar(data) {
- // Get ajax response
- var rsp = data.rsp;
- var args = data.msg.split(';');
- var statBarId = args[0].replace('out=', '');
- var cmd = args[1].replace('cmd=', '');
- var tgts = args[2].replace('tgt=', '').split(',');
-
- if (cmd == 'unlock' || cmd == 'updatenode') {
- // Hide loader
- $('#' + statBarId).find('img').hide();
-
- // Write ajax response to status bar
- var prg = writeRsp(rsp, '');
- $('#' + statBarId).find('div').append(prg);
- } else if (cmd == 'rmvm') {
- // Get data table
- var dTable = $('#' + nodesTableId).dataTable();
- var failed = false;
-
- // Hide loader
- $('#' + statBarId).find('img').hide();
-
- // Write ajax response to status bar
- var prg = writeRsp(rsp, '');
- $('#' + statBarId).find('div').append(prg);
-
- // If there was an error, do not continue
- if (prg.html().indexOf('Error') > -1) {
- failed = true;
- }
- } else if (cmd == 'xdsh') {
- // Hide loader
- $('#' + statBarId).find('img').hide();
- $('#' + statBarId).find('#loadingpic2').remove();
-
- // Write ajax response to status bar
- var prg = $('
');
- for (var i in rsp) {
- for (var j in tgts) {
- rsp[i] = rsp[i].replace(new RegExp(tgts[j] + ':', 'g'), '');
- }
-
- prg.append(rsp[i]);
- prg.append('
');
- }
- $('#' + statBarId).find('div').append(prg);
- $('#' + statBarId).find('div').append('
');
-
- // The status area division contains useful scrollTop() and "scrollHeight dom 0" information.
- // The inner div grows in height along with the status bar scroll height
- // The status area client does not grow, that is the visible scroll area
- var scrtop = $('#' + statBarId ).scrollTop();
- var scrheight = $('#' + statBarId )[0].scrollHeight;
- var dcheight = $('#' + statBarId)[0].clientHeight;
- var dcheight2 = $('#' + statBarId).find('div')[0].clientHeight;
-
- // Adjust the scroll bar to move to the bottom
- if (scrtop < (scrheight-dcheight)) {
- $('#' + statBarId ).scrollTop(scrheight-dcheight);
- }
-
- // Enable fields
- $('#' + statBarId).parent().find('input').removeAttr('disabled');
- $('#' + statBarId).parent().find('textarea').removeAttr('disabled');
-
- // Enable buttons
- $('#' + statBarId).parent().find('button').removeAttr('disabled');
- } else if (cmd == 'noderm') {
- // Hide loader
- $('#' + statBarId).find('img').hide();
-
- // Write ajax response to status bar
- var prg = $('
Entries deleted in database ');
- $('#' + statBarId).find('div').append(prg);
- } else {
- // Hide loader
- $('#' + statBarId).find('img').hide();
-
- // Write ajax response to status bar
- var prg = writeRsp(rsp, '');
- $('#' + statBarId).find('div').append(prg);
- }
-}
-
-/**
- * Update power status of a node in the datatable
- *
- * @param data Data from HTTP request
- */
-function updatePowerStatus(data) {
- // Hide power loader
- var powerCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
- powerCol.find('img').hide();
-
- // Get datatable
- var dTable = $('#' + nodesTableId).dataTable();
-
- // Get xCAT response
- var rsp = data.rsp;
- // Loop through each line
- var node, status, rowPos, strPos;
- for (var i in rsp) {
- // Get node name
- node = rsp[i].split(":")[0];
-
- // If there is no error
- if (rsp[i].indexOf("Error") < 0 || rsp[i].indexOf("Failed") < 0) {
- // Get the row containing the node link
- rowPos = findRow(node, '#' + nodesTableId, 1);
-
- // If it was power on, then the data return would contain "Starting"
- strPos = rsp[i].indexOf("Starting");
- if (strPos > -1) {
- status = 'on';
- } else {
- status = 'off';
- }
-
- // Update the power status column
- dTable.fnUpdate(status, rowPos, 3, false);
- } else {
- // Power on/off failed
- alert(rsp[i]);
- }
- }
-
- // Adjust datatable column size
- adjustColumnSize(nodesTableId);
-}
-
-/**
- * Run a script
- *
- * @param inst Remote script tab instance
- */
-function runScript(inst) {
- // Get tab ID
- var tabId = 'scriptTab' + inst;
- // Get node name
- var tgts = $('#' + tabId + ' input[name=target]').val();
- // Get script
- var script = $('#' + tabId + ' textarea').val();
-
- var statBarId = 'scriptStatusBar' + inst;
-
- // The status area division contains useful scrollTop() and "scrollHeight dom 0" information.
- // The inner div grows in height along with the status bar scroll height
- // The status area client does not grow, that is the visible scroll area
- var scrtop = $('#' + statBarId ).scrollTop();
- var scrheight = $('#' + statBarId )[0].scrollHeight;
- var dcheight = $('#' + statBarId)[0].clientHeight;
- var dcheight2 = $('#' + statBarId).find('div')[0].clientHeight;
-
- //If this is not first time for run script and it has scrolled then add a progress gif at the end.
- if (scrheight > dcheight) {
- $('#'+statBarId).find('div').append("
");
- scrtop = $('#' + statBarId ).scrollTop();
- scrheight = $('#' + statBarId )[0].scrollHeight;
- dcheight = $('#' + statBarId)[0].clientHeight;
- // Scroll down so gif shows
- $('#' + statBarId ).scrollTop(scrheight-dcheight);
- }
-
- $('#' + statBarId).show(); // Show status bar
- $('#' + statBarId + ' img').show(); // Show loader
- $('#' + statBarId + ' p').remove(); // Clear status bar
-
- // Disable all fields
- $('#' + tabId + ' input').attr('disabled', 'true');
- $('#' + tabId + ' textarea').attr('disabled', 'true');
-
- // Disable buttons
- $('#' + tabId + ' button').attr('disabled', 'true');
-
- // Run script
- $.ajax( {
- url : 'lib/zCmd.php',
- dataType : 'json',
- data : {
- cmd : 'xdsh',
- tgt : tgts,
- args : '-e',
- att : script,
- msg : 'out=scriptStatusBar' + inst + ';cmd=xdsh;tgt=' + tgts
- },
-
- success : updateStatusBar
- });
-}
-
-/**
- * Get an attribute of a given node
- *
- * @param node The node
- * @param attrName The attribute
- * @return The attribute of the node
- */
-function getNodeAttr(node, attrName) {
- // Get the row
- var row = $('[id=' + node + ']').parents('tr');
-
- // Search for the column containing the attribute
- var attrCol;
-
- var cols = row.parents('.dataTables_scroll').find('.dataTables_scrollHead thead tr:eq(0) th');
- // Loop through each column
- for (var i in cols) {
- // Find column that matches the attribute
- if (cols.eq(i).html() == attrName) {
- attrCol = cols.eq(i);
- break;
- }
- }
-
- // If the column containing the attribute is found
- if (attrCol) {
- // Get the attribute column index
- var attrIndex = attrCol.index();
-
- // Get the attribute for the given node
- var attr = row.find('td:eq(' + attrIndex + ')');
- return attr.text();
- } else {
- return '';
- }
-}
-
-/**
- * Set a cookie for the OS images
- *
- * @param data Data from HTTP request
- */
-function setOSImageCookies(data) {
- // Get response
- var rsp = data.rsp;
-
- var imageNames = new Array;
- var profilesHash = new Object();
- var osVersHash = new Object();
- var osArchsHash = new Object();
- var imagePos = 0;
- var profilePos = 0;
- var osversPos = 0;
- var osarchPos = 0;
-
- // Get column value
- 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;
- default :
- break;
- }
- }
-
- // Go through each index
- for (var i = 1; i < rsp.length; i++) {
- // Get image name
- var cols = rsp[i].split(',');
- var osImage = cols[imagePos].replace(new RegExp('"', 'g'), '');
- var profile = cols[profilePos].replace(new RegExp('"', 'g'), '');
- var osVer = cols[osversPos].replace(new RegExp('"', 'g'), '');
- var osArch = cols[osarchPos].replace(new RegExp('"', 'g'), '');
-
- imageNames.push(osImage);
- profilesHash[profile] = 1;
- osVersHash[osVer] = 1;
- osArchsHash[osArch] = 1;
- }
-
- // Save image names in a cookie
- $.cookie('xcat_imagenames', imageNames, { path: '/xcat', secure:true });
-
- // Save profiles in a cookie
- var tmp = new Array;
- for (var key in profilesHash) {
- tmp.push(key);
- }
- $.cookie('xcat_profiles', tmp, { path: '/xcat', secure:true });
-
- // Save OS versions in a cookie
- tmp = new Array;
- for (var key in osVersHash) {
- tmp.push(key);
- }
- $.cookie('xcat_osvers', tmp, { path: '/xcat', secure:true });
-
- // Save OS architectures in a cookie
- tmp = new Array;
- for (var key in osArchsHash) {
- tmp.push(key);
- }
- $.cookie('xcat_osarchs', tmp, { path: '/xcat', secure:true });
-}
-
-/**
- * Set a cookie for the groups
- *
- * @param data Data from HTTP request
- */
-function setGroupsCookies(data) {
- var rsp = data.rsp;
- $.cookie('xcat_groups', rsp, { path: '/xcat', secure:true });
-}
-
-/**
- * Find the row index containing a column with a given string
- *
- * @param str String to search for
- * @param table Table to check
- * @param col Column to find string under
- * @return The row index containing the search string
- */
-function findRow(str, table, col){
- // Get datatable
- var dTable = $(table).dataTable();
- var rows = dTable.fnGetData();
-
- // Loop through each row
- for (var i in rows) {
- // If the column contains the search string
- if (rows[i][col].indexOf(str) > -1) {
- return parseInt(i);
- }
- }
-
- return -1;
-}
-
-/**
- * Select all checkboxes in the datatable
- *
- * @param event Event on element
- * @param obj Object triggering event
- */
-function selectAllCheckbox(event, obj) {
- // Get datatable ID
- // This will ascend from
- var tableObj = obj.parents('.dataTables_scroll').find('.dataTables_scrollBody');
- var status = obj.attr('checked');
- tableObj.find(' :checkbox').attr('checked', status);
- event.stopPropagation();
-}
-
-/**
- * Load rcons page
- *
- * @param tgtNodes Targets to run rcons against
- */
-function loadRconsPage(tgtNodes){
- var hostName = window.location.host;
- var urlPath = window.location.pathname;
- var redirectUrl = 'https://';
- var pos = 0;
-
- // We only support one node
- if (-1 != tgtNodes.indexOf(',')){
- alert("You can only open one console at a time!");
- return;
- }
-
- redirectUrl += hostName;
- pos = urlPath.lastIndexOf('/');
- redirectUrl += urlPath.substring(0, pos + 1);
- redirectUrl += 'rcons.php';
-
- // Open the rcons page
- window.open(redirectUrl + "?rconsnd=" + tgtNodes, '', "toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=no,width=590,height=436");
-}
-
-/**
- * Create a tool tip for comments
- *
- * @param comment Comments to be placed in a tool tip
- * @return Tool tip
- */
-function createCommentsToolTip(comment) {
- // Create tooltip container
- var toolTip = $('
');
- // Create textarea to hold comment
- var txtArea = $('').css({
- 'font-size': '10px',
- 'height': '50px',
- 'width': '200px',
- 'background-color': '#000',
- 'color': '#fff',
- 'border': '0px',
- 'display': 'block'
- });
-
- // Create links to save and cancel changes
- var lnkStyle = {
- 'color': '#58ACFA',
- 'font-size': '10px',
- 'display': 'inline-block',
- 'padding': '5px',
- 'float': 'right'
- };
-
- var saveLnk = $('Save ').css(lnkStyle).hide();
- var cancelLnk = $('Cancel ').css(lnkStyle).hide();
- var infoSpan = $('Click to edit ').css(lnkStyle);
-
- // Save changes onclick
- saveLnk.bind('click', function(){
- // Get node and comment
- var node = $(this).parent().parent().find('img').attr('id').replace('Tip', '');
- var comments = $(this).parent().find('textarea').val();
-
- // Save comment
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'chdef',
- tgt : '',
- args : '-t;node;-o;' + node + ';usercomment=' + comments,
- msg : 'out=nodesTab;tgt=' + node
- },
-
- success: showChdefOutput
- });
-
- // Hide cancel and save links
- $(this).hide();
- cancelLnk.hide();
- });
-
- // Cancel changes onclick
- cancelLnk.bind('click', function(){
- // Get original comment and put it back
- var orignComments = $(this).parent().find('textarea').text();
- $(this).parent().find('textarea').val(orignComments);
-
- // Hide cancel and save links
- $(this).hide();
- saveLnk.hide();
- infoSpan.show();
- });
-
- // Show save link when comment is edited
- txtArea.bind('click', function(){
- saveLnk.show();
- cancelLnk.show();
- infoSpan.hide();
- });
-
- toolTip.append(txtArea);
- toolTip.append(cancelLnk);
- toolTip.append(saveLnk);
- toolTip.append(infoSpan);
-
- return toolTip;
-}
-
-/**
- * Create a tool tip for node status
- *
- * @return Tool tip
- */
-function createStatusToolTip() {
- // Create tooltip container
- var toolTip = $('
').css({
- 'width': '150px',
- 'font-weight': 'normal'
- });
-
- // Create info text
- var info = $('
').css({
- 'white-space': 'normal'
- });
- info.append('Click here to refresh the node status. To configure the xCAT monitor, ');
-
- // Create link to turn on xCAT monitoring
- var monitorLnk = $('click here ').css({
- 'color': '#58ACFA',
- 'font-size': '10px'
- });
-
- // Open dialog to configure xCAT monitor
- monitorLnk.bind('click', function(){
- // Check if xCAT monitor is enabled
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'monls',
- tgt : '',
- args : 'xcatmon',
- msg : ''
- },
-
- success : openConfXcatMon
- });
- });
-
- info.append(monitorLnk);
- toolTip.append(info);
-
- return toolTip;
-}
-
-/**
- * Create a tool tip for power status
- *
- * @return Tool tip
- */
-function createPowerToolTip() {
- // Create tooltip container
- var toolTip = $('Click here to refresh the power status
').css({
- 'width': '150px',
- 'white-space': 'normal',
- 'font-weight': 'normal'
- });
- return toolTip;
-}
-
-/**
- * Create a tool tip for monitoring status
- *
- * @return Tool tip
- */
-function createMonitorToolTip() {
- // Create tooltip container
- var toolTip = $('Click here to refresh the monitoring status
').css({
- 'width': '150px',
- 'white-space': 'normal',
- 'font-weight': 'normal'
- });
- return toolTip;
-}
-
-/**
- * Open dialog to configure xCAT monitor
- *
- * @param data Data returned from HTTP request
- */
-function openConfXcatMon(data) {
- // Create info bar
- var info = createInfoBar('Configure the xCAT monitor. Select to enable or disable the monitor below.');
- var dialog = $('
');
- dialog.append(info);
-
- // Create status area
- var statusArea = $('
').css('padding-top', '10px');
- var label = $('Status: ');
- statusArea.append(label);
-
- // Get xCAT monitor status
- var status = data.rsp[0];
- var buttons;
- // If xCAT monitor is disabled
- if (status.indexOf('not-monitored') > -1) {
- status = $('Disabled ').css('padding', '0px 5px');
- statusArea.append(status);
-
- // Create enable and cancel buttons
- buttons = {
- "Enable": function(){
- // Enable xCAT monitor
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'monstart',
- tgt : '',
- args : 'xcatmon',
- msg : ''
- },
-
- success : function(data){
- openDialog('info', data.rsp[0]);
- }
- });
- $(this).dialog("close");
- },
- "Cancel": function(){
- $(this).dialog("close");
- }
- };
- } else {
- status = $('Enabled ').css('padding', '0px 5px');
- statusArea.append(status);
-
- // Create disable and cancel buttons
- buttons = {
- "Disable": function(){
- // Disable xCAT monitor
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'monstop',
- tgt : '',
- args : 'xcatmon',
- msg : ''
- },
-
- success : function(data){
- openDialog('info', data.rsp[0]);
- }
- });
- $(this).dialog("close");
- },
- "Cancel": function(){
- $(this).dialog("close");
- }
- };
- }
-
- dialog.append(statusArea);
-
- // Open dialog
- dialog.dialog({
- modal: true,
- width: 500,
- buttons: buttons
- });
-}
-
-/**
- * Show chdef output
- *
- * @param data Data returned from HTTP request
- */
-function showChdefOutput(data) {
- // Get output
- var out = data.rsp;
- var args = data.msg.split(';');
- var tabID = args[0].replace('out=', '');
- var tgt = args[1].replace('tgt=', '');
-
- // Find info bar on nodes tab, if any
- var info = $('#' + tabID).find('.ui-state-highlight');
- if (!info.length) {
- // Create info bar if one does not exist
- info = createInfoBar('');
- $('#' + tabID).append(info);
- }
-
- // Go through output and append to paragraph
- var prg = $('
');
- for (var i in out) {
- prg.append(tgt + ': ' + out[i] + ' ');
- }
-
- info.append(prg);
-}
-
-/**
- * Set node attributes
- *
- * @param data Data returned from HTTP request
- */
-function setNodeAttrs(data) {
- // Clear hash table containing definable node attributes
- nodeAttrs = 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));
-
- // Remove arrow brackets
- descr = descr.replace(new RegExp('<|>', 'g'), '');
-
- // Set hash table where key = attribute name and value = description
- nodeAttrs[key] = descr;
- } else {
- // Remove arrow brackets
- attr = attr.replace(new RegExp('<|>', 'g'), '');
-
- // Append description to hash table
- nodeAttrs[key] = nodeAttrs[key] + '\n' + attr;
- }
- } // End of if
- } // End of for
-}
-
-
-/**
- * Load the discover z/VM virtual systems page
- *
- * @param tgtNode Target node to set properties
- */
-function discoverVMNodes(tgtNodes) {
- var fs, legend, htmlLine;
-
- // Get nodes tab
- var tab = getNodesTab();
-
- // Generate new tab ID
- var inst = 0;
- var newTabId = 'discoverVMNodesTab' + inst;
- while ($('#' + newTabId).length) {
- // If one already exists, generate another one
- inst = inst + 1;
- newTabId = 'discoverVMNodesTab' + inst;
- }
-
- // Open new tab
- // Create set properties form
- var discoverVMNodesForm = $('
');
-
- // Create info bar
- var infoBar = createInfoBar( 'Initiate, stop or query the status of z/VM node discovery. ' +
- 'To initiate discovery, specify discovery parameters and click on the Discover button. ' +
- 'To stop an on-going discovery related to a z/VM host, specify the host node name and '+
- 'click on the Stop button. ' +
- 'To obtain the status of discovery for a particular host, specify the host node name and '+
- 'click on the Stop button.'
- );
- discoverVMNodesForm.append(infoBar);
-
- // Create the status bar and hide it.
- var statBarId = 'statusBar_' + newTabId;
- //var statBar = $( '
' );
- //discoverVMNodesForm.append( statBar );
- statBar = createStatusBar( statBarId );
- statBar.hide();
- discoverVMNodesForm.append( statBar );
-
- // Create Host fieldset
- fs = $(' ');
- legend = $('z/VM Host ');
- fs.append(legend);
- discoverVMNodesForm.append(fs);
-
- // Target node or group
- htmlLine = $('z/VM host range:
');
- discoverVMNodesForm.append( htmlLine );
-
- // Create Discovery Parameters fieldset
- fs = $(' ');
- legend = $('Discovery Parameters ');
- fs.append( legend );
- discoverVMNodesForm.append( fs );
-
- // Create an input for each definable attribute
- var div, label, input, descr, value;
-
- // Define DefineTo radio buttons
- div = $('
').css( 'display', 'inline-block' ).css( 'vertical-align', 'top' );
- div.append( 'Define systems to: ' );
- div.append( ' xCAT and OpenStack ' );
- div.append( ' xCAT only ' );
- div.append( ' OpenStack only (only already discovered xCAT nodes) ' );
- discoverVMNodesForm.append( div );
- discoverVMNodesForm.append( ' ' );
-
- // Userid filter
- divUserid = newTabId + "_divUserid";
- div = $('
').css( 'display', 'inline-table' ).css( 'vertical-align', 'top' );
- div.append( 'z/VM Userid Filter: ' );
- div.append( ' ' ).css( 'margin-top', '5px' );
- discoverVMNodesForm.append( div );
- discoverVMNodesForm.append( ' ' );
-
- // IP address filter
- divIP = newTabId + "_divIP";
- div = $('
').css( 'display', 'inline-table' ).css( 'vertical-align', 'top' );
- div.append( 'IP Address Filter: ' );
- div.append( ' ' ).css( 'margin-top', '5px' );
- discoverVMNodesForm.append( div );
- discoverVMNodesForm.append( ' ' );
-
- // Group name input
- divGroup = newTabId + '_divGroup';
- div = $('
').css( 'display', 'inline-table' ).css( 'vertical-align', 'top' );
- div.append( 'Assign to group(s): ' );
- div.append( ' ' ).css( 'margin-top', '5px' );
- discoverVMNodesForm.append( div );
- discoverVMNodesForm.append( ' ' );
-
- // Node Name Format input
- divNodename = newTabId + '_divNodename';
- div = $('
').css( 'display', 'inline-table' ).css( 'vertical-align', 'top' );
- div.append( 'xCAT node name format: ' );
- div.append( ' ' ).css( 'margin-top', '5px' );
- discoverVMNodesForm.append( div );
- discoverVMNodesForm.append( ' ' );
- discoverVMNodesForm.find('#' + divNodename).hide();
-
- // OpenStack operand input
- divOpenStackOps = newTabId + '_divOpenStackOps';
- div = $('
').css( 'display', 'inline-table' ).css( 'vertical-align', 'top' );
- div.append( 'Assign to OpenStack Project: ' );
- div.append( ' ' ).css( 'margin-top', '5px' );
- div.append( ' ' );
- div.append( 'Assign to OpenStack User: ' );
- div.append( ' ' ).css( 'margin-top', '5px' );
- discoverVMNodesForm.append( div );
- discoverVMNodesForm.append( ' ' );
-
- // Define Verbose radio buttons
- div = $('
').css( 'display', 'inline-table' ).css( 'vertical-align', 'top' ).css( 'text-align', 'top' );
- div.append( 'Node discovery output: ' );
- div.append( ' Normal response, showing only important information ' );
- div.append( ' Verbose response, normal response plus additional information (e.g. reason a system is ignored) ' );
- discoverVMNodesForm.append( div );
- discoverVMNodesForm.append( ' ' );
-
- // Generate tooltips
- discoverVMNodesForm.find('div input[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"
- }
- });
-
- // Show appropriate input fields for defineto choices.
- discoverVMNodesForm.change(function(){
- var defineTo = $(this).parent().find('input[name="defineTo"]:checked').val();
- if ( defineTo == 'both' ) {
- discoverVMNodesForm.find('#' + divUserid).show();
- discoverVMNodesForm.find('#' + divIP).show();
- discoverVMNodesForm.find('#' + divGroup).show();
- discoverVMNodesForm.find('#' + divOpenStackOps).show();
- discoverVMNodesForm.find('#' + divNodename).hide();
- } else if ( defineTo == 'xcatonly' ) {
- discoverVMNodesForm.find('#' + divUserid).show();
- discoverVMNodesForm.find('#' + divIP).show();
- discoverVMNodesForm.find('#' + divGroup).show();
- discoverVMNodesForm.find('#' + divOpenStackOps).hide();
- discoverVMNodesForm.find('#' + divNodename).show();
- } else if ( defineTo == 'openstackonly' ) {
- discoverVMNodesForm.find('#' + divUserid).hide();
- discoverVMNodesForm.find('#' + divIP).hide();
- discoverVMNodesForm.find('#' + divGroup).hide();
- discoverVMNodesForm.find('#' + divOpenStackOps).show();
- discoverVMNodesForm.find('#' + divNodename).hide();
- }
- });
-
-
- // Discover nodes button action
- var discoverBtn = createButton('Discover');
- discoverBtn.click(function() {
- var argList = '';
- var filter = '';
-
- var hosts = $(this).parent().find('input[name=hosts]').val();
- if ( hosts != '' ) {
- argList = 'zvmhost=' + hosts;
- }
-
- var defineTo = $(this).parent().find('input[name="defineTo"]:checked').val();
- argList = argList + '||defineto=' + defineTo;
-
- var verbose = $(this).parent().find('input[name="verbose"]:checked').val();
- if ( verbose == 'yes' ) {
- argList = argList + '||--verbose';
- }
-
- var useridFilter = $(this).parent().find('input[name=useridFilter]').val();
- if (( defineTo == 'both' || defineTo == 'xcatonly' ) && ( useridFilter != '' )) {
- argList = argList + '||useridfilter=' + useridFilter;
- }
-
- var ipFilter = $(this).parent().find('input[name=ipFilter]').val();
- if (( defineTo == 'both' || defineTo == 'xcatonly' ) && ( ipFilter != '' )) {
- argList = argList + '||ipfilter=' + ipFilter;
- }
-
- var group = $(this).parent().find('input[name=group]').val();
- if (( defineTo == 'both' || defineTo == 'xcatonly' ) && ( group != '' )) {
- argList = argList + '||groups=' + group;
- }
-
- var nodeNameFmt = $(this).parent().find('input[name=nodeNameFmt]').val();
- if ( defineTo == 'xcatonly' && nodeNameFmt != '' ) {
- argList = argList + '||nodenameformat=' + nodeNameFmt;
- }
-
- var openStackProj = $(this).parent().find('input[name=openStackProj]').val();
- var openStackUser = $(this).parent().find('input[name=openStackUser]').val();
- if ((( defineTo == 'both' ) || ( defineTo == 'openstackonly' )) &&
- (( openStackProj != '' ) || ( openStackUser != '' ))) {
- if ( openStackProj != '' ) {
- osArgs = '--project ' + openStackProj;
- } else {
- osArgs = '';
- }
- if ( openStackUser != '' ) {
- if ( osArgs != '' ) {
- osArgs = osArgs + ' --user ' + openStackUser;
- } else {
- osArgs = '--user ' + openStackUser;
- }
- }
- argList = argList + "||openstackoperands='" + osArgs + "'";
- }
-
- var out = $('
');
- out.append( 'Starting node discovery...' );
- out.append( ' ' );
- out.append( 'If node discovery is a short running task then its response will follow. If, however, the time it takes to complete discovery exceeds the http request timeout of a few minutes then the discovery response will not be returned to the browser. The status and list buttons can be used to obtained status on the discovery and see what systems have been discovered.' );
- $( '#' + statBarId ).find( 'div' ).append( out );
- statBar.show();
-
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'nodediscoverstart',
- tgt : '',
- args : argList,
- att : '',
- msg : statBarId
- },
- success: function(data) {
- updateDiscoverStatusBar( data, 1 );
- }
- });
-
- });
- discoverVMNodesForm.append(discoverBtn);
-
- // Status button
- var statusBtn = createButton('Status');
- statusBtn.click( function() {
- var hosts = $(this).parent().find('input[name=hosts]').val();
- var out = $('
');
- out.append( 'Querying status for discovery on ' + hosts + '...' );
- out.append( ' ' );
- $( '#' + statBarId ).find( 'div' ).append( out );
-
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'nodediscoverstatus',
- tgt : '',
- args : '--zvmhost||' + hosts,
- att : '',
- msg : statBarId
- },
- success: function(data) {
- updateDiscoverStatusBar( data, 1 );
- }
- });
-
- });
- discoverVMNodesForm.append( statusBtn );
-
- // List button
- var listBtn = createButton('List');
- listBtn.click( function() {
- var hosts = $(this).parent().find('input[name=hosts]').val();
- var out = $('
');
- out.append( 'Listing systems discovered by the latest discovery on ' + hosts + '...' );
- out.append( ' ' );
- $( '#' + statBarId ).find( 'div' ).append( out );
-
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'nodediscoverls',
- tgt : '',
- args : '-t||zvm||--zvmhost||' + hosts,
- att : '',
- msg : statBarId
- },
- success: function(data) {
- updateDiscoverStatusBar( data, 1 );
- }
- });
- });
- discoverVMNodesForm.append( listBtn );
-
- // Stop button
- var stopBtn = createButton('Stop');
- stopBtn.click(function() {
- var hosts = $(this).parent().find('input[name=hosts]').val();
- var out = $('
');
- out.append( 'Stopping discovery on ' + hosts + '...' );
- out.append( ' ' );
- $( '#' + statBarId ).find( 'div' ).append( out );
-
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'nodediscoverstop',
- tgt : '',
- args : '--zvmhost||' + hosts,
- att : '',
- msg : statBarId
- },
- success: function(data) {
- updateDiscoverStatusBar( data, 1 );
- }
- });
- });
- discoverVMNodesForm.append( stopBtn );
-
- // Append to discover tab
- tab.add(newTabId, 'Discover', discoverVMNodesForm, true);
-
- // Select new tab
- tab.select(newTabId);
-}
-
-
-/**
- * Update discovery status bar
- *
- * @param data Data returned from HTTP request
- */
-function updateDiscoverStatusBar( data, preformatted ) {
- var statBarId = data.msg;
- var rsp = data.rsp;
- var statBar = $( '#' + statBarId );
-
- // Go through response to make it readable in the status bar.
- var out = $('
');
- for ( var i in rsp ) {
- if ( preformatted == 1 ) {
- out.append( '' + rsp[i] + ' ' );
- } else {
- out.append( rsp[i] + ' ' );
- }
- }
-
- // Write response to status bar and show the bar.
- $( '#' + statBarId ).find( 'div' ).append( out );
- statBar.show();
-}
-
-/**
- * Load set node properties page
- *
- * @param tgtNode Target node to set properties
- */
-function editNodeProps(tgtNode) {
- // Get nodes tab
- var tab = getNodesTab();
-
- // Generate new tab ID
- var inst = 0;
- var newTabId = 'editPropsTab' + inst;
- while ($('#' + newTabId).length) {
- // If one already exists, generate another one
- inst = inst + 1;
- newTabId = 'editPropsTab' + inst;
- }
-
- // Open new tab
- // Create set properties form
- var editPropsForm = $('
');
-
- // Create info bar
- var infoBar = createInfoBar('Choose the properties you wish to change on the node. When you are finished, click Save.');
- editPropsForm.append(infoBar);
-
- // Create an input for each definable attribute
- var div, label, input, descr, value;
- // Set node attribute
- origAttrs[tgtNode]['node'] = tgtNode;
- for (var key in nodeAttrs) {
- // If an attribute value exists
- if (origAttrs[tgtNode][key]) {
- // Set the value
- value = origAttrs[tgtNode][key];
- } else {
- value = '';
- }
-
- // Create label and input for attribute
- div = $('
').css('display', 'inline-table');
- label = $('' + key + ': ').css('vertical-align', 'middle');
- input = $(' ').css('margin-top', '5px');
-
- // Change border to blue onchange
- input.bind('change', function(event) {
- $(this).css('border-color', 'blue');
- });
-
- div.append(label);
- div.append(input);
- editPropsForm.append(div);
- }
-
- // Change style for last division
- div.css({
- 'display': 'block',
- 'margin': '0px 0px 10px 0px'
- });
-
- // Generate tooltips
- editPropsForm.find('div input[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"
- }
- });
-
- // Save changes
- var saveBtn = createButton('Save');
- saveBtn.click(function() {
- // 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 node attributes
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'chdef',
- tgt : '',
- args : '-t;node;-o;' + tgtNode + ';' + args,
- msg : 'out=' + newTabId + ';tgt=' + tgtNode
- },
-
- success: showChdefOutput
- });
- });
- editPropsForm.append(saveBtn);
-
- // Cancel changes
- var cancelBtn = createButton('Cancel');
- cancelBtn.click(function() {
- // Close the tab
- tab.remove($(this).parent().parent().attr('id'));
- });
- editPropsForm.append(cancelBtn);
-
- // Append to discover tab
- tab.add(newTabId, 'Edit', editPropsForm, true);
-
- // Select new tab
- tab.select(newTabId);
-}
-
-/**
- * Open set node attributes dialog
- */
-function openSetAttrsDialog() {
- // Open new tab
- // Create set properties form
- var setPropsForm = $('
');
-
- // 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, descr, value;
- for (var key in nodeAttrs) {
- value = '';
-
- // Create label and input for attribute
- div = $('
').css('display', 'inline');
- label = $('' + key + ': ').css('vertical-align', 'middle');
- input = $(' ').css('margin-top', '5px');
-
- // Change border to blue onchange
- input.bind('change', function(event) {
- $(this).css('border-color', 'blue');
- });
-
- div.append(label);
- div.append(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: 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());
- }
- });
-
- // Enable vertical scroll
- setPropsForm.css('overflow', 'auto');
-
- // Open form as a dialog
- setPropsForm.dialog({
- title: 'Set attributes',
- modal: true,
- close: function(){
- $(this).remove();
- },
- height: 400,
- width: 800,
- buttons: {
- "Save": function() {
- // Remove any warning messages
- $(this).find('.ui-state-error').remove();
-
- // Get all inputs
- var inputs = $(this).find('input');
-
- // Go through each input
- var args = '';
- var tgtNode, 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();
-
- // Get node name
- if (attrName == 'node') {
- tgtNode = attrVal;
- } else {
- // Build argument string
- if (args) {
- // Handle subsequent arguments
- args += ';' + attrName + '=' + attrVal;
- } else {
- // Handle the 1st argument
- args += attrName + '=' + attrVal;
- }
- }
- }
- });
-
- // Send command to change node attributes
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'chdef',
- tgt : '',
- args : '-t;node;-o;' + tgtNode + ';' + args,
- msg : 'node=' + tgtNode
- },
-
- /**
- * Show results
- *
- * @param data
- * Data returned from HTTP request
- * @return Nothing
- */
- success: function(data) {
- // Get output
- var out = data.rsp;
- var node = data.msg.replace('node=', '');
-
- // Go through output and append to paragraph
- var msg = '';
- for (var i in out) {
- if (!msg) {
- msg = node + ': ' + out[i];
- } else {
- msg += ' ' + node + ': ' + out[i];
- }
- }
-
- openDialog('info', msg);
- }
- });
-
- // Close dialog
- $(this).dialog( "close" );
- },
- "Cancel": function(){
- $(this).dialog( "close" );
- }
- }
- });
-}
-
-/**
- * Turn on monitoring for a given node
- *
- * @param node Node to monitor on or off
- * @param monitor Monitor state, on or off
- */
-function monitorNode(node, monitor) {
- // Show ganglia loader
- var gangliaCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)');
- gangliaCol.find('img').show();
-
- if (monitor == 'on') {
- // Append loader to warning bar
- var warningBar = $('#nodesTab').find('.ui-state-error p');
- if (warningBar.length) {
- warningBar.append(createLoader(''));
- }
-
- if (node) {
- // Check if ganglia RPMs are installed
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'gangliacheck;' + node,
- msg : node // Node range will be passed along in data.msg
- },
-
- /**
- * Start ganglia on a given node range
- *
- * @param data Data returned from HTTP request
- */
- success : function(data) {
- // Get response
- var out = data.rsp[0].split(/\n/);
-
- // Go through each line
- var warn = false;
- var warningMsg = '';
- for (var i in out) {
- // If an RPM is not installed
- if (out[i].indexOf('not installed') > -1) {
- warn = true;
-
- if (warningMsg) {
- warningMsg += ' ' + out[i];
- } else {
- warningMsg = out[i];
- }
- }
- }
-
- // If there are warnings
- if (warn) {
- // Create warning bar
- var warningBar = createWarnBar(warningMsg);
- warningBar.css('margin-bottom', '10px');
- warningBar.prependTo($('#nodesTab'));
- } else {
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'gangliastart;' + data.msg + ';-r',
- msg : data.msg
- },
-
- success : function(data) {
- // Remove any warnings
- $('#nodesTab').find('.ui-state-error').remove();
-
- // Update datatable
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'gangliastatus;' + data.msg,
- msg : ''
- },
-
- success : loadGangliaStatus
- });
- }
- });
- } // End of if (warn)
- } // End of function(data)
- });
- } else {
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'gangliastart',
- msg : ''
- },
-
- success : function(data) {
- // Remove any warnings
- $('#nodesTab').find('.ui-state-error').remove();
- }
- });
- } // End of if (node)
- } else {
- var args;
- if (node) {
- args = 'gangliastop;' + node + ';-r';
- } else {
- args = 'gangliastop';
- }
-
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : args,
- msg : ''
- },
-
- success : function(data) {
- // Hide ganglia loader
- var gangliaCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)');
- gangliaCol.find('img').hide();
- }
- });
- }
-}
-
-/**
- * Install Ganglia on a given node
- *
- * @param node Node to install Ganglia on
- */
-function installGanglia(node) {
- var iframe = createIFrame('lib/cmd.php?cmd=webrun&tgt=&args=installganglia;' + node + '&msg=' + node + '&opts=flush');
- iframe.prependTo($('#nodesTab'));
-
- // Turn on Ganglia for node
- monitorNode(node, 'on');
-}
-
-/**
- * After nodes are loaded, load more information based on different hardware architectures
- *
- * @param group Group name
- */
-function advancedLoad(group){
- var tempIndex = 0;
- var tableHeaders = $('#' + nodesTableId).parents('.dataTables_scroll').find('.dataTables_scrollHead thead tr:eq(0) th');
- var colNameHash = new Object();
- var colName = '';
- var archCol = 0, hcpCol = 0;
-
- // Find out the column name and their index
- for (tempIndex = 0; tempIndex < tableHeaders.size(); tempIndex++){
- var header = tableHeaders.eq(tempIndex);
- // Skip headers that are links, e.g. status, power, and monitor
- if (header.find('a').size() > 0){
- continue;
- }
-
- colName = header.text();
-
- if (colName) {
- colNameHash[colName] = tempIndex;
- }
- }
-
- // If there is no arch column, exit because you cannot distinguish hardware type
- if (!colNameHash['arch']) {
- return;
- }
-
- if (!colNameHash['hcp']) {
- return;
- }
- archCol = colNameHash['arch'];
- hcpCol = colNameHash['hcp'];
-
- // Get hardware control point
- var rows = $('#' + nodesTableId + ' tbody tr');
- var hcps = new Object();
- var rowsNum = rows.size();
- for (var j = 0; j < rowsNum; j++) {
- var val = rows.eq(j).find('td').eq(hcpCol).html();
- var archval = rows.eq(j).find('td').eq(archCol).html();
- if (-1 == archval.indexOf('390')){
- continue;
- }
- hcps[val] = 1;
- }
-
- if (Object.keys(hcps).length == 0) {
- openDialog('warn', "No node found with hcp column filled in and 390 arch!");
- return;
- }
- // Get Nodes info bar
- //var nodeInfoBar = getNodesTabInfoBar();
- //nodeInfoBar.append("\nEntering Advanced Load...\n")
-
- var args;
- var shortzHcps = new Array();
- var zhcpHash = new Object();
- for (var h in hcps) {
- // Get node without domain name
- args = h.split('.');
-
- if (!zhcpHash[args[0]]) {
-
- shortzHcps.push(args[0]);
- zhcpHash[args[0]] = 1;
-
- // If there are no disk pools or network names cookie for this hcp
- if (!$.cookie('xcat_' + args[0] + 'diskpools') || !$.cookie('xcat_' + args[0] + 'networks')) {
- // Check if SMAPI is online
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'lsvm',
- tgt : args[0],
- args : '',
- msg : 'group=' + group + ';hcp=' + args[0]
- },
-
- // Load hardware control point specific info
- // Get disk pools and network names
- success : loadHcpInfo
- });
- }
- }
- } // End of for
-
- // Save zHCPs as a cookie
- setzHcpCookies(shortzHcps);
-
- // Retrieve z/VM hypervisors and their zHCPs
- if (!$.cookie('xcat_zvms')) {
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webportal',
- tgt : '',
- args : 'lszvm',
- msg : ''
- },
-
- success : function(data) {
- setzVMCookies(data);
- }
- });
- }
-}
-
-/**
- * Jump to provision page on-click
- *
- * @param tgtNodes Target nodes
- */
-function jump2Provision(tgtNodes){
- var nodeArray = tgtNodes.split(',');
- var nodeName = '';
- var index = 0;
- var archType = '';
- var errorMsg = '';
- var master = '';
- var tftpserver = '';
- var nfsserver = '';
- var diaDiv = $('
');
-
- // Check the first node's arch type
- for (index in nodeArray){
- nodeName = nodeArray[index];
-
- // Skip if node does not have arch
- if (!origAttrs[nodeName]['arch']){
- errorMsg = 'Nodes should have arch defined! ';
- break;
- }
-
- if (index == 0) {
- archType = origAttrs[nodeName]['arch'];
- }
-
- // Skip if nodes do not have same arch
- if (archType != origAttrs[nodeName]['arch']){
- errorMsg = 'Nodes should belong to the same arch! ';
- break;
- }
- }
-
- // Skip if nodes do not have MAC address
- for (index in nodeArray){
- if (!origAttrs[nodeName]['mac'] || !origAttrs[nodeName]['ip']){
- errorMsg += 'Nodes should have the IP and MAC addresses defined! ';
- break;
- }
- }
-
- if (archType.indexOf('390') != -1) {
- errorMsg += 'Please use the provision page';
- }
-
- // Open dialog to show error message
- if (errorMsg){
- diaDiv.append(createWarnBar(errorMsg));
- diaDiv.dialog({
- modal: true,
- close: function(){
- $(this).remove();
- },
- width: 400,
- buttons: {
- 'Close': function(){
- $(this).dialog('destroy');
- }
- }
- });
-
- return;
- }
-
- if (origAttrs[nodeName]['xcatmaster']) {
- master = origAttrs[nodeName]['xcatmaster'];
- }
-
- if (origAttrs[nodeName]['tftpserver']) {
- tftpserver = origAttrs[nodeName]['tftpserver'];
- }
-
- if (origAttrs[nodeName]['nfsserver']) {
- nfsserver = origAttrs[nodeName]['nfsserver'];
- }
-
- window.location.href = 'provision.php?nodes=' + tgtNodes + '&arch=' + archType + '&master=' + master +
- '&tftpserver=' + tftpserver + '&nfsserver=' + nfsserver;
-}
\ No newline at end of file
+/**
+ * Global variables
+ *Test Git update in MCP_DEV branch */
+var nodesTab; // Nodes tabs
+var origAttrs = new Object(); // Original node attributes
+var nodeAttrs; // Node attributes
+var nodesList; // Node list
+var nodesTableId = 'nodesDatatable'; // Nodes datatable ID
+var nodesTabInfoBar;
+var builtInXCAT = 1; // 1 means xCAT shipped with zVM
+
+/**
+ * Set node tab
+ *
+ * @param tab
+ * Tab object
+ * @return Nothing
+ */
+function setNodesTab(tab) {
+ nodesTab = tab;
+}
+
+/**
+ * Get node tab
+ *
+ * @return Tab object
+ */
+function getNodesTab() {
+ return nodesTab;
+}
+
+/**
+ * Set node tab info bar. Used by zvmUtils.js
+ *
+ * @param tab
+ * infobar object
+ * @return Nothing
+ */
+function setNodesTabInfoBar(tabinfo) {
+ nodesTabInfoBar = tabinfo;
+}
+
+/**
+ * Get node tab info bar
+ *
+ * @return Tab info bar object
+ */
+function getNodesTabInfoBar() {
+ return nodesTabInfoBar;
+}
+
+/**
+ * Get node list
+ *
+ * @return Node list
+ */
+function getNodesList() {
+ return nodesList;
+}
+
+/**
+ * Get nodes table ID
+ *
+ * @return Nodes table ID
+ */
+function getNodesTableId() {
+ return nodesTableId;
+}
+
+/**
+ * Load nodes page
+ */
+function loadNodesPage() {
+ // If groups are not already loaded
+ if (!$('#groups').length) {
+ // Create a groups division
+ var groups = $('
');
+ var nodes = $('
');
+ $('#content').append(groups);
+ $('#content').append(nodes);
+
+ // Create loader and info bar
+ groups.append(createLoader());
+
+ // Get groups
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'extnoderange',
+ tgt : '/.*',
+ args : 'subgroups',
+ msg : ''
+ },
+
+ // Load groups
+ success : function(data){
+ data = decodeRsp(data);
+ loadGroups(data);
+
+ var cookieGroup = $.cookie('xcat_selectgrouponnodes');
+ if (cookieGroup) {
+ $('#groups .groupdiv div').each(function(){
+ if ($(this).text() == cookieGroup){
+ $(this).trigger('click');
+ return false;
+ }
+ });
+ } else {
+ // Trigger the first group click event
+ $('#groups .groupdiv div').eq(0).trigger('click');
+ }
+ }
+ });
+ }
+}
+
+/**
+ * Show cluster summary in pie charts
+ *
+ * @param groupName Group name
+ */
+function loadPieSummary(groupName){
+ var summaryTable = '' +
+ '' +
+ '
' +
+ '
' +
+ '
' +
+ ' ' +
+ '' +
+ '
' +
+ '
' +
+ '
';
+ $('#summaryTab').append(summaryTable);
+ $('#summaryTab .summarypie').append(createLoader());
+
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'summary;' + groupName,
+ msg : ''
+ },
+
+ success:function(data) {
+ data = decodeRsp(data);
+ for (var i in data.rsp) {
+ drawPieSummary(i, data.rsp[i]);
+ }
+ }
+ });
+}
+
+/**
+ * Get nodes information and draw pie chart
+ *
+ * @param index Node index
+ * @param valuePair Node information key value pairing
+ */
+function drawPieSummary(index, valuePair){
+ var position = 0;
+ var key = '';
+ var val = '';
+ var chartTitle = '';
+ var dataArray = [];
+ var tempArray = [];
+ var container = $('#summaryTab .summarypie').eq(index);
+
+ position = valuePair.indexOf('=');
+ chartTitle = valuePair.substr(0, position);
+ tempArray = valuePair.substr(position + 1).split(';');
+
+ for (var i in tempArray) {
+ position = tempArray[i].indexOf(':');
+ key = tempArray[i].substr(0, position);
+ val = Number(tempArray[i].substr(position + 1));
+ dataArray.push([key,val]);
+ }
+
+ container.empty();
+
+ var plot = $.jqplot(container.attr('id'), [dataArray], {
+ title: chartTitle,
+ seriesDefaults: {
+ renderer: $.jqplot.PieRenderer,
+ rendererOptions: {
+ padding: 5,
+ fill: true,
+ shadow: true,
+ shadowOffset: 2,
+ shadowDepth: 5,
+ shadowAlpha: 0.07,
+ dataLabels : 'value',
+ showDataLabels: true
+ }
+ },
+ legend: {
+ show:true,
+ location: 'e'
+ }
+ });
+}
+
+/**
+ * Load groups
+ *
+ * @param data Data returned from HTTP request
+ */
+function loadGroups(data) {
+ // Remove loader
+ $('#groups').find('img').remove();
+
+ // Save group in cookie
+ var groups = data.rsp;
+ setGroupsCookies(data);
+
+ // Create a list of groups
+ $('#groups').append('Groups
');
+ var grouplist= $('
');
+ // Create a link for each group
+ for (var i = 0; i < groups.length; i++) {
+ grouplist.append('' + groups[i] + '
');
+ }
+
+ $('#groups').append(grouplist);
+
+ // Bind the click event
+ $('#groups .groupdiv div').bind('click', function(){
+ var thisGroup = $(this).text();
+ $('#groups .groupdiv div').removeClass('selectgroup');
+ $(this).addClass('selectgroup');
+
+ // Save selected group into cookie
+ $.cookie('xcat_selectgrouponnodes', thisGroup, { expires: 7, path: '/xcat', secure:true });
+
+ drawNodesArea(thisGroup,'',thisGroup);
+ });
+
+ // Make a link to add nodes
+ $('#groups').append('
');
+ $('#groups #adddiv').append(mkAddNodeLink());
+}
+
+/**
+ * Empty the nodes area and add three tabs for nodes result
+ *
+ * @param targetgroup The name range for nodels command
+ * @param cmdargs Filter arguments for nodels command
+ * @param message The useful information from the HTTP request
+ */
+function drawNodesArea(targetgroup, cmdargs, message){
+ // Clear nodes division
+ $('#nodes').empty();
+
+ // Create a tab for this group
+ var tab = new Tab('nodesPageTabs');
+ setNodesTab(tab);
+ tab.init();
+ $('#nodes').append(tab.object());
+ tab.add('summaryTab', 'Summary', '', false);
+ tab.add('nodesTab', 'Nodes', '', false);
+ if (builtInXCAT == 0) {
+ tab.add('graphTab', 'Graphic', '', false);
+ }
+
+ // Load nodes table when tab is selected
+ $('#nodesPageTabs').bind('tabsselect', function(event, ui) {
+ // Load summary when tab is selected
+ if (!$('#summaryTab').children().length && ui.index == 0) {
+ loadPieSummary(targetgroup);
+ }
+
+ // Load nodes table when tab is selected
+ else if (!$('#nodesTab').children().length && ui.index == 1) {
+ // Create loader
+ $('#nodesTab').append($(' ').append(createLoader()));
+
+ // To improve performance, get all nodes within selected group
+ // Get node definitions only for first 50 nodes
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'nodels',
+ tgt : targetgroup,
+ args : cmdargs,
+ msg : message
+ },
+
+ /**
+ * Get node definitions for first 50 nodes
+ *
+ * @param data Data returned from HTTP request
+ */
+ success : function(data) {
+ data = decodeRsp(data);
+ var rsp = data.rsp;
+ var group = data.msg;
+
+ // Save nodes in a list so it can be accessed later
+ nodesList = new Array();
+ for (var i in rsp) {
+ if (rsp[i][0]) {
+ nodesList.push(rsp[i][0]);
+ }
+ }
+
+ // Sort nodes list
+ nodesList.sort();
+
+ // Get first 50 nodes
+ var nodes = '';
+ for (var i = 0; i < nodesList.length; i++) {
+ if (i > 49) {
+ break;
+ }
+
+ nodes += nodesList[i] + ',';
+ }
+
+ // Remove last comma
+ nodes = nodes.substring(0, nodes.length-1);
+
+ // Get nodes definitions
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'lsdef',
+ tgt : '',
+ args : nodes,
+ msg : targetgroup
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ loadNodes(data);
+ }
+ });
+
+ }
+ });
+ }
+
+ // Load graphical layout when tab is selected
+ else if ((builtInXCAT == 0) && (!$('#graphTab').children().length && ui.index == 2)) {
+ // For the graphical tab, check the graphical data first
+ createPhysicalLayout(nodesList);
+ }
+
+ });
+
+ // Get last view (if any)
+ // This can be summary, nodes, or graphic
+ if ($.cookie('xcat_tabindex_history')) {
+ var order = $.cookie('xcat_tabindex_history').split(',');
+ order[0] = parseInt(order[0]);
+ order[1] = parseInt(order[1]);
+ if (order[0] == 0 || order[1] == 0) {
+ // For some reason, you cannot trigger a select of index 0
+ loadPieSummary(targetgroup);
+ } else if (order[0] == 1 || order[0] == 2) {
+ $('#nodesPageTabs').tabs('select', order[0]);
+ } else if (order[1] == 1 || order[1] == 2) {
+ $('#nodesPageTabs').tabs('select', order[1]);
+ } else {
+ loadPieSummary(targetgroup);
+ }
+ } else {
+ loadPieSummary(targetgroup);
+ }
+}
+
+/**
+ * Make a link to add nodes
+ *
+ * @returns Link to add nodes
+ */
+function mkAddNodeLink() {
+ // Create link to add nodes
+ var addNodeLink = $('+ Add node ');
+ addNodeLink.click(function() {
+ // Create info bar
+ var info = createInfoBar('Select the hardware management for the new node range');
+
+ // Create form to add node
+ var addNodeForm = $('
');
+ addNodeForm.append(info);
+ if (builtInXCAT == 0) {
+ addNodeForm.append('Hardware management: '
+ + ''
+ + 'ESX '
+ + 'KVM '
+ + 'z\/VM '
+ + 'iDataPlex '
+ + 'BladeCenter '
+ + 'System p ' // Documentation refers to 'IBM System p' (where p is NOT capitalized)
+ + ' '
+ + '
');
+ } else {
+ addNodeForm.append('Hardware management: '
+ + ''
+ + 'z\/VM '
+ + ' '
+ + '
');
+ }
+
+ // Create advanced link to set advanced node properties
+ var advanced = $('
');
+ var advancedLnk = $('Advanced ').css({
+ 'cursor': 'pointer',
+ 'color': '#0000FF'
+ });
+ advancedLnk.click(function() {
+ // Get node attributes
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'lsdef',
+ tgt : '',
+ args : '-t;node;-h',
+ msg : ''
+ },
+
+ /**
+ * Set node attributes and open dialog
+ *
+ * @param data Data returned from HTTP request
+ */
+ success : function(data) {
+ data = decodeRsp(data);
+ // Save node attributes
+ setNodeAttrs(data);
+ // Open a dialog to set node attributes
+ openSetAttrsDialog();
+ }
+ });
+
+ // Close dialog
+ addNodeForm.dialog('destroy').remove();
+ });
+ advanced.append(advancedLnk);
+ addNodeForm.append(advanced);
+
+ // Open dialog to add node
+ addNodeForm.dialog({
+ modal: true,
+ width: 400,
+ title:'Add node',
+ close: function() {$(this).remove();},
+ buttons: {
+ 'Ok': function() {
+ // Get hardware management
+ var mgt = $(this).find('select[name=mgt]').val();
+
+ var plugin;
+ switch(mgt) {
+ case "kvm":
+ plugin = new kvmPlugin();
+ break;
+ case "esx":
+ plugin = new esxPlugin();
+ break;
+ case "blade":
+ plugin = new bladePlugin();
+ break;
+ case "hmc":
+ plugin = new hmcPlugin();
+ break;
+ case "ipmi":
+ plugin = new ipmiPlugin();
+ break;
+ case "zvm":
+ plugin = new zvmPlugin();
+ break;
+ }
+
+ $(this).dialog('destroy').remove();
+ plugin.addNode();
+ },
+ 'Cancel': function(){
+ $(this).dialog('destroy').remove();
+ }
+ }
+ });
+
+ });
+
+ // Generate tooltips
+ addNodeLink.tooltip({
+ position: 'center right',
+ offset: [-2, 10],
+ effect: 'fade',
+ opacity: 0.7,
+ predelay: 800
+ });
+
+ return addNodeLink;
+}
+
+/**
+ * Load nodes belonging to a given group
+ *
+ * @param data Data returned from HTTP request
+ */
+function loadNodes(data) {
+ // Clear the tab before inserting the table
+ $('#nodesTab').children().remove();
+
+ // Data returned
+ var rsp = data.rsp;
+ // Group name
+ var group = data.msg;
+ // Hash of Node attributes
+ var attrs = new Object();
+ // Node attributes
+ var headers = new Object();
+
+ // Variable to send command and request node status
+ var getNodeStatus = true;
+
+ // Clear hash table containing node attributes
+ origAttrs = '';
+
+ var node, args;
+ for (var i in rsp) {
+ // Get node name
+ if (rsp[i].indexOf('Object name:') > -1) {
+ var temp = rsp[i].split(': ');
+ node = jQuery.trim(temp[1]);
+
+ // Create a hash for the node attributes
+ attrs[node] = new Object();
+ i++;
+ }
+
+ // Get key and value
+ args = rsp[i].split('=', 2);
+ var key = jQuery.trim(args[0]);
+ var val = jQuery.trim(rsp[i].substring(rsp[i].indexOf('=') + 1));
+
+ // Create a hash table
+ attrs[node][key] = val;
+ headers[key] = 1;
+
+ // If node status is available
+ if (key == 'status') {
+ // Do not request node status
+ getNodeStatus = false;
+ }
+ }
+
+ // Add nodes that are not in data returned
+ for (var i in nodesList) {
+ if (!attrs[nodesList[i]]) {
+ // Create attributes list and save node name
+ attrs[nodesList[i]] = new Object();
+ attrs[nodesList[i]]['node'] = nodesList[i];
+ }
+ }
+
+ // Save attributes in hash table
+ origAttrs = attrs;
+
+ // Sort headers
+ var sorted = new Array();
+ for (var key in headers) {
+ // Do not put comments and status in twice
+ if (key != 'usercomment' && key != 'status' && key.indexOf('status') < 0) {
+ sorted.push(key);
+ }
+ }
+ sorted.sort();
+
+ // Add column for check box, node, ping, power, monitor, and comments
+ sorted.unshift(' ',
+ 'node',
+ 'status ',
+ 'power ',
+ 'monitor ',
+ 'comments');
+
+ // Create a datatable
+ var nodesTable = new DataTable(nodesTableId);
+ nodesTable.init(sorted);
+
+ // Go through each node
+ for (var node in attrs) {
+ // Create a row
+ var row = new Array();
+
+ // Create a check box, node link, and get node status
+ var checkBx = ' ';
+ var nodeLink = $('' + node + ' ').bind('click', loadNode);
+
+ // If there is no status attribute for the node, do not try to access hash table
+ // else the code will break
+ var status = '';
+ if (attrs[node]['status']) {
+ status = attrs[node]['status'].replace('sshd', 'ping');
+ }
+
+ // Push in checkbox, node, status, monitor, and power
+ row.push(checkBx, nodeLink, status, '', '');
+
+ // If the node attributes are known (i.e the group is known)
+ if (attrs[node]['groups']) {
+ // Put in comments
+ var comments = attrs[node]['usercomment'];
+ // If no comments exists, show 'No comments' and set icon image source
+ var iconSrc;
+ if (!comments) {
+ comments = 'No comments';
+ iconSrc = 'images/nodes/ui-icon-no-comment.png';
+ } else {
+ iconSrc = 'images/nodes/ui-icon-comment.png';
+ }
+
+ // Create comments icon
+ var tipID = node + 'Tip';
+ var icon = $(' ').css({
+ 'width': '18px',
+ 'height': '18px'
+ });
+
+ // Create tooltip
+ var tip = createCommentsToolTip(comments);
+ var col = $(' ').append(icon);
+ col.append(tip);
+ row.push(col);
+
+ // Generate tooltips
+ icon.tooltip({
+ position: "center right",
+ offset: [-2, 10],
+ effect: "fade",
+ opacity: 0.8,
+ relative: true,
+ delay: 500
+ });
+ } else {
+ // Do not put in comments if attributes are not known
+ row.push('');
+ }
+
+ // Go through each header
+ for (var i = 6; i < sorted.length; i++) {
+ // Add the node attributes to the row
+ var key = sorted[i];
+
+ // Do not put comments and status in twice
+ if (key != 'usercomment' && key != 'status' && key.indexOf('status') < 0) {
+ var val = attrs[node][key];
+ if (val) {
+ row.push(val);
+ } else {
+ row.push('');
+ }
+ }
+ }
+
+ // Add the row to the table
+ nodesTable.add(row);
+ }
+
+ // Clear the tab before inserting the table
+ $('#nodesTab').children().remove();
+
+ // Create info bar for nodes tab
+ var info = createInfoBar('Double-click on a cell to edit a node\'s properties. Click outside the table to save changes. Hit the Escape key to ignore changes.');
+ $('#nodesTab').append(info);
+ info.id = 'NodesInfoBar';
+ setNodesTabInfoBar(info);
+
+ // Create action bar
+ var actionBar = $('
').css("width", "400px");
+
+ /**
+ * Create menu for actions to perform against a given node
+ */
+
+ // Power on
+ var powerOnLnk = $('Power on ');
+ powerOnLnk.click(function() {
+ var tgtNodes = getNodesChecked(nodesTableId);
+ if (tgtNodes) {
+ powerNode(tgtNodes, 'on');
+ }
+ });
+
+ // Power off
+ var powerOffLnk = $('Power off ');
+ powerOffLnk.click(function() {
+ var tgtNodes = getNodesChecked(nodesTableId);
+ if (tgtNodes) {
+
+ var msg = 'Do you want to power off: ' + tgtNodes + '?';
+ // Open dialog to confirm
+ var confirmDialog = $('');
+ confirmDialog.dialog({
+ title:'Confirm',
+ modal: true,
+ close: function(){
+ $(this).remove();
+ },
+ width: 400,
+ buttons: {
+ "Ok": function(){
+ powerNode(tgtNodes, 'off');
+ $(this).dialog("close");
+ },
+ "Cancel": function() {
+ $(this).dialog("close");
+ }
+ }
+ });
+ }
+ });
+
+ // Power softoff
+ var powerSoftoffLnk = $('Shutdown ');
+ powerSoftoffLnk.click(function() {
+ var tgtNodes = getNodesChecked(nodesTableId);
+ if (tgtNodes) {
+ var msg = 'Do you want to shutdown: ' + tgtNodes + '?';
+ // Open dialog to confirm
+ var confirmDialog = $('');
+ confirmDialog.dialog({
+ title:'Confirm',
+ modal: true,
+ close: function(){
+ $(this).remove();
+ },
+ width: 400,
+ buttons: {
+ "Ok": function(){
+ powerNode(tgtNodes, 'softoff');
+ $(this).dialog("close");
+ },
+ "Cancel": function() {
+ $(this).dialog("close");
+ }
+ }
+ });
+ }
+ });
+ if (builtInXCAT == 0) {
+ // Turn monitoring on
+ var monitorOnLnk = $('Monitor on ');
+ monitorOnLnk.click(function() {
+ var tgtNodes = getNodesChecked(nodesTableId);
+ if (tgtNodes) {
+ monitorNode(tgtNodes, 'on');
+ }
+ });
+
+ // Turn monitoring off
+ var monitorOffLnk = $('Monitor off ');
+ monitorOffLnk.click(function() {
+ var tgtNodes = getNodesChecked(nodesTableId);
+ if (tgtNodes) {
+ monitorNode(tgtNodes, 'off');
+ }
+ });
+ }
+
+ // Clone
+ var cloneLnk = $('Clone ');
+ cloneLnk.click(function() {
+ var tgtNodes = getNodesChecked(nodesTableId).split(',');
+ for (var i in tgtNodes) {
+ var mgt = getNodeAttr(tgtNodes[i], 'mgt');
+
+ // Create an instance of the plugin
+ var plugin;
+ switch(mgt) {
+ case "kvm":
+ plugin = new kvmPlugin();
+ break;
+ case "esx":
+ plugin = new esxPlugin();
+ break;
+ case "zvm":
+ plugin = new zvmPlugin();
+ break;
+ }
+ if (mgt == "zvm") {
+ var nodeOS = getNodeAttr(tgtNodes[i], 'os');
+ var nodeArch = getNodeAttr(tgtNodes[i], 'arch');
+ plugin.loadClonePage(tgtNodes[i], nodeOS, nodeArch);
+ } else {
+ plugin.loadClonePage(tgtNodes[i]);
+ }
+
+ }
+ });
+
+ // Delete
+ var deleteLnk = $('Delete ');
+ deleteLnk.click(function() {
+ var tgtNodes = getNodesChecked(nodesTableId);
+ if (tgtNodes) {
+ loadDeletePage(tgtNodes);
+ }
+ });
+
+ // Unlock Function
+ var unlockLnk = $('Unlock ');
+ unlockLnk.click(function() {
+
+ // Get the "master" value from the site table.
+ var siteMaster;
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'tabdump',
+ tgt : '',
+ args : 'site',
+ msg : 'cmd=tabdump site;'
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ var outId = $(data.msg);
+ var props = data.rsp;
+ if ( jQuery.isArray(data.rsp) ) {
+ for (var i in data.rsp) {
+ if ( data.rsp[i].indexOf('"master"') == 0 ) {
+ siteMaster = data.rsp[i].slice( 10, -3 );
+ }
+ }
+ } else {
+ if ( data.rsp.indexOf('"master"') == 0 ) {
+ siteMaster = data.rsp.slice( 10, -3 );
+ }
+ }
+
+ // Process the nodes that were checked.
+ var tgtNodes = getNodesChecked(nodesTableId).split(',');
+ var normalNodes = '';
+ var mnNode = '';
+ for (var i in tgtNodes) {
+ var nodeIP = getNodeAttr( tgtNodes[i], 'ip' );
+ if ( nodeIP == siteMaster ) {
+ if ( mnNode == '' ) {
+ // Only one xCAT node will have the same address as
+ // the site master IP address and this is the
+ // xCAT MN.
+ mnNode = tgtNodes[i];
+ }
+ } else {
+ if ( normalNodes == '' ) {
+ normalNodes = tgtNodes[i];
+ } else {
+ normalNodes = normalNodes + "," + tgtNodes[i];
+ }
+ }
+ }
+
+ if ( normalNodes != '' ) {
+ loadUnlockPage( normalNodes );
+ }
+ if ( mnNode != '' ) {
+ loadUnlockNonNodesPage( mnNode );
+ }
+ }
+ });
+ });
+
+ // Run script
+ var scriptLnk = $('Run script ');
+ scriptLnk.click(function() {
+ var tgtNodes = getNodesChecked(nodesTableId);
+ if (tgtNodes) {
+ loadScriptPage(tgtNodes);
+ } else {
+ openDialog('warn', "No nodes checked!");
+ }
+ });
+
+ // Migrate VM
+ var migrateLnk = $('Migrate ');
+ migrateLnk.click(function() {
+ var tgtNodes = getNodesChecked(nodesTableId).split(',');
+ var mgt = "", tmp = "";
+ var fromhcp = "";
+ for (var i in tgtNodes) {
+ tmp = getNodeAttr(tgtNodes[i], 'mgt');
+ fromhcp += getNodeAttr(tgtNodes[i], 'hcp') + ',';
+ if (!mgt) {
+ mgt = tmp
+ } else {
+ if (tmp != mgt) {
+ openDialog('warn', "You can pick only one type (mgt) of node to migrate!");
+ return;
+ }
+ }
+ }
+
+ // Create an instance of the plugin
+ var plugin;
+ switch(mgt) {
+ // Only hypervisors support migration
+ case "kvm":
+ plugin = new kvmPlugin();
+ break;
+ case "esx":
+ plugin = new esxPlugin();
+ break;
+ case "zvm":
+ plugin = new zvmPlugin();
+ break;
+ }
+ if (mgt == "zvm") {
+ plugin.loadMigratePage(tgtNodes, fromhcp);
+ } else {
+ plugin.loadMigratePage(tgtNodes);
+ }
+ });
+
+ // Update
+ var updateLnk = $('Update ');
+ updateLnk.click(function() {
+ var tgtNodes = getNodesChecked(nodesTableId);
+ if (tgtNodes) {
+ loadUpdatenodePage(tgtNodes);
+ }
+ });
+
+ // Set boot state
+ var setBootStateLnk = $('Set boot state ');
+ setBootStateLnk.click(function() {
+ var tgtNodes = getNodesChecked(nodesTableId);
+ if (tgtNodes) {
+ loadNodesetPage(tgtNodes);
+ }
+ });
+
+ // Boot to network
+ var boot2NetworkLnk = $('Boot to network ');
+ boot2NetworkLnk.click(function() {
+ var tgtNodes = getNodesChecked(nodesTableId);
+ if (tgtNodes) {
+ loadNetbootPage(tgtNodes);
+ }
+ });
+
+ // Provision node
+ var provisionLnk = $('Provision ');
+ provisionLnk.click(function() {
+ var tgtNodes = getNodesChecked(nodesTableId);
+ if (tgtNodes){
+ // Jump directly to the provision page
+ jump2Provision(tgtNodes);
+ }
+ });
+
+ // Remote console
+ var rcons = $('Open console ');
+ rcons.bind('click', function(event){
+ var tgtNodes = getNodesChecked(nodesTableId);
+ if (tgtNodes) {
+ loadRconsPage(tgtNodes);
+ }
+ });
+
+ // Discovery
+ var discoverLnk = $('Discover systems ');
+ discoverLnk.bind( 'click', function(event) {
+ var tgtNodes = getNodesChecked(nodesTableId).split(',');
+ if ( tgtNodes ) {
+ var hosts;
+ for (var i in tgtNodes) {
+ var hostType = getNodeAttr( tgtNodes[i], 'hosttype' );
+ if ( hostType == 'zvm' ) {
+ if ( hosts ) {
+ hosts += "," + tgtNodes[i];
+ } else {
+ hosts = tgtNodes[i];
+ }
+
+ } else {
+ openDialog('warn', tgtNodes[i] + " does not have a hosttype of 'zvm': " + hostType );
+ }
+ }
+ if ( hosts ) {
+ discoverVMNodes( hosts );
+ }
+ } else {
+ openDialog('warn', "No nodes checked!");
+ }
+ });
+
+ // Edit properties
+ var editProps = $('Edit properties ');
+ editProps.bind('click', function(event){
+ var tgtNodes = getNodesChecked(nodesTableId).split(',');
+ for (var i in tgtNodes) {
+ editNodeProps(tgtNodes[i]);
+ }
+ });
+
+ // Install Ganglia
+ var installMonLnk = $('Install monitoring ');
+ installMonLnk.click(function() {
+ var tgtNodes = getNodesChecked(nodesTableId);
+ if (tgtNodes) {
+ installGanglia(tgtNodes);
+ }
+ });
+
+ // Scan
+ var rscanLnk = $('Scan ');
+ rscanLnk.bind('click', function(event){
+ var tgtNodes = getNodesChecked(nodesTableId);
+ if (tgtNodes) {
+ loadRscanPage(tgtNodes);
+ }
+ });
+
+ // Event log
+ var logLnk = $('Event log ');
+ logLnk.click(function() {
+ var tgtNodes = getNodesChecked(nodesTableId).split(',');
+ for (var i in tgtNodes) {
+ var mgt = getNodeAttr(tgtNodes[i], 'mgt');
+
+ // Create an instance of the plugin
+ var plugin;
+ switch(mgt) {
+ case "kvm":
+ plugin = new kvmPlugin();
+ break;
+ case "esx":
+ plugin = new esxPlugin();
+ break;
+ case "blade":
+ plugin = new bladePlugin();
+ break;
+ case "hmc":
+ plugin = new hmcPlugin();
+ break;
+ case "ipmi":
+ plugin = new ipmiPlugin();
+ break;
+ case "zvm":
+ plugin = new zvmPlugin();
+ break;
+ }
+
+ plugin.loadLogPage(tgtNodes[i]);
+ }
+ });
+
+ // Actions
+ var actionsLnk = 'Actions ';
+ if (builtInXCAT == 0) {
+ if (group == 'hosts') {
+ var actsMenu = createMenu([deleteLnk]);
+ } else {
+ var actsMenu = createMenu([cloneLnk, deleteLnk, migrateLnk, monitorOnLnk, monitorOffLnk, powerOnLnk, powerOffLnk, scriptLnk, powerSoftoffLnk]);
+ }
+ } else {
+ if (group == 'hosts') {
+ var actsMenu = createMenu([deleteLnk]);
+ } else {
+ var actsMenu = createMenu([cloneLnk, deleteLnk, migrateLnk, powerOnLnk, powerOffLnk, scriptLnk, powerSoftoffLnk]);
+ }
+ }
+
+ // Configurations
+ var configLnk = 'Configuration ';
+ if (builtInXCAT == 0) {
+ if (group == 'hosts') {
+ var configMenu = createMenu([editProps]);
+ } else {
+ var configMenu = createMenu([editProps, logLnk, installMonLnk, rscanLnk, unlockLnk, updateLnk]);
+ }
+ } else {
+ if (group == 'hosts') {
+ var configMenu = createMenu([ discoverLnk, editProps ]);
+ } else {
+ var configMenu = createMenu([editProps, logLnk, rscanLnk, unlockLnk, updateLnk]);
+ }
+ }
+
+ // Provision
+ var provLnk = 'Provision ';
+ if (builtInXCAT == 0) {
+ var provMenu = createMenu([boot2NetworkLnk, rcons, setBootStateLnk, provisionLnk]);
+ } else {
+ var provMenu = createMenu([boot2NetworkLnk, setBootStateLnk]);
+ }
+
+ /**
+ * Refresh button
+ */
+ var refreshBtn = createButton('Refresh');
+ refreshBtn.click(function() {
+ // Remove any warning messages
+ $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
+
+ var zhcpsCheck = $.cookie('xcat_zhcps').split(',');
+ var zhcpHash = new Object();
+ for (var h in zhcpsCheck) {
+ if (!zhcpHash[zhcpsCheck[h]]) {
+
+ zhcpHash[zhcpsCheck[h]] = 1;
+ if (typeof console == "object"){
+ console.log("zhcp check for <"+zhcpsCheck[h]+">");
+ }
+
+ // Check if SMAPI is online
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'lsvm',
+ tgt : zhcpsCheck[h],
+ args : '',
+ msg : 'group=refreshgroups' + ';hcp=' + zhcpsCheck[h]
+ },
+
+ // Load hardware control point specific info
+ // Get disk pools and network names
+ success : function(data) {
+ data = decodeRsp(data);
+ loadHcpInfo(data);
+ }
+ });
+ }
+ }
+
+ window.location.reload();
+ });
+ refreshBtn.css({'width': '80px'});
+ refreshBtn.css({'height': '27px'});
+ //refreshBtn.css('vertical-align', 'top');
+ refreshBtn.css({'align': 'top'});
+
+ // Create an action menu
+ var actionsMenu;
+ if (group == 'hosts') {
+ actionsMenu = createMenu([ [ actionsLnk, actsMenu ], [ configLnk, configMenu ] ]);
+ } else {
+ actionsMenu = createMenu([ [ actionsLnk, actsMenu ], [ configLnk, configMenu ], [ provLnk, provMenu ] ]);
+ }
+ actionsMenu.superfish();
+ actionsMenu.css('display', 'inline-block');
+ actionBar.append(actionsMenu);
+ actionBar.append(refreshBtn);
+
+ // Set correct theme for action menu
+ actionsMenu.find('li').hover(function() {
+ setMenu2Theme($(this));
+ }, function() {
+ setMenu2Normal($(this));
+ });
+
+ // Insert action bar and nodes datatable
+ $('#nodesTab').append(nodesTable.object());
+
+ // Turn table into a datatable
+ var nodesDatatable = $('#' + nodesTableId).dataTable({
+ 'iDisplayLength': 50,
+ 'bLengthChange': false,
+ "bScrollCollapse": true,
+ "sScrollY": "400px",
+ "sScrollX": "110%",
+ "bAutoWidth": true,
+ "oLanguage": {
+ "oPaginate": {
+ "sNext": "",
+ "sPrevious": ""
+ }
+ }
+ });
+
+ // Filter table when enter key is pressed
+ $('#' + nodesTableId + '_filter input').unbind();
+ $('#' + nodesTableId + '_filter input').bind('keyup', function(e){
+ if (e.keyCode == 13) {
+ var table = $('#' + nodesTableId).dataTable();
+ table.fnFilter($(this).val());
+
+ // If there are nodes found, get the node attributes
+ if (!$('#' + nodesTableId + ' .dataTables_empty').length) {
+ getNodeAttrs(group);
+ }
+ }
+ });
+
+ // Load node definitions when next or previous buttons are clicked
+ $('#' + nodesTableId + '_next, #' + nodesTableId + '_previous').click(function() {
+ getNodeAttrs(group);
+ });
+
+ /**
+ * Change how datatable behaves
+ */
+
+ // Do not sort ping, power, and comment column
+ var cols = $('#' + nodesTableId + ' thead tr th').click(function() {
+ getNodeAttrs(group);
+ });
+ var checkboxCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(0)');
+ var pingCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(2)');
+ var powerCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
+ var monitorCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)');
+ var commentCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(5)');
+ checkboxCol.unbind('click');
+ pingCol.unbind('click');
+ powerCol.unbind('click');
+ monitorCol.unbind('click');
+ commentCol.unbind('click');
+
+ // Create enough space for loader to be displayed
+ // Center align power, ping, and comments
+ $('#' + nodesTableId + ' td:nth-child(3),td:nth-child(4),td:nth-child(5)').css({'text-align': 'center'});
+
+ // No minimum width for comments column
+ $('#' + nodesTableId + ' tbody tr td:nth-child(6)').css('text-align', 'center');
+
+ // Instead refresh the node, power, and monitor status
+ pingCol.find('span a').click(function() {
+ refreshNodeStatus(group, nodesTableId);
+ });
+ powerCol.find('span a').click(function() {
+ refreshPowerStatus(group, nodesTableId);
+ });
+ monitorCol.find('span a').click(function() {
+ refreshGangliaStatus(group, nodesTableId);
+ });
+
+ // Create a division to hold actions menu
+ var menuDiv = $(''); // # ');
+ update.append(createInfoBar('Updating table '));
+
+ update.dialog({
+ title: 'Updating',
+ modal: true,
+ width: 300,
+ position: 'center'
+ });
+ }
+}
+
+/**
+ * Add nodes to datatable
+ *
+ * @param data Data returned from HTTP request
+ */
+function addNodes2Table(data) {
+ // Data returned
+ var rsp = data.rsp;
+ // Group name
+ var group = data.msg;
+ // Hash of node attributes
+ var attrs = new Object();
+ // Node attributes
+ var headers = $('#' + nodesTableId).parents('.dataTables_scroll').find('.dataTables_scrollHead thead tr th');
+
+ // Variable to send command and request node status
+ var getNodeStatus = true;
+
+ // Go through each attribute
+ var node, args;
+ for (var i in rsp) {
+ // Get node name
+ if (rsp[i].indexOf('Object name:') > -1) {
+ var temp = rsp[i].split(': ');
+ node = jQuery.trim(temp[1]);
+
+ // Create a hash for node attributes
+ attrs[node] = new Object();
+ i++;
+ }
+
+ // Get key and value
+ args = rsp[i].split('=', 2);
+ var key = jQuery.trim(args[0]);
+ var val = jQuery.trim(rsp[i].substring(rsp[i].indexOf('=') + 1, rsp[i].length));
+
+ // Create a hash table
+ attrs[node][key] = val;
+ // Save attributes in original hash table
+ origAttrs[node][key] = val;
+
+ // If node status is available
+ if (key == 'status') {
+ // Do not request node status
+ getNodeStatus = false;
+ }
+ }
+
+ // Set the first five headers
+ var headersCol = new Object();
+ headersCol['node'] = 1;
+ headersCol['status'] = 2;
+ headersCol['power'] = 3;
+ headersCol['monitor'] = 4;
+ headersCol['comments'] = 5;
+
+ // Go through each header
+ for (var i = 6; i < headers.length; i++) {
+ // Get the column index
+ headersCol[headers.eq(i).html()] = i;
+ }
+
+ // Go through each node
+ var datatable = $('#' + nodesTableId).dataTable();
+ var rows = datatable.fnGetData();
+ for (var node in attrs) {
+ // Get row containing node
+ var nodeRowPos = 0;
+ for (var i in rows) {
+ // If column contains node
+ if (rows[i][1].indexOf('>' + node + '<') > -1) {
+ nodeRowPos = i;
+ break;
+ }
+ }
+
+ // Get node status
+ var status = '';
+ if (attrs[node]['status']){
+ status = attrs[node]['status'].replace('sshd', 'ping');
+ }
+
+ rows[nodeRowPos][headersCol['status']] = status;
+
+ // Go through each header
+ for (var key in headersCol) {
+ // Do not put comments and status in twice
+ if (key != 'usercomment' && key != 'status' && key.indexOf('status') < 0) {
+ var val = attrs[node][key];
+ if (val) {
+ rows[nodeRowPos][headersCol[key]] = val;
+ }
+ }
+ }
+
+ // Update row
+ datatable.fnUpdate(rows[nodeRowPos], parseInt(nodeRowPos), undefined, false);
+
+ // Insert node comments
+ // This is done after datatable is updated because
+ // you cannot insert an object using fnUpdate()
+ var comments = attrs[node]['usercomment'];
+
+ // If no comments exists, show 'No comments' and
+ // set icon image source
+ var iconSrc;
+ if (!comments) {
+ comments = 'No comments';
+ iconSrc = 'images/nodes/ui-icon-no-comment.png';
+ } else {
+ iconSrc = 'images/nodes/ui-icon-comment.png';
+ }
+
+ // Create icon for node comments
+ var tipID = node + 'Tip';
+ var commentsCol = $('#' + node).parent().parent().find('td').eq(5);
+
+ // Create tooltip
+ var icon = $(' ').css({
+ 'width': '18px',
+ 'height': '18px'
+ });
+
+ var tip = createCommentsToolTip(comments);
+ var span = $(' ').append(icon);
+ span.append(tip);
+ commentsCol.append(span);
+
+ // Generate tooltips
+ icon.tooltip({
+ position: "center right",
+ offset: [-2, 10],
+ effect: "fade",
+ opacity: 0.8,
+ relative: true,
+ delay: 500
+ });
+ }
+
+ // Enable node link
+ $('.node').bind('click', loadNode);
+
+ // Close dialog for updating table
+ $('.ui-dialog-content').dialog('destroy').remove();
+
+ /**
+ * Enable editable columns
+ */
+ // Do not make 1st, 2nd, 3rd, 4th, 5th, or 6th column editable
+ $('#' + nodesTableId + ' td:not(td:nth-child(1),td:nth-child(2),td:nth-child(3),td:nth-child(4),td:nth-child(5),td:nth-child(6))').editable(
+ function(value, settings) {
+ // If users did not do changes, return the value directly
+ // jeditable save the old value in this.revert
+ if ($(this).attr('revert') == value){
+ return value;
+ }
+ // Get column index
+ var colPos = this.cellIndex;
+
+ // Get row index
+ var dTable = $('#' + nodesTableId).dataTable();
+ var rowPos = dTable.fnGetPosition(this.parentNode);
+
+ // Update datatable
+ dTable.fnUpdate(value, rowPos, colPos, false);
+
+ // Get table headers
+ var headers = $('#' + nodesTableId + ' thead tr th');
+
+ // Get node name
+ var node = $(this).parent().find('td a.node').text();
+ // 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 node attributes
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'chdef',
+ tgt : '',
+ args : '-t;node;-o;' + node + ';' + args,
+ msg : 'out=nodesTab;tgt=' + node
+ },
+
+ success: function(data) {
+ data = decodeRsp(data);
+ showChdefOutput(data);
+ }
+ });
+
+ return value;
+ }, {
+ onblur : 'submit', // Clicking outside editable area submits changes
+ type : 'textarea',
+ placeholder: ' ',
+ event : 'dblclick',
+ height : '30px' // The height of the text area
+ });
+
+ // If request to get node status is made
+ if (getNodeStatus) {
+ // Get node status
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'nodestat',
+ tgt : group,
+ args : '-u',
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ loadNodeStatus(data);
+ }
+ });
+ } else {
+ // Hide status loader
+ var statCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(2)');
+ statCol.find('img').hide();
+ }
+
+ /**
+ * Additional ajax requests need to be made for zVM
+ */
+ advancedLoad(group);
+ adjustColumnSize(nodesTableId);
+}
+
+/**
+ * Load the status of Ganglia for a given group
+ *
+ * @param data Data returned from HTTP request
+ */
+function loadGangliaStatus(data) {
+ // Get datatable
+ var datatable = $('#' + nodesTableId).dataTable();
+ var ganglia = data.rsp;
+ var rowNum, node, status;
+
+ for ( var i in ganglia) {
+ // ganglia[0] = nodeName and ganglia[1] = state
+ node = jQuery.trim(ganglia[i][0]);
+ status = jQuery.trim(ganglia[i][1]);
+
+ if (node) {
+ // Get the row containing the node
+ rowNum = findRow(node, '#' + nodesTableId, 1);
+
+ // Update the power status column
+ datatable.fnUpdate(status, rowNum, 4);
+ }
+ }
+
+ // Hide Ganglia loader
+ var gangliaCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)');
+ gangliaCol.find('img').hide();
+ adjustColumnSize(nodesTableId);
+}
+
+/**
+ * Refresh the status of Ganglia for each node
+ *
+ * @param group Group name
+ */
+function refreshGangliaStatus(group) {
+ // Show ganglia loader
+ var gangliaCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)');
+ gangliaCol.find('img').show();
+
+ // Get power status for nodes shown
+ var nodes = getNodesShown(nodesTableId);
+
+ // Get the status of Ganglia
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'gangliastatus;' + nodes,
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ loadGangliaStatus(data);
+ }
+ });
+}
+
+/**
+ * Load power status for each node
+ *
+ * @param data Data returned from HTTP request
+ */
+function loadPowerStatus(data) {
+ var dTable = $('#' + nodesTableId).dataTable();
+ var power = data.rsp;
+ var rowPos, node, status, args;
+
+ for (var i in power) {
+ // power[0] = nodeName and power[1] = state
+ args = power[i].split(':');
+ node = jQuery.trim(args[0]);
+ status = jQuery.trim(args[1]);
+
+ // Get the row containing the node
+ rowPos = findRow(node, '#' + nodesTableId, 1);
+
+ // Update the power status column
+ dTable.fnUpdate(status, rowPos, 3);
+ }
+
+ // Hide power loader
+ var powerCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
+ powerCol.find('img').hide();
+ adjustColumnSize(nodesTableId);
+}
+
+/**
+ * Refresh power status for each node
+ *
+ * @param group Group name
+ * @param tableId Table to update node status
+ */
+function refreshPowerStatus(group, tableId) {
+ // Show power loader
+ var powerCol = $('#' + tableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
+ powerCol.find('img').show();
+
+ // Get power status for nodes shown
+ var nodes = getNodesShown(tableId);
+
+ // Get power status
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'rpower',
+ tgt : nodes,
+ args : 'stat',
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ loadPowerStatus(data);
+ }
+ });
+}
+
+/**
+ * Load node status for each node
+ *
+ * @param data Data returned from HTTP request
+ */
+function loadNodeStatus(data) {
+ var dTable = $('#' + nodesTableId).dataTable();
+ var rsp = data.rsp;
+ var args, rowPos, node, status;
+
+ // Get all nodes within datatable
+ for (var i in rsp) {
+ args = rsp[i].split(':');
+
+ // args[0] = node and args[1] = status
+ node = jQuery.trim(args[0]);
+ status = jQuery.trim(args[1]).replace('sshd', 'ping');
+
+ // Get row containing node
+ rowPos = findRow(node, '#' + nodesTableId, 1);
+
+ // Update ping status column
+ dTable.fnUpdate(status, rowPos, 2, false);
+ }
+
+ // Hide status loader
+ var statCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(2)');
+ statCol.find('img').hide();
+ adjustColumnSize(nodesTableId);
+}
+
+/**
+ * Refresh ping status for each node
+ *
+ * @param group Group name
+ * @param tableId Table to update node status
+ */
+function refreshNodeStatus(group, tableId) {
+ // Show ping loader
+ var pingCol = $('#' + tableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(2)');
+ pingCol.find('img').show();
+
+ // Get power status for nodes shown
+ var nodes = getNodesShown(tableId);
+
+ // Get the node status
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'nodestat',
+ tgt : nodes,
+ args : '-u',
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ loadNodeStatus(data);
+ }
+ });
+}
+
+/**
+ * Load inventory for given node
+ *
+ * @param e Windows event
+ */
+function loadNode(e) {
+ if (!e) {
+ e = window.event;
+ }
+
+ // Get node that was clicked
+ var node = (e.target) ? e.target.id : e.srcElement.id;
+ var mgt = getNodeAttr(node, 'mgt');
+
+ // Create an instance of the plugin
+ var plugin;
+ switch(mgt) {
+ case "kvm":
+ plugin = new kvmPlugin();
+ break;
+ case "esx":
+ plugin = new esxPlugin();
+ break;
+ case "blade":
+ plugin = new bladePlugin();
+ break;
+ case "hmc":
+ plugin = new hmcPlugin();
+ break;
+ case "ipmi":
+ plugin = new ipmiPlugin();
+ break;
+ case "zvm":
+ plugin = new zvmPlugin();
+ break;
+ }
+
+ // Get tab area where a new tab will be inserted
+ var myTab = getNodesTab();
+ var inst = 0;
+ var newTabId = 'nodeTab' + inst;
+ while ($('#' + newTabId).length) {
+ // If one already exists, generate another one
+ inst = inst + 1;
+ newTabId = 'nodeTab' + inst;
+ }
+ // Reset node process
+ $.cookie('xcat_' + node + 'Processes', 0, { path: '/xcat', secure:true });
+
+ // Add new tab, only if one does not exist
+ var loader = createLoader(newTabId + 'TabLoader');
+ loader = $(' ').append(loader);
+ myTab.add(newTabId, node, loader, true);
+
+ // Get node inventory
+ var msg = 'out=' + newTabId + ',node=' + node;
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'rinv',
+ tgt : node,
+ args : 'all',
+ msg : msg
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ plugin.loadInventory(data);
+ }
+ });
+
+ // Select new tab
+ myTab.select(newTabId);
+}
+
+/**
+ * Unlock a node by setting the ssh keys
+ *
+ * @param tgtNodes Nodes to unlock
+ */
+function loadUnlockPage(tgtNodes) {
+ // Get nodes tab
+ var tab = getNodesTab();
+
+ // Generate new tab ID
+ var instance = 0;
+ var newTabId = 'unlockTab' + instance;
+ while ($('#' + newTabId).length) {
+ // If one already exists, generate another one
+ instance = instance + 1;
+ newTabId = 'unlockTab' + instance;
+ }
+
+ // Create status bar, hide on load
+ var statBarId = 'unlockStatusBar' + instance;
+ var statBar = createStatusBar(statBarId).hide();
+
+ // Create loader
+ var loader = createLoader('');
+ statBar.find('div').append(loader);
+
+ // Create info bar
+ var infoBar = createInfoBar('Give the root password for this node range to setup its SSH keys.');
+
+ // Create unlock form
+ var unlockForm = $('
');
+ unlockForm.append(statBar, infoBar);
+
+ // Create VM fieldset
+ var vmFS = $(' ');
+ var vmLegend = $('Virtual Machine ');
+ vmFS.append(vmLegend);
+ unlockForm.append(vmFS);
+
+ var vmAttr = $('
');
+ vmFS.append($(''));
+ vmFS.append(vmAttr);
+
+ vmAttr.append('Target node range:
');
+ vmAttr.append('Password:
');
+
+ // Generate tooltips
+ unlockForm.find('div input[title]').tooltip({
+ position: "center right",
+ offset: [-2, 10],
+ effect: "fade",
+ opacity: 0.7,
+ predelay: 800,
+ events : {
+ def : "mouseover,mouseout",
+ input : "mouseover,mouseout",
+ widget : "focus mouseover,blur mouseout",
+ tooltip : "mouseover,mouseout"
+ }
+ });
+
+ /**
+ * Ok
+ */
+ var unlockBtn = createButton('Unlock');
+ unlockBtn.css({
+ 'width': '80px',
+ 'display': 'block'
+ });
+ unlockBtn.click(function() {
+ // Remove any warning messages
+ $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
+
+ // If a password is given
+ var password = $('#' + newTabId + ' input[name=password]').css('border', 'solid #BDBDBD 1px');
+ if (password.val()) {
+ // Setup SSH keys
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'unlock;' + tgtNodes + ';' + password.val(),
+ msg : 'out=' + statBarId + ';cmd=unlock;tgt=' + tgtNodes
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ updateStatusBar(data);
+ }
+ });
+
+ // Show status bar
+ statBar.show();
+
+ // Disable all inputs and Ok button
+ $('#' + newTabId + ' input').attr('disabled', 'disabled');
+ $(this).attr('disabled', 'true');
+ } else {
+ // Show warning message
+ var warn = createWarnBar('You are missing some values!');
+ warn.prependTo($(this).parents('.ui-tabs-panel'));
+ password.css('border', 'solid #FF0000 1px');
+ }
+ });
+
+ unlockForm.append(unlockBtn);
+ tab.add(newTabId, 'Unlock', unlockForm, true);
+ tab.select(newTabId);
+}
+
+function loadUnlockNonNodesPage( tgtNodes ) {
+
+ // Get nodes tab
+ var tab = getNodesTab();
+ var fs, legend;
+
+ // Generate new tab ID
+ var instance = 0;
+ var newTabId = 'unlockNonNodesTab' + instance;
+ while ($('#' + newTabId).length) {
+ // If one already exists, generate another one
+ instance = instance + 1;
+ newTabId = 'unlockNonNodesTab' + instance;
+ }
+
+ // Create info bar and status bar
+ var infoBar = createInfoBar( 'Unlock systems that have not been defined to xCAT. Either: ' +
+ '-Create a script to install the xCAT Management Node\'s public key on the target systems, or ' +
+ '-Unlock system(s) directly using their IP address(es) ' +
+ '(Specify multiple systems by separating the addresses with a comma), ' +
+ '-Show the xCAT Management Node\'s public key to use to unlock the system.' );
+
+ var statBarId = 'unlockNonNodesStatusBar' + instance;
+ var statBar = createStatusBar(statBarId).hide();
+ var loader = createLoader( '' );
+ statBar.find('div').append( loader );
+
+ // Create unlock form and put info and status bars on the form
+ var unlockNonNodesForm = $( '
' );
+ unlockNonNodesForm.append( infoBar, statBar );
+
+ // Create 'Create an Unlock Script' fieldset
+ fs = $( ' ' );
+ legend = $( 'Create an Unlock Script ' );
+ fs.append( legend );
+ unlockNonNodesForm.append( fs );
+
+ // Create Script bar
+ var scriptBarId = 'unlockNonNodesScriptBar' + instance;
+ var scriptBar = createStatusBar(scriptBarId).hide();
+ unlockNonNodesForm.append( scriptBar );
+
+ var createBtn = createButton( 'Create Script' );
+ createBtn.css({
+ 'width': '200px',
+ 'display': 'block'
+ });
+
+ createBtn.click(function() {
+ // Remove any warning messages
+ $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
+
+ // Get the SSH keys for a non-node
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'unlockshow;' + tgtNodes + ';script;',
+ msg : 'out=' + statBarId + ';scriptBar=' + scriptBarId +';cmd=unlock;tgt=' + tgtNodes
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ updateScriptBar(data);
+ }
+ });
+
+ // Show status bar
+ statBar.show();
+ });
+
+ unlockNonNodesForm.append( createBtn );
+
+ // Create 'Unlock a system using the root password' Script fieldset
+ fs = $( ' ' );
+ legend = $( 'Unlock a system using the root password ' );
+ fs.append( legend );
+ unlockNonNodesForm.append( fs );
+
+ var vmAttr = $('
' );
+ fs.append($(''));
+ fs.append( vmAttr );
+
+ vmAttr.append( 'IP Address:
' );
+ vmAttr.append( 'Password:
' );
+
+ /**
+ * Unlock button for non-nodes
+ */
+ var unlockBtn = createButton('Unlock');
+ unlockBtn.css({
+ 'width': '80px',
+ 'display': 'block'
+ });
+
+ unlockBtn.click(function() {
+ // Remove any warning messages
+ $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
+
+ // If an ip and password is given
+ var ip = $('#' + newTabId + ' input[name=ip]').css('border', 'solid #BDBDBD 1px');
+ var password = $( '#' + newTabId + ' input[name=password]').css('border', 'solid #BDBDBD 1px' );
+ if ( password.val() && ip.val() ) {
+ $('#' + statBarId).find('img').show();
+ // Setup SSH keys for a non-node
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'unlockbyip;' + tgtNodes + ';' + password.val() + ";" + ip.val(),
+ msg : 'out=' + statBarId + ';cmd=unlock;tgt=' + tgtNodes
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ updateStatusBar(data);
+ }
+ });
+
+ // Show status bar
+ statBar.show();
+ } else {
+ // Show warning message
+ var warn = createWarnBar('Both ip address and password must be specified.');
+ warn.prependTo($(this).parents('.ui-tabs-panel'));
+ password.css('border', 'solid #FF0000 1px');
+ }
+ });
+
+ unlockNonNodesForm.append(unlockBtn);
+
+ // Create 'SSH Key' fieldset
+ var sshKey = '';
+ fs = $( ' ' );
+ legend = $( 'xCAT Management Node Public Key ' );
+ fs.append( legend );
+ unlockNonNodesForm.append( fs );
+
+ // Create key bar, hide on load
+ var keyBarId = 'unlockNonNodesKeyBar' + instance;
+ var keyBar = createStatusBar(keyBarId).hide();
+ unlockNonNodesForm.append( keyBar );
+
+ // Generate tooltips
+ unlockNonNodesForm.find('div input[title]').tooltip({
+ position: "center right",
+ offset: [-2, 10],
+ effect: "fade",
+ opacity: 0.7,
+ predelay: 800,
+ events : {
+ def : "mouseover,mouseout",
+ input : "mouseover,mouseout",
+ widget : "focus mouseover,blur mouseout",
+ tooltip : "mouseover,mouseout"
+ }
+ });
+
+ /**
+ * "Get Key" button
+ */
+ var getBtn = createButton('Get Key');
+ getBtn.css({
+ 'width': '80px',
+ 'display': 'block'
+ });
+
+ getBtn.click(function() {
+ // Remove any warning messages
+ $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
+
+ // Get the SSH keys for a non-node
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'unlockshow;' + tgtNodes + ';key;',
+ msg : 'out=' + statBarId + ';keyBar=' + keyBarId +';cmd=unlock;tgt=' + tgtNodes
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ updateKeyBar(data);
+ }
+ });
+
+ // Show status bar
+ statBar.show();
+ });
+
+ unlockNonNodesForm.append(getBtn);
+
+ tab.add(newTabId, 'Unlock System', unlockNonNodesForm, true);
+ tab.select(newTabId);
+}
+
+
+/**
+ * Update key and status bar of a given tab
+ *
+ * @param data Data returned from HTTP request
+ */
+function updateKeyBar(data) {
+ // Get ajax response
+ var rsp = data.rsp;
+ var args = data.msg.split(';');
+ var statBarId = args[0].replace('out=', '');
+ var keyBarId = args[1].replace('keyBar=', '');
+ var cmd = args[2].replace('cmd=', '');
+ var tgts = args[3].replace('tgt=', '').split(',');
+
+ $('#' + statBarId).find('img').hide();
+
+ // Extract the key portion and status portions from the response
+ var keyRespStart = rsp[0].indexOf("");
+ var keyRespEnd = rsp[0].indexOf(" ");;
+ var keyOnly = rsp[0].substring( keyRespStart+9, keyRespEnd );
+ var statLines = rsp[0].substring( 0, keyRespStart-1 );
+
+ if ( keyOnly.length > 0 ) {
+ // Expected response was returned, show it in the key bar.
+ var keyLines = keyOnly.split(/\n/);
+ for ( var i in keyLines ) {
+ $('#' + keyBarId).find( 'div' ).append( keyLines[i] );
+ $('#' + keyBarId).find( 'div' ).append( ' ' );
+ }
+ $('#' + keyBarId).show();
+
+ // Other lines from the response are shown in the Status bar.
+ if ( statLines.length > 0 ) {
+ prg = statLines.split(/\n/);
+ prg = writeRsp( prg, '' );
+ $('#' + statBarId).find( 'div' ).append( prg );
+ }
+ } else {
+ // Did not find the expected response, write the ajax response to status bar.
+ var prg = writeRsp(rsp, '');
+ $('#' + statBarId).find('div').append(prg);
+ }
+
+}
+
+
+/**
+ * Update the script and status bar of a given tab
+ *
+ * @param data Data returned from HTTP request
+ */
+function updateScriptBar(data) {
+ // Get ajax response
+ var rsp = data.rsp;
+ var args = data.msg.split(';');
+ var statBarId = args[0].replace('out=', '');
+ var scriptBarId = args[1].replace('scriptBar=', '');
+ var cmd = args[2].replace('cmd=', '');
+ var tgts = args[3].replace('tgt=', '').split(',');
+
+ $('#' + statBarId).find('img').hide();
+
+ // Extract the key portion and status portions from the response
+ var scriptRespStart = rsp[0].indexOf("");
+ var scriptRespEnd = rsp[0].indexOf(" ");;
+ var scriptOnly = rsp[0].substring( scriptRespStart+12, scriptRespEnd );
+ var statLines = rsp[0].substring( 0, scriptRespStart-1 );
+
+ if ( scriptOnly.length > 0 ) {
+ // Expected response was returned, show it in the script bar along with the rest of the code.
+ var scriptLines = scriptOnly.split(/\n/);
+ for ( var i in scriptLines ) {
+ scriptLines[i] = scriptLines[i].replace(/^\s\s\s\s\s\s\s\s+/gm, ' ');
+ scriptLines[i] = scriptLines[i].replace(/^\s\s\s\s\s\s+/gm, ' ');
+ scriptLines[i] = scriptLines[i].replace(/^\s\s\s\s+/gm, ' ');
+ scriptLines[i] = scriptLines[i].replace(/^\s\s+/gm, ' ');
+ $('#' + scriptBarId).find( 'div' ).append( scriptLines[i] + ' ' );
+ }
+ $('#' + scriptBarId).show();
+
+ // Other lines from the response are shown in the Status bar.
+ if ( statLines.length > 0 ) {
+ prg = statLines.split(/\n/);
+ prg = writeRsp( prg, '' );
+ $('#' + statBarId).find( 'div' ).append( prg );
+ }
+ } else {
+ // Did not find the expected response, write the ajax response to status bar.
+ var prg = writeRsp(rsp, '');
+ $('#' + statBarId).find('div').append(prg);
+ }
+
+}
+
+
+/**
+ * Load script page
+ *
+ * @param tgtNodes Targets to run script against
+ */
+function loadScriptPage(tgtNodes) {
+ // Get nodes tab
+ var tab = getNodesTab();
+
+ // Generate new tab ID
+ var inst = 0;
+ var newTabId = 'scriptTab' + inst;
+ while ($('#' + newTabId).length) {
+ // If one already exists, generate another one
+ inst = inst + 1;
+ newTabId = 'scriptTab' + inst;
+ }
+
+ // Create remote script form
+ var scriptForm = $('
');
+
+ // Create status bar
+ var barId = 'scriptStatusBar' + inst;
+ var statBar = createStatusBar(barId);
+ statBar.hide();
+ var loader = createLoader('scriptLoader' + inst);
+ statBar.find('div').append(loader);
+
+ // Create info bar
+ var infoBar = createInfoBar('Load a script to run against this node range.');
+ scriptForm.append(infoBar, statBar);
+
+ // Create VM fieldset
+ var vmFS = $(' ');
+ var vmLegend = $('Virtual Machine ');
+ vmFS.append(vmLegend);
+ scriptForm.append(vmFS);
+
+ var vmAttr = $('
');
+ vmFS.append($(''));
+ vmFS.append(vmAttr);
+
+ // Create logs fieldset
+ var scriptFS = $(' ');
+ var scriptLegend = $('Script ');
+ scriptFS.append(scriptLegend);
+ scriptForm.append(scriptFS);
+
+ var scriptAttr = $('
');
+ scriptFS.append($(''));
+ scriptFS.append(scriptAttr);
+
+ // Target node or group
+ var tgt = $('Target node range:
');
+ vmAttr.append(tgt);
+
+ // Upload file
+ var upload = $('');
+ var label = $('Remote file: ');
+ var file = $(' ');
+ var subBtn = createButton('Load');
+ upload.append(label, file, subBtn);
+ scriptAttr.append(upload);
+
+ // Script
+ var script = $('Script: ');
+ scriptAttr.append(script);
+
+ // Generate tooltips
+ scriptForm.find('div input[title],textarea').tooltip({
+ position: "center right",
+ offset: [-2, 10],
+ effect: "fade",
+ opacity: 0.7,
+ predelay: 800,
+ events : {
+ def : "mouseover,mouseout",
+ input : "mouseover,mouseout",
+ widget : "focus mouseover,blur mouseout",
+ tooltip : "mouseover,mouseout"
+ }
+ });
+
+ // Ajax form options
+ var options = {
+ // Output to text area
+ target : '#' + newTabId + ' textarea'
+ };
+ upload.ajaxForm(options);
+
+ /**
+ * Run
+ */
+ var runBtn = createButton('Run');
+ runBtn.css({
+ 'width': '80px'
+ });
+ runBtn.click(function() {
+ // Remove any warning messages
+ $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
+
+ // Get script to run
+ var textarea = $('#' + newTabId + ' textarea').css('border', 'solid #BDBDBD 1px');
+
+ // If no inputs are empty
+ if (textarea.val()) {
+ // Run script
+ runScript(inst);
+ } else {
+ // Show warning message
+ var warn = createWarnBar('You are missing some values');
+ warn.prependTo($(this).parents('.ui-tabs-panel'));
+ textarea.css('border', 'solid #FF0000 1px');
+ }
+ });
+ scriptForm.append(runBtn);
+
+ // Append to discover tab
+ tab.add(newTabId, 'Script', scriptForm, true);
+
+ // Select new tab
+ tab.select(newTabId);
+}
+
+/**
+ * Sort a list
+ *
+ * @return Sorted list
+ */
+jQuery.fn.sort = function() {
+ return this.pushStack([].sort.apply(this, arguments), []);
+};
+
+function sortAlpha(a, b) {
+ return a.innerHTML > b.innerHTML ? 1 : -1;
+};
+
+/**
+ * Power on a given node
+ *
+ * @param node Node to power on or off
+ * @param power2 Power node to given state
+ */
+function powerNode(node, power2) {
+ // Show power loader
+ var powerCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
+ powerCol.find('img').show();
+
+ node = node.replace('Power', '');
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'rpower',
+ tgt : node,
+ args : power2,
+ msg : node
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ updatePowerStatus(data);
+ }
+ });
+}
+
+/**
+ * Load delete node page
+ *
+ * @param tgtNodes Nodes to delete
+ */
+function loadDeletePage(tgtNodes) {
+ // Get nodes tab
+ var myTab = getNodesTab();
+
+ // Generate new tab ID
+ var inst = 0;
+ newTabId = 'deleteTab' + inst;
+ while ($('#' + newTabId).length) {
+ // If one already exists, generate another one
+ inst = inst + 1;
+ newTabId = 'deleteTab' + inst;
+ }
+
+ // Create target nodes string
+ var tgtNodesStr = '';
+ var nodes = tgtNodes.split(',');
+ // Loop through each node
+ for (var i in nodes) {
+ // If it is the 1st and only node
+ if (i == 0 && i == nodes.length - 1) {
+ tgtNodesStr += nodes[i];
+ }
+ // If it is the 1st node of many nodes
+ else if (i == 0 && i != nodes.length - 1) {
+ // Append a comma to the string
+ tgtNodesStr += nodes[i] + ', ';
+ } else {
+ // If it is the last node
+ if (i == nodes.length - 1) {
+ // Append nothing to the string
+ tgtNodesStr += nodes[i];
+ } else {
+ // Append a comma to the string
+ tgtNodesStr += nodes[i] + ', ';
+ }
+ }
+ }
+
+ // Create delete form
+ var deleteForm = $('
');
+
+ // Create status bar, hide on load
+ var statBarId = 'deleteStatusBar' + inst;
+ var statBar = createStatusBar(statBarId).hide();
+
+ // Create loader
+ var loader = createLoader('');
+ statBar.find('div').append(loader);
+ statBar.hide();
+ deleteForm.append(statBar);
+
+ // Create confirm fieldset
+ var confirmFS = $('
');
+ var confirmLegend = $('
Confirm ');
+ confirmFS.append(confirmLegend);
+ deleteForm.append(confirmFS);
+
+ var confirmAttr = $('
');
+ confirmFS.append($('
'));
+ confirmFS.append(confirmAttr);
+
+ // Confirm delete
+ var instr = $('
Are you sure you want to delete ' + tgtNodesStr + ' ?
').css('word-wrap', 'break-word');
+ var dbOnly = $('
Only delete entries in database
');
+ confirmAttr.append(instr);
+ confirmAttr.append(dbOnly);
+
+ /**
+ * Delete
+ */
+ var deleteBtn = createButton('Delete');
+ deleteBtn.click(function() {
+ var cmd = "rmvm";
+ // Only delete entries in database if checked
+ if ($("#" + newTabId + " input[name='db-only']").attr('checked')) {
+ cmd = "noderm";
+ }
+
+ // Delete the virtual server or remove the node.
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : cmd,
+ tgt : tgtNodes,
+ args : '',
+ msg : 'out=' + statBarId + ';cmd=' + cmd + ';tgt=' + tgtNodes
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ updateStatusBar(data);
+ }
+ });
+
+ // Show status bar loader
+ statBar.show();
+
+ // Disable delete button
+ $(this).attr('disabled', 'true');
+ });
+
+ /**
+ * Cancel
+ */
+ var cancelBtn = createButton('Cancel');
+ cancelBtn.bind('click', function(){
+ myTab.remove($(this).parent().parent().attr('id'));
+ });
+
+ deleteForm.append(deleteBtn, cancelBtn);
+ myTab.add(newTabId, 'Delete', deleteForm, true);
+
+ myTab.select(newTabId);
+}
+
+/**
+ * Update status bar of a given tab
+ *
+ * @param data Data returned from HTTP request
+ */
+function updateStatusBar(data) {
+ // Get ajax response
+ var rsp = data.rsp;
+ var args = data.msg.split(';');
+ var statBarId = args[0].replace('out=', '');
+ var cmd = args[1].replace('cmd=', '');
+ var tgts = args[2].replace('tgt=', '').split(',');
+
+ if (cmd == 'unlock' || cmd == 'updatenode') {
+ // Hide loader
+ $('#' + statBarId).find('img').hide();
+
+ // Write ajax response to status bar
+ var prg = writeRsp(rsp, '');
+ $('#' + statBarId).find('div').append(prg);
+ } else if (cmd == 'rmvm') {
+ // Get data table
+ var dTable = $('#' + nodesTableId).dataTable();
+ var failed = false;
+
+ // Hide loader
+ $('#' + statBarId).find('img').hide();
+
+ // Write ajax response to status bar
+ var prg = writeRsp(rsp, '');
+ $('#' + statBarId).find('div').append(prg);
+
+ // If there was an error, do not continue
+ if (prg.html().indexOf('Error') > -1) {
+ failed = true;
+ }
+ } else if (cmd == 'xdsh') {
+ // Hide loader
+ $('#' + statBarId).find('img').hide();
+ $('#' + statBarId).find('#loadingpic2').remove();
+
+ // Write ajax response to status bar
+ var prg = $('
');
+ for (var i in rsp) {
+ for (var j in tgts) {
+ rsp[i] = rsp[i].replace(new RegExp(tgts[j] + ':', 'g'), '');
+ }
+
+ prg.append(rsp[i]);
+ prg.append('
');
+ }
+ $('#' + statBarId).find('div').append(prg);
+ $('#' + statBarId).find('div').append('
');
+
+ // The status area division contains useful scrollTop() and "scrollHeight dom 0" information.
+ // The inner div grows in height along with the status bar scroll height
+ // The status area client does not grow, that is the visible scroll area
+ var scrtop = $('#' + statBarId ).scrollTop();
+ var scrheight = $('#' + statBarId )[0].scrollHeight;
+ var dcheight = $('#' + statBarId)[0].clientHeight;
+ var dcheight2 = $('#' + statBarId).find('div')[0].clientHeight;
+
+ // Adjust the scroll bar to move to the bottom
+ if (scrtop < (scrheight-dcheight)) {
+ $('#' + statBarId ).scrollTop(scrheight-dcheight);
+ }
+
+ // Enable fields
+ $('#' + statBarId).parent().find('input').removeAttr('disabled');
+ $('#' + statBarId).parent().find('textarea').removeAttr('disabled');
+
+ // Enable buttons
+ $('#' + statBarId).parent().find('button').removeAttr('disabled');
+ } else if (cmd == 'noderm') {
+ // Hide loader
+ $('#' + statBarId).find('img').hide();
+
+ // Write ajax response to status bar
+ var prg = $('
Entries deleted in database ');
+ $('#' + statBarId).find('div').append(prg);
+ } else {
+ // Hide loader
+ $('#' + statBarId).find('img').hide();
+
+ // Write ajax response to status bar
+ var prg = writeRsp(rsp, '');
+ $('#' + statBarId).find('div').append(prg);
+ }
+}
+
+/**
+ * Update power status of a node in the datatable
+ *
+ * @param data Data from HTTP request
+ */
+function updatePowerStatus(data) {
+ // Hide power loader
+ var powerCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
+ powerCol.find('img').hide();
+
+ // Get datatable
+ var dTable = $('#' + nodesTableId).dataTable();
+
+ // Get xCAT response
+ var rsp = data.rsp;
+ // Loop through each line
+ var node, status, rowPos, strPos;
+ for (var i in rsp) {
+ // Get node name
+ node = rsp[i].split(":")[0];
+
+ // If there is no error
+ if (rsp[i].indexOf("Error") < 0 || rsp[i].indexOf("Failed") < 0) {
+ // Get the row containing the node link
+ rowPos = findRow(node, '#' + nodesTableId, 1);
+
+ // If it was power on, then the data return would contain "Starting"
+ strPos = rsp[i].indexOf("Starting");
+ if (strPos > -1) {
+ status = 'on';
+ } else {
+ status = 'off';
+ }
+
+ // Update the power status column
+ dTable.fnUpdate(status, rowPos, 3, false);
+ } else {
+ // Power on/off failed
+ alert(rsp[i]);
+ }
+ }
+
+ // Adjust datatable column size
+ adjustColumnSize(nodesTableId);
+}
+
+/**
+ * Run a script
+ *
+ * @param inst Remote script tab instance
+ */
+function runScript(inst) {
+ // Get tab ID
+ var tabId = 'scriptTab' + inst;
+ // Get node name
+ var tgts = $('#' + tabId + ' input[name=target]').val();
+ // Get script
+ var script = $('#' + tabId + ' textarea').val();
+
+ var statBarId = 'scriptStatusBar' + inst;
+
+ // The status area division contains useful scrollTop() and "scrollHeight dom 0" information.
+ // The inner div grows in height along with the status bar scroll height
+ // The status area client does not grow, that is the visible scroll area
+ var scrtop = $('#' + statBarId ).scrollTop();
+ var scrheight = $('#' + statBarId )[0].scrollHeight;
+ var dcheight = $('#' + statBarId)[0].clientHeight;
+ var dcheight2 = $('#' + statBarId).find('div')[0].clientHeight;
+
+ //If this is not first time for run script and it has scrolled then add a progress gif at the end.
+ if (scrheight > dcheight) {
+ $('#'+statBarId).find('div').append("
");
+ scrtop = $('#' + statBarId ).scrollTop();
+ scrheight = $('#' + statBarId )[0].scrollHeight;
+ dcheight = $('#' + statBarId)[0].clientHeight;
+ // Scroll down so gif shows
+ $('#' + statBarId ).scrollTop(scrheight-dcheight);
+ }
+
+ $('#' + statBarId).show(); // Show status bar
+ $('#' + statBarId + ' img').show(); // Show loader
+ $('#' + statBarId + ' p').remove(); // Clear status bar
+
+ // Disable all fields
+ $('#' + tabId + ' input').attr('disabled', 'true');
+ $('#' + tabId + ' textarea').attr('disabled', 'true');
+
+ // Disable buttons
+ $('#' + tabId + ' button').attr('disabled', 'true');
+
+ // Run script
+ $.ajax( {
+ url : 'lib/zCmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'xdsh',
+ tgt : tgts,
+ args : '-e',
+ att : script,
+ msg : 'out=scriptStatusBar' + inst + ';cmd=xdsh;tgt=' + tgts
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ updateStatusBar(data);
+ }
+ });
+}
+
+/**
+ * Get an attribute of a given node
+ *
+ * @param node The node
+ * @param attrName The attribute
+ * @return The attribute of the node
+ */
+function getNodeAttr(node, attrName) {
+ // Get the row
+ var row = $('[id=' + node + ']').parents('tr');
+
+ // Search for the column containing the attribute
+ var attrCol;
+
+ var cols = row.parents('.dataTables_scroll').find('.dataTables_scrollHead thead tr:eq(0) th');
+ // Loop through each column
+ for (var i in cols) {
+ // Find column that matches the attribute
+ if (cols.eq(i).html() == attrName) {
+ attrCol = cols.eq(i);
+ break;
+ }
+ }
+
+ // If the column containing the attribute is found
+ if (attrCol) {
+ // Get the attribute column index
+ var attrIndex = attrCol.index();
+
+ // Get the attribute for the given node
+ var attr = row.find('td:eq(' + attrIndex + ')');
+ return attr.text();
+ } else {
+ return '';
+ }
+}
+
+/**
+ * Set a cookie for the OS images
+ *
+ * @param data Data from HTTP request
+ */
+function setOSImageCookies(data) {
+ // Get response
+ var rsp = data.rsp;
+
+ var imageNames = new Array;
+ var profilesHash = new Object();
+ var osVersHash = new Object();
+ var osArchsHash = new Object();
+ var imagePos = 0;
+ var profilePos = 0;
+ var osversPos = 0;
+ var osarchPos = 0;
+
+ // Get column value
+ 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;
+ default :
+ break;
+ }
+ }
+
+ // Go through each index
+ for (var i = 1; i < rsp.length; i++) {
+ // Get image name
+ var cols = rsp[i].split(',');
+ var osImage = cols[imagePos].replace(new RegExp('"', 'g'), '');
+ var profile = cols[profilePos].replace(new RegExp('"', 'g'), '');
+ var osVer = cols[osversPos].replace(new RegExp('"', 'g'), '');
+ var osArch = cols[osarchPos].replace(new RegExp('"', 'g'), '');
+
+ imageNames.push(osImage);
+ profilesHash[profile] = 1;
+ osVersHash[osVer] = 1;
+ osArchsHash[osArch] = 1;
+ }
+
+ // Save image names in a cookie
+ $.cookie('xcat_imagenames', imageNames, { path: '/xcat', secure:true });
+
+ // Save profiles in a cookie
+ var tmp = new Array;
+ for (var key in profilesHash) {
+ tmp.push(key);
+ }
+ $.cookie('xcat_profiles', tmp, { path: '/xcat', secure:true });
+
+ // Save OS versions in a cookie
+ tmp = new Array;
+ for (var key in osVersHash) {
+ tmp.push(key);
+ }
+ $.cookie('xcat_osvers', tmp, { path: '/xcat', secure:true });
+
+ // Save OS architectures in a cookie
+ tmp = new Array;
+ for (var key in osArchsHash) {
+ tmp.push(key);
+ }
+ $.cookie('xcat_osarchs', tmp, { path: '/xcat', secure:true });
+}
+
+/**
+ * Set a cookie for the groups
+ *
+ * @param data Data from HTTP request
+ */
+function setGroupsCookies(data) {
+ var rsp = data.rsp;
+ $.cookie('xcat_groups', rsp, { path: '/xcat', secure:true });
+}
+
+/**
+ * Find the row index containing a column with a given string
+ *
+ * @param str String to search for
+ * @param table Table to check
+ * @param col Column to find string under
+ * @return The row index containing the search string
+ */
+function findRow(str, table, col){
+ // Get datatable
+ var dTable = $(table).dataTable();
+ var rows = dTable.fnGetData();
+
+ // Loop through each row
+ for (var i in rows) {
+ // If the column contains the search string
+ if (rows[i][col].indexOf(str) > -1) {
+ return parseInt(i);
+ }
+ }
+
+ return -1;
+}
+
+/**
+ * Select all checkboxes in the datatable
+ *
+ * @param event Event on element
+ * @param obj Object triggering event
+ */
+function selectAllCheckbox(event, obj) {
+ // Get datatable ID
+ // This will ascend from
+ var tableObj = obj.parents('.dataTables_scroll').find('.dataTables_scrollBody');
+ var status = obj.attr('checked');
+ tableObj.find(' :checkbox').attr('checked', status);
+ event.stopPropagation();
+}
+
+/**
+ * Load rcons page
+ *
+ * @param tgtNodes Targets to run rcons against
+ */
+function loadRconsPage(tgtNodes){
+ var hostName = window.location.host;
+ var urlPath = window.location.pathname;
+ var redirectUrl = 'https://';
+ var pos = 0;
+
+ // We only support one node
+ if (-1 != tgtNodes.indexOf(',')){
+ alert("You can only open one console at a time!");
+ return;
+ }
+
+ redirectUrl += hostName;
+ pos = urlPath.lastIndexOf('/');
+ redirectUrl += urlPath.substring(0, pos + 1);
+ redirectUrl += 'rcons.php';
+
+ // Open the rcons page
+ window.open(redirectUrl + "?rconsnd=" + tgtNodes, '', "toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=no,width=590,height=436");
+}
+
+/**
+ * Create a tool tip for comments
+ *
+ * @param comment Comments to be placed in a tool tip
+ * @return Tool tip
+ */
+function createCommentsToolTip(comment) {
+ // Create tooltip container
+ var toolTip = $('
');
+ // Create textarea to hold comment
+ var txtArea = $('').css({
+ 'font-size': '10px',
+ 'height': '50px',
+ 'width': '200px',
+ 'background-color': '#000',
+ 'color': '#fff',
+ 'border': '0px',
+ 'display': 'block'
+ });
+
+ // Create links to save and cancel changes
+ var lnkStyle = {
+ 'color': '#58ACFA',
+ 'font-size': '10px',
+ 'display': 'inline-block',
+ 'padding': '5px',
+ 'float': 'right'
+ };
+
+ var saveLnk = $('Save ').css(lnkStyle).hide();
+ var cancelLnk = $('Cancel ').css(lnkStyle).hide();
+ var infoSpan = $('Click to edit ').css(lnkStyle);
+
+ // Save changes onclick
+ saveLnk.bind('click', function(){
+ // Get node and comment
+ var node = $(this).parent().parent().find('img').attr('id').replace('Tip', '');
+ var comments = $(this).parent().find('textarea').val();
+
+ // Save comment
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'chdef',
+ tgt : '',
+ args : '-t;node;-o;' + node + ';usercomment=' + comments,
+ msg : 'out=nodesTab;tgt=' + node
+ },
+
+ success: function(data) {
+ data = decodeRsp(data);
+ showChdefOutput(data);
+ }
+ });
+
+ // Hide cancel and save links
+ $(this).hide();
+ cancelLnk.hide();
+ });
+
+ // Cancel changes onclick
+ cancelLnk.bind('click', function(){
+ // Get original comment and put it back
+ var orignComments = $(this).parent().find('textarea').text();
+ $(this).parent().find('textarea').val(orignComments);
+
+ // Hide cancel and save links
+ $(this).hide();
+ saveLnk.hide();
+ infoSpan.show();
+ });
+
+ // Show save link when comment is edited
+ txtArea.bind('click', function(){
+ saveLnk.show();
+ cancelLnk.show();
+ infoSpan.hide();
+ });
+
+ toolTip.append(txtArea);
+ toolTip.append(cancelLnk);
+ toolTip.append(saveLnk);
+ toolTip.append(infoSpan);
+
+ return toolTip;
+}
+
+/**
+ * Create a tool tip for node status
+ *
+ * @return Tool tip
+ */
+function createStatusToolTip() {
+ // Create tooltip container
+ var toolTip = $('
').css({
+ 'width': '150px',
+ 'font-weight': 'normal'
+ });
+
+ // Create info text
+ var info = $('
').css({
+ 'white-space': 'normal'
+ });
+ info.append('Click here to refresh the node status. To configure the xCAT monitor, ');
+
+ // Create link to turn on xCAT monitoring
+ var monitorLnk = $('click here ').css({
+ 'color': '#58ACFA',
+ 'font-size': '10px'
+ });
+
+ // Open dialog to configure xCAT monitor
+ monitorLnk.bind('click', function(){
+ // Check if xCAT monitor is enabled
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'monls',
+ tgt : '',
+ args : 'xcatmon',
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ openConfXcatMon(data);
+ }
+ });
+ });
+
+ info.append(monitorLnk);
+ toolTip.append(info);
+
+ return toolTip;
+}
+
+/**
+ * Create a tool tip for power status
+ *
+ * @return Tool tip
+ */
+function createPowerToolTip() {
+ // Create tooltip container
+ var toolTip = $('Click here to refresh the power status
').css({
+ 'width': '150px',
+ 'white-space': 'normal',
+ 'font-weight': 'normal'
+ });
+ return toolTip;
+}
+
+/**
+ * Create a tool tip for monitoring status
+ *
+ * @return Tool tip
+ */
+function createMonitorToolTip() {
+ // Create tooltip container
+ var toolTip = $('Click here to refresh the monitoring status
').css({
+ 'width': '150px',
+ 'white-space': 'normal',
+ 'font-weight': 'normal'
+ });
+ return toolTip;
+}
+
+/**
+ * Open dialog to configure xCAT monitor
+ *
+ * @param data Data returned from HTTP request
+ */
+function openConfXcatMon(data) {
+ // Create info bar
+ var info = createInfoBar('Configure the xCAT monitor. Select to enable or disable the monitor below.');
+ var dialog = $('
');
+ dialog.append(info);
+
+ // Create status area
+ var statusArea = $('
').css('padding-top', '10px');
+ var label = $('Status: ');
+ statusArea.append(label);
+
+ // Get xCAT monitor status
+ var status = data.rsp[0];
+ var buttons;
+ // If xCAT monitor is disabled
+ if (status.indexOf('not-monitored') > -1) {
+ status = $('Disabled ').css('padding', '0px 5px');
+ statusArea.append(status);
+
+ // Create enable and cancel buttons
+ buttons = {
+ "Enable": function(){
+ // Enable xCAT monitor
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'monstart',
+ tgt : '',
+ args : 'xcatmon',
+ msg : ''
+ },
+
+ success : function(data){
+ data = decodeRsp(data);
+ openDialog('info', data.rsp[0]);
+ }
+ });
+ $(this).dialog("close");
+ },
+ "Cancel": function(){
+ $(this).dialog("close");
+ }
+ };
+ } else {
+ status = $('Enabled ').css('padding', '0px 5px');
+ statusArea.append(status);
+
+ // Create disable and cancel buttons
+ buttons = {
+ "Disable": function(){
+ // Disable xCAT monitor
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'monstop',
+ tgt : '',
+ args : 'xcatmon',
+ msg : ''
+ },
+
+ success : function(data){
+ data = decodeRsp(data);
+ openDialog('info', data.rsp[0]);
+ }
+ });
+ $(this).dialog("close");
+ },
+ "Cancel": function(){
+ $(this).dialog("close");
+ }
+ };
+ }
+
+ dialog.append(statusArea);
+
+ // Open dialog
+ dialog.dialog({
+ modal: true,
+ width: 500,
+ buttons: buttons
+ });
+}
+
+/**
+ * Show chdef output
+ *
+ * @param data Data returned from HTTP request
+ */
+function showChdefOutput(data) {
+ // Get output
+ var out = data.rsp;
+ var args = data.msg.split(';');
+ var tabID = args[0].replace('out=', '');
+ var tgt = args[1].replace('tgt=', '');
+
+ // Find info bar on nodes tab, if any
+ var info = $('#' + tabID).find('.ui-state-highlight');
+ if (!info.length) {
+ // Create info bar if one does not exist
+ info = createInfoBar('');
+ $('#' + tabID).append(info);
+ }
+
+ // Go through output and append to paragraph
+ var prg = $('
');
+ for (var i in out) {
+ prg.append(tgt + ': ' + out[i] + ' ');
+ }
+
+ info.append(prg);
+}
+
+/**
+ * Set node attributes
+ *
+ * @param data Data returned from HTTP request
+ */
+function setNodeAttrs(data) {
+ // Clear hash table containing definable node attributes
+ nodeAttrs = 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));
+
+ // Remove arrow brackets
+ descr = descr.replace(new RegExp('<|>', 'g'), '');
+
+ // Set hash table where key = attribute name and value = description
+ nodeAttrs[key] = descr;
+ } else {
+ // Remove arrow brackets
+ attr = attr.replace(new RegExp('<|>', 'g'), '');
+
+ // Append description to hash table
+ nodeAttrs[key] = nodeAttrs[key] + '\n' + attr;
+ }
+ } // End of if
+ } // End of for
+}
+
+
+/**
+ * Load the discover z/VM virtual systems page
+ *
+ * @param tgtNode Target node to set properties
+ */
+function discoverVMNodes(tgtNodes) {
+ var fs, legend, htmlLine;
+
+ // Get nodes tab
+ var tab = getNodesTab();
+
+ // Generate new tab ID
+ var inst = 0;
+ var newTabId = 'discoverVMNodesTab' + inst;
+ while ($('#' + newTabId).length) {
+ // If one already exists, generate another one
+ inst = inst + 1;
+ newTabId = 'discoverVMNodesTab' + inst;
+ }
+
+ // Open new tab
+ // Create set properties form
+ var discoverVMNodesForm = $('
');
+
+ // Create info bar
+ var infoBar = createInfoBar( 'Initiate, stop or query the status of z/VM node discovery. ' +
+ 'To initiate discovery, specify discovery parameters and click on the Discover button. ' +
+ 'To stop an on-going discovery related to a z/VM host, specify the host node name and '+
+ 'click on the Stop button. ' +
+ 'To obtain the status of discovery for a particular host, specify the host node name and '+
+ 'click on the Stop button.'
+ );
+ discoverVMNodesForm.append(infoBar);
+
+ // Create the status bar and hide it.
+ var statBarId = 'statusBar_' + newTabId;
+ //var statBar = $( '
' );
+ //discoverVMNodesForm.append( statBar );
+ statBar = createStatusBar( statBarId );
+ statBar.hide();
+ discoverVMNodesForm.append( statBar );
+
+ // Create Host fieldset
+ fs = $(' ');
+ legend = $('z/VM Host ');
+ fs.append(legend);
+ discoverVMNodesForm.append(fs);
+
+ // Target node or group
+ htmlLine = $('z/VM host range:
');
+ discoverVMNodesForm.append( htmlLine );
+
+ // Create Discovery Parameters fieldset
+ fs = $(' ');
+ legend = $('Discovery Parameters ');
+ fs.append( legend );
+ discoverVMNodesForm.append( fs );
+
+ // Create an input for each definable attribute
+ var div, label, input, descr, value;
+
+ // Define DefineTo radio buttons
+ div = $('
').css( 'display', 'inline-block' ).css( 'vertical-align', 'top' );
+ div.append( 'Define systems to: ' );
+ div.append( ' xCAT and OpenStack ' );
+ div.append( ' xCAT only ' );
+ div.append( ' OpenStack only (only already discovered xCAT nodes) ' );
+ discoverVMNodesForm.append( div );
+ discoverVMNodesForm.append( ' ' );
+
+ // Userid filter
+ divUserid = newTabId + "_divUserid";
+ div = $('
').css( 'display', 'inline-table' ).css( 'vertical-align', 'top' );
+ div.append( 'z/VM Userid Filter: ' );
+ div.append( ' ' ).css( 'margin-top', '5px' );
+ discoverVMNodesForm.append( div );
+ discoverVMNodesForm.append( ' ' );
+
+ // IP address filter
+ divIP = newTabId + "_divIP";
+ div = $('
').css( 'display', 'inline-table' ).css( 'vertical-align', 'top' );
+ div.append( 'IP Address Filter: ' );
+ div.append( ' ' ).css( 'margin-top', '5px' );
+ discoverVMNodesForm.append( div );
+ discoverVMNodesForm.append( ' ' );
+
+ // Group name input
+ divGroup = newTabId + '_divGroup';
+ div = $('
').css( 'display', 'inline-table' ).css( 'vertical-align', 'top' );
+ div.append( 'Assign to group(s): ' );
+ div.append( ' ' ).css( 'margin-top', '5px' );
+ discoverVMNodesForm.append( div );
+ discoverVMNodesForm.append( ' ' );
+
+ // Node Name Format input
+ divNodename = newTabId + '_divNodename';
+ div = $('
').css( 'display', 'inline-table' ).css( 'vertical-align', 'top' );
+ div.append( 'xCAT node name format: ' );
+ div.append( ' ' ).css( 'margin-top', '5px' );
+ discoverVMNodesForm.append( div );
+ discoverVMNodesForm.append( ' ' );
+ discoverVMNodesForm.find('#' + divNodename).hide();
+
+ // OpenStack operand input
+ divOpenStackOps = newTabId + '_divOpenStackOps';
+ div = $('
').css( 'display', 'inline-table' ).css( 'vertical-align', 'top' );
+ div.append( 'Assign to OpenStack Project: ' );
+ div.append( ' ' ).css( 'margin-top', '5px' );
+ div.append( ' ' );
+ div.append( 'Assign to OpenStack User: ' );
+ div.append( ' ' ).css( 'margin-top', '5px' );
+ discoverVMNodesForm.append( div );
+ discoverVMNodesForm.append( ' ' );
+
+ // Define Verbose radio buttons
+ div = $('
').css( 'display', 'inline-table' ).css( 'vertical-align', 'top' ).css( 'text-align', 'top' );
+ div.append( 'Node discovery output: ' );
+ div.append( ' Normal response, showing only important information ' );
+ div.append( ' Verbose response, normal response plus additional information (e.g. reason a system is ignored) ' );
+ discoverVMNodesForm.append( div );
+ discoverVMNodesForm.append( ' ' );
+
+ // Generate tooltips
+ discoverVMNodesForm.find('div input[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"
+ }
+ });
+
+ // Show appropriate input fields for defineto choices.
+ discoverVMNodesForm.change(function(){
+ var defineTo = $(this).parent().find('input[name="defineTo"]:checked').val();
+ if ( defineTo == 'both' ) {
+ discoverVMNodesForm.find('#' + divUserid).show();
+ discoverVMNodesForm.find('#' + divIP).show();
+ discoverVMNodesForm.find('#' + divGroup).show();
+ discoverVMNodesForm.find('#' + divOpenStackOps).show();
+ discoverVMNodesForm.find('#' + divNodename).hide();
+ } else if ( defineTo == 'xcatonly' ) {
+ discoverVMNodesForm.find('#' + divUserid).show();
+ discoverVMNodesForm.find('#' + divIP).show();
+ discoverVMNodesForm.find('#' + divGroup).show();
+ discoverVMNodesForm.find('#' + divOpenStackOps).hide();
+ discoverVMNodesForm.find('#' + divNodename).show();
+ } else if ( defineTo == 'openstackonly' ) {
+ discoverVMNodesForm.find('#' + divUserid).hide();
+ discoverVMNodesForm.find('#' + divIP).hide();
+ discoverVMNodesForm.find('#' + divGroup).hide();
+ discoverVMNodesForm.find('#' + divOpenStackOps).show();
+ discoverVMNodesForm.find('#' + divNodename).hide();
+ }
+ });
+
+
+ // Discover nodes button action
+ var discoverBtn = createButton('Discover');
+ discoverBtn.click(function() {
+ var argList = '';
+ var filter = '';
+
+ var hosts = $(this).parent().find('input[name=hosts]').val();
+ if ( hosts != '' ) {
+ argList = 'zvmhost=' + hosts;
+ }
+
+ var defineTo = $(this).parent().find('input[name="defineTo"]:checked').val();
+ argList = argList + '||defineto=' + defineTo;
+
+ var verbose = $(this).parent().find('input[name="verbose"]:checked').val();
+ if ( verbose == 'yes' ) {
+ argList = argList + '||--verbose';
+ }
+
+ var useridFilter = $(this).parent().find('input[name=useridFilter]').val();
+ if (( defineTo == 'both' || defineTo == 'xcatonly' ) && ( useridFilter != '' )) {
+ argList = argList + '||useridfilter=' + useridFilter;
+ }
+
+ var ipFilter = $(this).parent().find('input[name=ipFilter]').val();
+ if (( defineTo == 'both' || defineTo == 'xcatonly' ) && ( ipFilter != '' )) {
+ argList = argList + '||ipfilter=' + ipFilter;
+ }
+
+ var group = $(this).parent().find('input[name=group]').val();
+ if (( defineTo == 'both' || defineTo == 'xcatonly' ) && ( group != '' )) {
+ argList = argList + '||groups=' + group;
+ }
+
+ var nodeNameFmt = $(this).parent().find('input[name=nodeNameFmt]').val();
+ if ( defineTo == 'xcatonly' && nodeNameFmt != '' ) {
+ argList = argList + '||nodenameformat=' + nodeNameFmt;
+ }
+
+ var openStackProj = $(this).parent().find('input[name=openStackProj]').val();
+ var openStackUser = $(this).parent().find('input[name=openStackUser]').val();
+ if ((( defineTo == 'both' ) || ( defineTo == 'openstackonly' )) &&
+ (( openStackProj != '' ) || ( openStackUser != '' ))) {
+ if ( openStackProj != '' ) {
+ osArgs = '--project ' + openStackProj;
+ } else {
+ osArgs = '';
+ }
+ if ( openStackUser != '' ) {
+ if ( osArgs != '' ) {
+ osArgs = osArgs + ' --user ' + openStackUser;
+ } else {
+ osArgs = '--user ' + openStackUser;
+ }
+ }
+ argList = argList + "||openstackoperands='" + osArgs + "'";
+ }
+
+ var out = $('
');
+ out.append( 'Starting node discovery...' );
+ out.append( ' ' );
+ out.append( 'If node discovery is a short running task then its response will follow. If, however, the time it takes to complete discovery exceeds the http request timeout of a few minutes then the discovery response will not be returned to the browser. The status and list buttons can be used to obtained status on the discovery and see what systems have been discovered.' );
+ $( '#' + statBarId ).find( 'div' ).append( out );
+ statBar.show();
+
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'nodediscoverstart',
+ tgt : '',
+ args : argList,
+ att : '',
+ msg : statBarId
+ },
+ success: function(data) {
+ data = decodeRsp(data);
+ updateDiscoverStatusBar( data, 1 );
+ }
+ });
+
+ });
+ discoverVMNodesForm.append(discoverBtn);
+
+ // Status button
+ var statusBtn = createButton('Status');
+ statusBtn.click( function() {
+ var hosts = $(this).parent().find('input[name=hosts]').val();
+ var out = $('
');
+ out.append( 'Querying status for discovery on ' + hosts + '...' );
+ out.append( ' ' );
+ $( '#' + statBarId ).find( 'div' ).append( out );
+
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'nodediscoverstatus',
+ tgt : '',
+ args : '--zvmhost||' + hosts,
+ att : '',
+ msg : statBarId
+ },
+ success: function(data) {
+ data = decodeRsp(data);
+ updateDiscoverStatusBar( data, 1 );
+ }
+ });
+
+ });
+ discoverVMNodesForm.append( statusBtn );
+
+ // List button
+ var listBtn = createButton('List');
+ listBtn.click( function() {
+ var hosts = $(this).parent().find('input[name=hosts]').val();
+ var out = $('
');
+ out.append( 'Listing systems discovered by the latest discovery on ' + hosts + '...' );
+ out.append( ' ' );
+ $( '#' + statBarId ).find( 'div' ).append( out );
+
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'nodediscoverls',
+ tgt : '',
+ args : '-t||zvm||--zvmhost||' + hosts,
+ att : '',
+ msg : statBarId
+ },
+ success: function(data) {
+ data = decodeRsp(data);
+ updateDiscoverStatusBar( data, 1 );
+ }
+ });
+ });
+ discoverVMNodesForm.append( listBtn );
+
+ // Stop button
+ var stopBtn = createButton('Stop');
+ stopBtn.click(function() {
+ var hosts = $(this).parent().find('input[name=hosts]').val();
+ var out = $('
');
+ out.append( 'Stopping discovery on ' + hosts + '...' );
+ out.append( ' ' );
+ $( '#' + statBarId ).find( 'div' ).append( out );
+
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'nodediscoverstop',
+ tgt : '',
+ args : '--zvmhost||' + hosts,
+ att : '',
+ msg : statBarId
+ },
+ success: function(data) {
+ data = decodeRsp(data);
+ updateDiscoverStatusBar( data, 1 );
+ }
+ });
+ });
+ discoverVMNodesForm.append( stopBtn );
+
+ // Append to discover tab
+ tab.add(newTabId, 'Discover', discoverVMNodesForm, true);
+
+ // Select new tab
+ tab.select(newTabId);
+}
+
+
+/**
+ * Update discovery status bar
+ *
+ * @param data Data returned from HTTP request
+ */
+function updateDiscoverStatusBar( data, preformatted ) {
+ var statBarId = data.msg;
+ var rsp = data.rsp;
+ var statBar = $( '#' + statBarId );
+
+ // Go through response to make it readable in the status bar.
+ var out = $('
');
+ for ( var i in rsp ) {
+ if ( preformatted == 1 ) {
+ out.append( '' + rsp[i] + ' ' );
+ } else {
+ out.append( rsp[i] + ' ' );
+ }
+ }
+
+ // Write response to status bar and show the bar.
+ $( '#' + statBarId ).find( 'div' ).append( out );
+ statBar.show();
+}
+
+
+/**
+ * Load set node properties page
+ *
+ * @param tgtNode Target node to set properties
+ */
+function editNodeProps(tgtNode) {
+ // Get nodes tab
+ var tab = getNodesTab();
+
+ // Generate new tab ID
+ var inst = 0;
+ var newTabId = 'editPropsTab' + inst;
+ while ($('#' + newTabId).length) {
+ // If one already exists, generate another one
+ inst = inst + 1;
+ newTabId = 'editPropsTab' + inst;
+ }
+
+ // Open new tab
+ // Create set properties form
+ var editPropsForm = $('
');
+
+ // Create info bar
+ var infoBar = createInfoBar('Choose the properties you wish to change on the node. When you are finished, click Save.');
+ editPropsForm.append(infoBar);
+
+ // Create an input for each definable attribute
+ var div, label, input, descr, value;
+ // Set node attribute
+ origAttrs[tgtNode]['node'] = tgtNode;
+ for (var key in nodeAttrs) {
+ // If an attribute value exists
+ if (origAttrs[tgtNode][key]) {
+ // Set the value
+ value = origAttrs[tgtNode][key];
+ } else {
+ value = '';
+ }
+
+ // Create label and input for attribute
+ div = $('
').css('display', 'inline-table');
+ label = $('' + key + ': ').css('vertical-align', 'middle');
+ input = $(' ').css('margin-top', '5px');
+
+ // Change border to blue onchange
+ input.bind('change', function(event) {
+ $(this).css('border-color', 'blue');
+ });
+
+ div.append(label);
+ div.append(input);
+ editPropsForm.append(div);
+ }
+
+ // Change style for last division
+ div.css({
+ 'display': 'block',
+ 'margin': '0px 0px 10px 0px'
+ });
+
+ // Generate tooltips
+ editPropsForm.find('div input[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"
+ }
+ });
+
+ // Save changes
+ var saveBtn = createButton('Save');
+ saveBtn.click(function() {
+ // 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 node attributes
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'chdef',
+ tgt : '',
+ args : '-t;node;-o;' + tgtNode + ';' + args,
+ msg : 'out=' + newTabId + ';tgt=' + tgtNode
+ },
+
+ success: function(data) {
+ data = decodeRsp(data);
+ showChdefOutput(data);
+ }
+ });
+ });
+ editPropsForm.append(saveBtn);
+
+ // Cancel changes
+ var cancelBtn = createButton('Cancel');
+ cancelBtn.click(function() {
+ // Close the tab
+ tab.remove($(this).parent().parent().attr('id'));
+ });
+ editPropsForm.append(cancelBtn);
+
+ // Append to discover tab
+ tab.add(newTabId, 'Edit', editPropsForm, true);
+
+ // Select new tab
+ tab.select(newTabId);
+}
+
+/**
+ * Open set node attributes dialog
+ */
+function openSetAttrsDialog() {
+ // Open new tab
+ // Create set properties form
+ var setPropsForm = $('
');
+
+ // 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, descr, value;
+ for (var key in nodeAttrs) {
+ value = '';
+
+ // Create label and input for attribute
+ div = $('
').css('display', 'inline');
+ label = $('' + key + ': ').css('vertical-align', 'middle');
+ input = $(' ').css('margin-top', '5px');
+
+ // Change border to blue onchange
+ input.bind('change', function(event) {
+ $(this).css('border-color', 'blue');
+ });
+
+ div.append(label);
+ div.append(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: 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());
+ }
+ });
+
+ // Enable vertical scroll
+ setPropsForm.css('overflow', 'auto');
+
+ // Open form as a dialog
+ setPropsForm.dialog({
+ title: 'Set attributes',
+ modal: true,
+ close: function(){
+ $(this).remove();
+ },
+ height: 400,
+ width: 800,
+ buttons: {
+ "Save": function() {
+ // Remove any warning messages
+ $(this).find('.ui-state-error').remove();
+
+ // Get all inputs
+ var inputs = $(this).find('input');
+
+ // Go through each input
+ var args = '';
+ var tgtNode, 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();
+
+ // Get node name
+ if (attrName == 'node') {
+ tgtNode = attrVal;
+ } else {
+ // Build argument string
+ if (args) {
+ // Handle subsequent arguments
+ args += ';' + attrName + '=' + attrVal;
+ } else {
+ // Handle the 1st argument
+ args += attrName + '=' + attrVal;
+ }
+ }
+ }
+ });
+
+ // Send command to change node attributes
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'chdef',
+ tgt : '',
+ args : '-t;node;-o;' + tgtNode + ';' + args,
+ msg : 'node=' + tgtNode
+ },
+
+ /**
+ * Show results
+ *
+ * @param data
+ * Data returned from HTTP request
+ * @return Nothing
+ */
+ success: function(data) {
+ // Get output
+ data = decodeRsp(data);
+ var out = data.rsp;
+ var node = data.msg.replace('node=', '');
+
+ // Go through output and append to paragraph
+ var msg = '';
+ for (var i in out) {
+ if (!msg) {
+ msg = node + ': ' + out[i];
+ } else {
+ msg += ' ' + node + ': ' + out[i];
+ }
+ }
+
+ openDialog('info', msg);
+ }
+ });
+
+ // Close dialog
+ $(this).dialog( "close" );
+ },
+ "Cancel": function(){
+ $(this).dialog( "close" );
+ }
+ }
+ });
+}
+
+/**
+ * Turn on monitoring for a given node
+ *
+ * @param node Node to monitor on or off
+ * @param monitor Monitor state, on or off
+ */
+function monitorNode(node, monitor) {
+ // Show ganglia loader
+ var gangliaCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)');
+ gangliaCol.find('img').show();
+
+ if (monitor == 'on') {
+ // Append loader to warning bar
+ var warningBar = $('#nodesTab').find('.ui-state-error p');
+ if (warningBar.length) {
+ warningBar.append(createLoader(''));
+ }
+
+ if (node) {
+ // Check if ganglia RPMs are installed
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'gangliacheck;' + node,
+ msg : node // Node range will be passed along in data.msg
+ },
+
+ /**
+ * Start ganglia on a given node range
+ *
+ * @param data Data returned from HTTP request
+ */
+ success : function(data) {
+ // Get response
+ data = decodeRsp(data);
+ var out = data.rsp[0].split(/\n/);
+
+ // Go through each line
+ var warn = false;
+ var warningMsg = '';
+ for (var i in out) {
+ // If an RPM is not installed
+ if (out[i].indexOf('not installed') > -1) {
+ warn = true;
+
+ if (warningMsg) {
+ warningMsg += ' ' + out[i];
+ } else {
+ warningMsg = out[i];
+ }
+ }
+ }
+
+ // If there are warnings
+ if (warn) {
+ // Create warning bar
+ var warningBar = createWarnBar(warningMsg);
+ warningBar.css('margin-bottom', '10px');
+ warningBar.prependTo($('#nodesTab'));
+ } else {
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'gangliastart;' + data.msg + ';-r',
+ msg : data.msg
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ // Remove any warnings
+ $('#nodesTab').find('.ui-state-error').remove();
+
+ // Update datatable
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'gangliastatus;' + data.msg,
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ loadGangliaStatus(data);
+ }
+ });
+ }
+ });
+ } // End of if (warn)
+ } // End of function(data)
+ });
+ } else {
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'gangliastart',
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ // Remove any warnings
+ $('#nodesTab').find('.ui-state-error').remove();
+ }
+ });
+ } // End of if (node)
+ } else {
+ var args;
+ if (node) {
+ args = 'gangliastop;' + node + ';-r';
+ } else {
+ args = 'gangliastop';
+ }
+
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : args,
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ // Hide ganglia loader
+ var gangliaCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)');
+ gangliaCol.find('img').hide();
+ }
+ });
+ }
+}
+
+/**
+ * Install Ganglia on a given node
+ *
+ * @param node Node to install Ganglia on
+ */
+function installGanglia(node) {
+ var iframe = createIFrame('lib/cmd.php?cmd=webrun&tgt=&args=installganglia;' + node + '&msg=' + node + '&opts=flush');
+ iframe.prependTo($('#nodesTab'));
+
+ // Turn on Ganglia for node
+ monitorNode(node, 'on');
+}
+
+/**
+ * After nodes are loaded, load more information based on different hardware architectures
+ *
+ * @param group Group name
+ */
+function advancedLoad(group){
+ var tempIndex = 0;
+ var tableHeaders = $('#' + nodesTableId).parents('.dataTables_scroll').find('.dataTables_scrollHead thead tr:eq(0) th');
+ var colNameHash = new Object();
+ var colName = '';
+ var archCol = 0, hcpCol = 0;
+
+ // Find out the column name and their index
+ for (tempIndex = 0; tempIndex < tableHeaders.size(); tempIndex++){
+ var header = tableHeaders.eq(tempIndex);
+ // Skip headers that are links, e.g. status, power, and monitor
+ if (header.find('a').size() > 0){
+ continue;
+ }
+
+ colName = header.text();
+
+ if (colName) {
+ colNameHash[colName] = tempIndex;
+ }
+ }
+
+ // If there is no arch column, exit because you cannot distinguish hardware type
+ if (!colNameHash['arch']) {
+ return;
+ }
+
+ if (!colNameHash['hcp']) {
+ return;
+ }
+ archCol = colNameHash['arch'];
+ hcpCol = colNameHash['hcp'];
+
+ // Get hardware control point
+ var rows = $('#' + nodesTableId + ' tbody tr');
+ var hcps = new Object();
+ var rowsNum = rows.size();
+ for (var j = 0; j < rowsNum; j++) {
+ var val = rows.eq(j).find('td').eq(hcpCol).html();
+ var archval = rows.eq(j).find('td').eq(archCol).html();
+ if (-1 == archval.indexOf('390')){
+ continue;
+ }
+ hcps[val] = 1;
+ }
+
+ if (Object.keys(hcps).length == 0) {
+ openDialog('warn', "No node found with hcp column filled in and 390 arch!");
+ return;
+ }
+ // Get Nodes info bar
+ //var nodeInfoBar = getNodesTabInfoBar();
+ //nodeInfoBar.append("\nEntering Advanced Load...\n")
+
+ var args;
+ var shortzHcps = new Array();
+ var zhcpHash = new Object();
+ for (var h in hcps) {
+ // Get node without domain name
+ args = h.split('.');
+
+ if (!zhcpHash[args[0]]) {
+
+ shortzHcps.push(args[0]);
+ zhcpHash[args[0]] = 1;
+
+ // If there are no disk pools or network names cookie for this hcp
+ if (!$.cookie('xcat_' + args[0] + 'diskpools') || !$.cookie('xcat_' + args[0] + 'networks')) {
+ // Check if SMAPI is online
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'lsvm',
+ tgt : args[0],
+ args : '',
+ msg : 'group=' + group + ';hcp=' + args[0]
+ },
+
+ // Load hardware control point specific info
+ // Get disk pools and network names
+ success : function(data) {
+ data = decodeRsp(data);
+ loadHcpInfo(data);
+ }
+ });
+ }
+ }
+ } // End of for
+
+ // Save zHCPs as a cookie
+ setzHcpCookies(shortzHcps);
+
+ // Retrieve z/VM hypervisors and their zHCPs
+ if (!$.cookie('xcat_zvms')) {
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webportal',
+ tgt : '',
+ args : 'lszvm',
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ setzVMCookies(data);
+ }
+ });
+ }
+}
+
+/**
+ * Jump to provision page on-click
+ *
+ * @param tgtNodes Target nodes
+ */
+function jump2Provision(tgtNodes){
+ var nodeArray = tgtNodes.split(',');
+ var nodeName = '';
+ var index = 0;
+ var archType = '';
+ var errorMsg = '';
+ var master = '';
+ var tftpserver = '';
+ var nfsserver = '';
+ var diaDiv = $('
');
+
+ // Check the first node's arch type
+ for (index in nodeArray){
+ nodeName = nodeArray[index];
+
+ // Skip if node does not have arch
+ if (!origAttrs[nodeName]['arch']){
+ errorMsg = 'Nodes should have arch defined! ';
+ break;
+ }
+
+ if (index == 0) {
+ archType = origAttrs[nodeName]['arch'];
+ }
+
+ // Skip if nodes do not have same arch
+ if (archType != origAttrs[nodeName]['arch']){
+ errorMsg = 'Nodes should belong to the same arch! ';
+ break;
+ }
+ }
+
+ // Skip if nodes do not have MAC address
+ for (index in nodeArray){
+ if (!origAttrs[nodeName]['mac'] || !origAttrs[nodeName]['ip']){
+ errorMsg += 'Nodes should have the IP and MAC addresses defined! ';
+ break;
+ }
+ }
+
+ if (archType.indexOf('390') != -1) {
+ errorMsg += 'Please use the provision page';
+ }
+
+ // Open dialog to show error message
+ if (errorMsg){
+ diaDiv.append(createWarnBar(errorMsg));
+ diaDiv.dialog({
+ modal: true,
+ close: function(){
+ $(this).remove();
+ },
+ width: 400,
+ buttons: {
+ 'Close': function(){
+ $(this).dialog('destroy');
+ }
+ }
+ });
+
+ return;
+ }
+
+ if (origAttrs[nodeName]['xcatmaster']) {
+ master = origAttrs[nodeName]['xcatmaster'];
+ }
+
+ if (origAttrs[nodeName]['tftpserver']) {
+ tftpserver = origAttrs[nodeName]['tftpserver'];
+ }
+
+ if (origAttrs[nodeName]['nfsserver']) {
+ nfsserver = origAttrs[nodeName]['nfsserver'];
+ }
+
+ window.location.href = 'provision.php?nodes=' + tgtNodes + '&arch=' + archType + '&master=' + master +
+ '&tftpserver=' + tftpserver + '&nfsserver=' + nfsserver;
+}
diff --git a/xCAT-UI/js/nodes/nodeset.js b/xCAT-UI/js/nodes/nodeset.js
index c1b2acfe8..87d84ba1e 100644
--- a/xCAT-UI/js/nodes/nodeset.js
+++ b/xCAT-UI/js/nodes/nodeset.js
@@ -1,296 +1,308 @@
-/**
- * Load nodeset page
- *
- * @param tgtNodes Targets to run nodeset against
- */
-function loadNodesetPage(tgtNodes) {
- // Get OS images
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'tabdump',
- tgt : '',
- args : 'osimage',
- msg : ''
- },
-
- success : setOSImageCookies
- });
-
- // Get nodes tab
- var tab = getNodesTab();
-
- // Generate new tab ID
- var inst = 0;
- var tabId = 'nodesetTab' + inst;
- while ($('#' + tabId).length) {
- // If one already exists, generate another one
- inst = inst + 1;
- tabId = 'nodesetTab' + inst;
- }
-
- // Create nodeset form
- var nodesetForm = $('
');
-
- // Create status bar
- var statBarId = 'nodesetStatusBar' + inst;
- var statBar = createStatusBar(statBarId).hide();
-
- // Create loader
- var loader = createLoader('nodesetLoader');
- statBar.find('div').append(loader);
-
- // Create info bar
- var infoBar = createInfoBar('Set the boot state for a node range');
- nodesetForm.append(statBar, infoBar);
-
- // Create VM fieldset
- var vmFS = $(' ');
- var vmLegend = $('Virtual Machine ');
- vmFS.append(vmLegend);
- nodesetForm.append(vmFS);
-
- var vmAttr = $('
');
- vmFS.append($(''));
- vmFS.append(vmAttr);
-
- // Create options fieldset
- var imageFS = $(' ');
- var imageLegend = $('Image ');
- imageFS.append(imageLegend);
- nodesetForm.append(imageFS);
-
- var imageAttr = $('
');
- imageFS.append($(''));
- imageFS.append(imageAttr);
-
- // Create target node or group
- var tgt = $('Target node range:
');
- vmAttr.append(tgt);
-
- // Create boot type drop down
- var type = $('
');
- var typeLabel = $('Boot type: ');
- var typeSelect = $(' ');
- typeSelect.append('zvm '
- + 'pxe '
- + 'yaboot '
- );
- type.append(typeLabel);
- type.append(typeSelect);
- imageAttr.append(type);
-
- // Create operating system image input
- var os = $('
');
- var osLabel = $('Operating system image: ');
- var osSelect = $(' ');
- osSelect.append($(' '));
-
- var imageNames = $.cookie('xcat_imagenames').split(',');
- if (imageNames) {
- imageNames.sort();
- for (var i in imageNames) {
- osSelect.append($('' + imageNames[i] + ' '));
- }
- }
- os.append(osLabel);
- os.append(osSelect);
- imageAttr.append(os);
-
- // Generate tooltips
- nodesetForm.find('div input[title],select').tooltip({
- position: "center right",
- offset: [-2, 10],
- effect: "fade",
- opacity: 0.7,
- predelay: 800,
- events : {
- def : "mouseover,mouseout",
- input : "mouseover,mouseout",
- widget : "focus mouseover,blur mouseout",
- tooltip : "mouseover,mouseout"
- }
- });
-
- /**
- * Ok
- */
- var okBtn = createButton('Ok');
- okBtn.css({
- 'width': '80px',
- 'display': 'block'
- });
- okBtn.bind('click', function(event) {
- // Remove any warning messages
- $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
-
- // Check state, OS, arch, and profile
- var ready = true;
- var inputs = $('#' + tabId + ' input');
- for ( var i = 0; i < inputs.length; i++) {
- if (!inputs.eq(i).val() && inputs.eq(i).attr('name') != 'diskPw') {
- inputs.eq(i).css('border', 'solid #FF0000 1px');
- ready = false;
- } else {
- inputs.eq(i).css('border', 'solid #BDBDBD 1px');
- }
- }
-
- if (ready) {
- // Get nodes
- var tgts = $('#' + tabId + ' input[name=target]').val();
- // Get boot type
- var type = $('#' + tabId + ' select[id=bootType]').val();
- // Get operating system image
- var os = $('#' + tabId + ' select[name=os]').val();
-
- // Disable all inputs, selects, and Ok button
- inputs.attr('disabled', 'disabled');
- $('#' + tabId + ' select').attr('disabled', 'disabled');
- $(this).attr('disabled', 'true');
-
- /**
- * (1) Set the OS, arch, and profile
- */
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'nodeadd',
- tgt : '',
- args : tgts + ';noderes.netboot=' + type,
- msg : 'cmd=nodeadd;inst=' + inst
- },
-
- success : updateNodesetStatus
- });
-
- // Show status bar
- statBar.show();
- } else {
- // Show warning message
- var warn = createWarnBar('You are missing some values!');
- warn.prependTo($(this).parents('.ui-tabs-panel'));
- }
- });
- nodesetForm.append(okBtn);
-
- // Append to discover tab
- tab.add(tabId, 'Nodeset', nodesetForm, true);
-
- // Select new tab
- tab.select(tabId);
-}
-
-/**
- * Update nodeset status
- *
- * @param data Data returned from HTTP request
- */
-function updateNodesetStatus(data) {
- // Get ajax response
- var rsp = data.rsp;
- var args = data.msg.split(';');
- var cmd = args[0].replace('cmd=', '');
-
- // Get nodeset instance
- var inst = args[1].replace('inst=', '');
- // Get status bar ID
- var statBarId = 'nodesetStatusBar' + inst;
- // Get tab ID
- var tabId = 'nodesetTab' + inst;
-
- // Get nodes
- var tgts = $('#' + tabId + ' input[name=target]').val();
- // Get operating system image
- var os = $('#' + tabId + ' select[name=os]').val();
-
- /**
- * (2) Update /etc/hosts
- */
- if (cmd == 'nodeadd') {
- if (rsp.length) {
- $('#' + statBarId).find('img').hide();
- $('#' + statBarId).find('div').append('(Error) Failed to create node definition ');
- } else {
- // Create target nodes string
- var tgtNodesStr = '';
- var nodes = tgts.split(',');
-
- // Loop through each node
- for ( var i in nodes) {
- // If it is the 1st and only node
- if (i == 0 && i == nodes.length - 1) {
- tgtNodesStr += nodes[i];
- }
- // If it is the 1st node of many nodes
- else if (i == 0 && i != nodes.length - 1) {
- // Append a comma to the string
- tgtNodesStr += nodes[i] + ', ';
- } else {
- // If it is the last node
- if (i == nodes.length - 1) {
- // Append nothing to the string
- tgtNodesStr += nodes[i];
- } else {
- // Append a comma to the string
- tgtNodesStr += nodes[i] + ', ';
- }
- }
- }
-
- $('#' + statBarId).find('div').append('Node definition created for ' + tgtNodesStr + ' ');
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'makehosts',
- tgt : '',
- args : '',
- msg : 'cmd=makehosts;inst=' + inst
- },
-
- success : updateNodesetStatus
- });
- }
- }
-
- /**
- * (4) Update DNS
- */
- else if (cmd == 'makehosts') {
- // If no output, no errors occurred
- if (rsp.length) {
- $('#' + statBarId).find('div').append('(Error) Failed to update /etc/hosts ');
- } else {
- $('#' + statBarId).find('div').append('/etc/hosts updated ');
- }
-
- // Go straight to prepare node for boot
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'nodeset',
- tgt : tgts,
- args : 'osimage=' + os,
- msg : 'cmd=nodeset;inst=' + inst
- },
-
- success : updateNodesetStatus
- });
- }
-
- /**
- * (5) Boot node from network
- */
- else if (cmd == 'nodeset') {
- // Write ajax response to status bar
- var prg = writeRsp(rsp, '');
- $('#' + statBarId).find('div').append(prg);
-
- // Hide loader
- $('#' + statBarId).find('img').hide();
- }
+/**
+ * Load nodeset page
+ *
+ * @param tgtNodes Targets to run nodeset against
+ */
+function loadNodesetPage(tgtNodes) {
+ // Get OS images
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'tabdump',
+ tgt : '',
+ args : 'osimage',
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ setOSImageCookies(data);
+ }
+ });
+
+ // Get nodes tab
+ var tab = getNodesTab();
+
+ // Generate new tab ID
+ var inst = 0;
+ var tabId = 'nodesetTab' + inst;
+ while ($('#' + tabId).length) {
+ // If one already exists, generate another one
+ inst = inst + 1;
+ tabId = 'nodesetTab' + inst;
+ }
+
+ // Create nodeset form
+ var nodesetForm = $('
');
+
+ // Create status bar
+ var statBarId = 'nodesetStatusBar' + inst;
+ var statBar = createStatusBar(statBarId).hide();
+
+ // Create loader
+ var loader = createLoader('nodesetLoader');
+ statBar.find('div').append(loader);
+
+ // Create info bar
+ var infoBar = createInfoBar('Set the boot state for a node range');
+ nodesetForm.append(statBar, infoBar);
+
+ // Create VM fieldset
+ var vmFS = $(' ');
+ var vmLegend = $('Virtual Machine ');
+ vmFS.append(vmLegend);
+ nodesetForm.append(vmFS);
+
+ var vmAttr = $('
');
+ vmFS.append($(''));
+ vmFS.append(vmAttr);
+
+ // Create options fieldset
+ var imageFS = $(' ');
+ var imageLegend = $('Image ');
+ imageFS.append(imageLegend);
+ nodesetForm.append(imageFS);
+
+ var imageAttr = $('
');
+ imageFS.append($(''));
+ imageFS.append(imageAttr);
+
+ // Create target node or group
+ var tgt = $('Target node range:
');
+ vmAttr.append(tgt);
+
+ // Create boot type drop down
+ var type = $('
');
+ var typeLabel = $('Boot type: ');
+ var typeSelect = $(' ');
+ typeSelect.append('zvm '
+ + 'pxe '
+ + 'yaboot '
+ );
+ type.append(typeLabel);
+ type.append(typeSelect);
+ imageAttr.append(type);
+
+ // Create operating system image input
+ var os = $('
');
+ var osLabel = $('Operating system image: ');
+ var osSelect = $(' ');
+ osSelect.append($(' '));
+
+ var imageNames = $.cookie('xcat_imagenames').split(',');
+ if (imageNames) {
+ imageNames.sort();
+ for (var i in imageNames) {
+ osSelect.append($('' + imageNames[i] + ' '));
+ }
+ }
+ os.append(osLabel);
+ os.append(osSelect);
+ imageAttr.append(os);
+
+ // Generate tooltips
+ nodesetForm.find('div input[title],select').tooltip({
+ position: "center right",
+ offset: [-2, 10],
+ effect: "fade",
+ opacity: 0.7,
+ predelay: 800,
+ events : {
+ def : "mouseover,mouseout",
+ input : "mouseover,mouseout",
+ widget : "focus mouseover,blur mouseout",
+ tooltip : "mouseover,mouseout"
+ }
+ });
+
+ /**
+ * Ok
+ */
+ var okBtn = createButton('Ok');
+ okBtn.css({
+ 'width': '80px',
+ 'display': 'block'
+ });
+ okBtn.bind('click', function(event) {
+ // Remove any warning messages
+ $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
+
+ // Check state, OS, arch, and profile
+ var ready = true;
+ var inputs = $('#' + tabId + ' input');
+ for ( var i = 0; i < inputs.length; i++) {
+ if (!inputs.eq(i).val() && inputs.eq(i).attr('name') != 'diskPw') {
+ inputs.eq(i).css('border', 'solid #FF0000 1px');
+ ready = false;
+ } else {
+ inputs.eq(i).css('border', 'solid #BDBDBD 1px');
+ }
+ }
+
+ if (ready) {
+ // Get nodes
+ var tgts = $('#' + tabId + ' input[name=target]').val();
+ // Get boot type
+ var type = $('#' + tabId + ' select[id=bootType]').val();
+ // Get operating system image
+ var os = $('#' + tabId + ' select[name=os]').val();
+
+ // Disable all inputs, selects, and Ok button
+ inputs.attr('disabled', 'disabled');
+ $('#' + tabId + ' select').attr('disabled', 'disabled');
+ $(this).attr('disabled', 'true');
+
+ /**
+ * (1) Set the OS, arch, and profile
+ */
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'nodeadd',
+ tgt : '',
+ args : tgts + ';noderes.netboot=' + type,
+ msg : 'cmd=nodeadd;inst=' + inst
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ updateNodesetStatus(data);
+ }
+ });
+
+ // Show status bar
+ statBar.show();
+ } else {
+ // Show warning message
+ var warn = createWarnBar('You are missing some values!');
+ warn.prependTo($(this).parents('.ui-tabs-panel'));
+ }
+ });
+ nodesetForm.append(okBtn);
+
+ // Append to discover tab
+ tab.add(tabId, 'Nodeset', nodesetForm, true);
+
+ // Select new tab
+ tab.select(tabId);
+}
+
+/**
+ * Update nodeset status
+ *
+ * @param data Data returned from HTTP request
+ */
+function updateNodesetStatus(data) {
+ // Get ajax response
+ var rsp = data.rsp;
+ var args = data.msg.split(';');
+ var cmd = args[0].replace('cmd=', '');
+
+ // Get nodeset instance
+ var inst = args[1].replace('inst=', '');
+ // Get status bar ID
+ var statBarId = 'nodesetStatusBar' + inst;
+ // Get tab ID
+ var tabId = 'nodesetTab' + inst;
+
+ // Get nodes
+ var tgts = $('#' + tabId + ' input[name=target]').val();
+ // Get operating system image
+ var os = $('#' + tabId + ' select[name=os]').val();
+
+ /**
+ * (2) Update /etc/hosts
+ */
+ if (cmd == 'nodeadd') {
+ if (rsp.length) {
+ $('#' + statBarId).find('img').hide();
+ $('#' + statBarId).find('div').append('(Error) Failed to create node definition ');
+ } else {
+ // Create target nodes string
+ var tgtNodesStr = '';
+ var nodes = tgts.split(',');
+
+ // Loop through each node
+ for ( var i in nodes) {
+ // If it is the 1st and only node
+ if (i == 0 && i == nodes.length - 1) {
+ tgtNodesStr += nodes[i];
+ }
+ // If it is the 1st node of many nodes
+ else if (i == 0 && i != nodes.length - 1) {
+ // Append a comma to the string
+ tgtNodesStr += nodes[i] + ', ';
+ } else {
+ // If it is the last node
+ if (i == nodes.length - 1) {
+ // Append nothing to the string
+ tgtNodesStr += nodes[i];
+ } else {
+ // Append a comma to the string
+ tgtNodesStr += nodes[i] + ', ';
+ }
+ }
+ }
+
+ $('#' + statBarId).find('div').append('Node definition created for ' + tgtNodesStr + ' ');
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'makehosts',
+ tgt : '',
+ args : '',
+ msg : 'cmd=makehosts;inst=' + inst
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ updateNodesetStatus(data);
+ }
+ });
+ }
+ }
+
+ /**
+ * (4) Update DNS
+ */
+ else if (cmd == 'makehosts') {
+ // If no output, no errors occurred
+ if (rsp.length) {
+ $('#' + statBarId).find('div').append('(Error) Failed to update /etc/hosts ');
+ } else {
+ $('#' + statBarId).find('div').append('/etc/hosts updated ');
+ }
+
+ // Go straight to prepare node for boot
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'nodeset',
+ tgt : tgts,
+ args : 'osimage=' + os,
+ msg : 'cmd=nodeset;inst=' + inst
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ updateNodesetStatus(data);
+ }
+ });
+ }
+
+ /**
+ * (5) Boot node from network
+ */
+ else if (cmd == 'nodeset') {
+ // Write ajax response to status bar
+ var prg = writeRsp(rsp, '');
+ $('#' + statBarId).find('div').append(prg);
+
+ // Hide loader
+ $('#' + statBarId).find('img').hide();
+ }
}
\ No newline at end of file
diff --git a/xCAT-UI/js/nodes/physical.js b/xCAT-UI/js/nodes/physical.js
index e8df2d4c8..24b010c8c 100644
--- a/xCAT-UI/js/nodes/physical.js
+++ b/xCAT-UI/js/nodes/physical.js
@@ -1,933 +1,935 @@
-var bpaList;
-var fspList;
-var lparList;
-var bladeList;
-var rackList;
-var unknownList;
-var graphicalNodeList;
-var selectNode;
-
-/**
- * Get all nodes useful attributes from remote server
- *
- * @param dataTypeIndex The index in the array which contains attributes we need.
- * @param attrNullNode The target node list for this attribute
- */
-function initGraphicalData() {
- $('#graphTab').append(createLoader());
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'graph',
- msg : ''
- },
- success : function(data) {
- if (!data.rsp[0]) {
- return;
- }
- extractGraphicalData(data.rsp[0]);
- getNodesAndDraw();
- }
- });
-}
-
-/**
- * Extract all nodes userful data into a hash, which will be used for creating graphical
- *
- * @param data The response from xCAT command 'nodels all nodetype.nodetype ppc.parent ...'
- * @return nodes list for next time query
- */
-function extractGraphicalData(data) {
- var nodes = data.split(';');
- var attrs;
- var nodeName;
-
- // Extract useful info into tempList
- for (var i = 0; i < nodes.length; i++) {
- attrs = nodes[i].split(':');
- nodeName = attrs[0];
- if (undefined == graphicalNodeList[nodeName]) {
- graphicalNodeList[nodeName] = new Object();
- }
-
- graphicalNodeList[nodeName]['type'] = attrs[1].toLowerCase();
- switch (attrs[1].toLowerCase()) {
- case 'cec':
- case 'frame':
- case 'lpar':
- case 'lpar,osi':
- case 'osi,lpar':
- graphicalNodeList[nodeName]['parent'] = attrs[2];
- graphicalNodeList[nodeName]['mtm'] = attrs[3];
- graphicalNodeList[nodeName]['status'] = attrs[4];
- break;
- case 'blade':
- graphicalNodeList[nodeName]['mpa'] = attrs[2];
- graphicalNodeList[nodeName]['unit'] = attrs[3];
- graphicalNodeList[nodeName]['status'] = attrs[4];
- break;
- case 'systemx':
- graphicalNodeList[nodeName]['rack'] = attrs[2];
- graphicalNodeList[nodeName]['unit'] = attrs[3];
- graphicalNodeList[nodeName]['mtm'] = attrs[4];
- graphicalNodeList[nodeName]['status'] = attrs[5];
- break;
- default:
- break;
- }
- }
-}
-
-function createPhysicalLayout(nodeList) {
- var flag = false;
-
- // When the graphical layout is shown, do not need to redraw
- if (1 < $('#graphTab').children().length) {
- return;
- }
-
- // Save the new selected nodes
- if (graphicalNodeList) {
- for (var i in graphicalNodeList) {
- flag = true;
- break;
- }
- }
-
- bpaList = new Object();
- fspList = new Object();
- lparList = new Object();
- bladeList = new Object();
- selectNode = new Object();
- rackList = new Object();
- unknownList = new Array();
-
- // There is no graphical data, get the info now
- if (!flag) {
- graphicalNodeList = new Object();
- initGraphicalData();
- } else {
- getNodesAndDraw();
- }
-}
-
-function getNodesAndDraw() {
- var groupName = $.cookie('xcat_selectgrouponnodes');
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'nodels',
- tgt : groupName,
- args : '',
- msg : ''
- },
- success : function(data) {
- for (var temp in data.rsp) {
- var nodeName = data.rsp[temp][0];
- if ('' == nodeName) {
- continue;
- }
- fillList(nodeName);
- }
- $('#graphTab').empty();
- createGraphical();
- }
- });
-}
-
-function fillList(nodeName, defaultnodetype) {
- var parentName = '';
- var mtm = '';
- var status = '';
- var nodeType = '';
- var mpa = '';
- var unit = '';
- var rack = '';
- if (!graphicalNodeList[nodeName]) {
- parentName = '';
- mtm = '';
- status = '';
- nodeType = defaultnodetype;
- } else {
- status = graphicalNodeList[nodeName]['status'];
- nodeType = graphicalNodeList[nodeName]['type'];
- switch (nodeType) {
- case 'frame':
- case 'lpar,osi':
- case 'lpar':
- case 'osi':
- case 'cec':
- parentName = graphicalNodeList[nodeName]['parent'];
- mtm = graphicalNodeList[nodeName]['mtm'];
- break;
- case 'blade':
- mpa = graphicalNodeList[nodeName]['mpa'];
- unit = graphicalNodeList[nodeName]['unit'];
- break;
- case 'systemx':
- rack = graphicalNodeList[nodeName]['rack'];
- unit = graphicalNodeList[nodeName]['unit'];
- break;
- default:
- break;
- }
-
- }
-
- if ('' == status) {
- status = 'unknown';
- }
-
- switch (nodeType) {
- case 'frame':
- if (undefined == bpaList[nodeName]) {
- bpaList[nodeName] = new Array();
- }
-
- break;
- case 'lpar,osi':
- case 'lpar':
- case 'osi':
- if ('' == parentName) {
- break;
- }
-
- if (undefined == fspList[parentName]) {
- fillList(parentName, 'cec');
- }
-
- fspList[parentName]['children'].push(nodeName);
- lparList[nodeName] = status;
-
- break;
- case 'cec':
- if (undefined != fspList[nodeName]) {
- break;
- }
-
- fspList[nodeName] = new Object();
- fspList[nodeName]['children'] = new Array();
- fspList[nodeName]['mtm'] = mtm;
-
- if ('' == parentName) {
- break;
- }
-
- if (undefined == bpaList[parentName]) {
- fillList(parentName, 'frame');
- }
-
- bpaList[parentName].push(nodeName);
- break;
- case 'blade':
- if (undefined == bladeList[mpa]) {
- bladeList[mpa] = new Array();
- }
- bladeList[mpa].push(nodeName + ',' + unit);
-
- break;
- case 'systemx':
- if (!rack) {
- rack = '_notsupply_';
- }
-
- if (undefined == rackList[rack]) {
- rackList[rack] = new Array();
- }
-
- rackList[rack].push(nodeName + ',' + unit);
-
- break;
- default:
- unknownList.push(nodeName);
- break;
- }
-}
-
-function createGraphical() {
- var tabArea = $('#graphTab');
- var selectNodeDiv = $('
');
- var temp = 0;
- for (var i in selectNode) {
- temp++;
- break;
- }
-
- // There is no selected LPAR, show the info bar
- if (temp == 0) {
- tabArea.append(createInfoBar('Hover over a CEC and select the LPARs to do operations against.'));
- } else {
- // Show selected LPARs
- updateSelectNodeDiv();
- }
-
- // Add buttons
- tabArea.append(createActionMenu());
- tabArea.append(selectNodeDiv);
- createSystempGraphical(bpaList, fspList, tabArea);
- createBladeGraphical(bladeList, tabArea);
- createSystemxGraphical(rackList, tabArea);
- addUnknownGraphical(unknownList, tabArea);
-}
-
-/**
- * Create the physical/graphical layout for System p machines
- *
- * @param bpa All BPA and their related FSPs
- * @param fsp All FSP and their related LPARs
- * @param area The element to append graphical layout
- */
-function createSystempGraphical(bpa, fsp, area) {
- var usedFsp = new Object();
- var graphTable = $('');
- var elementNum = 0;
- var row = null;
- var showFlag = false;
-
- // There is a node in the BPA list, so show add the title and show all frames
- for (var bpaName in bpa) {
- showFlag = true;
- $('#graphTab').append('system p ');
- $('#graphTab').append(graphTable);
- break;
- }
-
- for (var bpaName in bpa) {
- if (0 == elementNum % 3) {
- row = $(' ');
- graphTable.append(row);
- }
-
- elementNum++;
-
- var td = $(' ');
- var frameDiv = $('
');
- frameDiv.append('
');
-
- // For P7-IH, all the CECs are insert into the frame from bottom to up,
- // so we have to show the CECs same as the physical layout
- var tempBlankDiv = $('
');
- var tempHeight = 0;
- for (var fspIndex in bpa[bpaName]) {
- var fspName = bpa[bpaName][fspIndex];
- usedFsp[fspName] = 1;
-
- // This is the P7-IH, we should add the blank at the top
- if ((0 == fspIndex) && ('9125-F2C' == fsp[fspName]['mtm'])) {
- frameDiv.append(tempBlankDiv);
- }
-
- frameDiv.append(createFspDiv(fspName, fsp[fspName]['mtm'], fsp));
- frameDiv.append(createFspTip(fspName, fsp[fspName]['mtm'], fsp));
-
- tempHeight += calculateBlank(fsp[fspName]['mtm']);
- }
-
- // tempHeight is the total height for all CECs, so we should minus BPA div
- // height and CEC div heights
- tempHeight = 428 - tempHeight;
- tempBlankDiv.css('height', tempHeight);
- td.append(frameDiv);
- row.append(td);
- }
-
- // Find the single FSP and sort descend by units
- var singleFsp = new Array();
- for (var fspName in fsp) {
- if (usedFsp[fspName]) {
- continue;
- }
-
- singleFsp.push([ fspName, fsp[fspName]['mtm'] ]);
- }
-
- // If there is no frame, we should check if there is single CEC and show
- // the title and add node area
- if (!showFlag) {
- for (var fspIndex in singleFsp) {
- $('#graphTab').append('system p ');
- $('#graphTab').append(graphTable);
- break;
- }
- }
-
- singleFsp.sort(function(a, b) {
- var unitNumA = 4;
- var unitNumB = 4;
- if (hardwareInfo[a[1]]) {
- unitNumA = hardwareInfo[a[1]][1];
- }
-
- if (hardwareInfo[b[1]]) {
- unitNumB = hardwareInfo[b[1]][1];
- }
-
- return (unitNumB - unitNumA);
- });
-
- elementNum = 0;
- for (var fspIndex in singleFsp) {
- var fspName = singleFsp[fspIndex][0];
- if (0 == elementNum % 3) {
- row = $(' ');
- graphTable.append(row);
- }
- elementNum++;
-
- var td = $(' ');
- td.append(createFspDiv(fspName, fsp[fspName]['mtm'], fsp));
- td.append(createFspTip(fspName, fsp[fspName]['mtm'], fsp));
- row.append(td);
- }
-
- $('.tooltip input[type = checkbox]').bind('click', function() {
- var lparName = $(this).attr('name');
- if ('' == lparName) {
- return;
- }
- if (true == $(this).attr('checked')) {
- changeNode(lparName, 'select');
- } else {
- changeNode(lparName, 'unselect');
- }
-
- updateSelectNodeDiv();
- });
-
- $('.fspDiv2, .fspDiv4, .fspDiv42').tooltip({
- position : "center right",
- relative : true,
- offset : [ 10, -40 ],
- effect : "fade",
- opacity : 0.9
- });
-
- $('.tooltip a').bind('click', function() {
- var lparName = $(this).html();
- $('#nodesDatatable #' + lparName).trigger('click');
- });
-
- $('.fspDiv2, .fspDiv4, .fspDiv42').bind('click', function() {
- var fspName = $(this).attr('value');
- var selectCount = 0;
- for (var lparIndex in fspList[fspName]['children']) {
- var lparName = fspList[fspName]['children'][lparIndex];
- if (selectNode[lparName]) {
- selectCount++;
- }
- }
-
- // All LPARs are selected, so unselect nodes
- if (selectCount == fspList[fspName]['children'].length) {
- for (var lparIndex in fspList[fspName]['children']) {
- var lparName = fspList[fspName]['children'][lparIndex];
- changeNode(lparName, 'unselect');
- }
- }
-
- // No selected LPARs on the cec, so add all LPARs into selectNode hash
- else {
- for (var lparIndex in fspList[fspName]['children']) {
- var lparName = fspList[fspName]['children'][lparIndex];
- changeNode(lparName, 'select');
- }
- }
-
- updateSelectNodeDiv();
- });
-
- $('.fspCheckbox').bind('click', function() {
- var itemName = $(this).attr('name');
- name = itemName.substr(6);
-
- if ($(this).attr('checked')) {
- selectNode[name] = 1;
- } else {
- delete selectNode[name];
- }
-
- updateSelectNodeDiv();
- });
-}
-
-/**
- * Create the physical/graphical layout for blades
- *
- * @param blades The blade list in global
- * @param area The element to append the graphical layout
- */
-function createBladeGraphical(blades, area) {
- var graphTable = $('');
- var mpa = '';
- var bladeName = '';
- var index = 0;
- var mpaNumber = 0;
- var row;
- var showFlag = false;
-
- // Only show the title and nodes when there are blade in the blade list
- for (mpa in blades) {
- showFlag = true;
- break;
- }
-
- if (showFlag) {
- $('#graphTab').append('Blade ');
- $('#graphTab').append(graphTable);
- }
- // If there is no blade node, return directly
- else {
- return;
- }
-
- for (mpa in blades) {
- var tempArray = new Array(14);
- var bladeInfo = new Array();
- var unit = 0;
- if (0 == mpaNumber % 3) {
- row = $(' ');
- graphTable.append(row);
- }
-
- mpaNumber++;
-
- var td = $(' ');
- var chasisDiv = $('
');
-
- // Fill the array with blade information, to create the empty slot
- for (index in blades[mpa]) {
- bladeInfo = blades[mpa][index].split(',');
- unit = parseInt(bladeInfo[1]);
- tempArray[unit - 1] = bladeInfo[0];
-
- }
-
- // Draw the blades and empty slot in chasis
- for (index = 0; index < 14; index++) {
- if (tempArray[index]) {
- bladeName = tempArray[index];
- chasisDiv.append('
');
- } else {
- chasisDiv.append('
');
- }
- }
-
- td.append(chasisDiv);
- row.append(td);
- }
-
-}
-
-/**
- * Create the physical/graphical layout for System x machines
- *
- * @param xnodes The system x node list in global
- * @param area The element to append graphical layout
- */
-function createSystemxGraphical(xnodes, area) {
- var graphTable = $('');
- var xnodename = '';
- var index = 0;
- var rack = '';
- var row;
- var xNodeCount = 0;
- var showflag = false;
-
- // Only the title and System x node when there are x nodes in the list
- for (rack in rackList) {
- showflag = true;
- break;
- }
-
- if (showflag) {
- $('#graphTab').append('system x ');
- $('#graphTab').append(graphTable);
- }
- // There is nothing to show, return directly
- else {
- return;
- }
-
- for (rack in rackList) {
- for (index in rackList[rack]) {
- var xNodeName = rackList[rack][index];
- if (0 == xNodeCount % 3) {
- row = $(' ');
- graphTable.append(row);
- }
- xNodeCount++;
- var td = $(' ');
- var xNodeDiv = '
';
- td.append(xNodeDiv);
- row.append(td);
- }
- }
-}
-
-function addUnknownGraphical(unknownNodes, tab) {
- // Do not continue if no nodes were found
- if (unknownNodes.length < 1)
- return;
-
- var list = "";
- tab.append('Unknown Node Type ');
- for (var index in unknownNodes) {
- list += unknownNodes[index] + ', ';
-
- }
-
- // Delete last comma
- list = list.substr(0, list.length - 2);
- tab.append(list);
-}
-
-/**
- * Update the LPARs background in CEC, LPAR area and selectNode
- */
-function updateSelectNodeDiv() {
- var temp = 0;
- $('#selectNodeDiv').empty();
-
- // Add buttons
- if (selectNode.length) {
- $('#selectNodeDiv').append('Nodes: ');
- for (var lparName in selectNode) {
- $('#selectNodeDiv').append(lparName + ' ');
- temp++;
- if (temp > 6) {
- $('#selectNodeDiv').append('...');
- break;
- }
- }
- }
-}
-
-/**
- * Create the action menu
- */
-function createActionMenu() {
- // Create action bar
- var actionBar = $('
').css("width", "400px");
-
- // Power on
- var powerOnLnk = $('Power on ');
- powerOnLnk.click(function() {
- var tgtNodes = getSelectNodes();
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'rpower',
- tgt : tgtNodes,
- args : 'on',
- msg : ''
- }
- });
- });
-
- // Power off
- var powerOffLnk = $('Power off ');
- powerOffLnk.click(function() {
- var tgtNodes = getSelectNodes();
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'rpower',
- tgt : tgtNodes,
- args : 'off',
- msg : ''
- }
- });
- });
-
- // Delete
- var deleteLnk = $('Delete ');
- deleteLnk.click(function() {
- var tgtNodes = getSelectNodes();
- if (tgtNodes) {
- loadDeletePage(tgtNodes);
- }
- });
-
- // Unlock
- var unlockLnk = $('Unlock ');
- unlockLnk.click(function() {
- var tgtNodes = getSelectNodes();
- if (tgtNodes) {
- loadUnlockPage(tgtNodes);
- }
- });
-
- // Run script
- var scriptLnk = $('Run script ');
- scriptLnk.click(function() {
- var tgtNodes = getSelectNodes();
- if (tgtNodes) {
- loadScriptPage(tgtNodes);
- }
- });
-
- // Update
- var updateLnk = $('Update ');
- updateLnk.click(function() {
- var tgtNodes = getSelectNodes();
- if (tgtNodes) {
- loadUpdatenodePage(tgtNodes);
- }
- });
-
- // Set boot state
- var setBootStateLnk = $('Set boot state ');
- setBootStateLnk.click(function() {
- var tgtNodes = getSelectNodes();
- if (tgtNodes) {
- loadNodesetPage(tgtNodes);
- }
- });
-
- // Boot to network
- var boot2NetworkLnk = $('Boot to network ');
- boot2NetworkLnk.click(function() {
- var tgtNodes = getSelectNodes();
- if (tgtNodes) {
- loadNetbootPage(tgtNodes);
- }
- });
-
- // Remote console
- var rconLnk = $('Open console ');
- rconLnk.bind('click', function(event) {
- var tgtNodes = getSelectNodes();
- if (tgtNodes) {
- loadRconsPage(tgtNodes);
- }
- });
-
- // Edit properties
- var editProps = $('Edit properties ');
- editProps.bind('click', function(event) {
- for (var node in selectNode) {
- loadEditPropsPage(node);
- }
- });
-
- // Actions
- var actionsLnk = 'Actions ';
- var actsMenu = createMenu([ deleteLnk, powerOnLnk, powerOffLnk, scriptLnk ]);
-
- // Configurations
- var configLnk = 'Configuration ';
- var configMenu = createMenu([ unlockLnk, updateLnk, editProps ]);
-
- // Provision
- var provLnk = 'Provision ';
- var provMenu = createMenu([ boot2NetworkLnk, setBootStateLnk, rconLnk ]);
-
- // Create an action menu
- var actionsMenu = createMenu([ [ actionsLnk, actsMenu ],
- [ configLnk, configMenu ], [ provLnk, provMenu ] ]);
- actionsMenu.superfish();
- actionsMenu.css('display', 'inline-block');
- actionBar.append(actionsMenu);
- actionBar.css('margin-top', '10px');
-
- // Set correct theme for action menu
- actionsMenu.find('li').hover(function() {
- setMenu2Theme($(this));
- }, function() {
- setMenu2Normal($(this));
- });
-
- return actionBar;
-}
-
-/**
- * Create the physical/graphical layout
- */
-function createFspDiv(fspName, mtm, fsp) {
- // Create FSP title
- var lparStatusRow = '';
- var temp = '';
-
- for (var lparIndex in fsp[fspName]['children']) {
- // Show 8 lpars on one cec at most.
- if (lparIndex >= 8) {
- break;
- }
-
- var lparName = fsp[fspName]['children'][lparIndex];
- var color = statusMap(lparList[lparName]);
- lparStatusRow += ' ';
- }
-
- // Select the backgroud
- var divClass = '';
- if ('' == mtm) {
- temp = '8231-E2B';
- } else {
- temp = mtm;
- }
-
- if (!hardwareInfo[temp]){
- hardwareInfo[temp] = ['unkown', 2];
- }
-
- if (hardwareInfo[temp][1]) {
- divClass += 'fspDiv' + hardwareInfo[temp][1];
- } else {
- divClass += 'fspDiv4';
- }
-
- // Create return value
- var retHtml = ' ';
- retHtml += '';
- return retHtml;
-}
-
-/**
- * Create the physical/graphical FSP tooltip which is used to select the LPAR
- */
-function createFspTip(fspName, mtm, fsp) {
- var tip = $('
');
- var tempTable = $('');
- var temp = '';
- if ('' == mtm) {
- temp = 'unkown';
- } else {
- temp = mtm;
- }
-
- if (hardwareInfo[temp]) {
- tip.append('' + fspName + '(' + hardwareInfo[temp][0] + ') ');
- } else {
- tip.append('' + fspName + ' ');
- }
-
- for (var lparIndex in fsp[fspName]['children']) {
- var lparName = fsp[fspName]['children'][lparIndex];
- var color = statusMap(lparList[lparName]);
- var row = ' ';
- row += '' + lparName + ' ';
- row += '' + lparList[lparName] + ' ';
- tempTable.append(row);
- }
-
- tip.append(tempTable);
- return tip;
-}
-/**
- * Map the LPAR status into a color
- *
- * @param status LPAR status in nodelist table
- * @return Corresponding color name
- */
-function statusMap(status) {
- var color = 'gainsboro';
-
- switch (status) {
- case 'alive':
- case 'ready':
- case 'pbs':
- case 'sshd':
- case 'booting':
- case 'booted':
- case 'ping':
- color = 'green';
- break;
- case 'noping':
- case 'unreachable':
- color = 'red';
- break;
- default:
- color = 'grey';
- break;
- }
-
- return color;
-}
-
-/**
- * Select all LPAR checkboxes
- */
-function selectAllLpars(checkbox) {
- var temp = checkbox.attr('checked');
- $('#selectNodeTable input[type = checkbox]').attr('checked', temp);
-}
-
-/**
- * Export all LPAR names from selectNode
- *
- * @return lpars' string
- */
-function getSelectNodes() {
- var ret = '';
- for (var lparName in selectNode) {
- ret += lparName + ',';
- }
-
- return ret.substring(0, ret.length - 1);
-}
-
-/**
- * When the node is selected or unselected, update the area on CEC, update
- * the global list, and update the tooltip table
- */
-function changeNode(lparName, status) {
- var imgUrl = '';
- var checkFlag = true;
- if ('select' == status) {
- selectNode[lparName] = 1;
- imgUrl = 'url(images/nodes/s-' + statusMap(lparList[lparName])
- + '.gif)';
- checkFlag = true;
- } else {
- delete selectNode[lparName];
- imgUrl = 'url(images/nodes/' + statusMap(lparList[lparName]) + '.gif)';
- checkFlag = false;
- }
- $('#' + lparName + 'status').css('background-image', imgUrl);
- $('.tooltip input[name="' + lparName + '"]').attr('checked', checkFlag);
-}
-
-/**
- * The P7-IH's CECs are insert from bottom to up, so we had to calculate the blank height
- *
- * @return Height for the CEC
- */
-function calculateBlank(mtm) {
- if ('' == mtm) {
- return 24;
- }
-
- if (!hardwareInfo[mtm]) {
- return 24;
- }
-
- switch (hardwareInfo[mtm][1]) {
- case 1:
- return 13;
- break;
- case 2:
- return 24;
- break;
- case 4:
- return 47;
- break;
- default:
- return 0;
- break;
- }
+var bpaList;
+var fspList;
+var lparList;
+var bladeList;
+var rackList;
+var unknownList;
+var graphicalNodeList;
+var selectNode;
+
+/**
+ * Get all nodes useful attributes from remote server
+ *
+ * @param dataTypeIndex The index in the array which contains attributes we need.
+ * @param attrNullNode The target node list for this attribute
+ */
+function initGraphicalData() {
+ $('#graphTab').append(createLoader());
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'graph',
+ msg : ''
+ },
+ success : function(data) {
+ data = decodeRsp(data);
+ if (!data.rsp[0]) {
+ return;
+ }
+ extractGraphicalData(data.rsp[0]);
+ getNodesAndDraw();
+ }
+ });
+}
+
+/**
+ * Extract all nodes userful data into a hash, which will be used for creating graphical
+ *
+ * @param data The response from xCAT command 'nodels all nodetype.nodetype ppc.parent ...'
+ * @return nodes list for next time query
+ */
+function extractGraphicalData(data) {
+ var nodes = data.split(';');
+ var attrs;
+ var nodeName;
+
+ // Extract useful info into tempList
+ for (var i = 0; i < nodes.length; i++) {
+ attrs = nodes[i].split(':');
+ nodeName = attrs[0];
+ if (undefined == graphicalNodeList[nodeName]) {
+ graphicalNodeList[nodeName] = new Object();
+ }
+
+ graphicalNodeList[nodeName]['type'] = attrs[1].toLowerCase();
+ switch (attrs[1].toLowerCase()) {
+ case 'cec':
+ case 'frame':
+ case 'lpar':
+ case 'lpar,osi':
+ case 'osi,lpar':
+ graphicalNodeList[nodeName]['parent'] = attrs[2];
+ graphicalNodeList[nodeName]['mtm'] = attrs[3];
+ graphicalNodeList[nodeName]['status'] = attrs[4];
+ break;
+ case 'blade':
+ graphicalNodeList[nodeName]['mpa'] = attrs[2];
+ graphicalNodeList[nodeName]['unit'] = attrs[3];
+ graphicalNodeList[nodeName]['status'] = attrs[4];
+ break;
+ case 'systemx':
+ graphicalNodeList[nodeName]['rack'] = attrs[2];
+ graphicalNodeList[nodeName]['unit'] = attrs[3];
+ graphicalNodeList[nodeName]['mtm'] = attrs[4];
+ graphicalNodeList[nodeName]['status'] = attrs[5];
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+function createPhysicalLayout(nodeList) {
+ var flag = false;
+
+ // When the graphical layout is shown, do not need to redraw
+ if (1 < $('#graphTab').children().length) {
+ return;
+ }
+
+ // Save the new selected nodes
+ if (graphicalNodeList) {
+ for (var i in graphicalNodeList) {
+ flag = true;
+ break;
+ }
+ }
+
+ bpaList = new Object();
+ fspList = new Object();
+ lparList = new Object();
+ bladeList = new Object();
+ selectNode = new Object();
+ rackList = new Object();
+ unknownList = new Array();
+
+ // There is no graphical data, get the info now
+ if (!flag) {
+ graphicalNodeList = new Object();
+ initGraphicalData();
+ } else {
+ getNodesAndDraw();
+ }
+}
+
+function getNodesAndDraw() {
+ var groupName = $.cookie('xcat_selectgrouponnodes');
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'nodels',
+ tgt : groupName,
+ args : '',
+ msg : ''
+ },
+ success : function(data) {
+ data = decodeRsp(data);
+ for (var temp in data.rsp) {
+ var nodeName = data.rsp[temp][0];
+ if ('' == nodeName) {
+ continue;
+ }
+ fillList(nodeName);
+ }
+ $('#graphTab').empty();
+ createGraphical();
+ }
+ });
+}
+
+function fillList(nodeName, defaultnodetype) {
+ var parentName = '';
+ var mtm = '';
+ var status = '';
+ var nodeType = '';
+ var mpa = '';
+ var unit = '';
+ var rack = '';
+ if (!graphicalNodeList[nodeName]) {
+ parentName = '';
+ mtm = '';
+ status = '';
+ nodeType = defaultnodetype;
+ } else {
+ status = graphicalNodeList[nodeName]['status'];
+ nodeType = graphicalNodeList[nodeName]['type'];
+ switch (nodeType) {
+ case 'frame':
+ case 'lpar,osi':
+ case 'lpar':
+ case 'osi':
+ case 'cec':
+ parentName = graphicalNodeList[nodeName]['parent'];
+ mtm = graphicalNodeList[nodeName]['mtm'];
+ break;
+ case 'blade':
+ mpa = graphicalNodeList[nodeName]['mpa'];
+ unit = graphicalNodeList[nodeName]['unit'];
+ break;
+ case 'systemx':
+ rack = graphicalNodeList[nodeName]['rack'];
+ unit = graphicalNodeList[nodeName]['unit'];
+ break;
+ default:
+ break;
+ }
+
+ }
+
+ if ('' == status) {
+ status = 'unknown';
+ }
+
+ switch (nodeType) {
+ case 'frame':
+ if (undefined == bpaList[nodeName]) {
+ bpaList[nodeName] = new Array();
+ }
+
+ break;
+ case 'lpar,osi':
+ case 'lpar':
+ case 'osi':
+ if ('' == parentName) {
+ break;
+ }
+
+ if (undefined == fspList[parentName]) {
+ fillList(parentName, 'cec');
+ }
+
+ fspList[parentName]['children'].push(nodeName);
+ lparList[nodeName] = status;
+
+ break;
+ case 'cec':
+ if (undefined != fspList[nodeName]) {
+ break;
+ }
+
+ fspList[nodeName] = new Object();
+ fspList[nodeName]['children'] = new Array();
+ fspList[nodeName]['mtm'] = mtm;
+
+ if ('' == parentName) {
+ break;
+ }
+
+ if (undefined == bpaList[parentName]) {
+ fillList(parentName, 'frame');
+ }
+
+ bpaList[parentName].push(nodeName);
+ break;
+ case 'blade':
+ if (undefined == bladeList[mpa]) {
+ bladeList[mpa] = new Array();
+ }
+ bladeList[mpa].push(nodeName + ',' + unit);
+
+ break;
+ case 'systemx':
+ if (!rack) {
+ rack = '_notsupply_';
+ }
+
+ if (undefined == rackList[rack]) {
+ rackList[rack] = new Array();
+ }
+
+ rackList[rack].push(nodeName + ',' + unit);
+
+ break;
+ default:
+ unknownList.push(nodeName);
+ break;
+ }
+}
+
+function createGraphical() {
+ var tabArea = $('#graphTab');
+ var selectNodeDiv = $('
');
+ var temp = 0;
+ for (var i in selectNode) {
+ temp++;
+ break;
+ }
+
+ // There is no selected LPAR, show the info bar
+ if (temp == 0) {
+ tabArea.append(createInfoBar('Hover over a CEC and select the LPARs to do operations against.'));
+ } else {
+ // Show selected LPARs
+ updateSelectNodeDiv();
+ }
+
+ // Add buttons
+ tabArea.append(createActionMenu());
+ tabArea.append(selectNodeDiv);
+ createSystempGraphical(bpaList, fspList, tabArea);
+ createBladeGraphical(bladeList, tabArea);
+ createSystemxGraphical(rackList, tabArea);
+ addUnknownGraphical(unknownList, tabArea);
+}
+
+/**
+ * Create the physical/graphical layout for System p machines
+ *
+ * @param bpa All BPA and their related FSPs
+ * @param fsp All FSP and their related LPARs
+ * @param area The element to append graphical layout
+ */
+function createSystempGraphical(bpa, fsp, area) {
+ var usedFsp = new Object();
+ var graphTable = $('');
+ var elementNum = 0;
+ var row = null;
+ var showFlag = false;
+
+ // There is a node in the BPA list, so show add the title and show all frames
+ for (var bpaName in bpa) {
+ showFlag = true;
+ $('#graphTab').append('system p ');
+ $('#graphTab').append(graphTable);
+ break;
+ }
+
+ for (var bpaName in bpa) {
+ if (0 == elementNum % 3) {
+ row = $(' ');
+ graphTable.append(row);
+ }
+
+ elementNum++;
+
+ var td = $(' ');
+ var frameDiv = $('
');
+ frameDiv.append('
');
+
+ // For P7-IH, all the CECs are insert into the frame from bottom to up,
+ // so we have to show the CECs same as the physical layout
+ var tempBlankDiv = $('
');
+ var tempHeight = 0;
+ for (var fspIndex in bpa[bpaName]) {
+ var fspName = bpa[bpaName][fspIndex];
+ usedFsp[fspName] = 1;
+
+ // This is the P7-IH, we should add the blank at the top
+ if ((0 == fspIndex) && ('9125-F2C' == fsp[fspName]['mtm'])) {
+ frameDiv.append(tempBlankDiv);
+ }
+
+ frameDiv.append(createFspDiv(fspName, fsp[fspName]['mtm'], fsp));
+ frameDiv.append(createFspTip(fspName, fsp[fspName]['mtm'], fsp));
+
+ tempHeight += calculateBlank(fsp[fspName]['mtm']);
+ }
+
+ // tempHeight is the total height for all CECs, so we should minus BPA div
+ // height and CEC div heights
+ tempHeight = 428 - tempHeight;
+ tempBlankDiv.css('height', tempHeight);
+ td.append(frameDiv);
+ row.append(td);
+ }
+
+ // Find the single FSP and sort descend by units
+ var singleFsp = new Array();
+ for (var fspName in fsp) {
+ if (usedFsp[fspName]) {
+ continue;
+ }
+
+ singleFsp.push([ fspName, fsp[fspName]['mtm'] ]);
+ }
+
+ // If there is no frame, we should check if there is single CEC and show
+ // the title and add node area
+ if (!showFlag) {
+ for (var fspIndex in singleFsp) {
+ $('#graphTab').append('system p ');
+ $('#graphTab').append(graphTable);
+ break;
+ }
+ }
+
+ singleFsp.sort(function(a, b) {
+ var unitNumA = 4;
+ var unitNumB = 4;
+ if (hardwareInfo[a[1]]) {
+ unitNumA = hardwareInfo[a[1]][1];
+ }
+
+ if (hardwareInfo[b[1]]) {
+ unitNumB = hardwareInfo[b[1]][1];
+ }
+
+ return (unitNumB - unitNumA);
+ });
+
+ elementNum = 0;
+ for (var fspIndex in singleFsp) {
+ var fspName = singleFsp[fspIndex][0];
+ if (0 == elementNum % 3) {
+ row = $(' ');
+ graphTable.append(row);
+ }
+ elementNum++;
+
+ var td = $(' ');
+ td.append(createFspDiv(fspName, fsp[fspName]['mtm'], fsp));
+ td.append(createFspTip(fspName, fsp[fspName]['mtm'], fsp));
+ row.append(td);
+ }
+
+ $('.tooltip input[type = checkbox]').bind('click', function() {
+ var lparName = $(this).attr('name');
+ if ('' == lparName) {
+ return;
+ }
+ if (true == $(this).attr('checked')) {
+ changeNode(lparName, 'select');
+ } else {
+ changeNode(lparName, 'unselect');
+ }
+
+ updateSelectNodeDiv();
+ });
+
+ $('.fspDiv2, .fspDiv4, .fspDiv42').tooltip({
+ position : "center right",
+ relative : true,
+ offset : [ 10, -40 ],
+ effect : "fade",
+ opacity : 0.9
+ });
+
+ $('.tooltip a').bind('click', function() {
+ var lparName = $(this).html();
+ $('#nodesDatatable #' + lparName).trigger('click');
+ });
+
+ $('.fspDiv2, .fspDiv4, .fspDiv42').bind('click', function() {
+ var fspName = $(this).attr('value');
+ var selectCount = 0;
+ for (var lparIndex in fspList[fspName]['children']) {
+ var lparName = fspList[fspName]['children'][lparIndex];
+ if (selectNode[lparName]) {
+ selectCount++;
+ }
+ }
+
+ // All LPARs are selected, so unselect nodes
+ if (selectCount == fspList[fspName]['children'].length) {
+ for (var lparIndex in fspList[fspName]['children']) {
+ var lparName = fspList[fspName]['children'][lparIndex];
+ changeNode(lparName, 'unselect');
+ }
+ }
+
+ // No selected LPARs on the cec, so add all LPARs into selectNode hash
+ else {
+ for (var lparIndex in fspList[fspName]['children']) {
+ var lparName = fspList[fspName]['children'][lparIndex];
+ changeNode(lparName, 'select');
+ }
+ }
+
+ updateSelectNodeDiv();
+ });
+
+ $('.fspCheckbox').bind('click', function() {
+ var itemName = $(this).attr('name');
+ name = itemName.substr(6);
+
+ if ($(this).attr('checked')) {
+ selectNode[name] = 1;
+ } else {
+ delete selectNode[name];
+ }
+
+ updateSelectNodeDiv();
+ });
+}
+
+/**
+ * Create the physical/graphical layout for blades
+ *
+ * @param blades The blade list in global
+ * @param area The element to append the graphical layout
+ */
+function createBladeGraphical(blades, area) {
+ var graphTable = $('');
+ var mpa = '';
+ var bladeName = '';
+ var index = 0;
+ var mpaNumber = 0;
+ var row;
+ var showFlag = false;
+
+ // Only show the title and nodes when there are blade in the blade list
+ for (mpa in blades) {
+ showFlag = true;
+ break;
+ }
+
+ if (showFlag) {
+ $('#graphTab').append('Blade ');
+ $('#graphTab').append(graphTable);
+ }
+ // If there is no blade node, return directly
+ else {
+ return;
+ }
+
+ for (mpa in blades) {
+ var tempArray = new Array(14);
+ var bladeInfo = new Array();
+ var unit = 0;
+ if (0 == mpaNumber % 3) {
+ row = $(' ');
+ graphTable.append(row);
+ }
+
+ mpaNumber++;
+
+ var td = $(' ');
+ var chasisDiv = $('
');
+
+ // Fill the array with blade information, to create the empty slot
+ for (index in blades[mpa]) {
+ bladeInfo = blades[mpa][index].split(',');
+ unit = parseInt(bladeInfo[1]);
+ tempArray[unit - 1] = bladeInfo[0];
+
+ }
+
+ // Draw the blades and empty slot in chasis
+ for (index = 0; index < 14; index++) {
+ if (tempArray[index]) {
+ bladeName = tempArray[index];
+ chasisDiv.append('
');
+ } else {
+ chasisDiv.append('
');
+ }
+ }
+
+ td.append(chasisDiv);
+ row.append(td);
+ }
+
+}
+
+/**
+ * Create the physical/graphical layout for System x machines
+ *
+ * @param xnodes The system x node list in global
+ * @param area The element to append graphical layout
+ */
+function createSystemxGraphical(xnodes, area) {
+ var graphTable = $('');
+ var xnodename = '';
+ var index = 0;
+ var rack = '';
+ var row;
+ var xNodeCount = 0;
+ var showflag = false;
+
+ // Only the title and System x node when there are x nodes in the list
+ for (rack in rackList) {
+ showflag = true;
+ break;
+ }
+
+ if (showflag) {
+ $('#graphTab').append('system x ');
+ $('#graphTab').append(graphTable);
+ }
+ // There is nothing to show, return directly
+ else {
+ return;
+ }
+
+ for (rack in rackList) {
+ for (index in rackList[rack]) {
+ var xNodeName = rackList[rack][index];
+ if (0 == xNodeCount % 3) {
+ row = $(' ');
+ graphTable.append(row);
+ }
+ xNodeCount++;
+ var td = $(' ');
+ var xNodeDiv = '
';
+ td.append(xNodeDiv);
+ row.append(td);
+ }
+ }
+}
+
+function addUnknownGraphical(unknownNodes, tab) {
+ // Do not continue if no nodes were found
+ if (unknownNodes.length < 1)
+ return;
+
+ var list = "";
+ tab.append('Unknown Node Type ');
+ for (var index in unknownNodes) {
+ list += unknownNodes[index] + ', ';
+
+ }
+
+ // Delete last comma
+ list = list.substr(0, list.length - 2);
+ tab.append(list);
+}
+
+/**
+ * Update the LPARs background in CEC, LPAR area and selectNode
+ */
+function updateSelectNodeDiv() {
+ var temp = 0;
+ $('#selectNodeDiv').empty();
+
+ // Add buttons
+ if (selectNode.length) {
+ $('#selectNodeDiv').append('Nodes: ');
+ for (var lparName in selectNode) {
+ $('#selectNodeDiv').append(lparName + ' ');
+ temp++;
+ if (temp > 6) {
+ $('#selectNodeDiv').append('...');
+ break;
+ }
+ }
+ }
+}
+
+/**
+ * Create the action menu
+ */
+function createActionMenu() {
+ // Create action bar
+ var actionBar = $('
').css("width", "400px");
+
+ // Power on
+ var powerOnLnk = $('Power on ');
+ powerOnLnk.click(function() {
+ var tgtNodes = getSelectNodes();
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'rpower',
+ tgt : tgtNodes,
+ args : 'on',
+ msg : ''
+ }
+ });
+ });
+
+ // Power off
+ var powerOffLnk = $('Power off ');
+ powerOffLnk.click(function() {
+ var tgtNodes = getSelectNodes();
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'rpower',
+ tgt : tgtNodes,
+ args : 'off',
+ msg : ''
+ }
+ });
+ });
+
+ // Delete
+ var deleteLnk = $('Delete ');
+ deleteLnk.click(function() {
+ var tgtNodes = getSelectNodes();
+ if (tgtNodes) {
+ loadDeletePage(tgtNodes);
+ }
+ });
+
+ // Unlock
+ var unlockLnk = $('Unlock ');
+ unlockLnk.click(function() {
+ var tgtNodes = getSelectNodes();
+ if (tgtNodes) {
+ loadUnlockPage(tgtNodes);
+ }
+ });
+
+ // Run script
+ var scriptLnk = $('Run script ');
+ scriptLnk.click(function() {
+ var tgtNodes = getSelectNodes();
+ if (tgtNodes) {
+ loadScriptPage(tgtNodes);
+ }
+ });
+
+ // Update
+ var updateLnk = $('Update ');
+ updateLnk.click(function() {
+ var tgtNodes = getSelectNodes();
+ if (tgtNodes) {
+ loadUpdatenodePage(tgtNodes);
+ }
+ });
+
+ // Set boot state
+ var setBootStateLnk = $('Set boot state ');
+ setBootStateLnk.click(function() {
+ var tgtNodes = getSelectNodes();
+ if (tgtNodes) {
+ loadNodesetPage(tgtNodes);
+ }
+ });
+
+ // Boot to network
+ var boot2NetworkLnk = $('Boot to network ');
+ boot2NetworkLnk.click(function() {
+ var tgtNodes = getSelectNodes();
+ if (tgtNodes) {
+ loadNetbootPage(tgtNodes);
+ }
+ });
+
+ // Remote console
+ var rconLnk = $('Open console ');
+ rconLnk.bind('click', function(event) {
+ var tgtNodes = getSelectNodes();
+ if (tgtNodes) {
+ loadRconsPage(tgtNodes);
+ }
+ });
+
+ // Edit properties
+ var editProps = $('Edit properties ');
+ editProps.bind('click', function(event) {
+ for (var node in selectNode) {
+ loadEditPropsPage(node);
+ }
+ });
+
+ // Actions
+ var actionsLnk = 'Actions ';
+ var actsMenu = createMenu([ deleteLnk, powerOnLnk, powerOffLnk, scriptLnk ]);
+
+ // Configurations
+ var configLnk = 'Configuration ';
+ var configMenu = createMenu([ unlockLnk, updateLnk, editProps ]);
+
+ // Provision
+ var provLnk = 'Provision ';
+ var provMenu = createMenu([ boot2NetworkLnk, setBootStateLnk, rconLnk ]);
+
+ // Create an action menu
+ var actionsMenu = createMenu([ [ actionsLnk, actsMenu ],
+ [ configLnk, configMenu ], [ provLnk, provMenu ] ]);
+ actionsMenu.superfish();
+ actionsMenu.css('display', 'inline-block');
+ actionBar.append(actionsMenu);
+ actionBar.css('margin-top', '10px');
+
+ // Set correct theme for action menu
+ actionsMenu.find('li').hover(function() {
+ setMenu2Theme($(this));
+ }, function() {
+ setMenu2Normal($(this));
+ });
+
+ return actionBar;
+}
+
+/**
+ * Create the physical/graphical layout
+ */
+function createFspDiv(fspName, mtm, fsp) {
+ // Create FSP title
+ var lparStatusRow = '';
+ var temp = '';
+
+ for (var lparIndex in fsp[fspName]['children']) {
+ // Show 8 lpars on one cec at most.
+ if (lparIndex >= 8) {
+ break;
+ }
+
+ var lparName = fsp[fspName]['children'][lparIndex];
+ var color = statusMap(lparList[lparName]);
+ lparStatusRow += ' ';
+ }
+
+ // Select the backgroud
+ var divClass = '';
+ if ('' == mtm) {
+ temp = '8231-E2B';
+ } else {
+ temp = mtm;
+ }
+
+ if (!hardwareInfo[temp]){
+ hardwareInfo[temp] = ['unkown', 2];
+ }
+
+ if (hardwareInfo[temp][1]) {
+ divClass += 'fspDiv' + hardwareInfo[temp][1];
+ } else {
+ divClass += 'fspDiv4';
+ }
+
+ // Create return value
+ var retHtml = ' ';
+ retHtml += '';
+ return retHtml;
+}
+
+/**
+ * Create the physical/graphical FSP tooltip which is used to select the LPAR
+ */
+function createFspTip(fspName, mtm, fsp) {
+ var tip = $('
');
+ var tempTable = $('');
+ var temp = '';
+ if ('' == mtm) {
+ temp = 'unkown';
+ } else {
+ temp = mtm;
+ }
+
+ if (hardwareInfo[temp]) {
+ tip.append('' + fspName + '(' + hardwareInfo[temp][0] + ') ');
+ } else {
+ tip.append('' + fspName + ' ');
+ }
+
+ for (var lparIndex in fsp[fspName]['children']) {
+ var lparName = fsp[fspName]['children'][lparIndex];
+ var color = statusMap(lparList[lparName]);
+ var row = ' ';
+ row += '' + lparName + ' ';
+ row += '' + lparList[lparName] + ' ';
+ tempTable.append(row);
+ }
+
+ tip.append(tempTable);
+ return tip;
+}
+/**
+ * Map the LPAR status into a color
+ *
+ * @param status LPAR status in nodelist table
+ * @return Corresponding color name
+ */
+function statusMap(status) {
+ var color = 'gainsboro';
+
+ switch (status) {
+ case 'alive':
+ case 'ready':
+ case 'pbs':
+ case 'sshd':
+ case 'booting':
+ case 'booted':
+ case 'ping':
+ color = 'green';
+ break;
+ case 'noping':
+ case 'unreachable':
+ color = 'red';
+ break;
+ default:
+ color = 'grey';
+ break;
+ }
+
+ return color;
+}
+
+/**
+ * Select all LPAR checkboxes
+ */
+function selectAllLpars(checkbox) {
+ var temp = checkbox.attr('checked');
+ $('#selectNodeTable input[type = checkbox]').attr('checked', temp);
+}
+
+/**
+ * Export all LPAR names from selectNode
+ *
+ * @return lpars' string
+ */
+function getSelectNodes() {
+ var ret = '';
+ for (var lparName in selectNode) {
+ ret += lparName + ',';
+ }
+
+ return ret.substring(0, ret.length - 1);
+}
+
+/**
+ * When the node is selected or unselected, update the area on CEC, update
+ * the global list, and update the tooltip table
+ */
+function changeNode(lparName, status) {
+ var imgUrl = '';
+ var checkFlag = true;
+ if ('select' == status) {
+ selectNode[lparName] = 1;
+ imgUrl = 'url(images/nodes/s-' + statusMap(lparList[lparName])
+ + '.gif)';
+ checkFlag = true;
+ } else {
+ delete selectNode[lparName];
+ imgUrl = 'url(images/nodes/' + statusMap(lparList[lparName]) + '.gif)';
+ checkFlag = false;
+ }
+ $('#' + lparName + 'status').css('background-image', imgUrl);
+ $('.tooltip input[name="' + lparName + '"]').attr('checked', checkFlag);
+}
+
+/**
+ * The P7-IH's CECs are insert from bottom to up, so we had to calculate the blank height
+ *
+ * @return Height for the CEC
+ */
+function calculateBlank(mtm) {
+ if ('' == mtm) {
+ return 24;
+ }
+
+ if (!hardwareInfo[mtm]) {
+ return 24;
+ }
+
+ switch (hardwareInfo[mtm][1]) {
+ case 1:
+ return 13;
+ break;
+ case 2:
+ return 24;
+ break;
+ case 4:
+ return 47;
+ break;
+ default:
+ return 0;
+ break;
+ }
}
\ No newline at end of file
diff --git a/xCAT-UI/js/nodes/rnetboot.js b/xCAT-UI/js/nodes/rnetboot.js
index c745c8922..7f03e069b 100644
--- a/xCAT-UI/js/nodes/rnetboot.js
+++ b/xCAT-UI/js/nodes/rnetboot.js
@@ -1,220 +1,223 @@
-/**
- * Load netboot page
- *
- * @param tgtNodes Targets to run rnetboot against
- */
-function loadNetbootPage(tgtNodes) {
- // Get node OS
- var osHash = new Object();
- var nodes = tgtNodes.split(',');
- for (var i in nodes) {
- var os = getNodeAttr(nodes[i], 'os');
- var osBase = os.match(/[a-zA-Z]+/);
- if (osBase) {
- nodes[osBase] = 1;
- }
- }
-
- // Get nodes tab
- var tab = getNodesTab();
-
- // Generate new tab ID
- var inst = 0;
- var newTabId = 'netbootTab' + inst;
- while ($('#' + newTabId).length) {
- // If one already exists, generate another one
- inst = inst + 1;
- newTabId = 'netbootTab' + inst;
- }
-
- // Create netboot form
- var netbootForm = $('
');
-
- // Create status bar
- var statBarId = 'netbootStatusBar' + inst;
- var statusBar = createStatusBar(statBarId).hide();
-
- // Create loader
- var loader = createLoader('netbootLoader');
- statusBar.find('div').append(loader);
-
- // Create info bar
- var infoBar = createInfoBar('Cause the range of nodes to boot to network');
- netbootForm.append(statusBar, infoBar);
-
- // Create VM fieldset
- var vmFS = $(' ');
- var vmLegend = $('Virtual Machine ');
- vmFS.append(vmLegend);
- netbootForm.append(vmFS);
-
- var vmAttr = $('
');
- vmFS.append($(''));
- vmFS.append(vmAttr);
-
- // Create options fieldset
- var optionsFS = $(' ');
- var optionsLegend = $('Options ');
- optionsFS.append(optionsLegend);
- netbootForm.append(optionsFS);
-
- var optionsAttr = $('
');
- optionsFS.append($(''));
- optionsFS.append(optionsAttr);
-
- // Create target node or group input
- var target = $('Target node range:
');
- vmAttr.append(target);
-
- // Create options
- var optsLabel = $('Options: ');
- var optsList = $('');
- optionsAttr.append(optsList);
-
- // Create boot order checkbox
- var opt = $(' ');
- var bootOrderChkBox = $(' ');
- opt.append(bootOrderChkBox);
- opt.append('Set the boot device order');
- optsList.append(opt);
- // Create boot order input
- var bootOrder = $('Boot order: ');
- bootOrder.hide();
- optsList.append(bootOrder);
-
- // Create force reboot checkbox
- optsList.append(' Force reboot ');
- // Create force shutdown checkbox
- optsList.append(' Force immediate shutdown of the partition ');
- if (osHash['AIX']) {
- // Create iscsi dump checkbox
- optsList.append(' Do a iscsi dump on AIX ');
- }
-
- // Show boot order when checkbox is checked
- bootOrderChkBox.bind('click', function(event) {
- if ($(this).is(':checked')) {
- bootOrder.show();
- } else {
- bootOrder.hide();
- }
- });
-
- // Determine plugin
- var tmp = tgtNodes.split(',');
- for ( var i = 0; i < tmp.length; i++) {
- var mgt = getNodeAttr(tmp[i], 'mgt');
- // If it is zvm
- if (mgt == 'zvm') {
- // Add IPL input
- optsList.append('IPL:
');
- break;
- }
- }
-
- // Generate tooltips
- netbootForm.find('div input[title]').tooltip({
- position: "center right",
- offset: [-2, 10],
- effect: "fade",
- opacity: 0.7,
- predelay: 800,
- events : {
- def : "mouseover,mouseout",
- input : "mouseover,mouseout",
- widget : "focus mouseover,blur mouseout",
- tooltip : "mouseover,mouseout"
- }
- });
-
- /**
- * Ok
- */
- var okBtn = createButton('Ok');
- okBtn.css({
- 'width': '80px',
- 'display': 'block'
- });
- okBtn.bind('click', function(event) {
- // Remove any warning messages
- $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
-
- // Check inputs
- var ready = true;
- var inputs = $("#" + newTabId + " input[type='text']:visible");
- for ( var i = 0; i < inputs.length; i++) {
- if (!inputs.eq(i).val()) {
- inputs.eq(i).css('border', 'solid #FF0000 1px');
- ready = false;
- } else {
- inputs.eq(i).css('border', 'solid #BDBDBD 1px');
- }
- }
-
- // Generate arguments
- var chkBoxes = $("#" + newTabId + " input[type='checkbox']:checked");
- var optStr = '';
- var opt;
- for ( var i = 0; i < chkBoxes.length; i++) {
- opt = chkBoxes.eq(i).attr('name');
- optStr += '-' + opt;
-
- // If it is the boot order
- if (opt == 's') {
- // Get the boot order
- optStr += ';' + $('#' + newTabId + ' input[name=bootOrder]').val();
- }
-
- // Append ; to end of string
- if (i < (chkBoxes.length - 1)) {
- optStr += ';';
- }
- }
-
- // If no inputs are empty
- if (ready) {
- // Get nodes
- var tgts = $('#' + newTabId + ' input[name=target]').val();
-
- // Get IPL address
- var ipl = $('#' + newTabId + ' input[name=ipl]');
- if (ipl) {
- optStr += 'ipl=' + ipl.val();
- }
-
- // Disable all inputs and Ok button
- $('#' + newTabId + ' input').attr('disabled', 'disabled');
- $(this).attr('disabled', 'true');
-
- /**
- * (1) Boot to network
- */
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'rnetboot',
- tgt : tgts,
- args : optStr,
- msg : 'out=' + statBarId + ';cmd=rnetboot;tgt=' + tgts
- },
-
- success : updateStatusBar
- });
-
- // Show status bar
- statusBar.show();
- } else {
- // Show warning message
- var warn = createWarnBar('Please provide a value for each missing field.');
- warn.prependTo($(this).parents('.ui-tabs-panel'));
- }
- });
- netbootForm.append(okBtn);
-
- // Append to discover tab
- tab.add(newTabId, 'Boot', netbootForm, true);
-
- // Select new tab
- tab.select(newTabId);
+/**
+ * Load netboot page
+ *
+ * @param tgtNodes Targets to run rnetboot against
+ */
+function loadNetbootPage(tgtNodes) {
+ // Get node OS
+ var osHash = new Object();
+ var nodes = tgtNodes.split(',');
+ for (var i in nodes) {
+ var os = getNodeAttr(nodes[i], 'os');
+ var osBase = os.match(/[a-zA-Z]+/);
+ if (osBase) {
+ nodes[osBase] = 1;
+ }
+ }
+
+ // Get nodes tab
+ var tab = getNodesTab();
+
+ // Generate new tab ID
+ var inst = 0;
+ var newTabId = 'netbootTab' + inst;
+ while ($('#' + newTabId).length) {
+ // If one already exists, generate another one
+ inst = inst + 1;
+ newTabId = 'netbootTab' + inst;
+ }
+
+ // Create netboot form
+ var netbootForm = $('
');
+
+ // Create status bar
+ var statBarId = 'netbootStatusBar' + inst;
+ var statusBar = createStatusBar(statBarId).hide();
+
+ // Create loader
+ var loader = createLoader('netbootLoader');
+ statusBar.find('div').append(loader);
+
+ // Create info bar
+ var infoBar = createInfoBar('Cause the range of nodes to boot to network');
+ netbootForm.append(statusBar, infoBar);
+
+ // Create VM fieldset
+ var vmFS = $(' ');
+ var vmLegend = $('Virtual Machine ');
+ vmFS.append(vmLegend);
+ netbootForm.append(vmFS);
+
+ var vmAttr = $('
');
+ vmFS.append($(''));
+ vmFS.append(vmAttr);
+
+ // Create options fieldset
+ var optionsFS = $(' ');
+ var optionsLegend = $('Options ');
+ optionsFS.append(optionsLegend);
+ netbootForm.append(optionsFS);
+
+ var optionsAttr = $('
');
+ optionsFS.append($(''));
+ optionsFS.append(optionsAttr);
+
+ // Create target node or group input
+ var target = $('Target node range:
');
+ vmAttr.append(target);
+
+ // Create options
+ var optsLabel = $('Options: ');
+ var optsList = $('');
+ optionsAttr.append(optsList);
+
+ // Create boot order checkbox
+ var opt = $(' ');
+ var bootOrderChkBox = $(' ');
+ opt.append(bootOrderChkBox);
+ opt.append('Set the boot device order');
+ optsList.append(opt);
+ // Create boot order input
+ var bootOrder = $('Boot order: ');
+ bootOrder.hide();
+ optsList.append(bootOrder);
+
+ // Create force reboot checkbox
+ optsList.append(' Force reboot ');
+ // Create force shutdown checkbox
+ optsList.append(' Force immediate shutdown of the partition ');
+ if (osHash['AIX']) {
+ // Create iscsi dump checkbox
+ optsList.append(' Do a iscsi dump on AIX ');
+ }
+
+ // Show boot order when checkbox is checked
+ bootOrderChkBox.bind('click', function(event) {
+ if ($(this).is(':checked')) {
+ bootOrder.show();
+ } else {
+ bootOrder.hide();
+ }
+ });
+
+ // Determine plugin
+ var tmp = tgtNodes.split(',');
+ for ( var i = 0; i < tmp.length; i++) {
+ var mgt = getNodeAttr(tmp[i], 'mgt');
+ // If it is zvm
+ if (mgt == 'zvm') {
+ // Add IPL input
+ optsList.append('IPL:
');
+ break;
+ }
+ }
+
+ // Generate tooltips
+ netbootForm.find('div input[title]').tooltip({
+ position: "center right",
+ offset: [-2, 10],
+ effect: "fade",
+ opacity: 0.7,
+ predelay: 800,
+ events : {
+ def : "mouseover,mouseout",
+ input : "mouseover,mouseout",
+ widget : "focus mouseover,blur mouseout",
+ tooltip : "mouseover,mouseout"
+ }
+ });
+
+ /**
+ * Ok
+ */
+ var okBtn = createButton('Ok');
+ okBtn.css({
+ 'width': '80px',
+ 'display': 'block'
+ });
+ okBtn.bind('click', function(event) {
+ // Remove any warning messages
+ $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
+
+ // Check inputs
+ var ready = true;
+ var inputs = $("#" + newTabId + " input[type='text']:visible");
+ for ( var i = 0; i < inputs.length; i++) {
+ if (!inputs.eq(i).val()) {
+ inputs.eq(i).css('border', 'solid #FF0000 1px');
+ ready = false;
+ } else {
+ inputs.eq(i).css('border', 'solid #BDBDBD 1px');
+ }
+ }
+
+ // Generate arguments
+ var chkBoxes = $("#" + newTabId + " input[type='checkbox']:checked");
+ var optStr = '';
+ var opt;
+ for ( var i = 0; i < chkBoxes.length; i++) {
+ opt = chkBoxes.eq(i).attr('name');
+ optStr += '-' + opt;
+
+ // If it is the boot order
+ if (opt == 's') {
+ // Get the boot order
+ optStr += ';' + $('#' + newTabId + ' input[name=bootOrder]').val();
+ }
+
+ // Append ; to end of string
+ if (i < (chkBoxes.length - 1)) {
+ optStr += ';';
+ }
+ }
+
+ // If no inputs are empty
+ if (ready) {
+ // Get nodes
+ var tgts = $('#' + newTabId + ' input[name=target]').val();
+
+ // Get IPL address
+ var ipl = $('#' + newTabId + ' input[name=ipl]');
+ if (ipl) {
+ optStr += 'ipl=' + ipl.val();
+ }
+
+ // Disable all inputs and Ok button
+ $('#' + newTabId + ' input').attr('disabled', 'disabled');
+ $(this).attr('disabled', 'true');
+
+ /**
+ * (1) Boot to network
+ */
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'rnetboot',
+ tgt : tgts,
+ args : optStr,
+ msg : 'out=' + statBarId + ';cmd=rnetboot;tgt=' + tgts
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ updateStatusBar(data);
+ }
+ });
+
+ // Show status bar
+ statusBar.show();
+ } else {
+ // Show warning message
+ var warn = createWarnBar('Please provide a value for each missing field.');
+ warn.prependTo($(this).parents('.ui-tabs-panel'));
+ }
+ });
+ netbootForm.append(okBtn);
+
+ // Append to discover tab
+ tab.add(newTabId, 'Boot', netbootForm, true);
+
+ // Select new tab
+ tab.select(newTabId);
}
\ No newline at end of file
diff --git a/xCAT-UI/js/nodes/rscan.js b/xCAT-UI/js/nodes/rscan.js
index 5c9585274..06fdbff09 100644
--- a/xCAT-UI/js/nodes/rscan.js
+++ b/xCAT-UI/js/nodes/rscan.js
@@ -1,171 +1,174 @@
-/**
- * Load rscan page
- *
- * @param tgtNodes Targets to run rscan against
- */
-function loadRscanPage(tgtNodes) {
- // Get node OS
- var osHash = new Object();
- var nodes = tgtNodes.split(',');
- for (var i in nodes) {
- var os = getNodeAttr(nodes[i], 'os');
- var osBase = os.match(/[a-zA-Z]+/);
- if (osBase) {
- nodes[osBase] = 1;
- }
- }
-
- // Get nodes tab
- var tab = getNodesTab();
-
- // Generate new tab ID
- var inst = 0;
- var newTabId = 'rscanTab' + inst;
- while ($('#' + newTabId).length) {
- // If one already exists, generate another one
- inst = inst + 1;
- newTabId = 'rscanTab' + inst;
- }
-
- // Create rscan form
- var rscanForm = $('
');
-
- // Create status bar
- var statBarId = 'rscanStatusBar' + inst;
- var statBar = createStatusBar(statBarId).hide();
-
- // Create loader
- var loader = createLoader('rscanLoader');
- statBar.find('div').append(loader);
-
- // Create info bar
- var infoBar = createInfoBar('Collects node information from one or more hardware control points');
- rscanForm.append(statBar, infoBar);
-
- // Create VM fieldset
- var vmFS = $(' ');
- var vmLegend = $('Virtual Machine ');
- vmFS.append(vmLegend);
- rscanForm.append(vmFS);
-
- var vmAttr = $('
');
- vmFS.append($(''));
- vmFS.append(vmAttr);
-
- // Create options fieldset
- var optionsFS = $(' ');
- var optionsLegend = $('Options ');
- optionsFS.append(optionsLegend);
- rscanForm.append(optionsFS);
-
- var optionsAttr = $('
');
- optionsFS.append($(''));
- optionsFS.append(optionsAttr);
-
- // Create target node or group input
- var target = $('Target node range:
');
- vmAttr.append(target);
-
- // Create options
- var optsList = $('');
- optionsAttr.append(optsList);
-
- optsList.append(' Updates and then prints out node definitions in the xCAT database for CEC/BPA ');
- optsList.append(' Writes output to xCAT database ');
- optsList.append(' XML format ');
- optsList.append(' Stanza formated output ');
-
- // Generate tooltips
- rscanForm.find('div input[title]').tooltip({
- position: "center right",
- offset: [-2, 10],
- effect: "fade",
- opacity: 0.7,
- predelay: 800,
- events : {
- def : "mouseover,mouseout",
- input : "mouseover,mouseout",
- widget : "focus mouseover,blur mouseout",
- tooltip : "mouseover,mouseout"
- }
- });
-
- /**
- * Ok
- */
- var okBtn = createButton('Ok');
- okBtn.css({
- 'width': '80px',
- 'display': 'block'
- });
- okBtn.bind('click', function(event) {
- // Remove any warning messages
- $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
-
- // Check inputs
- var ready = true;
- var inputs = $("#" + newTabId + " input[type='text']");
- for ( var i = 0; i < inputs.length; i++) {
- if (!inputs.eq(i).val()) {
- inputs.eq(i).css('border', 'solid #FF0000 1px');
- ready = false;
- } else {
- inputs.eq(i).css('border', 'solid #BDBDBD 1px');
- }
- }
-
- // Generate arguments
- var chkBoxes = $("#" + newTabId + " input[type='checkbox']:checked");
- var optStr = '';
- var opt;
- for ( var i = 0; i < chkBoxes.length; i++) {
- opt = chkBoxes.eq(i).attr('name');
- optStr += '-' + opt;
-
- // Append ; to end of string
- if (i < (chkBoxes.length - 1)) {
- optStr += ';';
- }
- }
-
- // If no inputs are empty
- if (ready) {
- // Get nodes
- var tgts = $('#' + newTabId + ' input[name=target]').val();
-
- // Disable all inputs and Ok button
- $('#' + newTabId + ' input').attr('disabled', 'disabled');
- $(this).attr('disabled', 'true');
-
- /**
- * (1) Scan
- */
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'rscan',
- tgt : tgts,
- args : optStr,
- msg : 'out=' + statBarId + ';cmd=rscan;tgt=' + tgts
- },
-
- success : updateStatusBar
- });
-
- // Show status bar
- statBar.show();
- } else {
- // Show warning message
- var warn = createWarnBar('Please provide a value for each missing field.');
- warn.prependTo($(this).parents('.ui-tabs-panel'));
- }
- });
- rscanForm.append(okBtn);
-
- // Append to discover tab
- tab.add(newTabId, 'Scan', rscanForm, true);
-
- // Select new tab
- tab.select(newTabId);
+/**
+ * Load rscan page
+ *
+ * @param tgtNodes Targets to run rscan against
+ */
+function loadRscanPage(tgtNodes) {
+ // Get node OS
+ var osHash = new Object();
+ var nodes = tgtNodes.split(',');
+ for (var i in nodes) {
+ var os = getNodeAttr(nodes[i], 'os');
+ var osBase = os.match(/[a-zA-Z]+/);
+ if (osBase) {
+ nodes[osBase] = 1;
+ }
+ }
+
+ // Get nodes tab
+ var tab = getNodesTab();
+
+ // Generate new tab ID
+ var inst = 0;
+ var newTabId = 'rscanTab' + inst;
+ while ($('#' + newTabId).length) {
+ // If one already exists, generate another one
+ inst = inst + 1;
+ newTabId = 'rscanTab' + inst;
+ }
+
+ // Create rscan form
+ var rscanForm = $('
');
+
+ // Create status bar
+ var statBarId = 'rscanStatusBar' + inst;
+ var statBar = createStatusBar(statBarId).hide();
+
+ // Create loader
+ var loader = createLoader('rscanLoader');
+ statBar.find('div').append(loader);
+
+ // Create info bar
+ var infoBar = createInfoBar('Collects node information from one or more hardware control points');
+ rscanForm.append(statBar, infoBar);
+
+ // Create VM fieldset
+ var vmFS = $(' ');
+ var vmLegend = $('Virtual Machine ');
+ vmFS.append(vmLegend);
+ rscanForm.append(vmFS);
+
+ var vmAttr = $('
');
+ vmFS.append($(''));
+ vmFS.append(vmAttr);
+
+ // Create options fieldset
+ var optionsFS = $(' ');
+ var optionsLegend = $('Options ');
+ optionsFS.append(optionsLegend);
+ rscanForm.append(optionsFS);
+
+ var optionsAttr = $('
');
+ optionsFS.append($(''));
+ optionsFS.append(optionsAttr);
+
+ // Create target node or group input
+ var target = $('Target node range:
');
+ vmAttr.append(target);
+
+ // Create options
+ var optsList = $('');
+ optionsAttr.append(optsList);
+
+ optsList.append(' Updates and then prints out node definitions in the xCAT database for CEC/BPA ');
+ optsList.append(' Writes output to xCAT database ');
+ optsList.append(' XML format ');
+ optsList.append(' Stanza formated output ');
+
+ // Generate tooltips
+ rscanForm.find('div input[title]').tooltip({
+ position: "center right",
+ offset: [-2, 10],
+ effect: "fade",
+ opacity: 0.7,
+ predelay: 800,
+ events : {
+ def : "mouseover,mouseout",
+ input : "mouseover,mouseout",
+ widget : "focus mouseover,blur mouseout",
+ tooltip : "mouseover,mouseout"
+ }
+ });
+
+ /**
+ * Ok
+ */
+ var okBtn = createButton('Ok');
+ okBtn.css({
+ 'width': '80px',
+ 'display': 'block'
+ });
+ okBtn.bind('click', function(event) {
+ // Remove any warning messages
+ $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
+
+ // Check inputs
+ var ready = true;
+ var inputs = $("#" + newTabId + " input[type='text']");
+ for ( var i = 0; i < inputs.length; i++) {
+ if (!inputs.eq(i).val()) {
+ inputs.eq(i).css('border', 'solid #FF0000 1px');
+ ready = false;
+ } else {
+ inputs.eq(i).css('border', 'solid #BDBDBD 1px');
+ }
+ }
+
+ // Generate arguments
+ var chkBoxes = $("#" + newTabId + " input[type='checkbox']:checked");
+ var optStr = '';
+ var opt;
+ for ( var i = 0; i < chkBoxes.length; i++) {
+ opt = chkBoxes.eq(i).attr('name');
+ optStr += '-' + opt;
+
+ // Append ; to end of string
+ if (i < (chkBoxes.length - 1)) {
+ optStr += ';';
+ }
+ }
+
+ // If no inputs are empty
+ if (ready) {
+ // Get nodes
+ var tgts = $('#' + newTabId + ' input[name=target]').val();
+
+ // Disable all inputs and Ok button
+ $('#' + newTabId + ' input').attr('disabled', 'disabled');
+ $(this).attr('disabled', 'true');
+
+ /**
+ * (1) Scan
+ */
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'rscan',
+ tgt : tgts,
+ args : optStr,
+ msg : 'out=' + statBarId + ';cmd=rscan;tgt=' + tgts
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ updateStatusBar(data);
+ }
+ });
+
+ // Show status bar
+ statBar.show();
+ } else {
+ // Show warning message
+ var warn = createWarnBar('Please provide a value for each missing field.');
+ warn.prependTo($(this).parents('.ui-tabs-panel'));
+ }
+ });
+ rscanForm.append(okBtn);
+
+ // Append to discover tab
+ tab.add(newTabId, 'Scan', rscanForm, true);
+
+ // Select new tab
+ tab.select(newTabId);
}
\ No newline at end of file
diff --git a/xCAT-UI/js/nodes/updatenode.js b/xCAT-UI/js/nodes/updatenode.js
index 943972e8e..d0a177a40 100644
--- a/xCAT-UI/js/nodes/updatenode.js
+++ b/xCAT-UI/js/nodes/updatenode.js
@@ -1,403 +1,409 @@
-/**
- * Load updatenode page
- *
- * @param tgtNodes Targets to run updatenode against
- */
-function loadUpdatenodePage(tgtNodes) {
- // Get OS images
- $.ajax({
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'tabdump',
- tgt : '',
- args : 'osimage',
- msg : ''
- },
-
- success : setOSImageCookies
- });
-
- // Get node OS
- var osHash = new Object();
- var nodes = tgtNodes.split(',');
- for (var i in nodes) {
- var os = getNodeAttr(nodes[i], 'os');
- var osBase = os.match(/[a-zA-Z]+/);
- if (osBase) {
- nodes[osBase] = 1;
- }
- }
-
- // Get nodes tab
- var tab = getNodesTab();
-
- // Generate new tab ID
- var inst = 0;
- var newTabId = 'updatenodeTab' + inst;
- while ($('#' + newTabId).length) {
- // If one already exists, generate another one
- inst = inst + 1;
- newTabId = 'updatenodeTab' + inst;
- }
-
- // Create rscan form
- var updatenodeForm = $('
');
-
- // Create status bar
- var statBarId = 'updatenodeStatusBar' + inst;
- var statusBar = createStatusBar(statBarId).hide();
-
- // Create loader
- var loader = createLoader('updatenodeLoader');
- statusBar.find('div').append(loader);
-
- // Create info bar
- var infoBar = createInfoBar('Update nodes in an xCAT environment');
- updatenodeForm.append(statusBar, infoBar);
-
- // Create VM fieldset
- var vmFS = $(' ');
- var vmLegend = $('Virtual Machine ');
- vmFS.append(vmLegend);
- updatenodeForm.append(vmFS);
-
- var vmAttr = $('
');
- vmFS.append($(''));
- vmFS.append(vmAttr);
-
- // Create options fieldset
- var optionsFS = $(' ');
- var optionsLegend = $('Options ');
- optionsFS.append(optionsLegend);
- updatenodeForm.append(optionsFS);
-
- var optionsAttr = $('
');
- optionsFS.append($(''));
- optionsFS.append(optionsAttr);
-
- // Create target node or group input
- var tgt = $('Target node range:
');
- vmAttr.append(tgt);
-
- // Create options
- var optionsList = $('');
- optionsAttr.append(optionsList);
-
- // Create update all software checkbox (only AIX)
- if (osHash['AIX']) {
- var updateAllOption = $(' ');
- var updateAllChkBox = $(' ');
- updateAllOption.append(updateAllChkBox);
- optionsList.append(updateAllOption);
- updateAllOption.append('Install or update all software contained in the source directory');
-
- // Create source directory input
- var allSwScrDirectory = $('Source directory: ');
- // Browse server directory and files
- var allSWSrcDirBrowse = createButton('Browse');
- allSWSrcDirBrowse.serverBrowser({
- onSelect : function(path) {
- $('#allSwSrcDirectory').val(path);
- },
- onLoad : function() {
- return $('#allSwSrcDirectory').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
- });
- allSwScrDirectory.append(allSWSrcDirBrowse);
- allSwScrDirectory.hide();
- optionsList.append(allSwScrDirectory);
-
- // Show source directory when checked
- updateAllChkBox.bind('click', function(event) {
- if ($(this).is(':checked')) {
- allSwScrDirectory.show();
- } else {
- allSwScrDirectory.hide();
- }
- });
- }
-
- // Create update software checkbox
- var updateOption = $(' ');
- var updateChkBox = $(' ');
- optionsList.append(updateOption);
- updateOption.append(updateChkBox);
- updateOption.append('Update existing software');
-
- // Create source directory input
- var scrDirectory = $('Source directory: ');
- // Browse server directory and files
- var srcDirBrowse = createButton('Browse');
- srcDirBrowse.serverBrowser({
- onSelect : function(path) {
- $('#srcDirectory').val(path);
- },
- onLoad : function() {
- return $('#srcDirectory').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
- });
- scrDirectory.append(srcDirBrowse);
- scrDirectory.hide();
- optionsList.append(scrDirectory);
-
- // Create other packages input
- var otherPkgs = $('otherpkgs: ');
- otherPkgs.hide();
- optionsList.append(otherPkgs);
-
- // Create RPM flags input (only AIX)
- var aixRpmFlags = $('rpm_flags: ');
- aixRpmFlags.hide();
- optionsList.append(aixRpmFlags);
-
- // Create installp flags input (only AIX)
- var aixInstallPFlags = $('installp_flags: ');
- aixInstallPFlags.hide();
- optionsList.append(aixInstallPFlags);
-
- // Create emgr flags input (only AIX)
- var aixEmgrFlags = $('emgr_flags: ');
- aixEmgrFlags.hide();
- optionsList.append(aixEmgrFlags);
-
- // Show flags when checked
- updateChkBox.bind('click', function(event) {
- if ($(this).is(':checked')) {
- scrDirectory.show();
- otherPkgs.show();
- if (osHash['AIX']) {
- aixRpmFlags.show();
- aixInstallPFlags.show();
- aixEmgrFlags.show();
- }
- } else {
- scrDirectory.hide();
- otherPkgs.hide();
- if (osHash['AIX']) {
- aixRpmFlags.hide();
- aixInstallPFlags.hide();
- aixEmgrFlags.hide();
- }
- }
- });
-
- // Create postscripts input
- var postOption = $(' ');
- var postChkBox = $(' ');
- optionsList.append(postOption);
- postOption.append(postChkBox);
- postOption.append('Run postscripts');
- var postscripts = $('Postscripts: ');
- postscripts.hide();
- optionsList.append(postscripts);
-
- // Show alternate source directory when checked
- postChkBox.bind('click', function(event) {
- if ($(this).is(':checked')) {
- postscripts.show();
- } else {
- postscripts.hide();
- }
- });
- optionsList.append(' Distribute and synchronize files ');
- optionsList.append(' Update the ssh keys and host keys for the service nodes and compute nodes ');
-
- // Create update OS checkbox
- if (!osHash['AIX']) {
- var osOption = $(' ');
- var osChkBox = $(' ');
- optionsList.append(osOption);
- osOption.append(osChkBox);
- osOption.append('Update the operating system');
-
- var os = $(' ').hide();
- var osLabel = $('Operating system: ');
- var osInput = $(' ');
- osInput.one('focus', function(){
- var tmp = $.cookie('xcat_osvers');
- if (tmp) {
- // Turn on auto complete
- $(this).autocomplete({
- source: tmp.split(',')
- });
- }
- });
- os.append(osLabel);
- os.append(osInput);
- optionsList.append(os);
-
- // Show alternate source directory when checked
- osChkBox.bind('click', function(event) {
- if ($(this).is(':checked')) {
- os.show();
- } else {
- os.hide();
- }
- });
- }
-
- // Generate tooltips
- updatenodeForm.find('div input[title]').tooltip({
- position: "center right",
- offset: [-2, 10],
- effect: "fade",
- opacity: 0.7,
- predelay: 800,
- events : {
- def : "mouseover,mouseout",
- input : "mouseover,mouseout",
- widget : "focus mouseover,blur mouseout",
- tooltip : "mouseover,mouseout"
- }
- });
-
- /**
- * Ok
- */
- var updateBtn = createButton('Update');
- updateBtn.css({
- 'width': '80px',
- 'display': 'block'
- });
- updateBtn.bind('click', function(event) {
- // Remove any warning messages
- $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
- var ready = true;
-
- // Generate arguments
- var chkBoxes = $("#" + newTabId + " input[type='checkbox']:checked");
- var optionsStr = '';
- var option;
- for ( var i = 0; i < chkBoxes.length; i++) {
- option = chkBoxes.eq(i).attr('name');
- optionsStr += '-' + option;
-
- // If update all software is checked
- if (option == 'S') {
- var srcDir = $('#' + newTabId + ' input[name=allSwSrcDirectory]').val();
- if (srcDir) {
- optionsStr += ';-d ' + srcDir;
- }
- }
-
- // If update software is checked
- if (option == 'S') {
- // Get source directory
- var srcDirectory = $('#' + newTabId + ' input[name=srcDirectory]').val();
- if (srcDirectory) {
- optionsStr += ';-d;' + srcDirectory;
- }
-
- // Get otherpkgs
- var otherpkgs = $('#' + newTabId + ' input[name=otherpkgs]').val();
- if (otherpkgs) {
- optionsStr += ';otherpkgs=' + otherpkgs;
- }
-
- // Get rpm_flags
- var rpm_flags = $('#' + newTabId + ' input[name=rpm_flags]').val();
- if (rpm_flags) {
- optionsStr += ';rpm_flags=' + rpm_flags;
- }
-
- // Get installp_flags
- var installp_flags = $('#' + newTabId + ' input[name=installp_flags]').val();
- if (installp_flags) {
- optionsStr += ';installp_flags=' + installp_flags;
- }
-
- // Get emgr_flags
- var emgr_flags = $('#' + newTabId + ' input[name=emgr_flags]').val();
- if (emgr_flags) {
- optionsStr += ';emgr_flags=' + emgr_flags;
- }
- }
-
- // If postscripts is checked
- if (option == 'P') {
- // Get postscripts
- optionsStr += ';' + $('#' + newTabId + ' input[name=postscripts]').val();
- }
-
- // If operating system is checked
- if (option == 'o') {
- // Get the OS
- optionsStr += ';' + $('#' + newTabId + ' input[name=os]').val();
- }
-
- // Append ; to end of string
- if (i < (chkBoxes.length - 1)) {
- optionsStr += ';';
- }
- }
-
- // If no inputs are empty
- if (ready) {
- // Get nodes
- var tgts = $('#' + newTabId + ' input[name=target]').val();
-
- // Disable all inputs and Ok button
- $('#' + newTabId + ' input').attr('disabled', 'disabled');
- $(this).attr('disabled', 'true');
-
- /**
- * (1) Boot to network
- */
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'updatenode',
- tgt : tgts,
- args : optionsStr,
- msg : 'out=' + statBarId + ';cmd=updatenode;tgt=' + tgts
- },
-
- success : updateStatusBar
- });
-
- // Show status bar
- statusBar.show();
- } else {
- // Show warning message
- var warn = createWarnBar('You are missing some values');
- warn.prependTo($(this).parents('.ui-tabs-panel'));
- }
- });
- updatenodeForm.append(updateBtn);
-
- // Append to discover tab
- tab.add(newTabId, 'Update', updatenodeForm, true);
-
- // Select new tab
- tab.select(newTabId);
+/**
+ * Load updatenode page
+ *
+ * @param tgtNodes Targets to run updatenode against
+ */
+function loadUpdatenodePage(tgtNodes) {
+ // Get OS images
+ $.ajax({
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'tabdump',
+ tgt : '',
+ args : 'osimage',
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ setOSImageCookies(data);
+ }
+ });
+
+ // Get node OS
+ var osHash = new Object();
+ var nodes = tgtNodes.split(',');
+ for (var i in nodes) {
+ var os = getNodeAttr(nodes[i], 'os');
+ var osBase = os.match(/[a-zA-Z]+/);
+ if (osBase) {
+ nodes[osBase] = 1;
+ }
+ }
+
+ // Get nodes tab
+ var tab = getNodesTab();
+
+ // Generate new tab ID
+ var inst = 0;
+ var newTabId = 'updatenodeTab' + inst;
+ while ($('#' + newTabId).length) {
+ // If one already exists, generate another one
+ inst = inst + 1;
+ newTabId = 'updatenodeTab' + inst;
+ }
+
+ // Create rscan form
+ var updatenodeForm = $('
');
+
+ // Create status bar
+ var statBarId = 'updatenodeStatusBar' + inst;
+ var statusBar = createStatusBar(statBarId).hide();
+
+ // Create loader
+ var loader = createLoader('updatenodeLoader');
+ statusBar.find('div').append(loader);
+
+ // Create info bar
+ var infoBar = createInfoBar('Update nodes in an xCAT environment');
+ updatenodeForm.append(statusBar, infoBar);
+
+ // Create VM fieldset
+ var vmFS = $(' ');
+ var vmLegend = $('Virtual Machine ');
+ vmFS.append(vmLegend);
+ updatenodeForm.append(vmFS);
+
+ var vmAttr = $('
');
+ vmFS.append($(''));
+ vmFS.append(vmAttr);
+
+ // Create options fieldset
+ var optionsFS = $(' ');
+ var optionsLegend = $('Options ');
+ optionsFS.append(optionsLegend);
+ updatenodeForm.append(optionsFS);
+
+ var optionsAttr = $('
');
+ optionsFS.append($(''));
+ optionsFS.append(optionsAttr);
+
+ // Create target node or group input
+ var tgt = $('Target node range:
');
+ vmAttr.append(tgt);
+
+ // Create options
+ var optionsList = $('');
+ optionsAttr.append(optionsList);
+
+ // Create update all software checkbox (only AIX)
+ if (osHash['AIX']) {
+ var updateAllOption = $(' ');
+ var updateAllChkBox = $(' ');
+ updateAllOption.append(updateAllChkBox);
+ optionsList.append(updateAllOption);
+ updateAllOption.append('Install or update all software contained in the source directory');
+
+ // Create source directory input
+ var allSwScrDirectory = $('Source directory: ');
+ // Browse server directory and files
+ var allSWSrcDirBrowse = createButton('Browse');
+ allSWSrcDirBrowse.serverBrowser({
+ onSelect : function(path) {
+ $('#allSwSrcDirectory').val(path);
+ },
+ onLoad : function() {
+ return $('#allSwSrcDirectory').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
+ });
+ allSwScrDirectory.append(allSWSrcDirBrowse);
+ allSwScrDirectory.hide();
+ optionsList.append(allSwScrDirectory);
+
+ // Show source directory when checked
+ updateAllChkBox.bind('click', function(event) {
+ if ($(this).is(':checked')) {
+ allSwScrDirectory.show();
+ } else {
+ allSwScrDirectory.hide();
+ }
+ });
+ }
+
+ // Create update software checkbox
+ var updateOption = $(' ');
+ var updateChkBox = $(' ');
+ optionsList.append(updateOption);
+ updateOption.append(updateChkBox);
+ updateOption.append('Update existing software');
+
+ // Create source directory input
+ var scrDirectory = $('Source directory: ');
+ // Browse server directory and files
+ var srcDirBrowse = createButton('Browse');
+ srcDirBrowse.serverBrowser({
+ onSelect : function(path) {
+ $('#srcDirectory').val(path);
+ },
+ onLoad : function() {
+ return $('#srcDirectory').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
+ });
+ scrDirectory.append(srcDirBrowse);
+ scrDirectory.hide();
+ optionsList.append(scrDirectory);
+
+ // Create other packages input
+ var otherPkgs = $('otherpkgs: ');
+ otherPkgs.hide();
+ optionsList.append(otherPkgs);
+
+ // Create RPM flags input (only AIX)
+ var aixRpmFlags = $('rpm_flags: ');
+ aixRpmFlags.hide();
+ optionsList.append(aixRpmFlags);
+
+ // Create installp flags input (only AIX)
+ var aixInstallPFlags = $('installp_flags: ');
+ aixInstallPFlags.hide();
+ optionsList.append(aixInstallPFlags);
+
+ // Create emgr flags input (only AIX)
+ var aixEmgrFlags = $('emgr_flags: ');
+ aixEmgrFlags.hide();
+ optionsList.append(aixEmgrFlags);
+
+ // Show flags when checked
+ updateChkBox.bind('click', function(event) {
+ if ($(this).is(':checked')) {
+ scrDirectory.show();
+ otherPkgs.show();
+ if (osHash['AIX']) {
+ aixRpmFlags.show();
+ aixInstallPFlags.show();
+ aixEmgrFlags.show();
+ }
+ } else {
+ scrDirectory.hide();
+ otherPkgs.hide();
+ if (osHash['AIX']) {
+ aixRpmFlags.hide();
+ aixInstallPFlags.hide();
+ aixEmgrFlags.hide();
+ }
+ }
+ });
+
+ // Create postscripts input
+ var postOption = $(' ');
+ var postChkBox = $(' ');
+ optionsList.append(postOption);
+ postOption.append(postChkBox);
+ postOption.append('Run postscripts');
+ var postscripts = $('Postscripts: ');
+ postscripts.hide();
+ optionsList.append(postscripts);
+
+ // Show alternate source directory when checked
+ postChkBox.bind('click', function(event) {
+ if ($(this).is(':checked')) {
+ postscripts.show();
+ } else {
+ postscripts.hide();
+ }
+ });
+ optionsList.append(' Distribute and synchronize files ');
+ optionsList.append(' Update the ssh keys and host keys for the service nodes and compute nodes ');
+
+ // Create update OS checkbox
+ if (!osHash['AIX']) {
+ var osOption = $(' ');
+ var osChkBox = $(' ');
+ optionsList.append(osOption);
+ osOption.append(osChkBox);
+ osOption.append('Update the operating system');
+
+ var os = $(' ').hide();
+ var osLabel = $('Operating system: ');
+ var osInput = $(' ');
+ osInput.one('focus', function(){
+ var tmp = $.cookie('xcat_osvers');
+ if (tmp) {
+ // Turn on auto complete
+ $(this).autocomplete({
+ source: tmp.split(',')
+ });
+ }
+ });
+ os.append(osLabel);
+ os.append(osInput);
+ optionsList.append(os);
+
+ // Show alternate source directory when checked
+ osChkBox.bind('click', function(event) {
+ if ($(this).is(':checked')) {
+ os.show();
+ } else {
+ os.hide();
+ }
+ });
+ }
+
+ // Generate tooltips
+ updatenodeForm.find('div input[title]').tooltip({
+ position: "center right",
+ offset: [-2, 10],
+ effect: "fade",
+ opacity: 0.7,
+ predelay: 800,
+ events : {
+ def : "mouseover,mouseout",
+ input : "mouseover,mouseout",
+ widget : "focus mouseover,blur mouseout",
+ tooltip : "mouseover,mouseout"
+ }
+ });
+
+ /**
+ * Ok
+ */
+ var updateBtn = createButton('Update');
+ updateBtn.css({
+ 'width': '80px',
+ 'display': 'block'
+ });
+ updateBtn.bind('click', function(event) {
+ // Remove any warning messages
+ $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove();
+ var ready = true;
+
+ // Generate arguments
+ var chkBoxes = $("#" + newTabId + " input[type='checkbox']:checked");
+ var optionsStr = '';
+ var option;
+ for ( var i = 0; i < chkBoxes.length; i++) {
+ option = chkBoxes.eq(i).attr('name');
+ optionsStr += '-' + option;
+
+ // If update all software is checked
+ if (option == 'S') {
+ var srcDir = $('#' + newTabId + ' input[name=allSwSrcDirectory]').val();
+ if (srcDir) {
+ optionsStr += ';-d ' + srcDir;
+ }
+ }
+
+ // If update software is checked
+ if (option == 'S') {
+ // Get source directory
+ var srcDirectory = $('#' + newTabId + ' input[name=srcDirectory]').val();
+ if (srcDirectory) {
+ optionsStr += ';-d;' + srcDirectory;
+ }
+
+ // Get otherpkgs
+ var otherpkgs = $('#' + newTabId + ' input[name=otherpkgs]').val();
+ if (otherpkgs) {
+ optionsStr += ';otherpkgs=' + otherpkgs;
+ }
+
+ // Get rpm_flags
+ var rpm_flags = $('#' + newTabId + ' input[name=rpm_flags]').val();
+ if (rpm_flags) {
+ optionsStr += ';rpm_flags=' + rpm_flags;
+ }
+
+ // Get installp_flags
+ var installp_flags = $('#' + newTabId + ' input[name=installp_flags]').val();
+ if (installp_flags) {
+ optionsStr += ';installp_flags=' + installp_flags;
+ }
+
+ // Get emgr_flags
+ var emgr_flags = $('#' + newTabId + ' input[name=emgr_flags]').val();
+ if (emgr_flags) {
+ optionsStr += ';emgr_flags=' + emgr_flags;
+ }
+ }
+
+ // If postscripts is checked
+ if (option == 'P') {
+ // Get postscripts
+ optionsStr += ';' + $('#' + newTabId + ' input[name=postscripts]').val();
+ }
+
+ // If operating system is checked
+ if (option == 'o') {
+ // Get the OS
+ optionsStr += ';' + $('#' + newTabId + ' input[name=os]').val();
+ }
+
+ // Append ; to end of string
+ if (i < (chkBoxes.length - 1)) {
+ optionsStr += ';';
+ }
+ }
+
+ // If no inputs are empty
+ if (ready) {
+ // Get nodes
+ var tgts = $('#' + newTabId + ' input[name=target]').val();
+
+ // Disable all inputs and Ok button
+ $('#' + newTabId + ' input').attr('disabled', 'disabled');
+ $(this).attr('disabled', 'true');
+
+ /**
+ * (1) Boot to network
+ */
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'updatenode',
+ tgt : tgts,
+ args : optionsStr,
+ msg : 'out=' + statBarId + ';cmd=updatenode;tgt=' + tgts
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ updateStatusBar(data);
+ }
+ });
+
+ // Show status bar
+ statusBar.show();
+ } else {
+ // Show warning message
+ var warn = createWarnBar('You are missing some values');
+ warn.prependTo($(this).parents('.ui-tabs-panel'));
+ }
+ });
+ updatenodeForm.append(updateBtn);
+
+ // Append to discover tab
+ tab.add(newTabId, 'Update', updatenodeForm, true);
+
+ // Select new tab
+ tab.select(newTabId);
}
\ No newline at end of file
diff --git a/xCAT-UI/js/provision/images.js b/xCAT-UI/js/provision/images.js
index d1a6f174d..fd4967321 100644
--- a/xCAT-UI/js/provision/images.js
+++ b/xCAT-UI/js/provision/images.js
@@ -1,1435 +1,1462 @@
-/**
- * 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(' ', '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 = ' ';
- // 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 = $('Copy CD ');
- copyCDLnk.click(function() {
- openCopyCdDialog();
- });
-
- // Generate stateless or statelite image
- var generateLnk = $('Generate image ');
- generateLnk.click(function() {
- loadCreateImage();
- });
-
- // Edit image attributes
- var editLnk = $('Edit ');
- editLnk.click(function() {
- var tgtImages = getNodesChecked(imgTableId).split(',');
- if (tgtImages) {
- for (var i in tgtImages) {
- openEditImagePage(tgtImages[i]);
- }
- }
- });
-
- // Add a row
- var addLnk = $('Add ');
- addLnk.click(function() {
- openAddImageDialog();
- });
-
- // Remove a row
- var removeLnk = $('Remove ');
- removeLnk.click(function() {
- var images = getNodesChecked(imgTableId);
- if (images) {
- confirmImageDeleteDialog(images);
- }
- });
-
- // Refresh image table
- var refreshLnk = $('Refresh ');
- 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 = $('
').css("width", "450px");
- var advancedLnk = 'Advanced ';
- 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 = $('');
- $('#' + 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 = $(''
- + '
Are you sure you want to remove ' + tmp + '?
'
- + '
');
-
- // 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 = $('
');
-
- // 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 = $(' ');
- var imageLegend = $('Image ');
- imageFS.append(imageLegend);
- var imageAttr = $('
');
- imageFS.append($(''));
- imageFS.append(imageAttr);
-
- var optionFS = $(' ');
- var optionLegend = $('Options ');
- optionFS.append(optionLegend);
- var optionAttr = $('
');
- optionFS.append($(''));
- optionFS.append(optionAttr);
-
- addImageForm.append(info, imageFS, optionFS);
-
- // Create inputs for image attributes
- var imageName = $('Image name:
');
- var imageType = $('Image type:
');
- var architecture = $('OS architecture:
');
- var osName = $('OS name:
');
- var osVersion = $('OS version:
');
- var profile = $('Profile:
');
- var provisionMethod = $('Provision method:
');
- var provisionSelect = $(''
- + ' '
- + 'install '
- + 'netboot '
- + 'statelite '
- + ' ');
- provisionMethod.append(provisionSelect);
-
- // Create inputs for optional attributes
- var otherpkgDirectory = $('Other package directory:
');
- var otherpkgDirectoryInput = $(' ');
- 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 = $('Package directory:
');
- var packageDirectoryInput = $(' ');
- 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 = $('Package list:
');
- var packageListInput = $(' ');
- 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 = $('Template:
');
- var templateInput = $(' ');
- 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] + '';
- } 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': '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("xcat_osvers").split(",");
- var imageArch = $.cookie("xcat_osarchs").split(",");
- var profiles = $.cookie("xcat_profiles").split(",");
-
- var createImgForm = $('
');
- var createImgFS = $(' ').append('Create Image ');
- 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 = $(' ');
- for (var i in imageOsVers)
- osVerSelect.append('' + imageOsVers[i] + ' ');
- createImgFS.append($('OS version:
').append(osVerSelect));
-
- // Drop down for OS architectures
- var imgSelect = $(' ');
- for (var i in imageArch)
- imgSelect.append('' + imageArch[i] + ' ');
- createImgFS.append($('OS architecture:
').append(imgSelect));
-
- // Netboot interface input
- createImgFS.append($('Netboot interface:
'));
-
- // Profile selector
- var profileSelect = $('');
- for (var i in profiles)
- profileSelect.append('' + profiles[i] + ' ');
- createImgFS.append($('Profile:
').append(profileSelect));
-
- // Boot method drop down
- createImgFS.append($('Boot method: ' +
- '' +
- 'stateless ' +
- 'statelite ' +
- '
'));
-
- // 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 = $(' ');
- hpcFieldset.append('HPC Software Stack ');
-
- var str = 'Before selecting the software, you should have the following already completed on your xCAT cluster: '
- + '1. If you are using the xCAT hierarchy, your service nodes are installed and running. '
- + '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. '
- + '3. You should have a diskless image created with the base OS installed and verified it on at least one test node. '
- + '4. You should install the software on the management node and copy all correponding packages into the location "/install/custom/otherpkgs/" based on '
- + 'these documents . ';
- hpcFieldset.append(createInfoBar(str));
-
- // Advanced software
- str = '' +
- '';
- hpcFieldset.append(str);
-
- container.append($('
').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 + ' ';
- }
- }
- $('#createImageTab #' + softwareName + 'li').find('img').remove();
-
- // No error, show the check image
- if (!errorStr) {
- var infoPart = '
';
- $('#createImageTab #' + softwareName + 'li').append(infoPart);
- } else {
- // Show the error message
- errorStr = 'To install the RSCT on your compute node. You should: ' + errorStr + '';
- 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] + ' ';
- }
- }
-
- 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 = $('
');
-
- // 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 = $('
').css('display', 'inline');
- label = $('' + key + ': ').css('vertical-align', 'middle');
- input = $(' ').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 = $('
');
-
- // 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 = $('
');
- var isoLabel = $(' Linux ISO/DVD: ').css('vertical-align', 'middle');
- var isoInput = $(' ').css('width', '300px');
- iso.append(isoLabel);
- iso.append(isoInput);
- copyLinuxForm.append(iso);
-
- // Create architecture input
- copyLinuxForm.append('Architecture:
');
- // Create distribution input
- copyLinuxForm.append('Distribution:
');
-
- /**
- * 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) {
-
- }
- });
+/**
+ * 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 : function(data) {
+ data = decodeRsp(data);
+ loadImages(data);
+ }
+ });
+}
+
+/**
+ * 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(' ', '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 = ' ';
+ // 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 = $('Copy CD ');
+ copyCDLnk.click(function() {
+ openCopyCdDialog();
+ });
+
+ // Generate stateless or statelite image
+ var generateLnk = $('Generate image ');
+ generateLnk.click(function() {
+ loadCreateImage();
+ });
+
+ // Edit image attributes
+ var editLnk = $('Edit ');
+ editLnk.click(function() {
+ var tgtImages = getNodesChecked(imgTableId).split(',');
+ if (tgtImages) {
+ for (var i in tgtImages) {
+ openEditImagePage(tgtImages[i]);
+ }
+ }
+ });
+
+ // Add a row
+ var addLnk = $('Add ');
+ addLnk.click(function() {
+ openAddImageDialog();
+ });
+
+ // Remove a row
+ var removeLnk = $('Remove ');
+ removeLnk.click(function() {
+ var images = getNodesChecked(imgTableId);
+ if (images) {
+ confirmImageDeleteDialog(images);
+ }
+ });
+
+ // Refresh image table
+ var refreshLnk = $('Refresh ');
+ 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 : function(data) {
+ data = decodeRsp(data);
+ loadImages(data);
+ }
+ });
+ });
+
+ // 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 = $('
').css("width", "450px");
+ var advancedLnk = 'Advanced ';
+ 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 = $('');
+ $('#' + 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 : function(data) {
+ data = decodeRsp(data);
+ showChdefOutput(data);
+ }
+ });
+
+ 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 : function(data) {
+ data = decodeRsp(data);
+ setImageDefAttrs(data);
+ }
+ });
+}
+
+/**
+ * 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 = $(''
+ + '
Are you sure you want to remove ' + tmp + '?
'
+ + '
');
+
+ // 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 : function(data) {
+ data = decodeRsp(data);
+ updateImageDialog(data);
+ }
+ });
+ },
+ "Cancel": function(){
+ $(this).dialog("close");
+ }
+ }
+ });
+}
+
+/**
+ * Open a dialog to add an image
+ */
+function openAddImageDialog() {
+ // Create dialog to add image
+ var dialogId = 'addImage';
+ var addImageForm = $('
');
+
+ // 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 = $(' ');
+ var imageLegend = $('Image ');
+ imageFS.append(imageLegend);
+ var imageAttr = $('
');
+ imageFS.append($(''));
+ imageFS.append(imageAttr);
+
+ var optionFS = $(' ');
+ var optionLegend = $('Options ');
+ optionFS.append(optionLegend);
+ var optionAttr = $('
');
+ optionFS.append($(''));
+ optionFS.append(optionAttr);
+
+ addImageForm.append(info, imageFS, optionFS);
+
+ // Create inputs for image attributes
+ var imageName = $('Image name:
');
+ var imageType = $('Image type:
');
+ var architecture = $('OS architecture:
');
+ var osName = $('OS name:
');
+ var osVersion = $('OS version:
');
+ var profile = $('Profile:
');
+ var provisionMethod = $('Provision method:
');
+ var provisionSelect = $(''
+ + ' '
+ + 'install '
+ + 'netboot '
+ + 'statelite '
+ + ' ');
+ provisionMethod.append(provisionSelect);
+
+ // Create inputs for optional attributes
+ var otherpkgDirectory = $('Other package directory:
');
+ var otherpkgDirectoryInput = $(' ');
+ 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 = $('Package directory:
');
+ var packageDirectoryInput = $(' ');
+ 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 = $('Package list:
');
+ var packageListInput = $(' ');
+ 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 = $('Template:
');
+ var templateInput = $(' ');
+ 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 : function(data) {
+ data = decodeRsp(data);
+ updateImageDialog(data);
+ }
+ });
+ }
+ },
+ "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] + '';
+ } 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': '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("xcat_osvers").split(",");
+ var imageArch = $.cookie("xcat_osarchs").split(",");
+ var profiles = $.cookie("xcat_profiles").split(",");
+
+ var createImgForm = $('
');
+ var createImgFS = $(' ').append('Create Image ');
+ 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 = $(' ');
+ for (var i in imageOsVers)
+ osVerSelect.append('' + imageOsVers[i] + ' ');
+ createImgFS.append($('OS version:
').append(osVerSelect));
+
+ // Drop down for OS architectures
+ var imgSelect = $(' ');
+ for (var i in imageArch)
+ imgSelect.append('' + imageArch[i] + ' ');
+ createImgFS.append($('OS architecture:
').append(imgSelect));
+
+ // Netboot interface input
+ createImgFS.append($('Netboot interface:
'));
+
+ // Profile selector
+ var profileSelect = $('');
+ for (var i in profiles)
+ profileSelect.append('' + profiles[i] + ' ');
+ createImgFS.append($('Profile:
').append(profileSelect));
+
+ // Boot method drop down
+ createImgFS.append($('Boot method: ' +
+ '' +
+ 'stateless ' +
+ 'statelite ' +
+ '
'));
+
+ // 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 = $(' ');
+ hpcFieldset.append('HPC Software Stack ');
+
+ var str = 'Before selecting the software, you should have the following already completed on your xCAT cluster: '
+ + '1. If you are using the xCAT hierarchy, your service nodes are installed and running. '
+ + '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. '
+ + '3. You should have a diskless image created with the base OS installed and verified it on at least one test node. '
+ + '4. You should install the software on the management node and copy all correponding packages into the location "/install/custom/otherpkgs/" based on '
+ + 'these documents . ';
+ hpcFieldset.append(createInfoBar(str));
+
+ // Advanced software
+ str = '' +
+ '';
+ hpcFieldset.append(str);
+
+ container.append($('
').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 : function(data) {
+ data = decodeRsp(data);
+ rpmCopyCheck(data);
+ }
+ });
+ }
+ }
+ });
+}
+
+/**
+ * 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 + ' ';
+ }
+ }
+ $('#createImageTab #' + softwareName + 'li').find('img').remove();
+
+ // No error, show the check image
+ if (!errorStr) {
+ var infoPart = '
';
+ $('#createImageTab #' + softwareName + 'li').append(infoPart);
+ } else {
+ // Show the error message
+ errorStr = 'To install the RSCT on your compute node. You should: ' + errorStr + '';
+ 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] + ' ';
+ }
+ }
+
+ 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 = $('
');
+
+ // 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 = $('
').css('display', 'inline');
+ label = $('' + key + ': ').css('vertical-align', 'middle');
+ input = $(' ').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 : function(data) {
+ data = decodeRsp(data);
+ showChdefOutput(data);
+ }
+ });
+ });
+ 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 = $('
');
+
+ // 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 = $('
');
+ var isoLabel = $(' Linux ISO/DVD: ').css('vertical-align', 'middle');
+ var isoInput = $(' ').css('width', '300px');
+ iso.append(isoLabel);
+ iso.append(isoInput);
+ copyLinuxForm.append(iso);
+
+ // Create architecture input
+ copyLinuxForm.append('Architecture:
');
+ // Create distribution input
+ copyLinuxForm.append('Distribution:
');
+
+ /**
+ * 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 : function(data) {
+ data = decodeRsp(data);
+ updateImageDialog(data);
+ }
+ });
+ },
+ "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) {
+ data = decodeRsp(data);
+ }
+ });
}
\ No newline at end of file
diff --git a/xCAT-UI/js/provision/provision.js b/xCAT-UI/js/provision/provision.js
index 00a059080..f3a394df5 100644
--- a/xCAT-UI/js/provision/provision.js
+++ b/xCAT-UI/js/provision/provision.js
@@ -1,252 +1,258 @@
-/**
- * Global variables
- */
-var provisionTabs; // Provision tabs
-
-/**
- * Set the provision tab
- *
- * @param obj Tab object
- */
-function setProvisionTab(obj) {
- provisionTabs = obj;
-}
-
-/**
- * Get the provision tab
- *
- * @param Nothing
- * @return Tab object
- */
-function getProvisionTab() {
- return provisionTabs;
-}
-
-/**
- * Load provision page
- */
-function loadProvisionPage() {
- // If the page is loaded
- if ($('#content').children().length) {
- // Do not load again
- return;
- }
-
- // Get OS image names
- if (!$.cookie('xcat_imagenames')){
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'tabdump',
- tgt : '',
- args : 'osimage',
- msg : ''
- },
-
- success : setOSImageCookies
- });
- }
-
- // Get groups
- if (!$.cookie('xcat_groups')){
- $.ajax( {
- url : 'lib/cmd.php',
- dataType : 'json',
- data : {
- cmd : 'extnoderange',
- tgt : '/.*',
- args : 'subgroups',
- msg : ''
- },
-
- success : setGroupsCookies
- });
- }
-
- // Create info bar
- var infoBar = createInfoBar('Select a platform to provision or re-provision a node on, then click Ok.');
-
- // Create provision page
- var provPg = $('
');
- provPg.append(infoBar);
-
- // Create provision tab
- var tab = new Tab('provisionPageTabs');
- setProvisionTab(tab);
- tab.init();
- $('#content').append(tab.object());
-
- // Create radio buttons for platforms
- var hwList = $('Platforms available: ');
- var esx = $(' ESX ');
- var kvm = $(' KVM ');
- var zvm = $(' z\/VM ');
- var ipmi = $(' iDataPlex ');
- var blade = $(' BladeCenter ');
- var hmc = $(' System p ');
-
- hwList.append(esx);
- hwList.append(kvm);
- hwList.append(zvm);
- hwList.append(blade);
- hwList.append(ipmi);
- hwList.append(hmc);
- provPg.append(hwList);
-
- /**
- * Ok
- */
- var okBtn = createButton('Ok');
- okBtn.bind('click', function(event) {
- // Get hardware that was selected
- var hw = $(this).parent().find('input[name="hw"]:checked').val();
-
- var inst = 0;
- var newTabId = hw + 'ProvisionTab' + inst;
- while ($('#' + newTabId).length) {
- // If one already exists, generate another one
- inst = inst + 1;
- newTabId = hw + 'ProvisionTab' + inst;
- }
-
- // Create an instance of the plugin
- var title = '';
- var plugin;
- switch (hw) {
- case "kvm":
- plugin = new kvmPlugin();
- title = 'KVM';
- break;
- case "esx":
- plugin = new esxPlugin();
- title = 'ESX';
- break;
- case "blade":
- plugin = new bladePlugin();
- title = 'BladeCenter';
- break;
- case "hmc":
- plugin = new hmcPlugin();
- title = 'System p';
- break;
- case "ipmi":
- plugin = new ipmiPlugin();
- title = 'iDataPlex';
- break;
- case "zvm":
- plugin = new zvmPlugin();
- title = 'z/VM';
- break;
- }
-
- // Select tab
- tab.add(newTabId, title, '', true);
- tab.select(newTabId);
- plugin.loadProvisionPage(newTabId);
- });
- provPg.append(okBtn);
-
- // Create resources tab
- var resrcPg = $('
');
-
- // Create info bar
- var resrcInfoBar = createInfoBar('Select a platform to view its current resources.');
- resrcPg.append(resrcInfoBar);
-
- // Create radio buttons for platforms
- var rsrcHwList = $('Platforms available: ');
- esx = $(' ESX ');
- kvm = $(' KVM ');
- zvm = $(' z\/VM ');
- ipmi = $(' iDataPlex ');
- blade = $(' BladeCenter ');
- hmc = $(' System p ');
-
- rsrcHwList.append(esx);
- rsrcHwList.append(kvm);
- rsrcHwList.append(zvm);
- rsrcHwList.append(blade);
- rsrcHwList.append(ipmi);
- rsrcHwList.append(hmc);
-
- resrcPg.append(rsrcHwList);
-
- var okBtn = createButton('Ok');
- okBtn.bind('click', function(event) {
- // Get hardware that was selected
- var hw = $(this).parent().find('input[name="rsrcHw"]:checked').val();
-
- // Generate new tab ID
- var newTabId = hw + 'ResourceTab';
- if (!$('#' + newTabId).length) {
- // Create loader
- var loader = $(' ').append(createLoader(hw + 'ResourceLoader'));
-
- // Create an instance of the plugin
- var plugin = null;
- var displayName = "";
- switch (hw) {
- case "kvm":
- plugin = new kvmPlugin();
- displayName = "KVM";
- break;
- case "esx":
- plugin = new esxPlugin();
- displayName = "ESX";
- break;
- case "blade":
- plugin = new bladePlugin();
- displayName = "BladeCenter";
- break;
- case "hmc":
- plugin = new hmcPlugin();
- displayName = "System p";
- break;
- case "ipmi":
- plugin = new ipmiPlugin();
- displayName = "iDataPlex";
- break;
- case "zvm":
- plugin = new zvmPlugin();
- displayName = "z\/VM";
- break;
- }
-
- // Add resource tab and load resources
- tab.add(newTabId, displayName, loader, true);
- plugin.loadResources();
- }
-
- // Select tab
- tab.select(newTabId);
- });
-
- resrcPg.append(okBtn);
-
- // Add provision tab
- tab.add('provisionTab', 'Provision', provPg, false);
- // Add image tab
- tab.add('imagesTab', 'Images', '', false);
- // Add resource tab
- tab.add('resourceTab', 'Resources', resrcPg, false);
-
- // Load tabs onselect
- $('#provisionPageTabs').bind('tabsselect', function(event, ui){
- // Load image page
- if (!$('#imagesTab').children().length && ui.index == 1) {
- $('#imagesTab').append($(' ').append(createLoader('')));
- loadImagesPage();
- }
- });
-
- // Open the quick provision tab
- if (window.location.search) {
- tab.add('quickProvisionTab', 'Quick Provision', '', true);
- tab.select('quickProvisionTab');
-
- var provForm = $('
');
- $('#quickProvisionTab').append(provForm);
- appendProvisionSection('quick', provForm);
- }
+/**
+ * Global variables
+ */
+var provisionTabs; // Provision tabs
+
+/**
+ * Set the provision tab
+ *
+ * @param obj Tab object
+ */
+function setProvisionTab(obj) {
+ provisionTabs = obj;
+}
+
+/**
+ * Get the provision tab
+ *
+ * @param Nothing
+ * @return Tab object
+ */
+function getProvisionTab() {
+ return provisionTabs;
+}
+
+/**
+ * Load provision page
+ */
+function loadProvisionPage() {
+ // If the page is loaded
+ if ($('#content').children().length) {
+ // Do not load again
+ return;
+ }
+
+ // Get OS image names
+ if (!$.cookie('xcat_imagenames')){
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'tabdump',
+ tgt : '',
+ args : 'osimage',
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ setOSImageCookies(data);
+ }
+ });
+ }
+
+ // Get groups
+ if (!$.cookie('xcat_groups')){
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'extnoderange',
+ tgt : '/.*',
+ args : 'subgroups',
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ setGroupsCookies(data);
+ }
+ });
+ }
+
+ // Create info bar
+ var infoBar = createInfoBar('Select a platform to provision or re-provision a node on, then click Ok.');
+
+ // Create provision page
+ var provPg = $('
');
+ provPg.append(infoBar);
+
+ // Create provision tab
+ var tab = new Tab('provisionPageTabs');
+ setProvisionTab(tab);
+ tab.init();
+ $('#content').append(tab.object());
+
+ // Create radio buttons for platforms
+ var hwList = $('Platforms available: ');
+ var esx = $(' ESX ');
+ var kvm = $(' KVM ');
+ var zvm = $(' z\/VM ');
+ var ipmi = $(' iDataPlex ');
+ var blade = $(' BladeCenter ');
+ var hmc = $(' System p ');
+
+ hwList.append(esx);
+ hwList.append(kvm);
+ hwList.append(zvm);
+ hwList.append(blade);
+ hwList.append(ipmi);
+ hwList.append(hmc);
+ provPg.append(hwList);
+
+ /**
+ * Ok
+ */
+ var okBtn = createButton('Ok');
+ okBtn.bind('click', function(event) {
+ // Get hardware that was selected
+ var hw = $(this).parent().find('input[name="hw"]:checked').val();
+
+ var inst = 0;
+ var newTabId = hw + 'ProvisionTab' + inst;
+ while ($('#' + newTabId).length) {
+ // If one already exists, generate another one
+ inst = inst + 1;
+ newTabId = hw + 'ProvisionTab' + inst;
+ }
+
+ // Create an instance of the plugin
+ var title = '';
+ var plugin;
+ switch (hw) {
+ case "kvm":
+ plugin = new kvmPlugin();
+ title = 'KVM';
+ break;
+ case "esx":
+ plugin = new esxPlugin();
+ title = 'ESX';
+ break;
+ case "blade":
+ plugin = new bladePlugin();
+ title = 'BladeCenter';
+ break;
+ case "hmc":
+ plugin = new hmcPlugin();
+ title = 'System p';
+ break;
+ case "ipmi":
+ plugin = new ipmiPlugin();
+ title = 'iDataPlex';
+ break;
+ case "zvm":
+ plugin = new zvmPlugin();
+ title = 'z/VM';
+ break;
+ }
+
+ // Select tab
+ tab.add(newTabId, title, '', true);
+ tab.select(newTabId);
+ plugin.loadProvisionPage(newTabId);
+ });
+ provPg.append(okBtn);
+
+ // Create resources tab
+ var resrcPg = $('
');
+
+ // Create info bar
+ var resrcInfoBar = createInfoBar('Select a platform to view its current resources.');
+ resrcPg.append(resrcInfoBar);
+
+ // Create radio buttons for platforms
+ var rsrcHwList = $('Platforms available: ');
+ esx = $(' ESX ');
+ kvm = $(' KVM ');
+ zvm = $(' z\/VM ');
+ ipmi = $(' iDataPlex ');
+ blade = $(' BladeCenter ');
+ hmc = $(' System p ');
+
+ rsrcHwList.append(esx);
+ rsrcHwList.append(kvm);
+ rsrcHwList.append(zvm);
+ rsrcHwList.append(blade);
+ rsrcHwList.append(ipmi);
+ rsrcHwList.append(hmc);
+
+ resrcPg.append(rsrcHwList);
+
+ var okBtn = createButton('Ok');
+ okBtn.bind('click', function(event) {
+ // Get hardware that was selected
+ var hw = $(this).parent().find('input[name="rsrcHw"]:checked').val();
+
+ // Generate new tab ID
+ var newTabId = hw + 'ResourceTab';
+ if (!$('#' + newTabId).length) {
+ // Create loader
+ var loader = $(' ').append(createLoader(hw + 'ResourceLoader'));
+
+ // Create an instance of the plugin
+ var plugin = null;
+ var displayName = "";
+ switch (hw) {
+ case "kvm":
+ plugin = new kvmPlugin();
+ displayName = "KVM";
+ break;
+ case "esx":
+ plugin = new esxPlugin();
+ displayName = "ESX";
+ break;
+ case "blade":
+ plugin = new bladePlugin();
+ displayName = "BladeCenter";
+ break;
+ case "hmc":
+ plugin = new hmcPlugin();
+ displayName = "System p";
+ break;
+ case "ipmi":
+ plugin = new ipmiPlugin();
+ displayName = "iDataPlex";
+ break;
+ case "zvm":
+ plugin = new zvmPlugin();
+ displayName = "z\/VM";
+ break;
+ }
+
+ // Add resource tab and load resources
+ tab.add(newTabId, displayName, loader, true);
+ plugin.loadResources();
+ }
+
+ // Select tab
+ tab.select(newTabId);
+ });
+
+ resrcPg.append(okBtn);
+
+ // Add provision tab
+ tab.add('provisionTab', 'Provision', provPg, false);
+ // Add image tab
+ tab.add('imagesTab', 'Images', '', false);
+ // Add resource tab
+ tab.add('resourceTab', 'Resources', resrcPg, false);
+
+ // Load tabs onselect
+ $('#provisionPageTabs').bind('tabsselect', function(event, ui){
+ // Load image page
+ if (!$('#imagesTab').children().length && ui.index == 1) {
+ $('#imagesTab').append($(' ').append(createLoader('')));
+ loadImagesPage();
+ }
+ });
+
+ // Open the quick provision tab
+ if (window.location.search) {
+ tab.add('quickProvisionTab', 'Quick Provision', '', true);
+ tab.select('quickProvisionTab');
+
+ var provForm = $('
');
+ $('#quickProvisionTab').append(provForm);
+ appendProvisionSection('quick', provForm);
+ }
}
\ No newline at end of file
diff --git a/xCAT-UI/js/service/service.js b/xCAT-UI/js/service/service.js
index 3d49b98d9..0ffcaf7d4 100644
--- a/xCAT-UI/js/service/service.js
+++ b/xCAT-UI/js/service/service.js
@@ -1,2153 +1,2192 @@
-/**
- * Global variables
- */
-var serviceTabs;
-var nodeName;
-var nodePath;
-var nodeStatus;
-var gangliaTimer;
-
-/**
- * Initialize service page
- */
-function initServicePage() {
- // Load theme
- var theme = $.cookie('xcat_theme');
- if (theme) {
- switch (theme) {
- case 'cupertino':
- includeCss("css/themes/jquery-ui-cupertino.css");
- break;
- case 'dark_hive':
- includeCss("css/themes/jquery-ui-dark_hive.css");
- break;
- case 'redmond':
- includeCss("css/themes/jquery-ui-redmond.css");
- break;
- case 'start':
- includeCss("css/themes/jquery-ui-start.css");
- break;
- case 'sunny':
- includeCss("css/themes/jquery-ui-sunny.css");
- break;
- case 'ui_dark':
- includeCss("css/themes/jquery-ui-ui_darkness.css");
- break;
- default:
- includeCss("css/themes/jquery-ui-start.css");
- }
- } else {
- includeCss("css/themes/jquery-ui-start.css");
- }
-
- // Load jQuery stylesheets
- includeCss("css/jquery.dataTables.css");
- includeCss("css/superfish.css");
- includeCss("css/jstree.css");
- includeCss("css/jquery.jqplot.css");
-
- // Load custom stylesheet
- includeCss("css/style.css");
-
- // Reuqired JQuery plugins
- includeJs("js/jquery/jquery.dataTables.min.js");
- includeJs("js/jquery/jquery.cookie.min.js");
- includeJs("js/jquery/tooltip.min.js");
- includeJs("js/jquery/superfish.min.js");
- includeJs("js/jquery/jquery.jqplot.min.js");
- includeJs("js/jquery/jqplot.dateAxisRenderer.min.js");
-
- // Custom plugins
- includeJs("js/custom/esx.js");
- includeJs("js/custom/kvm.js");
- includeJs("js/custom/zvm.js");
-
- // Enable settings link
- $('#xcat_settings').click(function() {
- openSettings();
- });
-
- // Show service page
- $("#content").children().remove();
- includeJs("js/service/utils.js");
- loadServicePage();
-
- // Initialize tab index history
- $.cookie('xcat_tabindex_history', '0,0', { path: '/xcat', secure:true });
-}
-
-/**
- * Load service page
- */
-function loadServicePage() {
- // If the page is loaded
- if ($('#content').children().length) {
- // Do not load again
- return;
- }
-
- // Create manage and provision tabs
- serviceTabs = new Tab();
- serviceTabs.init();
- $('#content').append(serviceTabs.object());
-
- var manageTabId = 'manageTab';
- serviceTabs.add(manageTabId, 'Manage', '', false);
-
- // Get nodes owned by user
- $.ajax( {
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'tabdump',
- tgt : '',
- args : 'nodetype',
- msg : ''
- },
-
- success : function(data) {
- setUserNodes(data);
- setMaxVM();
- getUserNodesDef();
- getNodesCurrentLoad();
- loadManagePage(manageTabId);
- }
- });
-
- // Get OS image names
- $.ajax({
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- async : true,
- data : {
- cmd : 'tabdump',
- tgt : '',
- args : 'osimage',
- msg : ''
- },
-
- success : function(data) {
- setOSImageCookies(data);
- }
- });
-
- // Get contents of hosts table
- $.ajax({
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- async : true,
- data : {
- cmd : 'tabdump',
- tgt : '',
- args : 'hosts',
- msg : ''
- },
-
- success : function(data) {
- setGroupCookies(data);
- }
- });
-
- var provTabId = 'provisionTab';
- serviceTabs.add(provTabId, 'Provision', '', false);
- loadServiceProvisionPage(provTabId);
-
- serviceTabs.select(manageTabId);
-}
-
-/**
- * Load the service portal's provision page
- *
- * @param tabId Tab ID where page will reside
- */
-function loadServiceProvisionPage(tabId) {
- // Create info bar
- var infoBar = createInfoBar('Select a platform to provision a node on, then click Ok.');
-
- // Create provision page
- var provPg = $('
');
- $('#' + tabId).append(infoBar, provPg);
-
- // 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);
- provPg.append(hwList);
-
- /**
- * Ok
- */
- var okBtn = createButton('Ok');
- okBtn.bind('click', function(event) {
- var userName = $.cookie('xcat_username');
- var tmp = $.cookie('xcat_' + userName + '_usrnodes');
-
- // Get maximun number for nodes from cookie
- var nodes = '';
- var maxVM = 0;
- if (tmp.length) {
- nodes = tmp.split(',');
- maxVM = parseInt($.cookie('xcat_' + userName + '_maxvm'));
-
- // Do not allow user to clone if the maximum number of VMs is reached
- if (nodes.length >= maxVM) {
- var warn = createWarnBar('You have reached the maximum number of virtual machines allowed (' + maxVM + '). Delete unused virtual machines or contact your system administrator request more virtual machines.');
- warn.prependTo($('#' + tabId));
- return;
- }
- }
-
- // Get hardware that was selected
- var hw = $(this).parent().find('input[name="hw"]:checked').val();
- var newTabId = hw + 'ProvisionTab';
-
- if ($('#' + newTabId).size() > 0){
- serviceTabs.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 "blade":
- plugin = new bladePlugin();
- title = 'BladeCenter';
- break;
- case "hmc":
- plugin = new hmcPlugin();
- title = 'System p';
- break;
- case "ipmi":
- plugin = new ipmiPlugin();
- title = 'iDataPlex';
- break;
- case "zvm":
- plugin = new zvmPlugin();
- title = 'z/VM';
-
- // Get zVM host names
- $.ajax({
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- async : false,
- data : {
- cmd : 'webportal',
- tgt : '',
- args : 'lszvm',
- msg : ''
- },
-
- success : function(data) {
- setzVMCookies(data);
- }
- });
-
- // Get master copies for clone
- $.ajax({
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- async : false,
- data : {
- cmd : 'webportal',
- tgt : '',
- args : 'lsgoldenimages',
- msg : ''
- },
-
- success : function(data) {
- setGoldenImagesCookies(data);
- }
- });
-
- break;
- }
-
- // Select tab
- serviceTabs.add(newTabId, title, '', true);
- serviceTabs.select(newTabId);
- plugin.loadServiceProvisionPage(newTabId);
- }
- });
- provPg.append(okBtn);
-}
-
-/**
- * Load manage page
- *
- * @param tabId Tab ID where page will reside
- */
-function loadManagePage(tabId) {
- // Create manage form
- var manageForm = $('
');
-
- // Append to manage tab
- $('#' + tabId).append(manageForm);
-}
-
-/**
- * Get the user nodes definitions
- */
-function getUserNodesDef() {
- var userName = $.cookie('xcat_username');
- var userNodes = $.cookie('xcat_' + userName + '_usrnodes');
- if (userNodes) {
- // Get nodes definitions
- $.ajax( {
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'lsdef',
- tgt : '',
- args : userNodes,
- msg : ''
- },
-
- success : loadNodesTable
- });
- } else {
- // Clear the tab before inserting the table
- $('#manageTab').append(createWarnBar('No nodes were found belonging to you!'));
- }
-}
-
-/**
- * Load user nodes definitions into a table
- *
- * @param data Data from HTTP request
- */
-function loadNodesTable(data) {
- // Clear the tab before inserting the table
- $('#manageTab').children().remove();
-
- // Nodes datatable ID
- var nodesDTId = 'userNodesDT';
-
- // Hash of node attributes
- var attrs = new Object();
- // Node attributes
- var headers = new Object();
- var node = null, args;
- // Create hash of node attributes
- for (var i in data.rsp) {
- // Get node name
- if (data.rsp[i].indexOf('Object name:') > -1) {
- var temp = data.rsp[i].split(': ');
- node = jQuery.trim(temp[1]);
-
- // Create a hash for the node attributes
- attrs[node] = new Object();
- i++;
- }
-
- // Get key and value
- args = data.rsp[i].split('=', 2);
- var key = jQuery.trim(args[0]);
- var val = jQuery.trim(data.rsp[i].substring(data.rsp[i].indexOf('=') + 1, data.rsp[i].length));
-
- // Create a hash table
- attrs[node][key] = val;
- headers[key] = 1;
- }
-
- // Sort headers
- var sorted = new Array();
- var attrs2show = new Array('arch', 'groups', 'hcp', 'hostnames', 'ip', 'os', 'userid', 'mgt');
- for (var key in headers) {
- // Show node attributes
- if (jQuery.inArray(key, attrs2show) > -1) {
- sorted.push(key);
- }
- }
- sorted.sort();
-
- // Add column for check box, node, ping, power, monitor, and comments
- sorted.unshift(' ',
- 'node',
- 'status ',
- 'power ',
- 'monitor ',
- 'comments');
-
- // Create a datatable
- var nodesDT = new DataTable(nodesDTId);
- nodesDT.init(sorted);
-
- // Go through each node
- for (var node in attrs) {
- // Create a row
- var row = new Array();
-
- // Create a check box, node link, and get node status
- var checkBx = $(' ');
- var nodeLink = $('' + node + ' ').bind('click', loadNode);
-
- // If there is no status attribute for the node, do not try to access hash table
- // Else the code will break
- var status = '';
- if (attrs[node]['status']) {
- status = attrs[node]['status'].replace('sshd', 'ping');
- }
-
- // Push in checkbox, node, status, monitor, and power
- row.push(checkBx, nodeLink, status, '', '');
-
- // If the node attributes are known (i.e the group is known)
- if (attrs[node]['groups']) {
- // Put in comments
- var comments = attrs[node]['usercomment'];
- // If no comments exists, show 'No comments' and set icon image source
- var iconSrc;
- if (!comments) {
- comments = 'No comments';
- iconSrc = 'images/nodes/ui-icon-no-comment.png';
- } else {
- iconSrc = 'images/nodes/ui-icon-comment.png';
- }
-
- // Create comments icon
- var tipID = node + 'Tip';
- var icon = $(' ').css({
- 'width': '18px',
- 'height': '18px'
- });
-
- // Create tooltip
- var tip = createCommentsToolTip(comments);
- var col = $(' ').append(icon);
- col.append(tip);
- row.push(col);
-
- // Generate tooltips
- icon.tooltip({
- position: "center right",
- offset: [-2, 10],
- effect: "fade",
- opacity: 0.8,
- relative: true,
- delay: 500
- });
- } else {
- // Do not put in comments if attributes are not known
- row.push('');
- }
-
- // Go through each header
- for (var i = 6; i < sorted.length; i++) {
- // Add the node attributes to the row
- var key = sorted[i];
-
- // Do not put comments and status in twice
- if (key != 'usercomment' && key != 'status' && key.indexOf('statustime') < 0) {
- var val = attrs[node][key];
- if (val) {
- row.push($('' + val + ' '));
- } else {
- row.push('');
- }
- }
- }
-
- // Add the row to the table
- nodesDT.add(row);
- }
-
- // Create info bar
- var infoBar = createInfoBar('Manage and monitor your virtual machines.');
- $('#manageTab').append(infoBar);
-
- // Insert action bar and nodes datatable
- $('#manageTab').append(nodesDT.object());
-
- // Turn table into a datatable
- $('#' + nodesDTId).dataTable({
- 'iDisplayLength': 50,
- 'bLengthChange': false,
- "bScrollCollapse": true,
- "sScrollY": "400px",
- "sScrollX": "110%",
- "bAutoWidth": true,
- "oLanguage": {
- "oPaginate": {
- "sNext": "",
- "sPrevious": ""
- }
- }
- });
-
- // Set datatable header class to add color
- // $('.datatable thead').attr('class', 'ui-widget-header');
-
- // Do not sort ping, power, and comment column
- $('#' + nodesDTId + ' thead tr th').click(function() {
- getNodeAttrs(group);
- });
- var checkboxCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(0)');
- var pingCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(2)');
- var powerCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
- var monitorCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)');
- var commentCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(5)');
- checkboxCol.unbind('click');
- pingCol.unbind('click');
- powerCol.unbind('click');
- monitorCol.unbind('click');
- commentCol.unbind('click');
-
- // Refresh the node ping, power, and monitor status on-click
- var nodes = getNodesShown(nodesDTId);
- pingCol.find('span a').click(function() {
- refreshNodeStatus(nodes);
- });
- powerCol.find('span a').click(function() {
- refreshPowerStatus(nodes);
- });
- monitorCol.find('span a').click(function() {
- refreshGangliaStatus(nodes);
- });
-
- // Create actions menu
- // Power on
- var powerOnLnk = $('Power on ');
- powerOnLnk.click(function() {
- var tgtNodes = getNodesChecked(nodesDTId);
- if (tgtNodes) {
- powerNode(tgtNodes, 'on');
- }
- });
-
- // Power off
- var powerOffLnk = $('Power off ');
- powerOffLnk.click(function() {
- var tgtNodes = getNodesChecked(nodesDTId);
- if (tgtNodes) {
- powerNode(tgtNodes, 'off');
- }
- });
-
- // Power softoff
- var powerSoftoffLnk = $('Shutdown ');
- powerSoftoffLnk.click(function() {
- var tgtNodes = getNodesChecked(nodesDTId);
- if (tgtNodes) {
- powerNode(tgtNodes, 'softoff');
- }
- });
-
- // Clone
- var cloneLnk = $('Clone ');
- cloneLnk.click(function() {
- var tgtNodes = getNodesChecked(nodesDTId);
- if (tgtNodes) {
- cloneNode(tgtNodes);
- }
- });
-
- // Delete
- var deleteLnk = $('Delete ');
- deleteLnk.click(function() {
- var tgtNodes = getNodesChecked(nodesDTId);
- if (tgtNodes) {
- deleteNode(tgtNodes);
- }
- });
-
- // Unlock
- var unlockLnk = $('Unlock ');
- unlockLnk.click(function() {
- var tgtNodes = getNodesChecked(nodesDTId);
- if (tgtNodes) {
- unlockNode(tgtNodes);
- }
- });
-
- // Create action bar
- var actionBar = $('
').css('width', '370px');
-
- // Prepend menu to datatable
- var actionsLnk = $('Actions ');
- var refreshLnk = $('Refresh ');
- refreshLnk.click(function() {
- // Get nodes owned by user
- $.ajax( {
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'tabdump',
- tgt : '',
- args : 'nodetype',
- msg : ''
- },
-
- success : function(data) {
- // Save nodes owned by user
- setUserNodes(data);
- getNodesCurrentLoad();
-
- // Refresh nodes table
- var userName = $.cookie('xcat_username');
- var userNodes = $.cookie('xcat_' + userName + '_usrnodes');
- if (userNodes) {
- // Get nodes definitions
- $.ajax( {
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'lsdef',
- tgt : '',
- args : userNodes,
- msg : ''
- },
-
- success : loadNodesTable
- });
- } else {
- // Clear the tab before inserting the table
- $('#manageTab').children().remove();
- $('#manageTab').append(createWarnBar('You are not managing any node. Try to provision a node.'));
- }
- }
- });
- });
-
- var actionMenu = createMenu([cloneLnk, deleteLnk, powerOnLnk, powerOffLnk, powerSoftoffLnk, unlockLnk]);
- var menu = createMenu([[actionsLnk, actionMenu], refreshLnk]);
- menu.superfish();
- actionBar.append(menu);
-
- // Set correct theme for action menu
- actionMenu.find('li').hover(function() {
- setMenu2Theme($(this));
- }, function() {
- setMenu2Normal($(this));
- });
-
- // Create a division to hold actions menu
- var menuDiv = $('');
- $('#' + nodesDTId + '_wrapper').prepend(menuDiv);
- menuDiv.append(actionBar);
- $('#' + nodesDTId + '_filter').appendTo(menuDiv);
-
- // Get power and monitor status
- var nodes = getNodesShown(nodesDTId);
- refreshPowerStatus(nodes);
- refreshGangliaStatus(nodes);
-}
-
-/**
- * Refresh ping status for each node
- *
- * @param nodes Nodes to get ping status
- */
-function refreshNodeStatus(nodes) {
- // Show ping loader
- var nodesDTId = 'userNodesDT';
- var pingCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(2)');
- pingCol.find('img').show();
-
- // Get the node ping status
- $.ajax( {
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'nodestat',
- tgt : nodes,
- args : '-u',
- msg : ''
- },
-
- success : loadNodePing
- });
-}
-
-/**
- * Load node ping status for each node
- *
- * @param data Data returned from HTTP request
- */
-function loadNodePing(data) {
- var nodesDTId = 'userNodesDT';
- var datatable = $('#' + nodesDTId).dataTable();
- var rsp = data.rsp;
- var args, rowPos, node, status;
-
- // Get all nodes within datatable
- for (var i in rsp) {
- args = rsp[i].split(':');
-
- // args[0] = node and args[1] = status
- node = jQuery.trim(args[0]);
- status = jQuery.trim(args[1]).replace('sshd', 'ping');
-
- // Get row containing node
- rowPos = findRow(node, '#' + nodesDTId, 1);
-
- // Update ping status column
- datatable.fnUpdate(status, rowPos, 2, false);
- }
-
- // Hide status loader
- var pingCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(2)');
- pingCol.find('img').hide();
- adjustColumnSize(nodesDTId);
-}
-
-/**
- * Refresh power status for each node
- *
- * @param nodes Nodes to get power status
- */
-function refreshPowerStatus(nodes) {
- // Show power loader
- var nodesDTId = 'userNodesDT';
- var powerCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
- powerCol.find('img').show();
-
- // Get power status
- $.ajax( {
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'rpower',
- tgt : nodes,
- args : 'stat',
- msg : ''
- },
-
- success : loadPowerStatus
- });
-}
-
-/**
- * Load power status for each node
- *
- * @param data Data returned from HTTP request
- */
-function loadPowerStatus(data) {
- var nodesDTId = 'userNodesDT';
- var datatable = $('#' + nodesDTId).dataTable();
- var power = data.rsp;
- var rowPos, node, status, args;
-
- for (var i in power) {
- // power[0] = nodeName and power[1] = state
- args = power[i].split(':');
- node = jQuery.trim(args[0]);
- status = jQuery.trim(args[1]);
-
- // Get the row containing the node
- rowPos = findRow(node, '#' + nodesDTId, 1);
-
- // Update the power status column
- datatable.fnUpdate(status, rowPos, 3, false);
- }
-
- // Hide power loader
- var powerCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
- powerCol.find('img').hide();
- adjustColumnSize(nodesDTId);
-}
-
-/**
- * Refresh the status of Ganglia for each node
- *
- * @param nodes Nodes to get Ganglia status
- */
-function refreshGangliaStatus(nodes) {
- // Show ganglia loader
- var nodesDTId = 'userNodesDT';
- var gangliaCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)');
- gangliaCol.find('img').show();
-
- // Get the status of Ganglia
- $.ajax( {
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'gangliastatus;' + nodes,
- msg : ''
- },
-
- success : loadGangliaStatus
- });
-}
-
-/**
- * Load the status of Ganglia for a given group
- *
- * @param data Data returned from HTTP request
- */
-function loadGangliaStatus(data) {
- // Get datatable
- var nodesDTId = 'userNodesDT';
- var datatable = $('#' + nodesDTId).dataTable();
- var ganglia = data.rsp;
- var rowNum, node, status;
-
- for ( var i in ganglia) {
- // ganglia[0] = nodeName and ganglia[1] = state
- node = jQuery.trim(ganglia[i][0]);
- status = jQuery.trim(ganglia[i][1]);
-
- if (node) {
- // Get the row containing the node
- rowNum = findRow(node, '#' + nodesDTId, 1);
-
- // Update the power status column
- datatable.fnUpdate(status, rowNum, 4);
- }
- }
-
- // Hide Ganglia loader
- var gangliaCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)');
- gangliaCol.find('img').hide();
- adjustColumnSize(nodesDTId);
-}
-
-/**
- * Load inventory for given node
- *
- * @param e Windows event
- */
-function loadNode(e) {
- if (!e) {
- e = window.event;
- }
-
- // Get node that was clicked
- var node = (e.target) ? e.target.id : e.srcElement.id;
-
- // Create a new tab to show inventory
- var tabId = node + '_inventory';
-
- if(!$('#' + tabId).length) {
- // Add new tab, only if one does not exist
- var loader = createLoader(node + 'Loader');
- loader = $(' ').append(loader);
- serviceTabs.add(tabId, node, loader, true);
-
- // Get node inventory
- var msg = 'out=' + tabId + ',node=' + node;
- $.ajax( {
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'rinv',
- tgt : node,
- args : 'all',
- msg : msg
- },
-
- success : function(data) {
- var args = data.msg.split(',');
-
- // Get node
- var node = args[1].replace('node=', '');
-
- // Get the management plugin
- var mgt = getNodeAttr(node, 'mgt');
-
- // Create an instance of the plugin
- var plugin;
- switch (mgt) {
- case "kvm":
- plugin = new kvmPlugin();
- break;
- case "esx":
- plugin = new esxPlugin();
- break;
- case "zvm":
- plugin = new zvmPlugin();
- break;
- }
-
- // Select tab
- plugin.loadServiceInventory(data);
- }
- });
- }
-
- // Select new tab
- serviceTabs.select(tabId);
-}
-
-/**
- * Set a cookie for group names
- *
- * @param data Data from HTTP request
- */
-function setGroupCookies(data) {
- if (data.rsp) {
- var groups = new Array();
-
- // Index 0 is the table header
- var cols, name, ip, hostname, desc, selectable, comments, tmp;
- for (var i = 1; i < data.rsp.length; i++) {
- // Set default description and selectable
- selectable = "no";
- desc = "No description";
-
- // Split into columns:
- // node, ip, hostnames, otherinterfaces, comments, disable
- cols = data.rsp[i].split(',');
- name = cols[0].replace(new RegExp('"', 'g'), '');
- ip = cols[1].replace(new RegExp('"', 'g'), '');
- hostname = cols[2].replace(new RegExp('"', 'g'), '');
-
- // It should return: "description: All machines; network: 10.1.100.0/24;"
- comments = cols[4].replace(new RegExp('"', 'g'), '');
- 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);
- }
- }
-
- // Save groups that are selectable
- if (selectable == "yes")
- groups.push(name + ':' + ip + ':' + hostname + ':' + desc);
- }
-
- // Set cookie to expire in 60 minutes
- var exDate = new Date();
- exDate.setTime(exDate.getTime() + (240 * 60 * 1000));
- $.cookie('xcat_srv_groups', groups, { expires: exDate, path: '/xcat', secure:true });
- }
-}
-
-/**
- * Set a cookie for the OS images
- *
- * @param data Data from HTTP request
- */
-function setOSImageCookies(data) {
- // Get response
- var rsp = data.rsp;
-
- var imageNames = new Array();
- var profilesHash = new Object();
- var osVersHash = new Object();
- var osArchsHash = new Object();
- var imagePos = 0;
- var profilePos = 0;
- var osversPos = 0;
- var osarchPos = 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 '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 osImage = 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 osComments = cols[comments].replace(new RegExp('"', 'g'), '');
-
- // Only save install boot
- if (provMethod.indexOf('install') > -1) {
- if (osComments) {
- // Only enable images where description and selectable comments exist
- // Set default description and selectable
- selectable = "no";
- desc = "No description";
-
- 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);
- }
- }
-
- // Save images that are selectable
- if (selectable == "yes")
- imageNames.push(osImage + ':' + desc);
- }
-
- profilesHash[profile] = 1;
- osVersHash[osVer] = 1;
- osArchsHash[osArch] = 1;
- }
- }
-
- // Save image names in a cookie
- $.cookie('xcat_srv_imagenames', imageNames);
-
- // Save profiles in a cookie
- var tmp = new Array;
- for (var key in profilesHash) {
- tmp.push(key);
- }
- $.cookie('xcat_srv_profiles', tmp);
-
- // Save OS versions in a cookie
- tmp = new Array;
- for (var key in osVersHash) {
- tmp.push(key);
- }
- $.cookie('xcat_srv_osvers', tmp);
-
- // Save OS architectures in a cookie
- tmp = new Array;
- for (var key in osArchsHash) {
- tmp.push(key);
- }
- $.cookie('xcat_srv_osarchs', tmp);
-}
-
-
-
-/**
- * Set a cookie for user nodes
- *
- * @param data Data from HTTP request
- */
-function setUserNodes(data) {
- if (data.rsp) {
- // Get user name that is logged in
- var userName = $.cookie('xcat_username');
- var usrNodes = new Array();
-
- // Ignore first columns because it is the header
- for ( var i = 1; i < data.rsp.length; i++) {
- // Go through each column
- // where column names are: node, os, arch, profile, provmethod, supportedarchs, nodetype, comments, disable
- var cols = data.rsp[i].split(',');
- var node = cols[0].replace(new RegExp('"', 'g'), '');
-
- // Comments can contain the owner and description
- var comments = new Array();
- if (cols[7].indexOf(';') > -1) {
- comments = cols[7].replace(new RegExp('"', 'g'), '').split(';');
- } else {
- comments.push(cols[7].replace(new RegExp('"', 'g'), ''));
- }
-
- // Extract the owner
- var owner;
- for (var j in comments) {
- if (comments[j].indexOf('owner:') > -1) {
- owner = comments[j].replace('owner:', '');
-
- if (owner == userName) {
- usrNodes.push(node);
- }
-
- break;
- }
- }
- } // End of for
-
- // Set cookie to expire in 240 minutes
- var exDate = new Date();
- exDate.setTime(exDate.getTime() + (240 * 60 * 1000));
- $.cookie('xcat_' + userName + '_usrnodes', usrNodes, { expires: exDate, path: '/xcat', secure:true });
- } // End of if
-}
-
-/**
- * Power on a given node
- *
- * @param tgtNodes Node to power on or off
- * @param power2 Power node to given state
- */
-function powerNode(tgtNodes, power2) {
- // Show power loader
- var nodesDTId = 'userNodesDT';
- var powerCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
- powerCol.find('img').show();
-
- var nodes = tgtNodes.split(',');
- for (var n in nodes) {
- // Get hardware that was selected
- var hw = getUserNodeAttr(nodes[n], 'mgt');
-
- // Change to power softoff (to gracefully shutdown)
- switch (hw) {
- case "blade":
- break;
- case "hmc":
- break;
- case "ipmi":
- break;
- case "zvm":
- if (power2 == 'off') {
- power2 = 'softoff';
- }
-
- break;
- }
- }
-
- $.ajax({
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'rpower',
- tgt : tgtNodes,
- args : power2,
- msg : tgtNodes
- },
-
- success : updatePowerStatus
- });
-}
-
-/**
- * Update power status of a node in the datatable
- *
- * @param data Data from HTTP request
- */
-function updatePowerStatus(data) {
- // Get datatable
- var nodesDTId = 'userNodesDT';
- var dTable = $('#' + nodesDTId).dataTable();
-
- // Get xCAT response
- var rsp = data.rsp;
- // Loop through each line
- var node, status, rowPos, strPos;
- for (var i in rsp) {
- // Get node name
- node = rsp[i].split(":")[0];
-
- // If there is no error
- if (rsp[i].indexOf("Error") < 0 || rsp[i].indexOf("Failed") < 0) {
- // Get the row containing the node link
- rowPos = findRow(node, '#' + nodesDTId, 1);
-
- // If it was power on, then the data return would contain "Starting"
- strPos = rsp[i].indexOf("Starting");
- if (strPos > -1) {
- status = 'on';
- } else {
- status = 'off';
- }
-
- // Update the power status column
- dTable.fnUpdate(status, rowPos, 3, false);
- } else {
- // Power on/off failed
- alert(rsp[i]);
- }
- }
-
- var powerCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
- powerCol.find('img').hide();
- adjustColumnSize(nodesDTId);
-}
-
-/**
- * Turn on monitoring for a given node
- *
- * @param node Node to monitor on or off
- * @param monitor Monitor state, on or off
- */
-function monitorNode(node, monitor) {
- // Show ganglia loader
- var nodesDTId = 'userNodesDT';
- var gangliaCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)');
- gangliaCol.find('img').show();
-
- if (monitor == 'on') {
- if (node) {
- // Check if ganglia RPMs are installed
- $.ajax( {
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'gangliacheck;' + node,
- msg : node // Node range will be passed along in data.msg
- },
-
- /**
- * Start ganglia on a given node range
- *
- * @param data
- * Data returned from HTTP request
- * @return Nothing
- */
- success : function(data) {
- // Get response
- var out = data.rsp[0].split(/\n/);
-
- // Go through each line
- var warn = false;
- var warningMsg = '';
- for (var i in out) {
- // If an RPM is not installed
- if (out[i].indexOf('not installed') > -1) {
- warn = true;
-
- if (warningMsg) {
- warningMsg += ' ' + out[i];
- } else {
- warningMsg = out[i];
- }
- }
- }
-
- // If there are warnings
- if (warn) {
- // Create warning bar
- var warningBar = createWarnBar(warningMsg);
- warningBar.css('margin-bottom', '10px');
- warningBar.prependTo($('#nodesTab'));
- } else {
- $.ajax( {
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'gangliastart;' + data.msg,
- msg : data.msg
- },
-
- success : function(data) {
- // Remove any warnings
- $('#nodesTab').find('.ui-state-error').remove();
- refreshGangliaStatus(data.msg);
- }
- });
- } // End of if (warn)
- } // End of function(data)
- });
- }
- } else {
- var args;
- if (node) {
- args = 'gangliastop;' + node;
- $.ajax( {
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : args,
- msg : node
- },
-
- success : function(data) {
- refreshGangliaStatus(data.msg);
- }
- });
- }
- }
-}
-
-/**
- * Open a dialog to clone node
- *
- * @param tgtNodes Nodes to clone
- */
-function cloneNode(tgtNodes) {
- var userName = $.cookie('xcat_username');
- var nodes = tgtNodes.split(',');
- var tmp = $.cookie('xcat_' + userName + '_usrnodes');
- var usrNodes = tmp.split(',');
-
- var maxVM = parseInt($.cookie('xcat_' + userName + '_maxvm'));
-
- // Do not allow user to clone if the maximum number of VMs is reached
- if (usrNodes.length >= maxVM) {
- var warn = createWarnBar('You have reached the maximum number of virtual machines allowed (' + maxVM + '). Delete un-used virtual machines or contact your system administrator request more virtual machines.');
- warn.prependTo($('#manageTab'));
- return;
- }
-
- for (var n in nodes) {
- // Get hardware that was selected
- var hw = getUserNodeAttr(nodes[n], 'mgt');
-
- // Create an instance of the plugin
- var plugin;
- switch (hw) {
- case "kvm":
- plugin = new kvmPlugin();
- break;
- case "esx":
- plugin = new esxPlugin();
- break;
- case "zvm":
- plugin = new zvmPlugin();
- break;
- }
-
- // Clone node
- plugin.serviceClone(nodes[n]);
- }
-}
-
-
-/**
- * Open a dialog to delete node
- *
- * @param tgtNodes Nodes to delete
- */
-function deleteNode(tgtNodes) {
- var nodes = tgtNodes.split(',');
-
- // Loop through each node and create target nodes string
- var tgtNodesStr = '';
- for (var i in nodes) {
- if (i == 0 && i == nodes.length - 1) {
- // If it is the 1st and only node
- tgtNodesStr += nodes[i];
- } else if (i == 0 && i != nodes.length - 1) {
- // If it is the 1st node of many nodes, append a comma to the string
- tgtNodesStr += nodes[i] + ', ';
- } else {
- if (i == nodes.length - 1) {
- // If it is the last node, append nothing to the string
- tgtNodesStr += nodes[i];
- } else {
- // Append a comma to the string
- tgtNodesStr += nodes[i] + ', ';
- }
- }
- }
-
- // Confirm delete of node
- var dialog = $('
');
- var warn = createWarnBar('Are you sure you want to delete ' + tgtNodesStr + '?');
- dialog.append(warn);
-
- // Open dialog
- dialog.dialog({
- title: "Confirm",
- modal: true,
- close: function(){
- $(this).remove();
- },
- width: 400,
- buttons: {
- "Yes": function(){
- // Create status bar and append to tab
- var instance = 0;
- var statBarId = 'deleteStat' + instance;
- while ($('#' + statBarId).length) {
- // If one already exists, generate another one
- instance = instance + 1;
- statBarId = 'deleteStat' + instance;
- }
-
- var statBar = createStatusBar(statBarId);
- var loader = createLoader('');
- statBar.find('div').append(loader);
- statBar.prependTo($('#manageTab'));
-
- // Delete the virtual server
- $.ajax( {
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'rmvm',
- tgt : tgtNodes,
- args : '',
- msg : 'out=' + statBarId + ';cmd=rmvm;tgt=' + tgtNodes
- },
-
- success : function(data) {
- var args = data.msg.split(';');
- var statBarId = args[0].replace('out=', '');
- var tgts = args[2].replace('tgt=', '').split(',');
-
- // Get data table
- var nodesDTId = 'userNodesDT';
- var dTable = $('#' + nodesDTId).dataTable();
- var failed = false;
-
- // Create an info box to show output
- var output = writeRsp(data.rsp, '');
- output.css('margin', '0px');
- // Remove loader and append output
- $('#' + statBarId + ' img').remove();
- $('#' + statBarId + ' div').append(output);
-
- // If there was an error, do not continue
- if (output.html().indexOf('Error') > -1) {
- failed = true;
- }
-
- // Update data table
- var rowPos;
- for (var i in tgts) {
- if (!failed) {
- // Get row containing the node link and delete it
- rowPos = findRow(tgts[i], '#' + nodesDTId, 1);
- dTable.fnDeleteRow(rowPos);
- }
- }
-
- // Refresh nodes owned by user
- $.ajax( {
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'tabdump',
- tgt : '',
- args : 'nodetype',
- msg : ''
- },
-
- success : function(data) {
- setUserNodes(data);
- }
- });
- }
- });
-
- $(this).dialog("close");
- },
- "No": function() {
- $(this).dialog("close");
- }
- }
- });
-}
-
-/**
- * Unlock a node by setting the ssh keys
- *
- * @param tgtNodes Nodes to unlock
- */
-function unlockNode(tgtNodes) {
- var nodes = tgtNodes.split(',');
-
- // Loop through each node and create target nodes string
- var tgtNodesStr = '';
- for (var i in nodes) {
- if (i == 0 && i == nodes.length - 1) {
- // If it is the 1st and only node
- tgtNodesStr += nodes[i];
- } else if (i == 0 && i != nodes.length - 1) {
- // If it is the 1st node of many nodes, append a comma to the string
- tgtNodesStr += nodes[i] + ', ';
- } else {
- if (i == nodes.length - 1) {
- // If it is the last node, append nothing to the string
- tgtNodesStr += nodes[i];
- } else {
- // Append a comma to the string
- tgtNodesStr += nodes[i] + ', ';
- }
- }
- }
-
- var dialog = $('
');
- var infoBar = createInfoBar('Give the root password for this node range to setup its SSH keys.');
- dialog.append(infoBar);
-
- var unlockForm = $('
').css('margin', '5px');
- unlockForm.append('Target node range:
');
- unlockForm.append('Password:
');
- dialog.append(unlockForm);
-
- dialog.find('div input').css('margin', '5px');
-
- // Generate tooltips
- unlockForm.find('div input[title]').tooltip({
- position: "center right",
- offset: [-2, 10],
- effect: "fade",
- opacity: 0.7,
- predelay: 800,
- events : {
- def : "mouseover,mouseout",
- input : "mouseover,mouseout",
- widget : "focus mouseover,blur mouseout",
- tooltip : "mouseover,mouseout"
- }
- });
-
- // Open dialog
- dialog.dialog({
- title: "Confirm",
- modal: true,
- close: function(){
- $(this).remove();
- },
- width: 450,
- buttons: {
- "Ok": function(){
- // Create status bar and append to tab
- var instance = 0;
- var statBarId = 'unlockStat' + instance;
- while ($('#' + statBarId).length) {
- // If one already exists, generate another one
- instance = instance + 1;
- statBarId = 'unlockStat' + instance;
- }
-
- var statBar = createStatusBar(statBarId);
- var loader = createLoader('');
- statBar.find('div').append(loader);
- statBar.prependTo($('#manageTab'));
-
- // If a password is given
- var password = unlockForm.find('input[name=password]:eq(0)');
- if (password.val()) {
- // Setup SSH keys
- $.ajax( {
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'unlock;' + tgtNodes + ';' + password.val(),
- msg : 'out=' + statBarId + ';cmd=unlock;tgt=' + tgtNodes
- },
-
- success : function(data) {
- // Create an info box to show output
- var output = writeRsp(data.rsp, '');
- output.css('margin', '0px');
- // Remove loader and append output
- $('#' + statBarId + ' img').remove();
- $('#' + statBarId + ' div').append(output);
- }
- });
-
- $(this).dialog("close");
- }
- },
- "Cancel": function() {
- $(this).dialog("close");
- }
- }
- });
-}
-
-/**
- * Get nodes current load information
- */
-function getNodesCurrentLoad(){
- var userName = $.cookie('xcat_username');
- var nodes = $.cookie('xcat_' + userName + '_usrnodes');
-
- // Get nodes current status
- $.ajax({
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'gangliacurrent;node;' + nodes,
- msg : ''
- },
-
- success: saveNodeLoad
- });
-}
-
-/**
- * Save node load data
- *
- * @param status Data returned from HTTP request
- */
-function saveNodeLoad(status){
- // Save node path and status for future use
- nodePath = new Object();
- nodeStatus = new Object();
-
- // Get nodes status
- var nodes = status.rsp[0].split(';');
-
- var i = 0, pos = 0;
- var node = '', tmpStr = '';
- var tmpArry;
-
- for (i = 0; i < nodes.length; i++){
- tmpStr = nodes[i];
- pos = tmpStr.indexOf(':');
- node = tmpStr.substring(0, pos);
- tmpArry = tmpStr.substring(pos + 1).split(',');
-
- switch(tmpArry[0]){
- case 'UNKNOWN':{
- nodeStatus[node] = -2;
- }
- break;
- case 'ERROR':{
- nodeStatus[node] = -1;
- }
- break;
- case 'WARNING':{
- nodeStatus[node] = 0;
- nodePath[node] = tmpArry[1];
- }
- break;
- case 'NORMAL':{
- nodeStatus[node] = 1;
- nodePath[node] = tmpArry[1];
- }
- break;
- }
- }
-}
-
-/**
- * Get monitoring metrics and load into inventory fieldset
- *
- * @param node Node to collect metrics
- */
-function getMonitorMetrics(node) {
- // Inventory tab should have this fieldset already created
- // e.g.
- $('#' + node + '_monitor').children('div').remove();
-
- // Before trying to get the metrics, check if Ganglia is running
- $.ajax({
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'gangliastatus;' + node,
- msg : ''
- },
-
- success: function(data) {
- var ganglia = data.rsp;
- var node, status;
-
- // Get the ganglia status
- for (var i in ganglia) {
- // ganglia[0] = nodeName and ganglia[1] = state
- node = jQuery.trim(ganglia[i][0]);
- status = jQuery.trim(ganglia[i][1]);
-
- if (node && status == 'on') {
- // Get monitoring metrics
- $.ajax({
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'gangliashow;' + nodePath[node] + ';hour;_summary_',
- msg : node
- },
-
- success: drawMonitoringCharts
- });
- } else if (node && status == 'off') {
- var info = createInfoBar('Ganglia monitoring is disabled for this node');
- $('#' + node + '_monitor').append(info.css('width', '300px'));
- }
- } // End of for
- } // End of function
- });
-}
-
-/**
- * Draw monitoring charts based on node metrics
- *
- * @param data Data returned from HTTP request
- */
-function drawMonitoringCharts(data){
- var nodeMetrics = new Object();
- var metricData = data.rsp[0].split(';');
- var node = data.msg;
-
- var metricName = '';
- var metricVal = '';
- var pos = 0;
-
- // Go through the metrics returned
- for (var m = 0; m < metricData.length; m++){
- pos = metricData[m].indexOf(':');
-
- // Get metric name
- metricName = metricData[m].substr(0, pos);
- nodeMetrics[metricName] = new Array();
- // Get metric values
- metricVal = metricData[m].substr(pos + 1).split(',');
- // Save node metrics
- for (var i = 0; i < metricVal.length; i++){
- nodeMetrics[metricName].push(Number(metricVal[i]));
- }
- }
-
- drawLoadFlot(node, nodeMetrics['load_one'], nodeMetrics['cpu_num']);
- drawCpuFlot(node, nodeMetrics['cpu_idle']);
- drawMemFlot(node, nodeMetrics['mem_free'], nodeMetrics['mem_total']);
- drawDiskFlot(node, nodeMetrics['disk_free'], nodeMetrics['disk_total']);
- drawNetworkFlot(node, nodeMetrics['bytes_in'], nodeMetrics['bytes_out']);
-}
-
-/**
- * Draw load metrics flot
- *
- * @param node Node name
- * @param loadpair Load timestamp and value pair
- * @param cpupair CPU number and value pair
- */
-function drawLoadFlot(node, loadPair, cpuPair){
- var load = new Array();
- var cpu = new Array();
-
- var i = 0;
- var yAxisMax = 0;
- var interval = 1;
-
- // Append flot to node monitoring fieldset
- var loadFlot = $('
').css({
- 'float': 'left',
- 'height': '150px',
- 'margin': '0 0 10px',
- 'width': '300px'
- });
- $('#' + node + '_monitor').append(loadFlot);
- $('#' + node + '_load').empty();
-
- // Parse load pair where:
- // timestamp must be mutiplied by 1000 and Javascript timestamp is in ms
- for (i = 0; i < loadPair.length; i += 2){
- load.push([loadPair[i] * 1000, loadPair[i + 1]]);
- if (loadPair[i + 1] > yAxisMax){
- yAxisMax = loadPair[i + 1];
- }
- }
-
- // Parse CPU pair
- for (i = 0; i < cpuPair.length; i += 2){
- cpu.push([cpuPair[i] * 1000, cpuPair[i + 1]]);
- if (cpuPair[i + 1] > yAxisMax){
- yAxisMax = cpuPair[i + 1];
- }
- }
-
- interval = parseInt(yAxisMax / 3);
- if (interval < 1){
- interval = 1;
- }
-
- $.jqplot(node + '_load', [load, cpu],{
- title: ' Loads/Procs Last Hour',
- axes:{
- xaxis:{
- renderer : $.jqplot.DateAxisRenderer,
- numberTicks: 4,
- tickOptions : {
- formatString : '%R',
- show : true
- }
- },
- yaxis: {
- min : 0,
- tickInterval : interval
- }
- },
- legend : {
- show: true,
- location: 'nw'
- },
- series:[{label:'Load'}, {label: 'CPU Number'}],
- seriesDefaults : {showMarker: false}
- });
-}
-
-/**
- * Draw CPU usage flot
- *
- * @param node Node name
- * @param cpuPair CPU timestamp and value pair
- */
-function drawCpuFlot(node, cpuPair){
- var cpu = new Array();
-
- // Append flot to node monitoring fieldset
- var cpuFlot = $('
').css({
- 'float': 'left',
- 'height': '150px',
- 'margin': '0 0 10px',
- 'width': '300px'
- });
- $('#' + node + '_monitor').append(cpuFlot);
- $('#' + node + '_cpu').empty();
-
- // Time stamp should by mutiplied by 1000
- // CPU idle comes from server, subtract 1 from idle
- for(var i = 0; i < cpuPair.length; i +=2){
- cpu.push([(cpuPair[i] * 1000), (100 - cpuPair[i + 1])]);
- }
-
- $.jqplot(node + '_cpu', [cpu],{
- title: 'CPU Use Last Hour',
- axes:{
- xaxis:{
- renderer : $.jqplot.DateAxisRenderer,
- numberTicks: 4,
- tickOptions : {
- formatString : '%R',
- show : true
- }
- },
- yaxis: {
- min : 0,
- max : 100,
- tickOptions:{formatString : '%d\%'}
- }
- },
- seriesDefaults : {showMarker: false}
- });
-}
-
-/**
- * Draw memory usage flot
- *
- * @param node Node name
- * @param freePair Free memory timestamp and value pair
- * @param totalPair Total memory timestamp and value pair
- */
-function drawMemFlot(node, freePair, totalPair){
- var used = new Array();
- var total = new Array();
- var size = 0;
-
- // Append flot to node monitoring fieldset
- var memoryFlot = $('
').css({
- 'float': 'left',
- 'height': '150px',
- 'margin': '0 0 10px',
- 'width': '300px'
- });
- $('#' + node + '_monitor').append(memoryFlot);
- $('#' + node + '_memory').empty();
-
- if(freePair.length < totalPair.length){
- size = freePair.length;
- } else {
- size = freePair.length;
- }
-
- var tmpTotal, tmpUsed;
- for(var i = 0; i < size; i+=2){
- tmpTotal = totalPair[i+1];
- tmpUsed = tmpTotal-freePair[i+1];
- tmpTotal = tmpTotal/1000000;
- tmpUsed = tmpUsed/1000000;
- total.push([totalPair[i]*1000, tmpTotal]);
- used.push([freePair[i]*1000, tmpUsed]);
- }
-
- $.jqplot(node + '_memory', [used, total],{
- title: 'Memory Use Last Hour',
- axes:{
- xaxis:{
- renderer : $.jqplot.DateAxisRenderer,
- numberTicks: 4,
- tickOptions : {
- formatString : '%R',
- show : true
- }
- },
- yaxis: {
- min : 0,
- tickOptions:{formatString : '%.2fG'}
- }
- },
- legend : {
- show: true,
- location: 'nw'
- },
- series:[{label:'Used'}, {label: 'Total'}],
- seriesDefaults : {showMarker: false}
- });
-}
-
-/**
- * Draw disk usage flot
- *
- * @param node Node name
- * @param freePair Free disk space (Ganglia only logs free data)
- * @param totalPair Total disk space
- */
-function drawDiskFlot(node, freePair, totalPair) {
- var used = new Array();
- var total = new Array();
- var size = 0;
-
- // Append flot to node monitoring fieldset
- var diskFlot = $('
').css({
- 'float' : 'left',
- 'height' : '150px',
- 'margin' : '0 0 10px',
- 'width' : '300px'
- });
- $('#' + node + '_monitor').append(diskFlot);
- $('#' + node + '_disk').empty();
-
- if (freePair.length < totalPair.length) {
- size = freePair.length;
- } else {
- size = freePair.length;
- }
-
- var tmpTotal, tmpUsed;
- for ( var i = 0; i < size; i += 2) {
- tmpTotal = totalPair[i + 1];
- tmpUsed = tmpTotal - freePair[i + 1];
- total.push([ totalPair[i] * 1000, tmpTotal ]);
- used.push([ freePair[i] * 1000, tmpUsed ]);
- }
-
- $.jqplot(node + '_disk', [ used, total ], {
- title : 'Disk Use Last Hour',
- axes : {
- xaxis : {
- renderer : $.jqplot.DateAxisRenderer,
- numberTicks : 4,
- tickOptions : {
- formatString : '%R',
- show : true
- }
- },
- yaxis : {
- min : 0,
- tickOptions : {
- formatString : '%.2fG'
- }
- }
- },
- legend : {
- show : true,
- location : 'nw'
- },
- series : [ {
- label : 'Used'
- }, {
- label : 'Total'
- } ],
- seriesDefaults : {
- showMarker : false
- }
- });
-}
-
-/**
- * Draw network usage flot
- *
- * @param node Node name
- * @param freePair Free memory timestamp and value pair
- * @param totalPair Total memory timestamp and value pair
- */
-function drawNetworkFlot(node, inPair, outPair) {
- var inArray = new Array();
- var outArray = new Array();
- var maxVal = 0;
- var unitName = 'B';
- var divisor = 1;
-
- // Append flot to node monitoring fieldset
- var diskFlot = $('
').css({
- 'float' : 'left',
- 'height' : '150px',
- 'margin' : '0 0 10px',
- 'width' : '300px'
- });
- $('#' + node + '_monitor').append(diskFlot);
- $('#' + node + '_network').empty();
-
- for (var i = 0; i < inPair.length; i += 2) {
- if (inPair[i + 1] > maxVal) {
- maxVal = inPair[i + 1];
- }
- }
-
- for (var i = 0; i < outPair.length; i += 2) {
- if (outPair[i + 1] > maxVal) {
- maxVal = outPair[i + 1];
- }
- }
-
- if (maxVal > 3000000) {
- divisor = 1000000;
- unitName = 'GB';
- } else if (maxVal >= 3000) {
- divisor = 1000;
- unitName = 'MB';
- } else {
- // Do nothing
- }
-
- for (i = 0; i < inPair.length; i += 2) {
- inArray.push([ (inPair[i] * 1000), (inPair[i + 1] / divisor) ]);
- }
-
- for (i = 0; i < outPair.length; i += 2) {
- outArray.push([ (outPair[i] * 1000), (outPair[i + 1] / divisor) ]);
- }
-
- $.jqplot(node + '_network', [ inArray, outArray ], {
- title : 'Network Last Hour',
- axes : {
- xaxis : {
- renderer : $.jqplot.DateAxisRenderer,
- numberTicks : 4,
- tickOptions : {
- formatString : '%R',
- show : true
- }
- },
- yaxis : {
- min : 0,
- tickOptions : {
- formatString : '%d' + unitName
- }
- }
- },
- legend : {
- show : true,
- location : 'nw'
- },
- series : [ {
- label : 'In'
- }, {
- label : 'Out'
- } ],
- seriesDefaults : {
- showMarker : false
- }
- });
-}
-
-/**
- * Get an attribute of a given node
- *
- * @param node The node
- * @param attrName The attribute
- * @return The attribute of the node
- */
-function getNodeAttr(node, attrName) {
- // Get the row
- var row = $('[id=' + node + ']').parents('tr');
-
- // Search for the column containing the attribute
- var attrCol = null;
-
- var cols = row.parents('.dataTables_scroll').find('.dataTables_scrollHead thead tr:eq(0) th');
- // Loop through each column
- for (var i in cols) {
- // Find column that matches the attribute
- if (cols.eq(i).html() == attrName) {
- attrCol = cols.eq(i);
- break;
- }
- }
-
- // If the column containing the attribute is found
- if (attrCol) {
- // Get the attribute column index
- var attrIndex = attrCol.index();
-
- // Get the attribute for the given node
- var attr = row.find('td:eq(' + attrIndex + ')');
- return attr.text();
- } else {
- return '';
- }
-}
-
-/**
- * Set the maximum number of VMs a user could have
- */
-function setMaxVM() {
- var userName = $.cookie('xcat_username');
-
- $.ajax( {
- url : 'lib/srv_cmd.php',
- dataType : 'json',
- data : {
- cmd : 'webportal',
- tgt : '',
- args : 'getmaxvm;' + userName,
- msg : ''
- },
-
- success : function(data) {
- // Get response
- var rsp = jQuery.trim(data.rsp);
- rsp = rsp.replace('Max allowed:', '');
-
- // Set cookie to expire in 60 minutes
- var exDate = new Date();
- exDate.setTime(exDate.getTime() + (240 * 60 * 1000));
- $.cookie('xcat_' + userName + '_maxvm', rsp, { expires: exDate });
- }
- });
+/**
+ * Global variables
+ */
+var serviceTabs;
+var nodeName;
+var nodePath;
+var nodeStatus;
+var gangliaTimer;
+
+/**
+ * Initialize service page
+ */
+function initServicePage() {
+ // Load theme
+ var theme = $.cookie('xcat_theme');
+ if (theme) {
+ switch (theme) {
+ case 'cupertino':
+ includeCss("css/themes/jquery-ui-cupertino.css");
+ break;
+ case 'dark_hive':
+ includeCss("css/themes/jquery-ui-dark_hive.css");
+ break;
+ case 'redmond':
+ includeCss("css/themes/jquery-ui-redmond.css");
+ break;
+ case 'start':
+ includeCss("css/themes/jquery-ui-start.css");
+ break;
+ case 'sunny':
+ includeCss("css/themes/jquery-ui-sunny.css");
+ break;
+ case 'ui_dark':
+ includeCss("css/themes/jquery-ui-ui_darkness.css");
+ break;
+ default:
+ includeCss("css/themes/jquery-ui-start.css");
+ }
+ } else {
+ includeCss("css/themes/jquery-ui-start.css");
+ }
+
+ // Load jQuery stylesheets
+ includeCss("css/jquery.dataTables.css");
+ includeCss("css/superfish.css");
+ includeCss("css/jstree.css");
+ includeCss("css/jquery.jqplot.css");
+
+ // Load custom stylesheet
+ includeCss("css/style.css");
+
+ // Reuqired JQuery plugins
+ includeJs("js/jquery/jquery.dataTables.min.js");
+ includeJs("js/jquery/jquery.cookie.min.js");
+ includeJs("js/jquery/tooltip.min.js");
+ includeJs("js/jquery/superfish.min.js");
+ includeJs("js/jquery/jquery.jqplot.min.js");
+ includeJs("js/jquery/jqplot.dateAxisRenderer.min.js");
+
+ // Custom plugins
+ includeJs("js/custom/esx.js");
+ includeJs("js/custom/kvm.js");
+ includeJs("js/custom/zvm.js");
+
+ // Enable settings link
+ $('#xcat_settings').click(function() {
+ openSettings();
+ });
+
+ // Show service page
+ $("#content").children().remove();
+ includeJs("js/service/utils.js");
+ loadServicePage();
+
+ // Initialize tab index history
+ $.cookie('xcat_tabindex_history', '0,0', { path: '/xcat', secure:true });
+}
+
+/**
+ * Load service page
+ */
+function loadServicePage() {
+ // If the page is loaded
+ if ($('#content').children().length) {
+ // Do not load again
+ return;
+ }
+
+ // Create manage and provision tabs
+ serviceTabs = new Tab();
+ serviceTabs.init();
+ $('#content').append(serviceTabs.object());
+
+ var manageTabId = 'manageTab';
+ serviceTabs.add(manageTabId, 'Manage', '', false);
+
+ // Get nodes owned by user
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'tabdump',
+ tgt : '',
+ args : 'nodetype',
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ setUserNodes(data);
+ setMaxVM();
+ getUserNodesDef();
+ getNodesCurrentLoad();
+ loadManagePage(manageTabId);
+ }
+ });
+
+ // Get OS image names
+ $.ajax({
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ async : true,
+ data : {
+ cmd : 'tabdump',
+ tgt : '',
+ args : 'osimage',
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ setOSImageCookies(data);
+ }
+ });
+
+ // Get contents of hosts table
+ $.ajax({
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ async : true,
+ data : {
+ cmd : 'tabdump',
+ tgt : '',
+ args : 'hosts',
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ setGroupCookies(data);
+ }
+ });
+
+ var provTabId = 'provisionTab';
+ serviceTabs.add(provTabId, 'Provision', '', false);
+ loadServiceProvisionPage(provTabId);
+
+ serviceTabs.select(manageTabId);
+}
+
+/**
+ * Load the service portal's provision page
+ *
+ * @param tabId Tab ID where page will reside
+ */
+function loadServiceProvisionPage(tabId) {
+ // Create info bar
+ var infoBar = createInfoBar('Select a platform to provision a node on, then click Ok.');
+
+ // Create provision page
+ var provPg = $('
');
+ $('#' + tabId).append(infoBar, provPg);
+
+ // 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);
+ provPg.append(hwList);
+
+ /**
+ * Ok
+ */
+ var okBtn = createButton('Ok');
+ okBtn.bind('click', function(event) {
+ var userName = $.cookie('xcat_username');
+ var tmp = $.cookie('xcat_' + userName + '_usrnodes');
+
+ // Get maximun number for nodes from cookie
+ var nodes = '';
+ var maxVM = 0;
+ if (tmp.length) {
+ nodes = tmp.split(',');
+ maxVM = parseInt($.cookie('xcat_' + userName + '_maxvm'));
+
+ // Do not allow user to clone if the maximum number of VMs is reached
+ if (nodes.length >= maxVM) {
+ var warn = createWarnBar('You have reached the maximum number of virtual machines allowed (' + maxVM + '). Delete unused virtual machines or contact your system administrator request more virtual machines.');
+ warn.prependTo($('#' + tabId));
+ return;
+ }
+ }
+
+ // Get hardware that was selected
+ var hw = $(this).parent().find('input[name="hw"]:checked').val();
+ var newTabId = hw + 'ProvisionTab';
+
+ if ($('#' + newTabId).size() > 0){
+ serviceTabs.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 "blade":
+ plugin = new bladePlugin();
+ title = 'BladeCenter';
+ break;
+ case "hmc":
+ plugin = new hmcPlugin();
+ title = 'System p';
+ break;
+ case "ipmi":
+ plugin = new ipmiPlugin();
+ title = 'iDataPlex';
+ break;
+ case "zvm":
+ plugin = new zvmPlugin();
+ title = 'z/VM';
+
+ // Get zVM host names
+ $.ajax({
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ async : false,
+ data : {
+ cmd : 'webportal',
+ tgt : '',
+ args : 'lszvm',
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ setzVMCookies(data);
+ }
+ });
+
+ // Get master copies for clone
+ $.ajax({
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ async : false,
+ data : {
+ cmd : 'webportal',
+ tgt : '',
+ args : 'lsgoldenimages',
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ setGoldenImagesCookies(data);
+ }
+ });
+
+ break;
+ }
+
+ // Select tab
+ serviceTabs.add(newTabId, title, '', true);
+ serviceTabs.select(newTabId);
+ plugin.loadServiceProvisionPage(newTabId);
+ }
+ });
+ provPg.append(okBtn);
+}
+
+/**
+ * Load manage page
+ *
+ * @param tabId Tab ID where page will reside
+ */
+function loadManagePage(tabId) {
+ // Create manage form
+ var manageForm = $('
');
+
+ // Append to manage tab
+ $('#' + tabId).append(manageForm);
+}
+
+/**
+ * Get the user nodes definitions
+ */
+function getUserNodesDef() {
+ var userName = $.cookie('xcat_username');
+ var userNodes = $.cookie('xcat_' + userName + '_usrnodes');
+ if (userNodes) {
+ // Get nodes definitions
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'lsdef',
+ tgt : '',
+ args : userNodes,
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ loadNodesTable(data);
+ }
+ });
+ } else {
+ // Clear the tab before inserting the table
+ $('#manageTab').append(createWarnBar('No nodes were found belonging to you!'));
+ }
+}
+
+/**
+ * Load user nodes definitions into a table
+ *
+ * @param data Data from HTTP request
+ */
+function loadNodesTable(data) {
+ // Clear the tab before inserting the table
+ $('#manageTab').children().remove();
+
+ // Nodes datatable ID
+ var nodesDTId = 'userNodesDT';
+
+ // Hash of node attributes
+ var attrs = new Object();
+ // Node attributes
+ var headers = new Object();
+ var node = null, args;
+ // Create hash of node attributes
+ for (var i in data.rsp) {
+ // Get node name
+ if (data.rsp[i].indexOf('Object name:') > -1) {
+ var temp = data.rsp[i].split(': ');
+ node = jQuery.trim(temp[1]);
+
+ // Create a hash for the node attributes
+ attrs[node] = new Object();
+ i++;
+ }
+
+ // Get key and value
+ args = data.rsp[i].split('=', 2);
+ var key = jQuery.trim(args[0]);
+ var val = jQuery.trim(data.rsp[i].substring(data.rsp[i].indexOf('=') + 1, data.rsp[i].length));
+
+ // Create a hash table
+ attrs[node][key] = val;
+ headers[key] = 1;
+ }
+
+ // Sort headers
+ var sorted = new Array();
+ var attrs2show = new Array('arch', 'groups', 'hcp', 'hostnames', 'ip', 'os', 'userid', 'mgt');
+ for (var key in headers) {
+ // Show node attributes
+ if (jQuery.inArray(key, attrs2show) > -1) {
+ sorted.push(key);
+ }
+ }
+ sorted.sort();
+
+ // Add column for check box, node, ping, power, monitor, and comments
+ sorted.unshift(' ',
+ 'node',
+ 'status ',
+ 'power ',
+ 'monitor ',
+ 'comments');
+
+ // Create a datatable
+ var nodesDT = new DataTable(nodesDTId);
+ nodesDT.init(sorted);
+
+ // Go through each node
+ for (var node in attrs) {
+ // Create a row
+ var row = new Array();
+
+ // Create a check box, node link, and get node status
+ var checkBx = $(' ');
+ var nodeLink = $('' + node + ' ').bind('click', loadNode);
+
+ // If there is no status attribute for the node, do not try to access hash table
+ // Else the code will break
+ var status = '';
+ if (attrs[node]['status']) {
+ status = attrs[node]['status'].replace('sshd', 'ping');
+ }
+
+ // Push in checkbox, node, status, monitor, and power
+ row.push(checkBx, nodeLink, status, '', '');
+
+ // If the node attributes are known (i.e the group is known)
+ if (attrs[node]['groups']) {
+ // Put in comments
+ var comments = attrs[node]['usercomment'];
+ // If no comments exists, show 'No comments' and set icon image source
+ var iconSrc;
+ if (!comments) {
+ comments = 'No comments';
+ iconSrc = 'images/nodes/ui-icon-no-comment.png';
+ } else {
+ iconSrc = 'images/nodes/ui-icon-comment.png';
+ }
+
+ // Create comments icon
+ var tipID = node + 'Tip';
+ var icon = $(' ').css({
+ 'width': '18px',
+ 'height': '18px'
+ });
+
+ // Create tooltip
+ var tip = createCommentsToolTip(comments);
+ var col = $(' ').append(icon);
+ col.append(tip);
+ row.push(col);
+
+ // Generate tooltips
+ icon.tooltip({
+ position: "center right",
+ offset: [-2, 10],
+ effect: "fade",
+ opacity: 0.8,
+ relative: true,
+ delay: 500
+ });
+ } else {
+ // Do not put in comments if attributes are not known
+ row.push('');
+ }
+
+ // Go through each header
+ for (var i = 6; i < sorted.length; i++) {
+ // Add the node attributes to the row
+ var key = sorted[i];
+
+ // Do not put comments and status in twice
+ if (key != 'usercomment' && key != 'status' && key.indexOf('statustime') < 0) {
+ var val = attrs[node][key];
+ if (val) {
+ row.push($('' + val + ' '));
+ } else {
+ row.push('');
+ }
+ }
+ }
+
+ // Add the row to the table
+ nodesDT.add(row);
+ }
+
+ // Create info bar
+ var infoBar = createInfoBar('Manage and monitor your virtual machines.');
+ $('#manageTab').append(infoBar);
+
+ // Insert action bar and nodes datatable
+ $('#manageTab').append(nodesDT.object());
+
+ // Turn table into a datatable
+ $('#' + nodesDTId).dataTable({
+ 'iDisplayLength': 50,
+ 'bLengthChange': false,
+ "bScrollCollapse": true,
+ "sScrollY": "400px",
+ "sScrollX": "110%",
+ "bAutoWidth": true,
+ "oLanguage": {
+ "oPaginate": {
+ "sNext": "",
+ "sPrevious": ""
+ }
+ }
+ });
+
+ // Set datatable header class to add color
+ // $('.datatable thead').attr('class', 'ui-widget-header');
+
+ // Do not sort ping, power, and comment column
+ $('#' + nodesDTId + ' thead tr th').click(function() {
+ getNodeAttrs(group);
+ });
+ var checkboxCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(0)');
+ var pingCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(2)');
+ var powerCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
+ var monitorCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)');
+ var commentCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(5)');
+ checkboxCol.unbind('click');
+ pingCol.unbind('click');
+ powerCol.unbind('click');
+ monitorCol.unbind('click');
+ commentCol.unbind('click');
+
+ // Refresh the node ping, power, and monitor status on-click
+ var nodes = getNodesShown(nodesDTId);
+ pingCol.find('span a').click(function() {
+ refreshNodeStatus(nodes);
+ });
+ powerCol.find('span a').click(function() {
+ refreshPowerStatus(nodes);
+ });
+ monitorCol.find('span a').click(function() {
+ refreshGangliaStatus(nodes);
+ });
+
+ // Create actions menu
+ // Power on
+ var powerOnLnk = $('Power on ');
+ powerOnLnk.click(function() {
+ var tgtNodes = getNodesChecked(nodesDTId);
+ if (tgtNodes) {
+ powerNode(tgtNodes, 'on');
+ }
+ });
+
+ // Power off
+ var powerOffLnk = $('Power off ');
+ powerOffLnk.click(function() {
+ var tgtNodes = getNodesChecked(nodesDTId);
+ if (tgtNodes) {
+ powerNode(tgtNodes, 'off');
+ }
+ });
+
+ // Power softoff
+ var powerSoftoffLnk = $('Shutdown ');
+ powerSoftoffLnk.click(function() {
+ var tgtNodes = getNodesChecked(nodesDTId);
+ if (tgtNodes) {
+ powerNode(tgtNodes, 'softoff');
+ }
+ });
+
+ // Clone
+ var cloneLnk = $('Clone ');
+ cloneLnk.click(function() {
+ var tgtNodes = getNodesChecked(nodesDTId);
+ if (tgtNodes) {
+ cloneNode(tgtNodes);
+ }
+ });
+
+ // Delete
+ var deleteLnk = $('Delete ');
+ deleteLnk.click(function() {
+ var tgtNodes = getNodesChecked(nodesDTId);
+ if (tgtNodes) {
+ deleteNode(tgtNodes);
+ }
+ });
+
+ // Unlock
+ var unlockLnk = $('Unlock ');
+ unlockLnk.click(function() {
+ var tgtNodes = getNodesChecked(nodesDTId);
+ if (tgtNodes) {
+ unlockNode(tgtNodes);
+ }
+ });
+
+ // Create action bar
+ var actionBar = $('
').css('width', '370px');
+
+ // Prepend menu to datatable
+ var actionsLnk = $('Actions ');
+ var refreshLnk = $('Refresh ');
+ refreshLnk.click(function() {
+ // Get nodes owned by user
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'tabdump',
+ tgt : '',
+ args : 'nodetype',
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ // Save nodes owned by user
+ setUserNodes(data);
+ getNodesCurrentLoad();
+
+ // Refresh nodes table
+ var userName = $.cookie('xcat_username');
+ var userNodes = $.cookie('xcat_' + userName + '_usrnodes');
+ if (userNodes) {
+ // Get nodes definitions
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'lsdef',
+ tgt : '',
+ args : userNodes,
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ loadNodesTable(data);
+ }
+ });
+ } else {
+ // Clear the tab before inserting the table
+ $('#manageTab').children().remove();
+ $('#manageTab').append(createWarnBar('You are not managing any node. Try to provision a node.'));
+ }
+ }
+ });
+ });
+
+ var actionMenu = createMenu([cloneLnk, deleteLnk, powerOnLnk, powerOffLnk, powerSoftoffLnk, unlockLnk]);
+ var menu = createMenu([[actionsLnk, actionMenu], refreshLnk]);
+ menu.superfish();
+ actionBar.append(menu);
+
+ // Set correct theme for action menu
+ actionMenu.find('li').hover(function() {
+ setMenu2Theme($(this));
+ }, function() {
+ setMenu2Normal($(this));
+ });
+
+ // Create a division to hold actions menu
+ var menuDiv = $('');
+ $('#' + nodesDTId + '_wrapper').prepend(menuDiv);
+ menuDiv.append(actionBar);
+ $('#' + nodesDTId + '_filter').appendTo(menuDiv);
+
+ // Get power and monitor status
+ var nodes = getNodesShown(nodesDTId);
+ refreshPowerStatus(nodes);
+ refreshGangliaStatus(nodes);
+}
+
+/**
+ * Refresh ping status for each node
+ *
+ * @param nodes Nodes to get ping status
+ */
+function refreshNodeStatus(nodes) {
+ // Show ping loader
+ var nodesDTId = 'userNodesDT';
+ var pingCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(2)');
+ pingCol.find('img').show();
+
+ // Get the node ping status
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'nodestat',
+ tgt : nodes,
+ args : '-u',
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ loadNodePing(data);
+ }
+ });
+}
+
+/**
+ * Load node ping status for each node
+ *
+ * @param data Data returned from HTTP request
+ */
+function loadNodePing(data) {
+ var nodesDTId = 'userNodesDT';
+ var datatable = $('#' + nodesDTId).dataTable();
+ var rsp = data.rsp;
+ var args, rowPos, node, status;
+
+ // Get all nodes within datatable
+ for (var i in rsp) {
+ args = rsp[i].split(':');
+
+ // args[0] = node and args[1] = status
+ node = jQuery.trim(args[0]);
+ status = jQuery.trim(args[1]).replace('sshd', 'ping');
+
+ // Get row containing node
+ rowPos = findRow(node, '#' + nodesDTId, 1);
+
+ // Update ping status column
+ datatable.fnUpdate(status, rowPos, 2, false);
+ }
+
+ // Hide status loader
+ var pingCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(2)');
+ pingCol.find('img').hide();
+ adjustColumnSize(nodesDTId);
+}
+
+/**
+ * Refresh power status for each node
+ *
+ * @param nodes Nodes to get power status
+ */
+function refreshPowerStatus(nodes) {
+ // Show power loader
+ var nodesDTId = 'userNodesDT';
+ var powerCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
+ powerCol.find('img').show();
+
+ // Get power status
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'rpower',
+ tgt : nodes,
+ args : 'stat',
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ loadPowerStatus(data);
+ }
+ });
+}
+
+/**
+ * Load power status for each node
+ *
+ * @param data Data returned from HTTP request
+ */
+function loadPowerStatus(data) {
+ var nodesDTId = 'userNodesDT';
+ var datatable = $('#' + nodesDTId).dataTable();
+ var power = data.rsp;
+ var rowPos, node, status, args;
+
+ for (var i in power) {
+ // power[0] = nodeName and power[1] = state
+ args = power[i].split(':');
+ node = jQuery.trim(args[0]);
+ status = jQuery.trim(args[1]);
+
+ // Get the row containing the node
+ rowPos = findRow(node, '#' + nodesDTId, 1);
+
+ // Update the power status column
+ datatable.fnUpdate(status, rowPos, 3, false);
+ }
+
+ // Hide power loader
+ var powerCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
+ powerCol.find('img').hide();
+ adjustColumnSize(nodesDTId);
+}
+
+/**
+ * Refresh the status of Ganglia for each node
+ *
+ * @param nodes Nodes to get Ganglia status
+ */
+function refreshGangliaStatus(nodes) {
+ // Show ganglia loader
+ var nodesDTId = 'userNodesDT';
+ var gangliaCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)');
+ gangliaCol.find('img').show();
+
+ // Get the status of Ganglia
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'gangliastatus;' + nodes,
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ loadGangliaStatus(data);
+ }
+ });
+}
+
+/**
+ * Load the status of Ganglia for a given group
+ *
+ * @param data Data returned from HTTP request
+ */
+function loadGangliaStatus(data) {
+ // Get datatable
+ var nodesDTId = 'userNodesDT';
+ var datatable = $('#' + nodesDTId).dataTable();
+ var ganglia = data.rsp;
+ var rowNum, node, status;
+
+ for ( var i in ganglia) {
+ // ganglia[0] = nodeName and ganglia[1] = state
+ node = jQuery.trim(ganglia[i][0]);
+ status = jQuery.trim(ganglia[i][1]);
+
+ if (node) {
+ // Get the row containing the node
+ rowNum = findRow(node, '#' + nodesDTId, 1);
+
+ // Update the power status column
+ datatable.fnUpdate(status, rowNum, 4);
+ }
+ }
+
+ // Hide Ganglia loader
+ var gangliaCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)');
+ gangliaCol.find('img').hide();
+ adjustColumnSize(nodesDTId);
+}
+
+/**
+ * Load inventory for given node
+ *
+ * @param e Windows event
+ */
+function loadNode(e) {
+ if (!e) {
+ e = window.event;
+ }
+
+ // Get node that was clicked
+ var node = (e.target) ? e.target.id : e.srcElement.id;
+
+ // Create a new tab to show inventory
+ var tabId = node + '_inventory';
+
+ if(!$('#' + tabId).length) {
+ // Add new tab, only if one does not exist
+ var loader = createLoader(node + 'Loader');
+ loader = $(' ').append(loader);
+ serviceTabs.add(tabId, node, loader, true);
+
+ // Get node inventory
+ var msg = 'out=' + tabId + ',node=' + node;
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'rinv',
+ tgt : node,
+ args : 'all',
+ msg : msg
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ var args = data.msg.split(',');
+
+ // Get node
+ var node = args[1].replace('node=', '');
+
+ // Get the management plugin
+ var mgt = getNodeAttr(node, 'mgt');
+
+ // Create an instance of the plugin
+ var plugin;
+ switch (mgt) {
+ case "kvm":
+ plugin = new kvmPlugin();
+ break;
+ case "esx":
+ plugin = new esxPlugin();
+ break;
+ case "zvm":
+ plugin = new zvmPlugin();
+ break;
+ }
+
+ // Select tab
+ plugin.loadServiceInventory(data);
+ }
+ });
+ }
+
+ // Select new tab
+ serviceTabs.select(tabId);
+}
+
+/**
+ * Set a cookie for group names
+ *
+ * @param data Data from HTTP request
+ */
+function setGroupCookies(data) {
+ if (data.rsp) {
+ var groups = new Array();
+
+ // Index 0 is the table header
+ var cols, name, ip, hostname, desc, selectable, comments, tmp;
+ for (var i = 1; i < data.rsp.length; i++) {
+ // Set default description and selectable
+ selectable = "no";
+ desc = "No description";
+
+ // Split into columns:
+ // node, ip, hostnames, otherinterfaces, comments, disable
+ cols = data.rsp[i].split(',');
+ name = cols[0].replace(new RegExp('"', 'g'), '');
+ ip = cols[1].replace(new RegExp('"', 'g'), '');
+ hostname = cols[2].replace(new RegExp('"', 'g'), '');
+
+ // It should return: "description: All machines; network: 10.1.100.0/24;"
+ comments = cols[4].replace(new RegExp('"', 'g'), '');
+ 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);
+ }
+ }
+
+ // Save groups that are selectable
+ if (selectable == "yes")
+ groups.push(name + ':' + ip + ':' + hostname + ':' + desc);
+ }
+
+ // Set cookie to expire in 60 minutes
+ var exDate = new Date();
+ exDate.setTime(exDate.getTime() + (240 * 60 * 1000));
+ $.cookie('xcat_srv_groups', groups, { expires: exDate, path: '/xcat', secure:true });
+ }
+}
+
+/**
+ * Set a cookie for the OS images
+ *
+ * @param data Data from HTTP request
+ */
+function setOSImageCookies(data) {
+ // Get response
+ var rsp = data.rsp;
+
+ var imageNames = new Array();
+ var profilesHash = new Object();
+ var osVersHash = new Object();
+ var osArchsHash = new Object();
+ var imagePos = 0;
+ var profilePos = 0;
+ var osversPos = 0;
+ var osarchPos = 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 '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 osImage = 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 osComments = cols[comments].replace(new RegExp('"', 'g'), '');
+
+ // Only save install boot
+ if (provMethod.indexOf('install') > -1) {
+ if (osComments) {
+ // Only enable images where description and selectable comments exist
+ // Set default description and selectable
+ selectable = "no";
+ desc = "No description";
+
+ 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);
+ }
+ }
+
+ // Save images that are selectable
+ if (selectable == "yes")
+ imageNames.push(osImage + ':' + desc);
+ }
+
+ profilesHash[profile] = 1;
+ osVersHash[osVer] = 1;
+ osArchsHash[osArch] = 1;
+ }
+ }
+
+ // Save image names in a cookie
+ $.cookie('xcat_srv_imagenames', imageNames);
+
+ // Save profiles in a cookie
+ var tmp = new Array;
+ for (var key in profilesHash) {
+ tmp.push(key);
+ }
+ $.cookie('xcat_srv_profiles', tmp);
+
+ // Save OS versions in a cookie
+ tmp = new Array;
+ for (var key in osVersHash) {
+ tmp.push(key);
+ }
+ $.cookie('xcat_srv_osvers', tmp);
+
+ // Save OS architectures in a cookie
+ tmp = new Array;
+ for (var key in osArchsHash) {
+ tmp.push(key);
+ }
+ $.cookie('xcat_srv_osarchs', tmp);
+}
+
+
+
+/**
+ * Set a cookie for user nodes
+ *
+ * @param data Data from HTTP request
+ */
+function setUserNodes(data) {
+ if (data.rsp) {
+ // Get user name that is logged in
+ var userName = $.cookie('xcat_username');
+ var usrNodes = new Array();
+
+ // Ignore first columns because it is the header
+ for ( var i = 1; i < data.rsp.length; i++) {
+ // Go through each column
+ // where column names are: node, os, arch, profile, provmethod, supportedarchs, nodetype, comments, disable
+ var cols = data.rsp[i].split(',');
+ var node = cols[0].replace(new RegExp('"', 'g'), '');
+
+ // Comments can contain the owner and description
+ var comments = new Array();
+ if (cols[7].indexOf(';') > -1) {
+ comments = cols[7].replace(new RegExp('"', 'g'), '').split(';');
+ } else {
+ comments.push(cols[7].replace(new RegExp('"', 'g'), ''));
+ }
+
+ // Extract the owner
+ var owner;
+ for (var j in comments) {
+ if (comments[j].indexOf('owner:') > -1) {
+ owner = comments[j].replace('owner:', '');
+
+ if (owner == userName) {
+ usrNodes.push(node);
+ }
+
+ break;
+ }
+ }
+ } // End of for
+
+ // Set cookie to expire in 240 minutes
+ var exDate = new Date();
+ exDate.setTime(exDate.getTime() + (240 * 60 * 1000));
+ $.cookie('xcat_' + userName + '_usrnodes', usrNodes, { expires: exDate, path: '/xcat', secure:true });
+ } // End of if
+}
+
+/**
+ * Power on a given node
+ *
+ * @param tgtNodes Node to power on or off
+ * @param power2 Power node to given state
+ */
+function powerNode(tgtNodes, power2) {
+ // Show power loader
+ var nodesDTId = 'userNodesDT';
+ var powerCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
+ powerCol.find('img').show();
+
+ var nodes = tgtNodes.split(',');
+ for (var n in nodes) {
+ // Get hardware that was selected
+ var hw = getUserNodeAttr(nodes[n], 'mgt');
+
+ // Change to power softoff (to gracefully shutdown)
+ switch (hw) {
+ case "blade":
+ break;
+ case "hmc":
+ break;
+ case "ipmi":
+ break;
+ case "zvm":
+ if (power2 == 'off') {
+ power2 = 'softoff';
+ }
+
+ break;
+ }
+ }
+
+ $.ajax({
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'rpower',
+ tgt : tgtNodes,
+ args : power2,
+ msg : tgtNodes
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ updatePowerStatus(data);
+ }
+ });
+}
+
+/**
+ * Update power status of a node in the datatable
+ *
+ * @param data Data from HTTP request
+ */
+function updatePowerStatus(data) {
+ // Get datatable
+ var nodesDTId = 'userNodesDT';
+ var dTable = $('#' + nodesDTId).dataTable();
+
+ // Get xCAT response
+ var rsp = data.rsp;
+ // Loop through each line
+ var node, status, rowPos, strPos;
+ for (var i in rsp) {
+ // Get node name
+ node = rsp[i].split(":")[0];
+
+ // If there is no error
+ if (rsp[i].indexOf("Error") < 0 || rsp[i].indexOf("Failed") < 0) {
+ // Get the row containing the node link
+ rowPos = findRow(node, '#' + nodesDTId, 1);
+
+ // If it was power on, then the data return would contain "Starting"
+ strPos = rsp[i].indexOf("Starting");
+ if (strPos > -1) {
+ status = 'on';
+ } else {
+ status = 'off';
+ }
+
+ // Update the power status column
+ dTable.fnUpdate(status, rowPos, 3, false);
+ } else {
+ // Power on/off failed
+ alert(rsp[i]);
+ }
+ }
+
+ var powerCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
+ powerCol.find('img').hide();
+ adjustColumnSize(nodesDTId);
+}
+
+/**
+ * Turn on monitoring for a given node
+ *
+ * @param node Node to monitor on or off
+ * @param monitor Monitor state, on or off
+ */
+function monitorNode(node, monitor) {
+ // Show ganglia loader
+ var nodesDTId = 'userNodesDT';
+ var gangliaCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)');
+ gangliaCol.find('img').show();
+
+ if (monitor == 'on') {
+ if (node) {
+ // Check if ganglia RPMs are installed
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'gangliacheck;' + node,
+ msg : node // Node range will be passed along in data.msg
+ },
+
+ /**
+ * Start ganglia on a given node range
+ *
+ * @param data
+ * Data returned from HTTP request
+ * @return Nothing
+ */
+ success : function(data) {
+ data = decodeRsp(data);
+ // Get response
+ var out = data.rsp[0].split(/\n/);
+
+ // Go through each line
+ var warn = false;
+ var warningMsg = '';
+ for (var i in out) {
+ // If an RPM is not installed
+ if (out[i].indexOf('not installed') > -1) {
+ warn = true;
+
+ if (warningMsg) {
+ warningMsg += ' ' + out[i];
+ } else {
+ warningMsg = out[i];
+ }
+ }
+ }
+
+ // If there are warnings
+ if (warn) {
+ // Create warning bar
+ var warningBar = createWarnBar(warningMsg);
+ warningBar.css('margin-bottom', '10px');
+ warningBar.prependTo($('#nodesTab'));
+ } else {
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'gangliastart;' + data.msg,
+ msg : data.msg
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ // Remove any warnings
+ $('#nodesTab').find('.ui-state-error').remove();
+ refreshGangliaStatus(data.msg);
+ }
+ });
+ } // End of if (warn)
+ } // End of function(data)
+ });
+ }
+ } else {
+ var args;
+ if (node) {
+ args = 'gangliastop;' + node;
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : args,
+ msg : node
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ refreshGangliaStatus(data.msg);
+ }
+ });
+ }
+ }
+}
+
+/**
+ * Open a dialog to clone node
+ *
+ * @param tgtNodes Nodes to clone
+ */
+function cloneNode(tgtNodes) {
+ var userName = $.cookie('xcat_username');
+ var nodes = tgtNodes.split(',');
+ var tmp = $.cookie('xcat_' + userName + '_usrnodes');
+ var usrNodes = tmp.split(',');
+
+ var maxVM = parseInt($.cookie('xcat_' + userName + '_maxvm'));
+
+ // Do not allow user to clone if the maximum number of VMs is reached
+ if (usrNodes.length >= maxVM) {
+ var warn = createWarnBar('You have reached the maximum number of virtual machines allowed (' + maxVM + '). Delete un-used virtual machines or contact your system administrator request more virtual machines.');
+ warn.prependTo($('#manageTab'));
+ return;
+ }
+
+ for (var n in nodes) {
+ // Get hardware that was selected
+ var hw = getUserNodeAttr(nodes[n], 'mgt');
+
+ // Create an instance of the plugin
+ var plugin;
+ switch (hw) {
+ case "kvm":
+ plugin = new kvmPlugin();
+ break;
+ case "esx":
+ plugin = new esxPlugin();
+ break;
+ case "zvm":
+ plugin = new zvmPlugin();
+ break;
+ }
+
+ // Clone node
+ plugin.serviceClone(nodes[n]);
+ }
+}
+
+
+/**
+ * Open a dialog to delete node
+ *
+ * @param tgtNodes Nodes to delete
+ */
+function deleteNode(tgtNodes) {
+ var nodes = tgtNodes.split(',');
+
+ // Loop through each node and create target nodes string
+ var tgtNodesStr = '';
+ for (var i in nodes) {
+ if (i == 0 && i == nodes.length - 1) {
+ // If it is the 1st and only node
+ tgtNodesStr += nodes[i];
+ } else if (i == 0 && i != nodes.length - 1) {
+ // If it is the 1st node of many nodes, append a comma to the string
+ tgtNodesStr += nodes[i] + ', ';
+ } else {
+ if (i == nodes.length - 1) {
+ // If it is the last node, append nothing to the string
+ tgtNodesStr += nodes[i];
+ } else {
+ // Append a comma to the string
+ tgtNodesStr += nodes[i] + ', ';
+ }
+ }
+ }
+
+ // Confirm delete of node
+ var dialog = $('
');
+ var warn = createWarnBar('Are you sure you want to delete ' + tgtNodesStr + '?');
+ dialog.append(warn);
+
+ // Open dialog
+ dialog.dialog({
+ title: "Confirm",
+ modal: true,
+ close: function(){
+ $(this).remove();
+ },
+ width: 400,
+ buttons: {
+ "Yes": function(){
+ // Create status bar and append to tab
+ var instance = 0;
+ var statBarId = 'deleteStat' + instance;
+ while ($('#' + statBarId).length) {
+ // If one already exists, generate another one
+ instance = instance + 1;
+ statBarId = 'deleteStat' + instance;
+ }
+
+ var statBar = createStatusBar(statBarId);
+ var loader = createLoader('');
+ statBar.find('div').append(loader);
+ statBar.prependTo($('#manageTab'));
+
+ // Delete the virtual server
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'rmvm',
+ tgt : tgtNodes,
+ args : '',
+ msg : 'out=' + statBarId + ';cmd=rmvm;tgt=' + tgtNodes
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ var args = data.msg.split(';');
+ var statBarId = args[0].replace('out=', '');
+ var tgts = args[2].replace('tgt=', '').split(',');
+
+ // Get data table
+ var nodesDTId = 'userNodesDT';
+ var dTable = $('#' + nodesDTId).dataTable();
+ var failed = false;
+
+ // Create an info box to show output
+ var output = writeRsp(data.rsp, '');
+ output.css('margin', '0px');
+ // Remove loader and append output
+ $('#' + statBarId + ' img').remove();
+ $('#' + statBarId + ' div').append(output);
+
+ // If there was an error, do not continue
+ if (output.html().indexOf('Error') > -1) {
+ failed = true;
+ }
+
+ // Update data table
+ var rowPos;
+ for (var i in tgts) {
+ if (!failed) {
+ // Get row containing the node link and delete it
+ rowPos = findRow(tgts[i], '#' + nodesDTId, 1);
+ dTable.fnDeleteRow(rowPos);
+ }
+ }
+
+ // Refresh nodes owned by user
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'tabdump',
+ tgt : '',
+ args : 'nodetype',
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ setUserNodes(data);
+ }
+ });
+ }
+ });
+
+ $(this).dialog("close");
+ },
+ "No": function() {
+ $(this).dialog("close");
+ }
+ }
+ });
+}
+
+/**
+ * Unlock a node by setting the ssh keys
+ *
+ * @param tgtNodes Nodes to unlock
+ */
+function unlockNode(tgtNodes) {
+ var nodes = tgtNodes.split(',');
+
+ // Loop through each node and create target nodes string
+ var tgtNodesStr = '';
+ for (var i in nodes) {
+ if (i == 0 && i == nodes.length - 1) {
+ // If it is the 1st and only node
+ tgtNodesStr += nodes[i];
+ } else if (i == 0 && i != nodes.length - 1) {
+ // If it is the 1st node of many nodes, append a comma to the string
+ tgtNodesStr += nodes[i] + ', ';
+ } else {
+ if (i == nodes.length - 1) {
+ // If it is the last node, append nothing to the string
+ tgtNodesStr += nodes[i];
+ } else {
+ // Append a comma to the string
+ tgtNodesStr += nodes[i] + ', ';
+ }
+ }
+ }
+
+ var dialog = $('
');
+ var infoBar = createInfoBar('Give the root password for this node range to setup its SSH keys.');
+ dialog.append(infoBar);
+
+ var unlockForm = $('
').css('margin', '5px');
+ unlockForm.append('Target node range:
');
+ unlockForm.append('Password:
');
+ dialog.append(unlockForm);
+
+ dialog.find('div input').css('margin', '5px');
+
+ // Generate tooltips
+ unlockForm.find('div input[title]').tooltip({
+ position: "center right",
+ offset: [-2, 10],
+ effect: "fade",
+ opacity: 0.7,
+ predelay: 800,
+ events : {
+ def : "mouseover,mouseout",
+ input : "mouseover,mouseout",
+ widget : "focus mouseover,blur mouseout",
+ tooltip : "mouseover,mouseout"
+ }
+ });
+
+ // Open dialog
+ dialog.dialog({
+ title: "Confirm",
+ modal: true,
+ close: function(){
+ $(this).remove();
+ },
+ width: 450,
+ buttons: {
+ "Ok": function(){
+ // Create status bar and append to tab
+ var instance = 0;
+ var statBarId = 'unlockStat' + instance;
+ while ($('#' + statBarId).length) {
+ // If one already exists, generate another one
+ instance = instance + 1;
+ statBarId = 'unlockStat' + instance;
+ }
+
+ var statBar = createStatusBar(statBarId);
+ var loader = createLoader('');
+ statBar.find('div').append(loader);
+ statBar.prependTo($('#manageTab'));
+
+ // If a password is given
+ var password = unlockForm.find('input[name=password]:eq(0)');
+ if (password.val()) {
+ // Setup SSH keys
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'unlock;' + tgtNodes + ';' + password.val(),
+ msg : 'out=' + statBarId + ';cmd=unlock;tgt=' + tgtNodes
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ // Create an info box to show output
+ var output = writeRsp(data.rsp, '');
+ output.css('margin', '0px');
+ // Remove loader and append output
+ $('#' + statBarId + ' img').remove();
+ $('#' + statBarId + ' div').append(output);
+ }
+ });
+
+ $(this).dialog("close");
+ }
+ },
+ "Cancel": function() {
+ $(this).dialog("close");
+ }
+ }
+ });
+}
+
+/**
+ * Get nodes current load information
+ */
+function getNodesCurrentLoad(){
+ var userName = $.cookie('xcat_username');
+ var nodes = $.cookie('xcat_' + userName + '_usrnodes');
+
+ // Get nodes current status
+ $.ajax({
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'gangliacurrent;node;' + nodes,
+ msg : ''
+ },
+
+ success: function(data) {
+ data = decodeRsp(data);
+ saveNodeLoad(data);
+ }
+ });
+}
+
+/**
+ * Save node load data
+ *
+ * @param status Data returned from HTTP request
+ */
+function saveNodeLoad(status){
+ // Save node path and status for future use
+ nodePath = new Object();
+ nodeStatus = new Object();
+
+ // Get nodes status
+ var nodes = status.rsp[0].split(';');
+
+ var i = 0, pos = 0;
+ var node = '', tmpStr = '';
+ var tmpArry;
+
+ for (i = 0; i < nodes.length; i++){
+ tmpStr = nodes[i];
+ pos = tmpStr.indexOf(':');
+ node = tmpStr.substring(0, pos);
+ tmpArry = tmpStr.substring(pos + 1).split(',');
+
+ switch(tmpArry[0]){
+ case 'UNKNOWN':{
+ nodeStatus[node] = -2;
+ }
+ break;
+ case 'ERROR':{
+ nodeStatus[node] = -1;
+ }
+ break;
+ case 'WARNING':{
+ nodeStatus[node] = 0;
+ nodePath[node] = tmpArry[1];
+ }
+ break;
+ case 'NORMAL':{
+ nodeStatus[node] = 1;
+ nodePath[node] = tmpArry[1];
+ }
+ break;
+ }
+ }
+}
+
+/**
+ * Get monitoring metrics and load into inventory fieldset
+ *
+ * @param node Node to collect metrics
+ */
+function getMonitorMetrics(node) {
+ // Inventory tab should have this fieldset already created
+ // e.g.
+ $('#' + node + '_monitor').children('div').remove();
+
+ // Before trying to get the metrics, check if Ganglia is running
+ $.ajax({
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'gangliastatus;' + node,
+ msg : ''
+ },
+
+ success: function(data) {
+ data = decodeRsp(data);
+ var ganglia = data.rsp;
+ var node, status;
+
+ // Get the ganglia status
+ for (var i in ganglia) {
+ // ganglia[0] = nodeName and ganglia[1] = state
+ node = jQuery.trim(ganglia[i][0]);
+ status = jQuery.trim(ganglia[i][1]);
+
+ if (node && status == 'on') {
+ // Get monitoring metrics
+ $.ajax({
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'gangliashow;' + nodePath[node] + ';hour;_summary_',
+ msg : node
+ },
+
+ success: function(data) {
+ data = decodeRsp(data);
+ drawMonitoringCharts(data);
+ }
+ });
+ } else if (node && status == 'off') {
+ var info = createInfoBar('Ganglia monitoring is disabled for this node');
+ $('#' + node + '_monitor').append(info.css('width', '300px'));
+ }
+ } // End of for
+ } // End of function
+ });
+}
+
+/**
+ * Draw monitoring charts based on node metrics
+ *
+ * @param data Data returned from HTTP request
+ */
+function drawMonitoringCharts(data){
+ var nodeMetrics = new Object();
+ var metricData = data.rsp[0].split(';');
+ var node = data.msg;
+
+ var metricName = '';
+ var metricVal = '';
+ var pos = 0;
+
+ // Go through the metrics returned
+ for (var m = 0; m < metricData.length; m++){
+ pos = metricData[m].indexOf(':');
+
+ // Get metric name
+ metricName = metricData[m].substr(0, pos);
+ nodeMetrics[metricName] = new Array();
+ // Get metric values
+ metricVal = metricData[m].substr(pos + 1).split(',');
+ // Save node metrics
+ for (var i = 0; i < metricVal.length; i++){
+ nodeMetrics[metricName].push(Number(metricVal[i]));
+ }
+ }
+
+ drawLoadFlot(node, nodeMetrics['load_one'], nodeMetrics['cpu_num']);
+ drawCpuFlot(node, nodeMetrics['cpu_idle']);
+ drawMemFlot(node, nodeMetrics['mem_free'], nodeMetrics['mem_total']);
+ drawDiskFlot(node, nodeMetrics['disk_free'], nodeMetrics['disk_total']);
+ drawNetworkFlot(node, nodeMetrics['bytes_in'], nodeMetrics['bytes_out']);
+}
+
+/**
+ * Draw load metrics flot
+ *
+ * @param node Node name
+ * @param loadpair Load timestamp and value pair
+ * @param cpupair CPU number and value pair
+ */
+function drawLoadFlot(node, loadPair, cpuPair){
+ var load = new Array();
+ var cpu = new Array();
+
+ var i = 0;
+ var yAxisMax = 0;
+ var interval = 1;
+
+ // Append flot to node monitoring fieldset
+ var loadFlot = $('
').css({
+ 'float': 'left',
+ 'height': '150px',
+ 'margin': '0 0 10px',
+ 'width': '300px'
+ });
+ $('#' + node + '_monitor').append(loadFlot);
+ $('#' + node + '_load').empty();
+
+ // Parse load pair where:
+ // timestamp must be mutiplied by 1000 and Javascript timestamp is in ms
+ for (i = 0; i < loadPair.length; i += 2){
+ load.push([loadPair[i] * 1000, loadPair[i + 1]]);
+ if (loadPair[i + 1] > yAxisMax){
+ yAxisMax = loadPair[i + 1];
+ }
+ }
+
+ // Parse CPU pair
+ for (i = 0; i < cpuPair.length; i += 2){
+ cpu.push([cpuPair[i] * 1000, cpuPair[i + 1]]);
+ if (cpuPair[i + 1] > yAxisMax){
+ yAxisMax = cpuPair[i + 1];
+ }
+ }
+
+ interval = parseInt(yAxisMax / 3);
+ if (interval < 1){
+ interval = 1;
+ }
+
+ $.jqplot(node + '_load', [load, cpu],{
+ title: ' Loads/Procs Last Hour',
+ axes:{
+ xaxis:{
+ renderer : $.jqplot.DateAxisRenderer,
+ numberTicks: 4,
+ tickOptions : {
+ formatString : '%R',
+ show : true
+ }
+ },
+ yaxis: {
+ min : 0,
+ tickInterval : interval
+ }
+ },
+ legend : {
+ show: true,
+ location: 'nw'
+ },
+ series:[{label:'Load'}, {label: 'CPU Number'}],
+ seriesDefaults : {showMarker: false}
+ });
+}
+
+/**
+ * Draw CPU usage flot
+ *
+ * @param node Node name
+ * @param cpuPair CPU timestamp and value pair
+ */
+function drawCpuFlot(node, cpuPair){
+ var cpu = new Array();
+
+ // Append flot to node monitoring fieldset
+ var cpuFlot = $('
').css({
+ 'float': 'left',
+ 'height': '150px',
+ 'margin': '0 0 10px',
+ 'width': '300px'
+ });
+ $('#' + node + '_monitor').append(cpuFlot);
+ $('#' + node + '_cpu').empty();
+
+ // Time stamp should by mutiplied by 1000
+ // CPU idle comes from server, subtract 1 from idle
+ for(var i = 0; i < cpuPair.length; i +=2){
+ cpu.push([(cpuPair[i] * 1000), (100 - cpuPair[i + 1])]);
+ }
+
+ $.jqplot(node + '_cpu', [cpu],{
+ title: 'CPU Use Last Hour',
+ axes:{
+ xaxis:{
+ renderer : $.jqplot.DateAxisRenderer,
+ numberTicks: 4,
+ tickOptions : {
+ formatString : '%R',
+ show : true
+ }
+ },
+ yaxis: {
+ min : 0,
+ max : 100,
+ tickOptions:{formatString : '%d\%'}
+ }
+ },
+ seriesDefaults : {showMarker: false}
+ });
+}
+
+/**
+ * Draw memory usage flot
+ *
+ * @param node Node name
+ * @param freePair Free memory timestamp and value pair
+ * @param totalPair Total memory timestamp and value pair
+ */
+function drawMemFlot(node, freePair, totalPair){
+ var used = new Array();
+ var total = new Array();
+ var size = 0;
+
+ // Append flot to node monitoring fieldset
+ var memoryFlot = $('
').css({
+ 'float': 'left',
+ 'height': '150px',
+ 'margin': '0 0 10px',
+ 'width': '300px'
+ });
+ $('#' + node + '_monitor').append(memoryFlot);
+ $('#' + node + '_memory').empty();
+
+ if(freePair.length < totalPair.length){
+ size = freePair.length;
+ } else {
+ size = freePair.length;
+ }
+
+ var tmpTotal, tmpUsed;
+ for(var i = 0; i < size; i+=2){
+ tmpTotal = totalPair[i+1];
+ tmpUsed = tmpTotal-freePair[i+1];
+ tmpTotal = tmpTotal/1000000;
+ tmpUsed = tmpUsed/1000000;
+ total.push([totalPair[i]*1000, tmpTotal]);
+ used.push([freePair[i]*1000, tmpUsed]);
+ }
+
+ $.jqplot(node + '_memory', [used, total],{
+ title: 'Memory Use Last Hour',
+ axes:{
+ xaxis:{
+ renderer : $.jqplot.DateAxisRenderer,
+ numberTicks: 4,
+ tickOptions : {
+ formatString : '%R',
+ show : true
+ }
+ },
+ yaxis: {
+ min : 0,
+ tickOptions:{formatString : '%.2fG'}
+ }
+ },
+ legend : {
+ show: true,
+ location: 'nw'
+ },
+ series:[{label:'Used'}, {label: 'Total'}],
+ seriesDefaults : {showMarker: false}
+ });
+}
+
+/**
+ * Draw disk usage flot
+ *
+ * @param node Node name
+ * @param freePair Free disk space (Ganglia only logs free data)
+ * @param totalPair Total disk space
+ */
+function drawDiskFlot(node, freePair, totalPair) {
+ var used = new Array();
+ var total = new Array();
+ var size = 0;
+
+ // Append flot to node monitoring fieldset
+ var diskFlot = $('
').css({
+ 'float' : 'left',
+ 'height' : '150px',
+ 'margin' : '0 0 10px',
+ 'width' : '300px'
+ });
+ $('#' + node + '_monitor').append(diskFlot);
+ $('#' + node + '_disk').empty();
+
+ if (freePair.length < totalPair.length) {
+ size = freePair.length;
+ } else {
+ size = freePair.length;
+ }
+
+ var tmpTotal, tmpUsed;
+ for ( var i = 0; i < size; i += 2) {
+ tmpTotal = totalPair[i + 1];
+ tmpUsed = tmpTotal - freePair[i + 1];
+ total.push([ totalPair[i] * 1000, tmpTotal ]);
+ used.push([ freePair[i] * 1000, tmpUsed ]);
+ }
+
+ $.jqplot(node + '_disk', [ used, total ], {
+ title : 'Disk Use Last Hour',
+ axes : {
+ xaxis : {
+ renderer : $.jqplot.DateAxisRenderer,
+ numberTicks : 4,
+ tickOptions : {
+ formatString : '%R',
+ show : true
+ }
+ },
+ yaxis : {
+ min : 0,
+ tickOptions : {
+ formatString : '%.2fG'
+ }
+ }
+ },
+ legend : {
+ show : true,
+ location : 'nw'
+ },
+ series : [ {
+ label : 'Used'
+ }, {
+ label : 'Total'
+ } ],
+ seriesDefaults : {
+ showMarker : false
+ }
+ });
+}
+
+/**
+ * Draw network usage flot
+ *
+ * @param node Node name
+ * @param freePair Free memory timestamp and value pair
+ * @param totalPair Total memory timestamp and value pair
+ */
+function drawNetworkFlot(node, inPair, outPair) {
+ var inArray = new Array();
+ var outArray = new Array();
+ var maxVal = 0;
+ var unitName = 'B';
+ var divisor = 1;
+
+ // Append flot to node monitoring fieldset
+ var diskFlot = $('
').css({
+ 'float' : 'left',
+ 'height' : '150px',
+ 'margin' : '0 0 10px',
+ 'width' : '300px'
+ });
+ $('#' + node + '_monitor').append(diskFlot);
+ $('#' + node + '_network').empty();
+
+ for (var i = 0; i < inPair.length; i += 2) {
+ if (inPair[i + 1] > maxVal) {
+ maxVal = inPair[i + 1];
+ }
+ }
+
+ for (var i = 0; i < outPair.length; i += 2) {
+ if (outPair[i + 1] > maxVal) {
+ maxVal = outPair[i + 1];
+ }
+ }
+
+ if (maxVal > 3000000) {
+ divisor = 1000000;
+ unitName = 'GB';
+ } else if (maxVal >= 3000) {
+ divisor = 1000;
+ unitName = 'MB';
+ } else {
+ // Do nothing
+ }
+
+ for (i = 0; i < inPair.length; i += 2) {
+ inArray.push([ (inPair[i] * 1000), (inPair[i + 1] / divisor) ]);
+ }
+
+ for (i = 0; i < outPair.length; i += 2) {
+ outArray.push([ (outPair[i] * 1000), (outPair[i + 1] / divisor) ]);
+ }
+
+ $.jqplot(node + '_network', [ inArray, outArray ], {
+ title : 'Network Last Hour',
+ axes : {
+ xaxis : {
+ renderer : $.jqplot.DateAxisRenderer,
+ numberTicks : 4,
+ tickOptions : {
+ formatString : '%R',
+ show : true
+ }
+ },
+ yaxis : {
+ min : 0,
+ tickOptions : {
+ formatString : '%d' + unitName
+ }
+ }
+ },
+ legend : {
+ show : true,
+ location : 'nw'
+ },
+ series : [ {
+ label : 'In'
+ }, {
+ label : 'Out'
+ } ],
+ seriesDefaults : {
+ showMarker : false
+ }
+ });
+}
+
+/**
+ * Get an attribute of a given node
+ *
+ * @param node The node
+ * @param attrName The attribute
+ * @return The attribute of the node
+ */
+function getNodeAttr(node, attrName) {
+ // Get the row
+ var row = $('[id=' + node + ']').parents('tr');
+
+ // Search for the column containing the attribute
+ var attrCol = null;
+
+ var cols = row.parents('.dataTables_scroll').find('.dataTables_scrollHead thead tr:eq(0) th');
+ // Loop through each column
+ for (var i in cols) {
+ // Find column that matches the attribute
+ if (cols.eq(i).html() == attrName) {
+ attrCol = cols.eq(i);
+ break;
+ }
+ }
+
+ // If the column containing the attribute is found
+ if (attrCol) {
+ // Get the attribute column index
+ var attrIndex = attrCol.index();
+
+ // Get the attribute for the given node
+ var attr = row.find('td:eq(' + attrIndex + ')');
+ return attr.text();
+ } else {
+ return '';
+ }
+}
+
+/**
+ * Set the maximum number of VMs a user could have
+ */
+function setMaxVM() {
+ var userName = $.cookie('xcat_username');
+
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webportal',
+ tgt : '',
+ args : 'getmaxvm;' + userName,
+ msg : ''
+ },
+
+ success : function(data) {
+ data = decodeRsp(data);
+ // Get response
+ var rsp = jQuery.trim(data.rsp);
+ rsp = rsp.replace('Max allowed:', '');
+
+ // Set cookie to expire in 60 minutes
+ var exDate = new Date();
+ exDate.setTime(exDate.getTime() + (240 * 60 * 1000));
+ $.cookie('xcat_' + userName + '_maxvm', rsp, { expires: exDate });
+ }
+ });
}
\ No newline at end of file
diff --git a/xCAT-UI/js/ui.js b/xCAT-UI/js/ui.js
index 771fa5d65..3b5da6ba2 100644
--- a/xCAT-UI/js/ui.js
+++ b/xCAT-UI/js/ui.js
@@ -1,1068 +1,1101 @@
-/**
- * Tab constructor
- *
- * @param tabId
- * Tab ID
- * @param tabName
- * Tab name
- * @return Nothing
- */
-var Tab = function(tabId) {
- this.tabId = tabId;
- this.tabName = null;
- this.tab = null;
-};
-
-/**
- * Initialize the tab
- *
- * @param tabName Tab name to initialize
- */
-Tab.prototype.init = function() {
- // Create a division containing the tab
- this.tab = $('
');
- var tabList = $('');
- var tabItem = $('Dummy tab item ');
- tabList.append(tabItem);
- this.tab.append(tabList);
-
- // Create a template with close button
- var tabs = this.tab.tabs();
-
- tabs.bind('tabsselect', function(event, ui){
- // Save the order tabs were selected
- var order;
- if ($.cookie('xcat_tabindex_history')) {
- order = $.cookie('xcat_tabindex_history').split(',');
- order[1] = order[0]; // Set index 1 to last selected tab
- order[0] = ui.index; // Set index 0 to currently selected tab
- } else {
- // Create an array to track the tab selected
- order = new Array;
- order[0] = ui.index;
- order[1] = ui.index;
- }
-
- $.cookie('xcat_tabindex_history', order, { path: '/xcat', secure:true });
- });
-
- // Remove dummy tab
- this.tab.tabs("remove", 0);
-
- // Hide tab
- this.tab.hide();
-};
-
-/**
- * Return the tab object
- *
- * @return Object representing the tab
- */
-Tab.prototype.object = function() {
- return this.tab;
-};
-
-/**
- * Add a new tab
- *
- * @param tabId Tab ID
- * @param tabName Tab name
- * @param tabCont Tab content
- * @param closeable Is tab closeable
- */
-Tab.prototype.add = function(tabId, tabName, tabCont, closeable) {
- // Show tab
- if (this.tab.css("display") == "none") {
- this.tab.show();
- }
-
- var newTab = $('
');
- newTab.append(tabCont);
- this.tab.append(newTab);
- this.tab.tabs("add", "#" + tabId, tabName);
-
- // Append close button
- if (closeable) {
- var header = this.tab.find('ul.ui-tabs-nav a[href="#' + tabId +'"]').parent();
- header.append(' ');
-
- // Get this tab
- var tabs = this.tab;
- var tabLink = 'a[href="\#' + tabId + '"]';
- var thisTab = $(tabLink, tabs).parent();
-
- // Close tab when close button is clicked
- thisTab.find('span.tab-close').bind('click', function(event) {
- var tabIndex = ($('li', tabs).index(thisTab));
-
- // Do not remove first tab
- if (tabIndex != 0) {
- // Go back to last tab if user is trying to close currently selected tab
- if (tabs.tabs('option', 'selected') == tabIndex) {
- // Get last selected tab from history
- var order = $.cookie('xcat_tabindex_history').split(',');
- if (order[1]) {
- tabs.tabs('select', parseInt(order[1]));
- } else {
- tabs.tabs('select', 0);
- }
- }
-
- tabs.tabs('remove', tabIndex);
- }
- });
- }
-};
-
-/**
- * Select a tab
- *
- * @param id Tab ID to select
- */
-Tab.prototype.select = function(id) {
- this.tab.tabs("select", "#" + id);
-};
-
-/**
- * Remove a tab
- *
- * @param id Tab ID to remove
- */
-Tab.prototype.remove = function(id) {
- var selectorStr = 'a[href="\#' + id + '"]';
- var selectTab = $(selectorStr, this.tab).parent();
- var index = ($('li', this.tab).index(selectTab));
- this.tab.tabs("remove", index);
-};
-
-/**
- * Table constructor
- *
- * @param tabId Tab ID
- * @param tabName Tab name
- */
-var Table = function(tableId) {
- if ($('#' + tableId).length) {
- this.tableId = tableId;
- this.table = $('#' + tableId);
- } else {
- this.tableId = tableId;
- this.table = null;
- }
-};
-
-/**
- * Initialize the table
- *
- * @param Headers Array of table headers
- */
-Table.prototype.init = function(headers) {
- // Create a table
- this.table = $('');
- var thead = $('');
- var headRow = $(' ');
-
- // Append headers
- for (var i in headers) {
- headRow.append('' + headers[i] + ' ');
- }
-
- thead.append(headRow);
- this.table.append(thead);
-
- // Append table body
- var tableBody = $(' ');
- this.table.append(tableBody);
-};
-
-/**
- * Return the table object
- *
- * @return Object representing the table
- */
-Table.prototype.object = function() {
- return this.table;
-};
-
-/**
- * Add a row to the table
- *
- * @param rowCont Array of table row contents
- */
-Table.prototype.add = function(rowCont) {
- // Create table row
- var tableRow = $(' ');
-
- // Create a column for each content
- var tableCol;
- for (var i in rowCont) {
- tableCol = $(' ');
- tableCol.append(rowCont[i]);
- tableRow.append(tableCol);
- }
-
- // Append table row to table
- this.table.find('tbody').append(tableRow);
-};
-
-/**
- * Add a footer to the table
- *
- * @param rowCont Array of table row contents
- */
-Table.prototype.addFooter = function(rowCont) {
- // Create table row
- var tableFoot = $(' ');
- tableFoot.append(rowCont);
-
- // Append table row to table
- this.table.append(tableFoot);
-};
-
-/**
- * Remove a row from the table
- */
-Table.prototype.remove = function(id) {
- // To be continued
-};
-
-/**
- * Datatable class constructor
- *
- * @param tabId Tab ID
- * @param tabName Tab name
- */
-var DataTable = function(tableId) {
- this.dataTableId = tableId;
- this.dataTable = null;
-};
-
-/**
- * Initialize the datatable
- *
- * @param Headers Array of table headers
- */
-DataTable.prototype.init = function(headers) {
- // Create a table
- this.dataTable = $('');
- var thead = $('');
- var headRow = $(' ');
-
- // Append headers
- for (var i in headers) {
- headRow.append('' + headers[i] + ' ');
- }
-
- thead.append(headRow);
- this.dataTable.append(thead);
-
- // Append table body
- var tableBody = $(' ');
- this.dataTable.append(tableBody);
-};
-
-/**
- * Return the datatable object
- *
- * @return Object representing the table
- */
-DataTable.prototype.object = function() {
- return this.dataTable;
-};
-
-/**
- * Add a row to the datatable
- *
- * @param rowCont Array of table row contents
- */
-DataTable.prototype.add = function(rowCont) {
- // Create table row
- var tableRow = $(' ');
-
- // Create a column for each content
- var tableCol;
- for (var i in rowCont) {
- tableCol = $(' ');
- tableCol.append(rowCont[i]);
- tableRow.append(tableCol);
- }
-
- // Append table row to table
- this.dataTable.find('tbody').append(tableRow);
-};
-
-/**
- * Create status bar
- *
- * @param barId Status bar ID
- */
-function createStatusBar(barId) {
- // Do not change the background color or color! This is handled by the theme
- // the user selects.
- var statusBar = $('
').css({
- 'margin-bottom': '5px',
- 'min-height': '30px',
- 'max-height': '150px',
- 'overflow': 'auto'
- });
-
- // Create info icon
- var icon = $(' ').css({
- 'display': 'inline-block',
- 'margin': '10px 5px',
- 'vertical-align': 'top'
- });
-
- // Create message section
- var msg = $('
').css({
- 'display': 'inline-block',
- 'margin': '10px 0px',
- 'width': '90%'
- });
-
- // Create hide button
- var hide = $(' ').css({
- 'display': 'inline-block',
- 'float': 'right',
- 'cursor': 'pointer'
- }).click(function() {
- // Remove info box on-click
- $(this).parent().hide();
- });
-
- statusBar.append(icon);
- statusBar.append(msg);
- statusBar.append(hide);
- return statusBar;
-}
-
-/**
- * Create info bar
- *
- * @param msg Info message
- * @return Info bar
- */
-function createInfoBar(msg) {
- // Do not change the background color or color! This is handled by the theme
- // the user selects.
- var infoBar = $('
').css({
- 'margin': '5px 0px'
- });
- var icon = $(' ').css({
- 'display': 'inline-block',
- 'margin': '10px 5px'
- });
- var barMsg = $('' + msg + '
').css({
- 'display': 'inline-block',
- 'width': '90%'
- });
-
- infoBar.append(icon);
- infoBar.append(barMsg);
- return infoBar;
-}
-
-/**
- * Create warning bar
- *
- * @param msg Warning message
- * @return Warning bar
- */
-function createWarnBar(msg) {
- var warnBar = $('
');
- var icon = $(' ').css({
- 'display': 'inline-block',
- 'margin': '10px 5px'
- });
- var barMsg = $('' + msg + '
').css({
- 'display': 'inline-block',
- 'width': '90%'
- });
-
- warnBar.append(icon);
- warnBar.append(barMsg);
- return warnBar;
-}
-
-/**
- * Create a loader
- *
- * @param loaderId Loader ID
- */
-function createLoader(loaderId) {
- var loader = $(' ');
- return loader;
-}
-
-/**
- * Create a button
- *
- * @param name Name of the button
- */
-function createButton(name) {
- var button = $('' + name + ' ').button();
- return button;
-}
-
-/**
- * Create a menu
- *
- * @param items An array of items to go into the menu
- * @return A division containing the menu
- */
-function createMenu(items) {
- var menu = $('');
-
- // Loop through each item
- for ( var i in items) {
- // Append item to menu
- var item = $(' ');
-
- // If it is a sub menu
- if (items[i] instanceof Array) {
- // 1st index = Sub menu title
- item.append(items[i][0]);
- // 2nd index = Sub menu
- item.append(items[i][1]);
- } else {
- item.append(items[i]);
- }
-
- menu.append(item);
- }
-
- return menu;
-}
-
-/**
- * Initialize the page
- */
-function initPage() {
- // Load theme
- var theme = $.cookie('xcat_theme');
- if (theme) {
- switch (theme) {
- case 'cupertino':
- includeCss("css/themes/jquery-ui-cupertino.css");
- break;
- case 'dark_hive':
- includeCss("css/themes/jquery-ui-dark_hive.css");
- break;
- case 'redmond':
- includeCss("css/themes/jquery-ui-redmond.css");
- break;
- case 'start':
- includeCss("css/themes/jquery-ui-start.css");
- break;
- case 'sunny':
- includeCss("css/themes/jquery-ui-sunny.css");
- break;
- case 'ui_dark':
- includeCss("css/themes/jquery-ui-ui_darkness.css");
- break;
- default:
- includeCss("css/themes/jquery-ui-start.css");
- }
- } else {
- includeCss("css/themes/jquery-ui-start.css");
- }
-
- // Load jQuery stylesheets
- includeCss("css/jquery.dataTables.css");
- includeCss("css/superfish.css");
- // includeCss("css/jstree.css");
- includeCss("css/jquery.jqplot.css");
-
- // Load custom stylesheet
- includeCss("css/style.css");
-
- // JQuery plugins
- includeJs("js/jquery/jquery.dataTables.min.js");
- includeJs("js/jquery/jquery.form.min.js");
- includeJs("js/jquery/jquery.jeditable.min.js");
- includeJs("js/jquery/jquery.contextmenu.min.js");
- includeJs("js/jquery/superfish.min.js");
- includeJs("js/jquery/hoverIntent.min.js");
- // includeJs("js/jquery/jquery.jstree.min.js");
- includeJs("js/jquery/tooltip.min.js");
- includeJs("js/jquery/jquery.serverBrowser.min.js");
- includeJs("js/jquery/jquery.jqplot.min.js");
- includeJs("js/jquery/jqplot.pieRenderer.min.js");
- includeJs("js/jquery/jqplot.barRenderer.min.js");
- includeJs("js/jquery/jqplot.pointLabels.min.js");
- includeJs("js/jquery/jqplot.categoryAxisRenderer.min.js");
- includeJs("js/jquery/jqplot.dateAxisRenderer.min.js");
- includeJs("js/jquery/jquery.topzindex.min.js");
-
- // Page plugins
- includeJs("js/configure/configure.js");
- includeJs("js/monitor/monitor.js");
- includeJs("js/nodes/nodes.js");
- includeJs("js/provision/provision.js");
-
- // Custom plugins
- includeJs("js/custom/esx.js");
- includeJs("js/custom/kvm.js");
- includeJs("js/custom/blade.js");
- includeJs("js/custom/ipmi.js");
- includeJs("js/custom/zvm.js");
- includeJs("js/custom/hmc.js");
- includeJs("js/custom/customUtils.js");
-
- // Enable settings link
- $('#xcat_settings').click(function() {
- openSettings();
- });
-
- // Set header to theme
- var background = '', color = '';
- var theme = $.cookie('xcat_theme');
- if (theme) {
- switch (theme) {
- case 'cupertino':
- background = '#3BAAE3';
- color = 'white';
- break;
- case 'dark_hive':
- background = '#0972A5';
- break;
- case 'redmond':
- background = '#F5F8F9';
- color = '#E17009';
- break;
- case 'start':
- background = '#6EAC2C';
- break;
- case 'sunny':
- background = 'white';
- color = '#0074C7';
- break;
- case 'ui_dark':
- background = '#F58400';
- break;
- default:
- background = '#6EAC2C';
- }
- } else {
- background = '#6EAC2C';
- }
-
- $('#header').addClass('ui-state-default');
- $('#header').css('border', '0px');
-
- // Set theme to user span
- $('#login_user').css('color', color);
-
- // Style for selected page
- var style = {
- 'background-color': background,
- 'color': color
- };
-
- // Get the page being loaded
- var url = window.location.pathname;
- var page = url.replace('/xcat/', '');
- var headers = $('#header ul li a');
-
- // Show the page
- $("#content").children().remove();
- if (page == 'configure.php') {
- includeJs("js/configure/update.js");
- includeJs("js/configure/service.js");
- includeJs("js/configure/users.js");
- includeJs("js/configure/files.js");
- headers.eq(1).css(style);
- loadConfigPage();
- } else if (page == 'provision.php') {
- includeJs("js/provision/images.js");
- headers.eq(2).css(style);
- loadProvisionPage();
- } else if (page == 'help.php') {
- includeJs("js/help/help.js");
- headers.eq(4).css(style);
- loadHelpPage();
- } else {
- // Load nodes page by default
- includeJs("js/nodes/nodeset.js");
- includeJs("js/nodes/rnetboot.js");
- includeJs("js/nodes/updatenode.js");
- includeJs("js/nodes/rscan.js");
- headers.eq(0).css(style);
- loadNodesPage();
- }
-}
-
-/**
- * Include javascript file in
- *
- * @param file File to include
- */
-function includeJs(file) {
- var script = $("head script[src='" + file + "']");
-
- // If does not contain the javascript
- if (!script.length) {
- // Append the javascript to
- var script = $('');
- script.attr( {
- type : 'text/javascript',
- src : file
- });
-
- $('head').append(script);
- }
-}
-
-/**
- * Include CSS link in
- *
- * @param file File to include
- */
-function includeCss(file) {
- var link = $("head link[href='" + file + "']");
-
- // If does not contain the link
- if (!link.length) {
- // Append the CSS link to
- var link = $(' ');
- link.attr( {
- type : 'text/css',
- rel : 'stylesheet',
- href : file
- });
-
- $('head').append(link);
- }
-}
-
-/**
- * Write ajax response to a paragraph
- *
- * @param rsp Ajax response
- * @param pattern Pattern to replace with a break
- * @return Paragraph containing ajax response
- */
-function writeRsp(rsp, pattern) {
- // Create paragraph to hold ajax response
- var prg = $(' ');
-
- for ( var i in rsp) {
- if (rsp[i]) {
- // Create regular expression for given pattern
- // Replace pattern with break
- if (pattern) {
- rsp[i] = rsp[i].replace(new RegExp(pattern, 'g'), ' ');
- prg.append(rsp[i]);
- } else {
- prg.append(rsp[i]);
- prg.append(' ');
- }
- }
- }
-
- return prg;
-}
-
-/**
- * Open a dialog and show given message
- *
- * @param type Type of dialog, i.e. warn or info
- * @param msg Message to show
- */
-function openDialog(type, msg) {
- var msgDialog = $('
');
- var title = "";
- if (type == "warn") {
- // Create warning message
- msgDialog.append(createWarnBar(msg));
- title = "Warning";
- } else {
- // Create info message
- msgDialog.append(createInfoBar(msg));
- title = "Info";
- }
-
- // Open dialog
- msgDialog.dialog({
- title: title,
- modal: true,
- close: function(){
- $(this).remove();
- },
- width: 500,
- buttons: {
- "Ok": function(){
- $(this).dialog("close");
- }
- }
- });
-}
-
-/**
- * Create an iframe to hold the output of an xCAT command
- *
- * @param src The URL of the document to show in the iframe
- * @return Info box containing the iframe
- */
-function createIFrame(src) {
- // Put an iframe inside an info box
- var infoBar = $('
').css({
- 'margin-bottom': '5px'
- });
-
- // Create info and close icons
- var icon = $(' ').css({
- 'display': 'inline-block',
- 'margin': '10px 5px'
- });
- var close = $(' ').css({
- 'display': 'inline-block',
- 'float': 'right',
- 'margin': '10px 5px'
- }).click(function() {
- // Remove info box on-click
- $(this).parent().remove();
- });
-
- var iframe = $('').attr('src', src).css({
- 'display': 'block',
- 'border': '0px',
- 'margin': '10px',
- 'width': '100%'
- });
-
- var loader = createLoader('iLoader').css({
- 'display': 'block',
- 'margin': '10px 0px'
- });
-
- infoBar.append(icon);
- infoBar.append($('
').append(loader, iframe));
- infoBar.append(close);
-
- // Remove loader when done
- iframe.load(function() {
- loader.remove();
- });
-
- return infoBar;
-}
-
-
-/**
- * Open dialog to set xCAT UI settings
- */
-function openSettings() {
- // Create form to add node range
- var dialog = $('
');
- var info = createInfoBar('Select from the following options');
- dialog.append(info);
-
- var style = {
- 'color': 'blue',
- 'cursor': 'pointer',
- 'padding': '5px'
- };
-
- var changeThemeOption = $('').css(style);
- dialog.append(changeThemeOption);
-
- var changePasswordOption = $('').css(style);
- dialog.append(changePasswordOption);
-
- // Open form as a dialog
- dialog.dialog({
- modal: true,
- close: function(){
- $(this).remove();
- },
- title: 'Settings',
- width: 400,
- buttons: {
- "Cancel": function(){
- $(this).dialog("close");
- }
- }
- });
-
- // Bind to click event
- changeThemeOption.click(function() {
- dialog.dialog("close");
- changeTheme();
- });
-
- changePasswordOption.click(function() {
- dialog.dialog("close");
- changePassword();
- });
-}
-
-/**
- * Open dialog to change xCAT theme
- */
-function changeTheme() {
- // Create form to add node range
- var dialog = $('
');
- var info = createInfoBar('Select the xCAT theme you desire');
- dialog.append(info);
-
- // Create select drop down for themes
- var oList = $(' ');
- oList.append($(' Cupertino '));
- oList.append($(' Dark Hive '));
- oList.append($(' Redmond '));
- oList.append($(' Start (default) '));
- oList.append($(' Sunny '));
- oList.append($(' UI Darkness '));
- dialog.append(oList);
-
- if ($.cookie('xcat_theme')) {
- // Select theme
- oList.find('input[value="' + $.cookie('xcat_theme') + '"]').attr('checked', true);
- } else {
- oList.find('input[value="start"]').attr('checked', true);
- }
-
- // Open form as a dialog
- dialog.dialog({
- modal: true,
- close: function(){
- $(this).remove();
- },
- title: 'xCAT Theme',
- width: 400,
- buttons: {
- "Ok": function(){
- // Save selected theme
- var theme = $(this).find('input[name="theme"]:checked').val();
- $.cookie('xcat_theme', theme); // Do not expire cookie, keep it as long as possible
-
- // Show instructions to apply theme
- $(this).empty();
- var info = createInfoBar('You will need to reload this page in order for changes to take effect');
- $(this).append(info);
-
- // Only show close button
- $(this).dialog("option", "buttons", {
- "Close" : function() {
- $(this).dialog( "close" );
- }
- });
- },
- "Cancel": function(){
- $(this).dialog( "close" );
- }
- }
- });
-}
-
-/**
- * Open dialog to change user password
- */
-function changePassword() {
- // Create form to add node range
- var dialog = $('
');
- var info = createInfoBar('Change your password');
- dialog.append(info);
-
- dialog.append('New password:
');
- dialog.append('Confirm password:
');
-
- // Open form as a dialog
- dialog.dialog({
- modal: true,
- close: function(){
- $(this).remove();
- },
- title: 'Change Password',
- width: 400,
- buttons: {
- "Ok": function(){
- // Remove any warning messages
- $(this).find('.ui-state-error').remove();
-
- var errorMessage = "";
-
- // Check each input is provided
- $('#changePassword input').each(function() {
- if (!$(this).val()) {
- errorMessage = "Please provide a value for each missing input!";
- }
- });
-
- // Do not continue if error found
- if (errorMessage) {
- dialog.prepend(createWarnBar(errorMessage));
- return;
- }
-
- // Check new and confirm passwords match
- var user = $.cookie('xcat_username');
- var newPassword = $('#changePassword input[name="newPassword"]').val();
- var confirmPassword = $('#changePassword input[name="confirmPassword"]').val();
- if (newPassword != confirmPassword) {
- dialog.prepend(createWarnBar("Please confirm new password!"));
- return;
- }
-
- // Change dialog buttons
- $('#changePassword').dialog('option', 'buttons', {
- 'Close':function(){
- $('#changePassword').dialog('destroy').remove();
- }
- });
-
- // Send request to change password
- var url = window.location.pathname;
- var page = url.replace('/xcat/', '');
- var url = 'lib/cmd.php';
- // Service portal does not have access to cmd.php
- if (page == 'service.php')
- url = 'lib/srv_cmd.php';
- $.ajax( {
- url : url,
- dataType : 'json',
- data : {
- cmd : 'webrun',
- tgt : '',
- args : 'passwd;' + user + ';' + newPassword,
- msg : ''
- },
-
- success : function (data) {
- // Show response message
- var rspMessage = "";
- for (var i in data.rsp)
- rspMessage += data.rsp[i] + " ";
-
- $('#changePassword').prepend(createInfoBar(rspMessage));
- }
- });
- },
- "Cancel": function(){
- $(this).dialog( "close" );
- }
- }
- });
-}
-
-/**
- * Adjust datatable column size
- *
- * @param tableId Table ID
- */
-function adjustColumnSize(tableId) {
- var dTable = $('#' + tableId).dataTable();
- dTable.fnAdjustColumnSizing();
-}
-
-/**
- * Set menu theme
- *
- * @param menu Menu object
- */
-function setMenu2Theme(menu) {
- // On hover
- var background = '', color = '';
- var theme = $.cookie('xcat_theme');
- if (theme) {
- switch (theme) {
- case 'cupertino':
- background = '#3BAAE3';
- color = 'white';
- break;
- case 'dark_hive':
- background = '#0972A5';
- break;
- case 'redmond':
- background = '#F5F8F9';
- color = '#E17009';
- break;
- case 'start':
- background = '#6EAC2C';
- break;
- case 'sunny':
- background = 'white';
- color = '#0074C7';
- break;
- case 'ui_dark':
- background = '#F58400';
- break;
- default:
- background = '#6EAC2C';
- }
- } else {
- background = '#6EAC2C';
- }
-
- menu.css('background', background);
- menu.find('a:eq(0)').css('color', color);
-}
-
-/**
- * Set menu back to normal before applying theme
- *
- * @param menu Menu object
- */
-function setMenu2Normal(menu) {
- // Change back to normal
- menu.css('background', '');
- menu.find('a:eq(0)').css('color', '');
-}
-
-/**
- * Get nodes that are checked in a given datatable
- *
- * @param datatableId The datatable ID
- * @return Nodes that were checked
- */
-function getNodesChecked(datatableId) {
- var tgts = '';
-
- // Get nodes that were checked
- var nodes = $('#' + datatableId + ' input[type=checkbox]:checked');
- for (var i in nodes) {
- var tgtNode = nodes.eq(i).attr('name');
-
- if (tgtNode) {
- tgts += tgtNode;
-
- // Add a comma at the end
- if (i < nodes.length - 1) {
- tgts += ',';
- }
- }
- }
-
- return tgts;
-}
-
-/**
- * Check if return message contains errors
- *
- * @param msg Return message
- * @return 0 If return message contains no errors
- * -1 If return message contains errors
- */
-function containErrors(msg) {
- if (msg.indexOf('Failed') > -1 || msg.indexOf('Error') > -1) {
- return -1;
- } else {
- return 0;
- }
-}
-
-/**
- * Check if a value is an integer
- *
- * @param value Value to be checked
- * @returns true If value is an integer
- false If value is not an integer
- */
-function isInteger(value){
- if ((parseFloat(value) == parseInt(value)) && !isNaN(value)) {
- return true;
- } else {
- return false;
- }
-}
+/**
+ * Tab constructor
+ *
+ * @param tabId
+ * Tab ID
+ * @param tabName
+ * Tab name
+ * @return Nothing
+ */
+var Tab = function(tabId) {
+ this.tabId = tabId;
+ this.tabName = null;
+ this.tab = null;
+};
+
+/**
+ * Initialize the tab
+ *
+ * @param tabName Tab name to initialize
+ */
+Tab.prototype.init = function() {
+ // Create a division containing the tab
+ this.tab = $('
');
+ var tabList = $('');
+ var tabItem = $('Dummy tab item ');
+ tabList.append(tabItem);
+ this.tab.append(tabList);
+
+ // Create a template with close button
+ var tabs = this.tab.tabs();
+
+ tabs.bind('tabsselect', function(event, ui){
+ // Save the order tabs were selected
+ var order;
+ if ($.cookie('xcat_tabindex_history')) {
+ order = $.cookie('xcat_tabindex_history').split(',');
+ order[1] = order[0]; // Set index 1 to last selected tab
+ order[0] = ui.index; // Set index 0 to currently selected tab
+ } else {
+ // Create an array to track the tab selected
+ order = new Array;
+ order[0] = ui.index;
+ order[1] = ui.index;
+ }
+
+ $.cookie('xcat_tabindex_history', order, { path: '/xcat', secure:true });
+ });
+
+ // Remove dummy tab
+ this.tab.tabs("remove", 0);
+
+ // Hide tab
+ this.tab.hide();
+};
+
+/**
+ * Return the tab object
+ *
+ * @return Object representing the tab
+ */
+Tab.prototype.object = function() {
+ return this.tab;
+};
+
+/**
+ * Add a new tab
+ *
+ * @param tabId Tab ID
+ * @param tabName Tab name
+ * @param tabCont Tab content
+ * @param closeable Is tab closeable
+ */
+Tab.prototype.add = function(tabId, tabName, tabCont, closeable) {
+ // Show tab
+ if (this.tab.css("display") == "none") {
+ this.tab.show();
+ }
+
+ var newTab = $('
');
+ newTab.append(tabCont);
+ this.tab.append(newTab);
+ this.tab.tabs("add", "#" + tabId, tabName);
+
+ // Append close button
+ if (closeable) {
+ var header = this.tab.find('ul.ui-tabs-nav a[href="#' + tabId +'"]').parent();
+ header.append(' ');
+
+ // Get this tab
+ var tabs = this.tab;
+ var tabLink = 'a[href="\#' + tabId + '"]';
+ var thisTab = $(tabLink, tabs).parent();
+
+ // Close tab when close button is clicked
+ thisTab.find('span.tab-close').bind('click', function(event) {
+ var tabIndex = ($('li', tabs).index(thisTab));
+
+ // Do not remove first tab
+ if (tabIndex != 0) {
+ // Go back to last tab if user is trying to close currently selected tab
+ if (tabs.tabs('option', 'selected') == tabIndex) {
+ // Get last selected tab from history
+ var order = $.cookie('xcat_tabindex_history').split(',');
+ if (order[1]) {
+ tabs.tabs('select', parseInt(order[1]));
+ } else {
+ tabs.tabs('select', 0);
+ }
+ }
+
+ tabs.tabs('remove', tabIndex);
+ }
+ });
+ }
+};
+
+/**
+ * Select a tab
+ *
+ * @param id Tab ID to select
+ */
+Tab.prototype.select = function(id) {
+ this.tab.tabs("select", "#" + id);
+};
+
+/**
+ * Remove a tab
+ *
+ * @param id Tab ID to remove
+ */
+Tab.prototype.remove = function(id) {
+ var selectorStr = 'a[href="\#' + id + '"]';
+ var selectTab = $(selectorStr, this.tab).parent();
+ var index = ($('li', this.tab).index(selectTab));
+ this.tab.tabs("remove", index);
+};
+
+/**
+ * Table constructor
+ *
+ * @param tabId Tab ID
+ * @param tabName Tab name
+ */
+var Table = function(tableId) {
+ if ($('#' + tableId).length) {
+ this.tableId = tableId;
+ this.table = $('#' + tableId);
+ } else {
+ this.tableId = tableId;
+ this.table = null;
+ }
+};
+
+/**
+ * Initialize the table
+ *
+ * @param Headers Array of table headers
+ */
+Table.prototype.init = function(headers) {
+ // Create a table
+ this.table = $('');
+ var thead = $('');
+ var headRow = $(' ');
+
+ // Append headers
+ for ( var i in headers) {
+ headRow.append('' + headers[i] + ' ');
+ }
+
+ thead.append(headRow);
+ this.table.append(thead);
+
+ // Append table body
+ var tableBody = $(' ');
+ this.table.append(tableBody);
+};
+
+/**
+ * Return the table object
+ *
+ * @return Object representing the table
+ */
+Table.prototype.object = function() {
+ return this.table;
+};
+
+/**
+ * Add a row to the table
+ *
+ * @param rowCont Array of table row contents
+ */
+Table.prototype.add = function(rowCont) {
+ // Create table row
+ var tableRow = $(' ');
+
+ // Create a column for each content
+ var tableCol;
+ for ( var i in rowCont) {
+ tableCol = $(' ');
+ tableCol.append(rowCont[i]);
+ tableRow.append(tableCol);
+ }
+
+ // Append table row to table
+ this.table.find('tbody').append(tableRow);
+};
+
+/**
+ * Add a footer to the table
+ *
+ * @param rowCont Array of table row contents
+ */
+Table.prototype.addFooter = function(rowCont) {
+ // Create table row
+ var tableFoot = $(' ');
+ tableFoot.append(rowCont);
+
+ // Append table row to table
+ this.table.append(tableFoot);
+};
+
+/**
+ * Remove a row from the table
+ */
+Table.prototype.remove = function(id) {
+ // To be continued
+};
+
+/**
+ * Datatable class constructor
+ *
+ * @param tabId Tab ID
+ * @param tabName Tab name
+ */
+var DataTable = function(tableId) {
+ this.dataTableId = tableId;
+ this.dataTable = null;
+};
+
+/**
+ * Initialize the datatable
+ *
+ * @param Headers Array of table headers
+ */
+DataTable.prototype.init = function(headers) {
+ // Create a table
+ this.dataTable = $('');
+ var thead = $('');
+ var headRow = $(' ');
+
+ // Append headers
+ for ( var i in headers) {
+ headRow.append('' + headers[i] + ' ');
+ }
+
+ thead.append(headRow);
+ this.dataTable.append(thead);
+
+ // Append table body
+ var tableBody = $(' ');
+ this.dataTable.append(tableBody);
+};
+
+/**
+ * Return the datatable object
+ *
+ * @return Object representing the table
+ */
+DataTable.prototype.object = function() {
+ return this.dataTable;
+};
+
+/**
+ * Add a row to the datatable
+ *
+ * @param rowCont Array of table row contents
+ */
+DataTable.prototype.add = function(rowCont) {
+ // Create table row
+ var tableRow = $(' ');
+
+ // Create a column for each content
+ var tableCol;
+ for ( var i in rowCont) {
+ tableCol = $(' ');
+ tableCol.append(rowCont[i]);
+ tableRow.append(tableCol);
+ }
+
+ // Append table row to table
+ this.dataTable.find('tbody').append(tableRow);
+};
+
+/**
+ * Create status bar
+ *
+ * @param barId Status bar ID
+ */
+function createStatusBar(barId) {
+ // Do not change the background color or color! This is handled by the theme
+ // the user selects.
+ var statusBar = $('
').css({
+ 'margin-bottom': '5px',
+ 'min-height': '30px',
+ 'max-height': '150px',
+ 'overflow': 'auto'
+ });
+
+ // Create info icon
+ var icon = $(' ').css({
+ 'display': 'inline-block',
+ 'margin': '10px 5px',
+ 'vertical-align': 'top'
+ });
+
+ // Create message section
+ var msg = $('
').css({
+ 'display': 'inline-block',
+ 'margin': '10px 0px',
+ 'width': '90%'
+ });
+
+ // Create hide button
+ var hide = $(' ').css({
+ 'display': 'inline-block',
+ 'float': 'right',
+ 'cursor': 'pointer'
+ }).click(function() {
+ // Remove info box on-click
+ $(this).parent().hide();
+ });
+
+ statusBar.append(icon);
+ statusBar.append(msg);
+ statusBar.append(hide);
+ return statusBar;
+}
+
+/**
+ * Create info bar
+ *
+ * @param msg Info message
+ * @return Info bar
+ */
+function createInfoBar(msg) {
+ // Do not change the background color or color! This is handled by the theme
+ // the user selects.
+ var infoBar = $('
').css({
+ 'margin': '5px 0px'
+ });
+ var icon = $(' ').css({
+ 'display': 'inline-block',
+ 'margin': '10px 5px'
+ });
+ var barMsg = $('' + msg + '
').css({
+ 'display': 'inline-block',
+ 'width': '90%'
+ });
+
+ infoBar.append(icon);
+ infoBar.append(barMsg);
+ return infoBar;
+}
+
+/**
+ * Create warning bar
+ *
+ * @param msg Warning message
+ * @return Warning bar
+ */
+function createWarnBar(msg) {
+ var warnBar = $('
');
+ var icon = $(' ').css({
+ 'display': 'inline-block',
+ 'margin': '10px 5px'
+ });
+ var barMsg = $('' + msg + '
').css({
+ 'display': 'inline-block',
+ 'width': '90%'
+ });
+
+ warnBar.append(icon);
+ warnBar.append(barMsg);
+ return warnBar;
+}
+
+/**
+ * Create a loader
+ *
+ * @param loaderId Loader ID
+ */
+function createLoader(loaderId) {
+ var loader = $(' ');
+ return loader;
+}
+
+/**
+ * Create a button
+ *
+ * @param name Name of the button
+ */
+function createButton(name) {
+ var button = $('' + name + ' ').button();
+ return button;
+}
+
+/**
+ * Create a menu
+ *
+ * @param items An array of items to go into the menu
+ * @return A division containing the menu
+ */
+function createMenu(items) {
+ var menu = $('');
+
+ // Loop through each item
+ for ( var i in items) {
+ // Append item to menu
+ var item = $(' ');
+
+ // If it is a sub menu
+ if (items[i] instanceof Array) {
+ // 1st index = Sub menu title
+ item.append(items[i][0]);
+ // 2nd index = Sub menu
+ item.append(items[i][1]);
+ } else {
+ item.append(items[i]);
+ }
+
+ menu.append(item);
+ }
+
+ return menu;
+}
+
+/**
+ * Initialize the page
+ */
+function initPage() {
+ // Load theme
+ var theme = $.cookie('xcat_theme');
+ if (theme) {
+ switch (theme) {
+ case 'cupertino':
+ includeCss("css/themes/jquery-ui-cupertino.css");
+ break;
+ case 'dark_hive':
+ includeCss("css/themes/jquery-ui-dark_hive.css");
+ break;
+ case 'redmond':
+ includeCss("css/themes/jquery-ui-redmond.css");
+ break;
+ case 'start':
+ includeCss("css/themes/jquery-ui-start.css");
+ break;
+ case 'sunny':
+ includeCss("css/themes/jquery-ui-sunny.css");
+ break;
+ case 'ui_dark':
+ includeCss("css/themes/jquery-ui-ui_darkness.css");
+ break;
+ default:
+ includeCss("css/themes/jquery-ui-start.css");
+ }
+ } else {
+ includeCss("css/themes/jquery-ui-start.css");
+ }
+
+ // Load jQuery stylesheets
+ includeCss("css/jquery.dataTables.css");
+ includeCss("css/superfish.css");
+ includeCss("css/jstree.css");
+ includeCss("css/jquery.jqplot.css");
+
+ // Load custom stylesheet
+ includeCss("css/style.css");
+
+ // JQuery plugins
+ includeJs("js/jquery/jquery.dataTables.min.js");
+ includeJs("js/jquery/jquery.form.min.js");
+ includeJs("js/jquery/jquery.jeditable.min.js");
+ includeJs("js/jquery/jquery.contextmenu.min.js");
+ includeJs("js/jquery/superfish.min.js");
+ includeJs("js/jquery/hoverIntent.min.js");
+ includeJs("js/jquery/jquery.jstree.min.js");
+ includeJs("js/jquery/tooltip.min.js");
+ includeJs("js/jquery/jquery.serverBrowser.min.js");
+ includeJs("js/jquery/jquery.jqplot.min.js");
+ includeJs("js/jquery/jqplot.pieRenderer.min.js");
+ includeJs("js/jquery/jqplot.dateAxisRenderer.min.js");
+ includeJs("js/jquery/jquery.topzindex.min.js");
+
+ // Page plugins
+ includeJs("js/configure/configure.js");
+ includeJs("js/monitor/monitor.js");
+ includeJs("js/nodes/nodes.js");
+ includeJs("js/provision/provision.js");
+
+ // Custom plugins
+ includeJs("js/custom/zvm.js");
+ includeJs("js/custom/customUtils.js");
+
+ // Enable settings link
+ $('#xcat_settings').click(function() {
+ openSettings();
+ });
+
+ // Set header to theme
+ var background = '', color = '';
+ var theme = $.cookie('xcat_theme');
+ if (theme) {
+ switch (theme) {
+ case 'cupertino':
+ background = '#3BAAE3';
+ color = 'white';
+ break;
+ case 'dark_hive':
+ background = '#0972A5';
+ break;
+ case 'redmond':
+ background = '#F5F8F9';
+ color = '#E17009';
+ break;
+ case 'start':
+ background = '#6EAC2C';
+ break;
+ case 'sunny':
+ background = 'white';
+ color = '#0074C7';
+ break;
+ case 'ui_dark':
+ background = '#F58400';
+ break;
+ default:
+ background = '#6EAC2C';
+ }
+ } else {
+ background = '#6EAC2C';
+ }
+
+ $('#header').addClass('ui-state-default');
+ $('#header').css('border', '0px');
+
+ // Set theme to user span
+ $('#login_user').css('color', color);
+
+ // Style for selected page
+ var style = {
+ 'background-color': background,
+ 'color': color
+ };
+
+ // Get the page being loaded
+ var url = window.location.pathname;
+ var page = url.replace('/xcat/', '');
+ var headers = $('#header ul li a');
+
+ // Show the page
+ $("#content").children().remove();
+ if (page == 'configure.php') {
+ includeJs("js/configure/update.js");
+ includeJs("js/configure/service.js");
+ includeJs("js/configure/users.js");
+ includeJs("js/configure/files.js");
+ headers.eq(1).css(style);
+ loadConfigPage();
+ } else if (page == 'provision.php') {
+ includeJs("js/provision/images.js");
+ headers.eq(2).css(style);
+ loadProvisionPage();
+ } else if (page == 'help.php') {
+ includeJs("js/help/help.js");
+ headers.eq(4).css(style);
+ loadHelpPage();
+ } else {
+ // Load nodes page by default
+ includeJs("js/nodes/nodeset.js");
+ includeJs("js/nodes/rnetboot.js");
+ includeJs("js/nodes/updatenode.js");
+ includeJs("js/nodes/rscan.js");
+ headers.eq(0).css(style);
+ loadNodesPage();
+ }
+}
+
+/**
+ * Include javascript file in
+ *
+ * @param file File to include
+ */
+function includeJs(file) {
+ var script = $("head script[src='" + file + "']");
+
+ // If does not contain the javascript
+ if (!script.length) {
+ // Append the javascript to
+ var script = $('');
+ script.attr( {
+ type : 'text/javascript',
+ src : file
+ });
+
+ $('head').append(script);
+ }
+}
+
+/**
+ * Include CSS link in
+ *
+ * @param file File to include
+ */
+function includeCss(file) {
+ var link = $("head link[href='" + file + "']");
+
+ // If does not contain the link
+ if (!link.length) {
+ // Append the CSS link to
+ var link = $(' ');
+ link.attr( {
+ type : 'text/css',
+ rel : 'stylesheet',
+ href : file
+ });
+
+ $('head').append(link);
+ }
+}
+
+/**
+ * Write ajax response to a paragraph
+ *
+ * @param rsp Ajax response
+ * @param pattern Pattern to replace with a break
+ * @return Paragraph containing ajax response
+ */
+function writeRsp(rsp, pattern) {
+ // Create paragraph to hold ajax response
+ var prg = $(' ');
+
+ for ( var i in rsp) {
+ if (rsp[i]) {
+ // Create regular expression for given pattern
+ // Replace pattern with break
+ if (pattern) {
+ rsp[i] = rsp[i].replace(new RegExp(pattern, 'g'), ' ');
+ prg.append(rsp[i]);
+ } else {
+ prg.append(rsp[i]);
+ prg.append(' ');
+ }
+ }
+ }
+
+ return prg;
+}
+
+/**
+ * Open a dialog and show given message
+ *
+ * @param type Type of dialog, i.e. warn or info
+ * @param msg Message to show
+ */
+function openDialog(type, msg) {
+ var msgDialog = $('
');
+ var title = "";
+ if (type == "warn") {
+ // Create warning message
+ msgDialog.append(createWarnBar(msg));
+ title = "Warning";
+ } else {
+ // Create info message
+ msgDialog.append(createInfoBar(msg));
+ title = "Info";
+ }
+
+ // Open dialog
+ msgDialog.dialog({
+ title: title,
+ modal: true,
+ close: function(){
+ $(this).remove();
+ },
+ width: 500,
+ buttons: {
+ "Ok": function(){
+ $(this).dialog("close");
+ }
+ }
+ });
+}
+
+/**
+ * Create an iframe to hold the output of an xCAT command
+ *
+ * @param src The URL of the document to show in the iframe
+ * @return Info box containing the iframe
+ */
+function createIFrame(src) {
+ // Put an iframe inside an info box
+ var infoBar = $('
').css({
+ 'margin-bottom': '5px'
+ });
+
+ // Create info and close icons
+ var icon = $(' ').css({
+ 'display': 'inline-block',
+ 'margin': '10px 5px'
+ });
+ var close = $(' ').css({
+ 'display': 'inline-block',
+ 'float': 'right',
+ 'margin': '10px 5px'
+ }).click(function() {
+ // Remove info box on-click
+ $(this).parent().remove();
+ });
+
+ var iframe = $('').attr('src', src).css({
+ 'display': 'block',
+ 'border': '0px',
+ 'margin': '10px',
+ 'width': '100%'
+ });
+
+ var loader = createLoader('iLoader').css({
+ 'display': 'block',
+ 'margin': '10px 0px'
+ });
+
+ infoBar.append(icon);
+ infoBar.append($('
').append(loader, iframe));
+ infoBar.append(close);
+
+ // Remove loader when done
+ iframe.load(function() {
+ loader.remove();
+ });
+
+ return infoBar;
+}
+
+
+/**
+ * Open dialog to set xCAT UI settings
+ */
+function openSettings() {
+ // Create form to add node range
+ var dialog = $('
');
+ var info = createInfoBar('Select from the following options');
+ dialog.append(info);
+
+ var style = {
+ 'color': 'blue',
+ 'cursor': 'pointer',
+ 'padding': '5px'
+ };
+
+ var changeThemeOption = $('').css(style);
+ dialog.append(changeThemeOption);
+
+ var changePasswordOption = $('').css(style);
+ dialog.append(changePasswordOption);
+
+ // Open form as a dialog
+ dialog.dialog({
+ modal: true,
+ close: function(){
+ $(this).remove();
+ },
+ title: 'Settings',
+ width: 400,
+ buttons: {
+ "Cancel": function(){
+ $(this).dialog("close");
+ }
+ }
+ });
+
+ // Bind to click event
+ changeThemeOption.click(function() {
+ dialog.dialog("close");
+ changeTheme();
+ });
+
+ changePasswordOption.click(function() {
+ dialog.dialog("close");
+ changePassword();
+ });
+}
+
+/**
+ * Open dialog to change xCAT theme
+ */
+function changeTheme() {
+ // Create form to add node range
+ var dialog = $('
');
+ var info = createInfoBar('Select the xCAT theme you desire');
+ dialog.append(info);
+
+ // Create select drop down for themes
+ var oList = $(' ');
+ oList.append($(' Cupertino '));
+ oList.append($(' Dark Hive '));
+ oList.append($(' Redmond '));
+ oList.append($(' Start (default) '));
+ oList.append($(' Sunny '));
+ oList.append($(' UI Darkness '));
+ dialog.append(oList);
+
+ if ($.cookie('xcat_theme')) {
+ // Select theme
+ oList.find('input[value="' + $.cookie('xcat_theme') + '"]').attr('checked', true);
+ } else {
+ oList.find('input[value="start"]').attr('checked', true);
+ }
+
+ // Open form as a dialog
+ dialog.dialog({
+ modal: true,
+ close: function(){
+ $(this).remove();
+ },
+ title: 'xCAT Theme',
+ width: 400,
+ buttons: {
+ "Ok": function(){
+ // Save selected theme
+ var theme = $(this).find('input[name="theme"]:checked').val();
+ $.cookie('xcat_theme', theme); // Do not expire cookie, keep it as long as possible
+
+ // Show instructions to apply theme
+ $(this).empty();
+ var info = createInfoBar('You will need to reload this page in order for changes to take effect');
+ $(this).append(info);
+
+ // Only show close button
+ $(this).dialog("option", "buttons", {
+ "Close" : function() {
+ $(this).dialog( "close" );
+ }
+ });
+ },
+ "Cancel": function(){
+ $(this).dialog( "close" );
+ }
+ }
+ });
+}
+
+/**
+ * Open dialog to change user password
+ */
+function changePassword() {
+ // Create form to add node range
+ var dialog = $('
');
+ var info = createInfoBar('Change your password');
+ dialog.append(info);
+
+ dialog.append('New password:
');
+ dialog.append('Confirm password:
');
+
+ // Open form as a dialog
+ dialog.dialog({
+ modal: true,
+ close: function(){
+ $(this).remove();
+ },
+ title: 'Change Password',
+ width: 400,
+ buttons: {
+ "Ok": function(){
+ // Remove any warning messages
+ $(this).find('.ui-state-error').remove();
+
+ var errorMessage = "";
+
+ // Check each input is provided
+ $('#changePassword input').each(function() {
+ if (!$(this).val()) {
+ errorMessage = "Please provide a value for each missing input!";
+ }
+ });
+
+ // Do not continue if error found
+ if (errorMessage) {
+ dialog.prepend(createWarnBar(errorMessage));
+ return;
+ }
+
+ // Check new and confirm passwords match
+ var user = $.cookie('xcat_username');
+ var newPassword = $('#changePassword input[name="newPassword"]').val();
+ var confirmPassword = $('#changePassword input[name="confirmPassword"]').val();
+ if (newPassword != confirmPassword) {
+ dialog.prepend(createWarnBar("Please confirm new password!"));
+ return;
+ }
+
+ // Change dialog buttons
+ $('#changePassword').dialog('option', 'buttons', {
+ 'Close':function(){
+ $('#changePassword').dialog('destroy').remove();
+ }
+ });
+
+ // Send request to change password
+ var url = window.location.pathname;
+ var page = url.replace('/xcat/', '');
+ var url = 'lib/cmd.php';
+ // Service portal does not have access to cmd.php
+ if (page == 'service.php')
+ url = 'lib/srv_cmd.php';
+ $.ajax( {
+ url : url,
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'passwd;' + user + ';' + newPassword,
+ msg : ''
+ },
+
+ success : function (data) {
+ // Show response message
+ var rspMessage = "";
+ for (var i in data.rsp)
+ rspMessage += data.rsp[i] + " ";
+
+ $('#changePassword').prepend(createInfoBar(rspMessage));
+ }
+ });
+ },
+ "Cancel": function(){
+ $(this).dialog( "close" );
+ }
+ }
+ });
+}
+
+/**
+ * Adjust datatable column size
+ *
+ * @param tableId Table ID
+ */
+function adjustColumnSize(tableId) {
+ var dTable = $('#' + tableId).dataTable();
+ dTable.fnAdjustColumnSizing();
+}
+
+/**
+ * Set menu theme
+ *
+ * @param menu Menu object
+ */
+function setMenu2Theme(menu) {
+ // On hover
+ var background = '', color = '';
+ var theme = $.cookie('xcat_theme');
+ if (theme) {
+ switch (theme) {
+ case 'cupertino':
+ background = '#3BAAE3';
+ color = 'white';
+ break;
+ case 'dark_hive':
+ background = '#0972A5';
+ break;
+ case 'redmond':
+ background = '#F5F8F9';
+ color = '#E17009';
+ break;
+ case 'start':
+ background = '#6EAC2C';
+ break;
+ case 'sunny':
+ background = 'white';
+ color = '#0074C7';
+ break;
+ case 'ui_dark':
+ background = '#F58400';
+ break;
+ default:
+ background = '#6EAC2C';
+ }
+ } else {
+ background = '#6EAC2C';
+ }
+
+ menu.css('background', background);
+ menu.find('a:eq(0)').css('color', color);
+}
+
+/**
+ * Set menu back to normal before applying theme
+ *
+ * @param menu Menu object
+ */
+function setMenu2Normal(menu) {
+ // Change back to normal
+ menu.css('background', '');
+ menu.find('a:eq(0)').css('color', '');
+}
+
+/**
+ * Get nodes that are checked in a given datatable
+ *
+ * @param datatableId The datatable ID
+ * @return Nodes that were checked
+ */
+function getNodesChecked(datatableId) {
+ var tgts = '';
+
+ // Get nodes that were checked
+ var nodes = $('#' + datatableId + ' input[type=checkbox]:checked');
+ for (var i in nodes) {
+ var tgtNode = nodes.eq(i).attr('name');
+
+ if (tgtNode) {
+ tgts += tgtNode;
+
+ // Add a comma at the end
+ if (i < nodes.length - 1) {
+ tgts += ',';
+ }
+ }
+ }
+
+ return tgts;
+}
+
+/**
+ * Check if return message contains errors
+ *
+ * @param msg Return message
+ * @return 0 If return message contains no errors
+ * -1 If return message contains errors
+ */
+function containErrors(msg) {
+ if (msg.indexOf('Failed') > -1 || msg.indexOf('Error') > -1) {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+/**
+ * Check if a value is an integer
+ *
+ * @param value Value to be checked
+ * @returns true If value is an integer
+ false If value is not an integer
+ */
+function isInteger(value){
+ if ((parseFloat(value) == parseInt(value)) && !isNaN(value)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/**
+ * Remove html encoding from php htmlentities() conversion
+ *
+ * @param encodedString
+ */
+function decodeHTML(encodedString) {
+ var txt = document.createElement("textarea");
+ txt.innerHTML = encodedString;
+ return txt.value;
+}
+
+/**
+ * Remove html encoding from rsp.data array and rsp.msg
+ *
+ * @param encodedData from server response
+ */
+function decodeRsp(encodedData) {
+ /* response data has rsp and msg. msg is a string.
+ rsp is a string, or array of strings or array of arrays with strings*/
+ if ( (typeof encodedData.rsp != "undefined") && (encodedData.rsp.length > 0) ) {
+ if (encodedData.rsp.constructor === Array) {
+ for (var i in encodedData.rsp) {
+ if (encodedData.rsp[i].constructor === Array) {
+ for (var j in encodedData.rsp[i]) {
+ encodedData.rsp[i][j] = decodeHTML(encodedData.rsp[i][j]);
+ }
+ } else {
+ encodedData.rsp[i] = decodeHTML(encodedData.rsp[i]);
+ }
+ }
+ } else {
+ encodedData.rsp = decodeHTML(encodedData.rsp);
+ }
+ }
+ /* msg is a string */
+ if ( (typeof encodedData.msg != "undefined") && (encodedData.msg.length > 0) ){
+ encodedData.msg = decodeHTML(encodedData.msg);
+ }
+ return encodedData;
+}
diff --git a/xCAT-UI/lib/cmd.php b/xCAT-UI/lib/cmd.php
index f63f83000..db9a3a23b 100644
--- a/xCAT-UI/lib/cmd.php
+++ b/xCAT-UI/lib/cmd.php
@@ -1,225 +1,241 @@
-children() as $child) {
- foreach ($child->children() as $data) {
- if($data->name) {
- $node = $data->name;
-
- if ($data->data->contents) {
- $cont = $data->data->contents;
- } else {
- $cont = $data->data;
- }
-
- if ($data->data->desc) {
- $cont = $data->data->desc . ": " . $cont;
- }
-
- $cont = str_replace(":|:", "\n", $cont);
- array_push($rsp, "$node: $cont");
- } else if (strlen("$data") > 2) {
- $data = str_replace(":|:", "\n", $data);
- array_push($rsp, "$data");
- }
- }
- }
- }
-
- // Reply in the form of JSON
- $rtn = array("rsp" => $rsp, "msg" => $msg);
- echo json_encode($rtn);
-}
-
-/**
- * Extract the output for a webrun command
- *
- * @param $xml The XML output from docmd()
- * @return An array containing the output
- */
-function extractWebrun($xml) {
- $rsp = array();
- $i = 0;
-
- // Extract data returned
- foreach($xml->children() as $nodes){
- foreach($nodes->children() as $node){
- // Get the node name
- $name = $node->name;
-
- // Get the content
- $status = $node->data;
- $status = str_replace(":|:", "\n", $status);
-
- // Add to return array
- $rsp[$i] = array("$name", "$status");
- $i++;
- }
- }
-
- return $rsp;
-}
-
-/**
- * Extract the output for a nodels command
- *
- * @param $xml The XML output from docmd()
- * @return An array containing the output
- */
-function extractNodels($xml) {
- $rsp = array();
- $i = 0;
-
- // Extract data returned
- foreach($xml->children() as $nodes){
- foreach($nodes->children() as $node){
- // Get the node name
- $name = $node->name;
- // Get the content
- $status = $node->data->contents;
- $status = str_replace(":|:", "\n", $status);
-
- $description = $node->data->desc;
- // Add to return array
- $rsp[$i] = array("$name", "$status", "$description");
- $i++;
- }
- }
-
- return $rsp;
-}
-
-/**
- * Extract the output for a extnoderange command
- *
- * @param $xml The XML output from docmd()
- * @return The nodes and groups
- */
-function extractExtnoderange($xml) {
- $rsp = array();
-
- // Extract data returned
- foreach ($xml->xcatresponse->intersectinggroups as $group) {
- array_push($rsp, "$group");
- }
-
- return $rsp;
-}
+children() as $child) {
+ foreach ($child->children() as $data) {
+ if($data->name) {
+ $node = $data->name;
+
+ if ($data->data->contents) {
+ $cont = $data->data->contents;
+ } else {
+ $cont = $data->data;
+ }
+
+ if ($data->data->desc) {
+ $cont = $data->data->desc . ": " . $cont;
+ }
+
+ $cont = str_replace(":|:", "\n", $cont);
+ array_push($rsp, "$node: $cont");
+ } else if (strlen("$data") > 2) {
+ $data = str_replace(":|:", "\n", $data);
+ array_push($rsp, "$data");
+ }
+ }
+ }
+ }
+ // Remove any HTML that could be used for XSS attacks
+ foreach ($rsp as $key => &$value) {
+ $whatami = gettype($value);
+ if ("string" != $whatami) {
+ //echo "found a non string in rsp array \n";
+ foreach ($value as $key2 => $value2){
+ //echo "Key2:$key2 Value2 type:",gettype($value2)," value2 data: $value2 \n";
+ $value[$key2] = htmlentities($value2, ENT_QUOTES | ENT_HTML5, 'UTF-8');
+ }
+ } else {
+ //echo "Key:$key Value type:",gettype($value)," value data: $value \n";
+ $rsp[$key] = htmlentities($value, ENT_QUOTES | ENT_HTML5, 'UTF-8');
+ //echo "New value: $rsp[$key] \n";
+ }
+ }
+ $msg = htmlentities($msg, ENT_QUOTES | ENT_HTML5, 'UTF-8');
+
+ // Reply in the form of JSON
+ $rtn = array("rsp" => $rsp, "msg" => $msg);
+ echo json_encode($rtn);
+}
+
+/**
+ * Extract the output for a webrun command
+ *
+ * @param $xml The XML output from docmd()
+ * @return An array containing the output
+ */
+function extractWebrun($xml) {
+ $rsp = array();
+ $i = 0;
+
+ // Extract data returned
+ foreach($xml->children() as $nodes){
+ foreach($nodes->children() as $node){
+ // Get the node name
+ $name = $node->name;
+
+ // Get the content
+ $status = $node->data;
+ $status = str_replace(":|:", "\n", $status);
+
+ // Add to return array
+ $rsp[$i] = array("$name", "$status");
+ $i++;
+ }
+ }
+
+ return $rsp;
+}
+
+/**
+ * Extract the output for a nodels command
+ *
+ * @param $xml The XML output from docmd()
+ * @return An array containing the output
+ */
+function extractNodels($xml) {
+ $rsp = array();
+ $i = 0;
+
+ // Extract data returned
+ foreach($xml->children() as $nodes){
+ foreach($nodes->children() as $node){
+ // Get the node name
+ $name = $node->name;
+ // Get the content
+ $status = $node->data->contents;
+ $status = str_replace(":|:", "\n", $status);
+
+ $description = $node->data->desc;
+ // Add to return array
+ $rsp[$i] = array("$name", "$status", "$description");
+ $i++;
+ }
+ }
+
+ return $rsp;
+}
+
+/**
+ * Extract the output for a extnoderange command
+ *
+ * @param $xml The XML output from docmd()
+ * @return The nodes and groups
+ */
+function extractExtnoderange($xml) {
+ $rsp = array();
+
+ // Extract data returned
+ foreach ($xml->xcatresponse->intersectinggroups as $group) {
+ array_push($rsp, "$group");
+ }
+
+ return $rsp;
+}
?>
\ No newline at end of file
diff --git a/xCAT-UI/lib/srv_cmd.php b/xCAT-UI/lib/srv_cmd.php
index c1b226369..ecb4fc1a4 100644
--- a/xCAT-UI/lib/srv_cmd.php
+++ b/xCAT-UI/lib/srv_cmd.php
@@ -1,190 +1,206 @@
-children() as $child) {
- foreach ($child->children() as $data) {
- if($data->name) {
- $node = $data->name;
-
- if($data->data->contents){
- $cont = $data->data->contents;
- } else {
- $cont = $data->data;
- }
-
- $cont = str_replace(":|:", "\n", $cont);
- array_push($rsp, "$node: $cont");
- } else if (strlen("$data") > 2) {
- $data = str_replace(":|:", "\n", $data);
- array_push($rsp, "$data");
- }
- }
- }
- }
-
- // Reply in the form of JSON
- $rtn = array("rsp" => $rsp, "msg" => $msg);
- echo json_encode($rtn);
-}
-
-/**
- * Extract the output for a webrun command
- *
- * @param $xml The XML output from docmd()
- * @return An array containing the output
- */
-function extractWebrun($xml) {
- $rsp = array();
- $i = 0;
-
- // Extract data returned
- foreach($xml->children() as $nodes){
- foreach($nodes->children() as $node){
- // Get the node name
- $name = $node->name;
-
- // Get the content
- $status = $node->data;
- $status = str_replace(":|:", "\n", $status);
-
- // Add to return array
- $rsp[$i] = array("$name", "$status");
- $i++;
- }
- }
-
- return $rsp;
-}
-
-/**
- * Extract the output for a nodels command
- *
- * @param $xml The XML output from docmd()
- * @return An array containing the output
- */
-function extractNodels($xml) {
- $rsp = array();
- $i = 0;
-
- // Extract data returned
- foreach($xml->children() as $nodes){
- foreach($nodes->children() as $node){
- // Get the node name
- $name = $node->name;
- // Get the content
- $status = $node->data->contents;
- $status = str_replace(":|:", "\n", $status);
-
- $description = $node->data->desc;
- // Add to return array
- $rsp[$i] = array("$name", "$status", "$description");
- $i++;
- }
- }
-
- return $rsp;
-}
-
-/**
- * Extract the output for a extnoderange command
- *
- * @param $xml The XML output from docmd()
- * @return The nodes and groups
- */
-function extractExtnoderange($xml) {
- $rsp = array();
-
- // Extract data returned
- foreach ($xml->xcatresponse->intersectinggroups as $group) {
- array_push($rsp, "$group");
- }
-
- return $rsp;
-}
+children() as $child) {
+ foreach ($child->children() as $data) {
+ if($data->name) {
+ $node = $data->name;
+
+ if($data->data->contents){
+ $cont = $data->data->contents;
+ } else {
+ $cont = $data->data;
+ }
+
+ $cont = str_replace(":|:", "\n", $cont);
+ array_push($rsp, "$node: $cont");
+ } else if (strlen("$data") > 2) {
+ $data = str_replace(":|:", "\n", $data);
+ array_push($rsp, "$data");
+ }
+ }
+ }
+ }
+ // Remove any HTML that could be used for XSS attacks
+ foreach ($rsp as $key => &$value) {
+ $whatami = gettype($value);
+ if ("string" != $whatami) {
+ //echo "found a non string in rsp array \n";
+ foreach ($value as $key2 => $value2){
+ //echo "Key2:$key2 Value2 type:",gettype($value2)," value2 data: $value2 \n";
+ $value[$key2] = htmlentities($value2, ENT_QUOTES | ENT_HTML5, 'UTF-8');
+ }
+ } else {
+ //echo "Key:$key Value type:",gettype($value)," value data: $value \n";
+ $rsp[$key] = htmlentities($value, ENT_QUOTES | ENT_HTML5, 'UTF-8');
+ //echo "New value: $rsp[$key] \n";
+ }
+ }
+ $msg = htmlentities($msg, ENT_QUOTES | ENT_HTML5, 'UTF-8');
+
+ // Reply in the form of JSON
+ $rtn = array("rsp" => $rsp, "msg" => $msg);
+ echo json_encode($rtn);
+}
+
+/**
+ * Extract the output for a webrun command
+ *
+ * @param $xml The XML output from docmd()
+ * @return An array containing the output
+ */
+function extractWebrun($xml) {
+ $rsp = array();
+ $i = 0;
+
+ // Extract data returned
+ foreach($xml->children() as $nodes){
+ foreach($nodes->children() as $node){
+ // Get the node name
+ $name = $node->name;
+
+ // Get the content
+ $status = $node->data;
+ $status = str_replace(":|:", "\n", $status);
+
+ // Add to return array
+ $rsp[$i] = array("$name", "$status");
+ $i++;
+ }
+ }
+
+ return $rsp;
+}
+
+/**
+ * Extract the output for a nodels command
+ *
+ * @param $xml The XML output from docmd()
+ * @return An array containing the output
+ */
+function extractNodels($xml) {
+ $rsp = array();
+ $i = 0;
+
+ // Extract data returned
+ foreach($xml->children() as $nodes){
+ foreach($nodes->children() as $node){
+ // Get the node name
+ $name = $node->name;
+ // Get the content
+ $status = $node->data->contents;
+ $status = str_replace(":|:", "\n", $status);
+
+ $description = $node->data->desc;
+ // Add to return array
+ $rsp[$i] = array("$name", "$status", "$description");
+ $i++;
+ }
+ }
+
+ return $rsp;
+}
+
+/**
+ * Extract the output for a extnoderange command
+ *
+ * @param $xml The XML output from docmd()
+ * @return The nodes and groups
+ */
+function extractExtnoderange($xml) {
+ $rsp = array();
+
+ // Extract data returned
+ foreach ($xml->xcatresponse->intersectinggroups as $group) {
+ array_push($rsp, "$group");
+ }
+
+ return $rsp;
+}
?>
\ No newline at end of file
diff --git a/xCAT-UI/lib/systemcmd.php b/xCAT-UI/lib/systemcmd.php
index 7990aa035..94bbc4444 100644
--- a/xCAT-UI/lib/systemcmd.php
+++ b/xCAT-UI/lib/systemcmd.php
@@ -1,36 +1,39 @@
-Please login before continuing!");
- exit;
-}
-
-if (isset($_GET["cmd"])) {
- // HTTP GET requests
- $cmd = $_GET["cmd"];
- $msg = NULL;
- $ret = "";
-
- if (isset($_GET["msg"])) {
- $msg = $_GET["msg"];
- }
-
- if ($cmd == "ostype") {
- $ret = strtolower(PHP_OS);
- } else {
- $ret = shell_exec($cmd);
- }
-
- echo json_encode(array("rsp"=>$ret, "msg" => $msg));
-}
+Please login before continuing!");
+ exit;
+}
+
+if (isset($_GET["cmd"])) {
+ // HTTP GET requests
+ $cmd = $_GET["cmd"];
+ $msg = NULL;
+ $ret = "";
+
+ if (isset($_GET["msg"])) {
+ $msg = $_GET["msg"];
+ }
+
+ if ($cmd == "ostype") {
+ $ret = strtolower(PHP_OS);
+ } else {
+ $ret = shell_exec($cmd);
+ }
+
+ // Remove any HTML that could be used for XSS attacks
+ $ret = htmlentities($ret, ENT_QUOTES | ENT_HTML5, 'UTF-8');
+ $msg = htmlentities($msg, ENT_QUOTES | ENT_HTML5, 'UTF-8');
+ echo json_encode(array("rsp"=>$ret, "msg" => $msg));
+}
?>
\ No newline at end of file
diff --git a/xCAT-UI/lib/zCmd.php b/xCAT-UI/lib/zCmd.php
index c2a21eebf..c77f4b5fe 100644
--- a/xCAT-UI/lib/zCmd.php
+++ b/xCAT-UI/lib/zCmd.php
@@ -1,142 +1,159 @@
-children() as $child) {
- foreach ($child->children() as $data) {
- $data = str_replace(":|:", "\n", $data);
- array_push($rsp, "$data");
- }
- }
- }
-
- // Create virtual server
- else if (strncasecmp($cmd, "mkvm", 4) == 0) {
- // Directory /var/tmp permissions = 777
- // You can write anything to that directory
- $userEntry = "/var/tmp/$tgt.txt";
- $handle = fopen($userEntry, 'w') or die("Cannot open $userEntry");
- fwrite($handle, $att);
- fclose($handle);
-
- // CLI command: mkvm gpok3 /tmp/gpok3.txt
- // Create user entry
- array_unshift($arr, $userEntry);
- $xml = docmd($cmd, $tgt, $arr, NULL);
- foreach ($xml->children() as $child) {
- foreach ($child->children() as $data) {
- $data = str_replace(":|:", "\n", $data);
- array_push($rsp, "$data");
- }
- }
- }
-
- // Run shell script
- // This is a typical command used by all platforms. It is put here because
- // most of the code needed are already here
- else if (strncasecmp($cmd, "xdsh", 4) == 0) {
- // Directory /var/tmp permissions = 777
- // You can write anything to that directory
- $msgArgs = explode(";", $msg);
- $inst = str_replace("out=scriptStatusBar", "", $msgArgs[0]);
- $script = "/var/tmp/script$inst.sh";
-
- // Write to file
- $handle = fopen($script, 'w') or die("Cannot open $script");
- fwrite($handle, $att);
- fclose($handle);
-
- // Change it to executable
- chmod($script, 0777);
-
- // CLI command: xdsh gpok3 -e /var/tmp/gpok3.sh
- // Create user entry
- array_push($arr, $script);
- $xml = docmd($cmd, $tgt, $arr, NULL);
- foreach ($xml->children() as $child) {
- foreach ($child->children() as $data) {
- $data = str_replace(":|:", "\n", $data);
- array_push($rsp, "$data");
- }
- }
-
- // Remove this file
- unlink($script);
- }
-
- // Reply in the form of JSON
- $rtn = array("rsp" => $rsp, "msg" => $msg);
- echo json_encode($rtn);
-}
+children() as $child) {
+ foreach ($child->children() as $data) {
+ $data = str_replace(":|:", "\n", $data);
+ array_push($rsp, "$data");
+ }
+ }
+ }
+
+ // Create virtual server
+ else if (strncasecmp($cmd, "mkvm", 4) == 0) {
+ // Directory /var/tmp permissions = 777
+ // You can write anything to that directory
+ $userEntry = "/var/tmp/$tgt.txt";
+ $handle = fopen($userEntry, 'w') or die("Cannot open $userEntry");
+ fwrite($handle, $att);
+ fclose($handle);
+
+ // CLI command: mkvm gpok3 /tmp/gpok3.txt
+ // Create user entry
+ array_unshift($arr, $userEntry);
+ $xml = docmd($cmd, $tgt, $arr, NULL);
+ foreach ($xml->children() as $child) {
+ foreach ($child->children() as $data) {
+ $data = str_replace(":|:", "\n", $data);
+ array_push($rsp, "$data");
+ }
+ }
+ }
+
+ // Run shell script
+ // This is a typical command used by all platforms. It is put here because
+ // most of the code needed are already here
+ else if (strncasecmp($cmd, "xdsh", 4) == 0) {
+ // Directory /var/tmp permissions = 777
+ // You can write anything to that directory
+ $msgArgs = explode(";", $msg);
+ $inst = str_replace("out=scriptStatusBar", "", $msgArgs[0]);
+ $script = "/var/tmp/script$inst.sh";
+
+ // Write to file
+ $handle = fopen($script, 'w') or die("Cannot open $script");
+ fwrite($handle, $att);
+ fclose($handle);
+
+ // Change it to executable
+ chmod($script, 0777);
+
+ // CLI command: xdsh gpok3 -e /var/tmp/gpok3.sh
+ // Create user entry
+ array_push($arr, $script);
+ $xml = docmd($cmd, $tgt, $arr, NULL);
+ foreach ($xml->children() as $child) {
+ foreach ($child->children() as $data) {
+ $data = str_replace(":|:", "\n", $data);
+ array_push($rsp, "$data");
+ }
+ }
+
+ // Remove this file
+ unlink($script);
+ }
+
+ // Remove any HTML that could be used for XSS attacks
+ foreach ($rsp as $key => &$value) {
+ $whatami = gettype($value);
+ if ("string" != $whatami) {
+ //echo "found a non string in rsp array \n";
+ foreach ($value as $key2 => $value2){
+ //echo "Key2:$key2 Value2 type:",gettype($value2)," value2 data: $value2 \n";
+ $value[$key2] = htmlentities($value2, ENT_QUOTES | ENT_HTML5, 'UTF-8');
+ }
+ } else {
+ //echo "Key:$key Value type:",gettype($value)," value data: $value \n";
+ $rsp[$key] = htmlentities($value, ENT_QUOTES | ENT_HTML5, 'UTF-8');
+ //echo "New value: $rsp[$key] \n";
+ }
+ }
+ $msg = htmlentities($msg, ENT_QUOTES | ENT_HTML5, 'UTF-8');
+
+ // Reply in the form of JSON
+ $rtn = array("rsp" => $rsp, "msg" => $msg);
+ echo json_encode($rtn);
+}
?>
\ No newline at end of file
diff --git a/xCAT-client/bin/verifynode b/xCAT-client/bin/verifynode
index a769edb33..66c29ffdb 100644
--- a/xCAT-client/bin/verifynode
+++ b/xCAT-client/bin/verifynode
@@ -44,6 +44,7 @@ use xCAT::zvmUtils;
my $version = "1";
my $comments = ''; # Comments for the IVP run
+my $dataFile = ''; # Input data file
my $decode = ''; # String specified by the --decode operand.
my $disable = ''; # Disable scheduled IVP from running.
my $displayHelp = 0; # Display help information
@@ -56,6 +57,8 @@ my %hosts; # Information on host nodes known by xCAT
my $id = ''; # Id of the IVP run
my %ignored; # List of ignored messages
my $ignoreCnt = 0; # Number of times we ignored a message
+my $issueCmdOverIUCV = ''; # Issue a command to a node over IUCV
+my $issueCmdToNode = ''; # Issue a command to a node using IUCV or SSH
my %localIPs; # Hash of the Local IP addresses for the xCAT MN system
my $logDir = '/var/log/xcat/ivp'; # Log location
my $logFile = ''; # Log file name and location
@@ -63,7 +66,7 @@ my $logFileHandle; # File handle for the log file.
my @ivpSummary; # Summary output lines for an IVP run.
my $locApplSystemRole = '/var/lib/sspmod/appliance_system_role';
my %mnInfo; # Managed node environment information
-my %msgsToIgnore; # Hash of messages to ignore
+my %msgsToIgnore; # Hash of messages to ignore
my $needToFinishLogFile = 0; # If 1 then finishLogFile() needs to be called
my $nodeName = ''; # Name of node to be verified
my $notify = 0; # Notify a user
@@ -112,6 +115,14 @@ my %verifySets = (
[ 'Encoding a string',
'encodeDecodeString()',
],
+ '$issueCmdOverIUCV ne \'\'' =>
+ [ 'Issue a command to a node using IUCV',
+ 'cmdOnVM( \'onlyIUCV\' )',
+ ],
+ '$issueCmdToNode ne \'\'' =>
+ [ 'Issue a command to a node using IUCV or SSH',
+ 'cmdOnVM( \'either\' )',
+ ],
'$remove' =>
[ 'Remove an automated periodic IVP',
'removeIVP( $id )',
@@ -159,7 +170,7 @@ my %verifySets = (
'verifyPower( $nodeName )',
'verifyAccess( $nodeName )',
'getDistro( $nodeName )',
- 'verifyService($nodeOrIP, "cloud-config,2,3,4,5 cloud-final,2,3,4,5 cloud-init,2,3,4,5 cloud-init-local,2,3,4,5")',
+ 'verifyService($nodeName, "cloud-config,2,3,4,5 cloud-final,2,3,4,5 cloud-init,2,3,4,5 cloud-init-local,2,3,4,5")',
'showCILevel()',
],
'$verifyXcatconf4z' =>
@@ -167,7 +178,7 @@ my %verifySets = (
'verifyPower( $nodeName )',
'verifyAccess( $nodeName )',
'getDistro( $nodeName )',
- 'verifyXcatconf4z()',
+ 'verifyXcatconf4z( $nodeName )',
],
'$test' =>
[ 'Script test functon.',
@@ -193,6 +204,14 @@ my $usage_string = "Usage:\n
--capturereqs
Verify that node meets system capture
requirements for OpenStack.
+ --cmdoveriucv
+ Issue a command to a node using IUCV.
+ Specify a period for when combining this
+ option with the --file option.
+ --cmdtonode Issue a command to a node using IUCV or SSH
+ if IUCV is not available.
+ Specify a period for when combining this
+ option with the --file option.
-c | --cloudinit
Verify that node has cloud-init installed.
--comments
@@ -214,6 +233,9 @@ my $usage_string = "Usage:\n
string from the zvmivp table. The must be
an ASCII string. This function does not support
encoding a UTF-8 character string.
+ --file File location containing additional input.
+ When used with the --cmdoveriucv or --cmdtonode
+ operands, this file contains the command to issue.
--fullivp
Run the full end-to-end IVP. This
verification checks the compute node and builds
@@ -380,6 +402,127 @@ sub checkForDefault {
}
+#-------------------------------------------------------
+
+=head3 cmdOnVM
+
+ Description : Send a command to a node and show the result.
+ Arguments : Target function, either 'onlyIUCV' or 'either'.
+ Returns : Return code:
+ 0 - Normal Linux success
+ 255 - Unable to SSH to system
+ non-zero - command error
+ Output from the command or a error string on an SSH failure.
+ Example : $rc = cmdOnVM( 'onlyIUCV' );
+ $rc = cmdOnVM( 'either' );
+
+=cut
+
+#-------------------------------------------------------
+sub cmdOnVM {
+ my ( $targetFunc ) = @_;
+ my $cmd = '';
+ my $hcp = '';
+ my @lines;
+ my $rc = 0;
+ my $out = '';
+ my $sudo;
+ my $user;
+ my $userid = '';
+
+ # Get the command to issue.
+ if ( $targetFunc eq 'onlyIUCV' ) {
+ if ( $issueCmdOverIUCV ne '.' ) {
+ $cmd = $issueCmdOverIUCV;
+ }
+ } else {
+ if ( $issueCmdToNode ne '.' ) {
+ $cmd = $issueCmdToNode;
+ }
+ }
+
+ # Use the data file if it was specified.
+ if ( $dataFile ne '' ) {
+ if ( -e $dataFile ) {
+ open my $handle, '<', $dataFile;
+ chomp( @lines = <$handle> );
+ close $handle;
+ if ( $lines[0] ne '' ) {
+ $cmd = $lines[0];
+ } else {
+ logResponse( 'DF', 'GENERIC_RESPONSE', "$dataFile does not have anything in the first line.");
+ goto FINISH_cmdUsingIUCV;
+ }
+ } else {
+ logResponse( 'DF', 'GENERIC_RESPONSE', "$dataFile does not exist.");
+ goto FINISH_cmdUsingIUCV;
+ }
+ }
+
+ # Verify that we have a command to issue.
+ if ( $cmd eq '' ) {
+ logResponse( 'DF', 'GENERIC_RESPONSE', "A command to issue was not specified.");
+ goto FINISH_cmdUsingIUCV;
+ }
+
+ ($user, $sudo) = xCAT::zvmUtils->getSudoer();
+
+ # Get the required properties (hcp, userid, user) from the node
+ $out = `/opt/xcat/bin/lsdef $nodeName -i hcp,userid`;
+ $rc = $?;
+ if ( $rc eq 0 ) {
+ my $fndNode = 0;
+ @lines = split( '\n', $out );
+ my $host = '';
+ foreach my $line ( @lines ) {
+ $line =~ s/^\s+|\s+$//g; # trim blanks from both ends of the string
+ if ( $line =~ /Object name:/ ) {
+ $fndNode = 1;
+ next;
+ } elsif ( $line =~ /hcp\=/ ) {
+ ($hcp) = $line =~ m/hcp\=(.*)/;
+ next;
+ } elsif ( $line =~ /userid\=/ ) {
+ ($userid) = $line =~ m/userid\=(.*)/;
+ next;
+ }
+ }
+ if ( $fndNode != 1 ) {
+ logResponse( 'DF', 'GENERIC_RESPONSE', "'$nodeName' is not an xCAT node." );
+ goto FINISH_cmdUsingIUCV;
+ }
+ } else {
+ $rc = logResponse( 'DFS', 'GNRL01', "$cmd", $rc, $out );
+ goto FINISH_cmdUsingIUCV;
+ }
+
+ # Send the command through IUCV
+ logResponse( 'DF', '*NONFORMATTED*', "\n**************************\nData for the function call\n**************************" );
+ logResponse( 'DF', '*NONFORMATTED*', " Node: $nodeName" );
+ if ( $targetFunc eq 'onlyIUCV' ) {
+ logResponse( 'DF', '*NONFORMATTED*', "z/VM userid: $userid" );
+ logResponse( 'DF', '*NONFORMATTED*', " HCP: $hcp" );
+ logResponse( 'DF', '*NONFORMATTED*', " User: $user" );
+ logResponse( 'DF', '*NONFORMATTED*', " Function: xCAT::zvmUtils->execcmdthroughIUCV" );
+ } else {
+ logResponse( 'DF', '*NONFORMATTED*', " User: $user" );
+ logResponse( 'DF', '*NONFORMATTED*', " Function: xCAT::zvmUtils->execcmdonVM" );
+ }
+ logResponse( 'DF', '*NONFORMATTED*', " Cmd: $cmd" );
+
+ logResponse( 'DF', '*NONFORMATTED*', "\n*********************\nInvoking the function\n*********************" );
+ if ( $targetFunc eq 'onlyIUCV' ) {
+ $out = xCAT::zvmUtils->execcmdthroughIUCV( $user, $hcp, $userid, $cmd );
+ } else {
+ $out = xCAT::zvmUtils->execcmdonVM( $user, $nodeName, $cmd );
+ }
+ logResponse( 'DF', '*NONFORMATTED*', "\n******\nResult\n******\n$out" );
+
+FINISH_cmdUsingIUCV:
+ return $rc;
+}
+
+
#-------------------------------------------------------
=head3 driveCronList
@@ -2590,7 +2733,7 @@ FINISH_verifyService:
Description : Verify xcatconf4z is properly installed
and is the correct version.
- Arguments : None
+ Arguments : Node name or IP address
Returns : 0 - No error
non-zero - Terminating error detected.
Example : $rc = verifyXcatconf4z();
@@ -2695,10 +2838,13 @@ if (!GetOptions(
'disable' => \$disable,
'enable' => \$enable,
'encode=s' => \$encode,
+ 'file=s' => \$dataFile,
'fullivp' => \$runFullIVP,
'h|help' => \$displayHelp,
'i|id=s' => \$id,
'ignore=s' => \$ignoreOpt,
+ 'cmdoveriucv=s' => \$issueCmdOverIUCV,
+ 'cmdtonode=s' => \$issueCmdToNode,
'n|node=s' => \$nodeName,
'notify' => \$notifyOnErrorOrWarning,
'openstackuser=s' => \$openstackUser,
@@ -2810,9 +2956,7 @@ if ( $decode ne '' or
$remove or
$schedule ne '' ) {
# IVP runs do not need the node.
-} elsif ( $nodeName ne '' ) {
- $nodeName = lc( $nodeName );
-} else {
+} elsif ( $nodeName eq '' ) {
$rc = logResponse( 'DFS', 'OPER01', '-n or --node' );
goto FINISH_main;
}
diff --git a/xCAT-server/lib/xcat/plugins/zvm.pm b/xCAT-server/lib/xcat/plugins/zvm.pm
index 1743f69bd..6624fe7e1 100644
--- a/xCAT-server/lib/xcat/plugins/zvm.pm
+++ b/xCAT-server/lib/xcat/plugins/zvm.pm
@@ -742,7 +742,7 @@ sub process_request {
Arguments : Node to remove
Upstream instance ID (Optional)
Upstream request ID (Optional)
- Returns : Nothing
+ Returns : Nothing, errors returned in $callback
Example : removeVM($callback, $node);
=cut
@@ -776,6 +776,7 @@ sub removeVM {
xCAT::zvmUtils->printSyslog("sudoer:$::SUDOER zHCP:$hcp sudo:$::SUDO");
my $out;
+ my $outmsg;
my $requestId = "NoUpstreamRequestID"; # Default is still visible in the log
my $objectId = "NoUpstreamObjectID"; # Default is still visible in the log
@@ -796,6 +797,10 @@ sub removeVM {
# its resources. First, get any vswitches in directory.
xCAT::zvmUtils->printSyslog("Calling getVswitchIdsFromDirectory $::SUDOER, $hcp, $userId");
my @vswitch = xCAT::zvmUtils->getVswitchIdsFromDirectory( $::SUDOER, $hcp, $userId);
+ if (xCAT::zvmUtils->checkOutput( $vswitch[0] ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$vswitch[0]" );
+ return;
+ }
my %vswitchhash;
# For each vswitch revoke the userid vswitch authority
foreach (@vswitch) {
@@ -864,7 +869,14 @@ sub removeVM {
if (!(length $_)) {next;}
$pool = xCAT::zvmUtils->replaceStr( $_, ".conf", "" );
- @luns = split("\n", `ssh $::SUDOER\@$hcp "$::SUDO cat $::ZFCPPOOL/$_" | egrep -a -i $node`);
+ $out = `ssh $::SUDOER\@$hcp "$::SUDO cat $::ZFCPPOOL/$_"`;
+ ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO cat $::ZFCPPOOL/$_\"", $hcp, "removeVM", $out, $node );
+ if ($rc != 0) {
+ xCAT::zvmUtils->printLn( $callback, "$outmsg" );
+ return;
+ }
+ $out = `echo "$out" | egrep -a -i $node`;
+ @luns = split("\n", $out);
foreach (@luns) {
if (!(length $_)) {next;}
# Update entry: status,wwpn,lun,size,range,owner,channel,tag
@@ -916,7 +928,7 @@ sub removeVM {
Description : Change a virtual machine's configuration
Arguments : Node
Option
- Returns : Nothing
+ Returns : Nothing, errors returned in $callback
Example : changeVM($callback, $node, $args);
=cut
@@ -964,6 +976,11 @@ sub changeVM {
# Output string
my $out = "";
+ my $outmsg;
+ my $device = 0;
+ my $newlinkcall = 0;
+ my $rc = 0;
+ my $vdev;
# add3390 [disk pool] [device address] [size] [mode] [read password (optional)] [write password (optional)] [multi password (optional)] [fstype (optional)]
if ( $args->[0] eq "--add3390" ) {
@@ -1041,56 +1058,103 @@ sub changeVM {
if ( $fstype && !$error ) { # Format the disk before making it active.
# link the disk
- my $retry = 3;
- my $vdev = xCAT::zvmUtils->getFreeAddress( $::SUDOER, $hcp, 'vmcp' );
- while ( $retry > 0 ) {
- # wait 2 seconds for disk creation complete
- sleep(2);
- $out = `ssh $::SUDOER\@$hcp "$::SUDO /sbin/vmcp LINK TO $userId $addr AS $vdev M 2>&1"`;
- $error = (xCAT::zvmUtils->checkOutput( $out ) == -1) ? 1 : 0;
+ # Check if zhcp has the new routine to link and online the disk
+ $out = `ssh -o ConnectTimeout=30 $::SUDOER\@$hcp "$::SUDO $::DIR/linkdiskandbringonline $userId $addr $mode"`;
- if ($error) {
- $retry -= 1;
- $vdev = xCAT::zvmUtils->getFreeAddress( $::SUDOER, $hcp, 'vmcp' );
+ $rc = $? >> 8;
+ if ($rc == 255) {
+ xCAT::zvmUtils->printSyslog( "$node: changeVM() Unable to communicate with zHCP agent" );
+ xCAT::zvmUtils->printLn( $callback, "$node: changeVM() Unable to communicate with zHCP agent: $hcp" );
+ $error = 1;
+ } elsif ( $rc > 0 && $rc != 127 ) {
+ xCAT::zvmUtils->printSyslog( "$node: changeVM() Unexpected error from SSH call to linkdiskandbringonline rc: $rc $out" );
+ xCAT::zvmUtils->printLn( $callback, "$node: changeVM()Unexpected error from SSH call to linkdiskandbringonline rc: $rc $out" );
+ $error = 1;
+ } elsif ( $rc ==0 ) {
+ $newlinkcall = 1;
+ if ($out =~ m/Success:/i){
+ # sample output=>linkdiskandbringonline maint start time: 2017-03-03-16:20:48.011
+ # Success: Userid maint vdev 193 linked at ad35 device name dasdh
+ # linkdiskandbringonline exit time: 2017-03-03-16:20:52.150
+ $out = `echo "$out" | egrep -a -i "Success:"`;
+ my @info = split( ' ', $out );
+ $device = "/dev/" . $info[10];
} else {
- last;
+ xCAT::zvmUtils->printSyslog( "$node: changeVM() Error occurred in call to linkdiskandbringonline: $out" );
+ xCAT::zvmUtils->printLn( $callback, "$node: changeVM() Error occurred in call to linkdiskandbringonline: $out" );
+ $error = 1;
}
- }
+ } else {
+ xCAT::zvmUtils->printSyslog( "$node: changeVM() Could not find zhcp linkdiskandbringonline, using old code path." );
+ my $retry = 3;
+ $vdev = xCAT::zvmUtils->getFreeAddress( $::SUDOER, $hcp, 'vmcp' );
+ while ( $retry > 0 ) {
+ # wait 2 seconds for disk creation complete
+ sleep(2);
+ $out = `ssh $::SUDOER\@$hcp "$::SUDO /sbin/vmcp LINK TO $userId $addr AS $vdev M 2>&1"`;
+ $error = (xCAT::zvmUtils->checkOutput( $out ) == -1) ? 1 : 0;
- # make the disk online and get it's device name
- my $device = 0;
- if ( !$error ) {
- $out = `ssh $::SUDOER\@$hcp "$::SUDO /sbin/cio_ignore -r $vdev &> /dev/null"`;
- $out = xCAT::zvmUtils->disableEnableDisk( $::SUDOER, $hcp, "-e", $vdev );
- my $select = `ssh $::SUDOER\@$hcp "$::SUDO cat /proc/dasd/devices | grep -a 0.0.$vdev"`;
- chomp( $select );
- # A sample entry:
- # 0.0.0101(ECKD) at ( 94: 0) is dasda : active at blocksize: 4096, 600840 blocks, 2347 MB
- if ( $select ) {
- my @info = split( ' ', $select );
- $device = "/dev/" . $info[6];
+ if ($error) {
+ $retry -= 1;
+ $vdev = xCAT::zvmUtils->getFreeAddress( $::SUDOER, $hcp, 'vmcp' );
+ } else {
+ last;
+ }
+ }
+
+ # make the disk online and get it's device name
+ if ( !$error ) {
+ $out = `ssh $::SUDOER\@$hcp "$::SUDO /sbin/cio_ignore -r $vdev &> /dev/null"`;
+ $out = xCAT::zvmUtils->disableEnableDisk( $::SUDOER, $hcp, "-e", $vdev );
+ my $select = `ssh $::SUDOER\@$hcp "$::SUDO cat /proc/dasd/devices"`;
+ ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO cat /proc/dasd/devices\"", $hcp, "changeVM", $select, $node );
+ if ($rc != 0) {
+ xCAT::zvmUtils->printLn( $callback, "$outmsg" );
+ $error = 1;
+ } else {
+ $select = `echo "$select" | egrep -a -i "0.0.$vdev"`;
+ chomp( $select );
+ # A sample entry:
+ # 0.0.0101(ECKD) at ( 94: 0) is dasda : active at blocksize: 4096, 600840 blocks, 2347 MB
+ if ( $select ) {
+ my @info = split( ' ', $select );
+ $device = "/dev/" . $info[6];
+ }
+ $error = !$device;
+ }
}
- $error = !$device;
}
# format the disk
if ( !$error ) {
$out = `ssh $::SUDOER\@$hcp "$::SUDO /sbin/dasdfmt -y -b 4096 -d cdl -f $device 2>&1"`;
$error = (xCAT::zvmUtils->checkOutput( $out ) == -1) ? 1 : 0;
+ if ($error) {
+ xCAT::zvmUtils->printSyslog( "Error occurred during dasdfmt $device. Output: $out" );
+ }
}
if ( !$error ) {
$out = `ssh $::SUDOER\@$hcp "$::SUDO /sbin/fdasd -a $device 2>&1"`;
$error = (xCAT::zvmUtils->checkOutput( $out ) == -1) ? 1 : 0;
+ if ($error) {
+ xCAT::zvmUtils->printSyslog( "Error occurred during fdasd $device. Output: $out" );
+ }
}
if ( !$error ) {
$device .= '1';
if ( $fstype =~ m/xfs/i ) {
$out = `ssh $::SUDOER\@$hcp "$::SUDO mkfs.xfs $device 2>&1"`;
$error = (xCAT::zvmUtils->checkOutput( $out ) == -1) ? 1 : 0;
+ if ($error) {
+ xCAT::zvmUtils->printSyslog( "Error occurred during mkfs.xfs $device. Output: $out" );
+ }
} else {
$out = `ssh $::SUDOER\@$hcp "$::SUDO mkfs -t $fstype $device 2>&1"`;
$error = !($out =~ m/done/);
- }
+ if ($error) {
+ xCAT::zvmUtils->printSyslog( "Error occurred during mkfs $fstype $device. Output: $out" );
+ }
+ }
}
if ( $error ) {
xCAT::zvmUtils->printSyslog("$out");
@@ -1099,20 +1163,46 @@ sub changeVM {
$out = "";
}
- xCAT::zvmUtils->disableEnableDisk( $::SUDOER, $hcp, "-d", $vdev );
- `ssh $::SUDOER\@$hcp "$::SUDO /sbin/vmcp DETACH $vdev &> /dev/null"`;
- xCAT::zvmUtils->printSyslog("vmcp DETACH $vdev");
+ # offline and detach disk using new call so that zhcp records are updated
+ if ( $newlinkcall == 1 ){
+ $out = `ssh -o ConnectTimeout=30 $::SUDOER\@$hcp "$::SUDO $::DIR/offlinediskanddetach $userId $addr"`;
+ $rc = $?;
+
+ $rc = $? >> 8;
+ if ( $rc == 255 ) {
+ xCAT::zvmUtils->printSyslog( "$node: changeVM() Unable to communicate with zHCP agent" );
+ xCAT::zvmUtils->printLn( $callback, "$node: changeVM() Unable to communicate with zHCP agent: $hcp" );
+ $error = 1;
+ }
+ if ($out =~ m/Success:/i){
+ # sample output=>offlinediskanddetach maint start time: 2017-03-03-16:20:48.011
+ # Success: Userid maint vdev 193 unlinked
+ # offlinediskanddetach exit time: 2017-03-03-16:20:52.150
+ xCAT::zvmUtils->printSyslog("$out");
+ } else {
+ xCAT::zvmUtils->printSyslog( "$node: changeVM() Error occurred in call to offlinediskanddetach: $out" );
+ xCAT::zvmUtils->printLn( $callback, "$node: changeVM() Error occurred in call to offlinediskanddetach: $out" );
+ $error = 1;
+ }
+ # Use old code to disable and detach
+ } else {
+ xCAT::zvmUtils->disableEnableDisk( $::SUDOER, $hcp, "-d", $vdev );
+ `ssh $::SUDOER\@$hcp "$::SUDO /sbin/vmcp DETACH $vdev &> /dev/null"`;
+ xCAT::zvmUtils->printSyslog("vmcp DETACH $vdev");
+ }
}
- # Add to active configuration
- $out .= "Adding 3390 disk for $node as $addr ... Done";
- my $power = `/opt/xcat/bin/rpower $node stat`;
- if ($power =~ m/: on/i) {
- $out .= "\n" . `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli Image_Disk_Create -T $userId -v $addr -m $mode"`;
- xCAT::zvmUtils->printSyslog("smcli Image_Disk_Create -T $userId -v $addr -m $mode");
- }
+ if ( !$error ) {
+ # Add to active configuration
+ $out .= "Adding 3390 disk for $node as $addr ... Done";
+ my $power = `/opt/xcat/bin/rpower $node stat`;
+ if ($power =~ m/: on/i) {
+ $out .= "\n" . `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli Image_Disk_Create -T $userId -v $addr -m $mode"`;
+ xCAT::zvmUtils->printSyslog("smcli Image_Disk_Create -T $userId -v $addr -m $mode");
+ }
- $out = xCAT::zvmUtils->appendHostname( $node, $out );
+ $out = xCAT::zvmUtils->appendHostname( $node, $out );
+ }
}
# add3390active [device address] [mode]
@@ -1198,38 +1288,79 @@ sub changeVM {
$error = 1;
}
+ my $device = 0;
+ my $newlinkcall = 0;
+ my $rc = 0;
+ my $vdev;
+
if ( $fstype && !$error ) { # Format the disk before making it active.
# link the disk
- my $retry = 3;
- my $vdev = xCAT::zvmUtils->getFreeAddress( $::SUDOER, $hcp, 'vmcp' );
- while ( $retry > 0 ) {
- # wait 2 seconds for disk creation complete
- sleep(2);
- $out = `ssh $::SUDOER\@$hcp "$::SUDO /sbin/vmcp LINK TO $userId $addr AS $vdev M 2>&1"`;
- $error = (xCAT::zvmUtils->checkOutput( $out ) == -1) ? 1 : 0;
+ # Check if zhcp has the new routine to link and online the disk
+ $out = `ssh -o ConnectTimeout=30 $::SUDOER\@$hcp "$::SUDO $::DIR/linkdiskandbringonline $userId $addr $mode"`;
+ $rc = $?;
- if ($error) {
- $retry -= 1;
- $vdev = xCAT::zvmUtils->getFreeAddress( $::SUDOER, $hcp, 'vmcp' );
+ $rc = $? >> 8;
+ if ($rc == 255) {
+ xCAT::zvmUtils->printSyslog( "$node: changeVM() Unable to communicate with zHCP agent" );
+ xCAT::zvmUtils->printLn( $callback, "$node: changeVM() Unable to communicate with zHCP agent: $hcp" );
+ $error = 1;
+ } elsif ( $rc > 0 && $rc != 127 ) {
+ xCAT::zvmUtils->printSyslog( "$node: changeVM() Unexpected error from SSH call to linkdiskandbringonline rc: $rc $out" );
+ xCAT::zvmUtils->printLn( $callback, "$node: changeVM() Unexpected error from SSH call to linkdiskandbringonline rc: $rc $out" );
+ $error = 1;
+ } elsif ( $rc ==0 ) {
+ $newlinkcall = 1;
+ if ($out =~ m/Success:/i){
+ # sample output=>linkdiskandbringonline maint start time: 2017-03-03-16:20:48.011
+ # Success: Userid maint vdev 193 linked at ad35 device name dasdh
+ # linkdiskandbringonline exit time: 2017-03-03-16:20:52.150
+ $out = `echo "$out" | egrep -a -i "Success:"`;
+ my @info = split( ' ', $out );
+ $device = $info[10];
} else {
- last;
+ xCAT::zvmUtils->printSyslog( "$node: changeVM() Error occurred in call to linkdiskandbringonline: $out" );
+ xCAT::zvmUtils->printLn( $callback, "$node: changeVM()(Error occurred in call to linkdiskandbringonline: $out" );
+ $error = 1;
}
- }
+ } else {
+ xCAT::zvmUtils->printSyslog( "$node: changeVM() Could not find zhcp linkdiskandbringonline, using old code path." );
+ my $retry = 3;
+ $vdev = xCAT::zvmUtils->getFreeAddress( $::SUDOER, $hcp, 'vmcp' );
+ while ( $retry > 0 ) {
+ # wait 2 seconds for disk creation complete
+ sleep(2);
+ $out = `ssh $::SUDOER\@$hcp "$::SUDO /sbin/vmcp LINK TO $userId $addr AS $vdev M 2>&1"`;
+ $error = (xCAT::zvmUtils->checkOutput( $out ) == -1) ? 1 : 0;
- # make the disk online and get it's device name
- my $device = 0;
- if ( !$error ) {
- $out = `ssh $::SUDOER\@$hcp "$::SUDO /sbin/cio_ignore -r $vdev &> /dev/null"`;
- $out = xCAT::zvmUtils->disableEnableDisk( $::SUDOER, $hcp, "-e", $vdev );
- my $select = `ssh $::SUDOER\@$hcp "$::SUDO cat /proc/dasd/devices | grep -a 0.0.$vdev"`;
- chomp( $select );
- # A sample entry:
- # 0.0.1300(FBA ) at ( 94: 56) is dasdo : active at blocksize: 512, 7291441 blocks, 3560 MB
- if ( $select ) {
- my @info = split( ' ', $select );
- $device = "/dev/" . $info[7];
+ if ($error) {
+ $retry -= 1;
+ $vdev = xCAT::zvmUtils->getFreeAddress( $::SUDOER, $hcp, 'vmcp' );
+ } else {
+ last;
+ }
+ }
+
+ # make the disk online and get it's device name
+ if ( !$error ) {
+ $out = `ssh $::SUDOER\@$hcp "$::SUDO /sbin/cio_ignore -r $vdev &> /dev/null"`;
+ $out = xCAT::zvmUtils->disableEnableDisk( $::SUDOER, $hcp, "-e", $vdev );
+ my $select = `ssh $::SUDOER\@$hcp "$::SUDO cat /proc/dasd/devices"`;
+ ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO cat /proc/dasd/devices\"", $hcp, "changeVM", $select, $node );
+ if ($rc != 0) {
+ xCAT::zvmUtils->printLn( $callback, "$outmsg" );
+ $error = 1;
+ } else {
+ $out = `echo "$out" | egrep -a -i "0.0.$vdev"`;
+ chomp( $select );
+ # A sample entry:
+ # 0.0.0101(ECKD) at ( 94: 0) is dasda : active at blocksize: 4096, 600840 blocks, 2347 MB
+ if ( $select ) {
+ my @info = split( ' ', $select );
+ $device = "/dev/" . $info[6];
+ }
+ $error = !$device;
+ }
}
- $error = !$device;
}
#Delete the existing partition in case the disk already has partition on it
@@ -1240,6 +1371,9 @@ d
w
EOF"`;
$error = (xCAT::zvmUtils->checkOutput( $out ) == -1) ? 1 : 0;
+ if ($error) {
+ xCAT::zvmUtils->printSyslog( "Error occurred during fdisk $device. Output: $out" );
+ }
}
# Create one partition to use the entire disk space
@@ -1254,15 +1388,24 @@ p
w
EOF"`;
$error = (xCAT::zvmUtils->checkOutput( $out ) == -1) ? 1 : 0;
+ if ($error) {
+ xCAT::zvmUtils->printSyslog( "Error occurred during fdisk to make a partition on $device. Output: $out" );
+ }
}
if ( !$error ) {
$device .= '1';
if ( $fstype =~ m/xfs/i ) {
$out = `ssh $::SUDOER\@$hcp "$::SUDO mkfs.xfs $device 2>&1"`;
$error = (xCAT::zvmUtils->checkOutput( $out ) == -1) ? 1 : 0;
+ if ($error) {
+ xCAT::zvmUtils->printSyslog( "Error occurred during mkfs.xfs $device. Output: $out" );
+ }
} else {
$out = `ssh $::SUDOER\@$hcp "$::SUDO mkfs -t $fstype $device 2>&1"`;
$error = !($out =~ m/done/);
+ if ($error) {
+ xCAT::zvmUtils->printSyslog( "Error occurred during mkfs $fstype $device. Output: $out" );
+ }
}
}
if ( $error ) {
@@ -1272,20 +1415,48 @@ EOF"`;
$out = "";
}
- xCAT::zvmUtils->disableEnableDisk( $::SUDOER, $hcp, "-d", $vdev );
- `ssh $::SUDOER\@$hcp "$::SUDO /sbin/vmcp DETACH $vdev &> /dev/null"`;
- xCAT::zvmUtils->printSyslog("vmcp DETACH $vdev");
- }
+ # offline and detach disk using new call so that zhcp records are updated
+ if ( $newlinkcall == 1 ){
+ $out = `ssh -o ConnectTimeout=30 $::SUDOER\@$hcp "$::SUDO $::DIR/offlinediskanddetach $userId $addr"`;
+ $rc = $?;
- # Add to active configuration
- $out .= "Adding 9336 disk for $node as $addr ... Done";
- my $power = `/opt/xcat/bin/rpower $node stat`;
- if ($power =~ m/: on/i) {
- $out .= "\n" . `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli Image_Disk_Create -T $userId -v $addr -m $mode"`;
- xCAT::zvmUtils->printSyslog("smcli Image_Disk_Create -T $userId -v $addr -m $mode");
+ $rc = $? >> 8;
+ if ( $rc == 255 ) {
+ xCAT::zvmUtils->printSyslog( "$node: changeVM() Unable to communicate with zHCP agent" );
+ xCAT::zvmUtils->printLn( $callback, "$node: changeVM()( is unable to communicate with zHCP agent: $hcp" );
+ $error = 1;
+ }
+ if ( $rc > 0 ) {
+ xCAT::zvmUtils->printSyslog( "$node: changeVM() Unexpected error from SSH call to offlinediskanddetach rc: $rc $out" );
+ xCAT::zvmUtils->printLn( $callback, "$node: changeVM()Unexpected error from SSH call to offlinediskanddetach rc: $rc $out" );
+ $error = 1;
+ }
+ if ($out =~ m/Success:/i){
+ # sample output=>Success: Userid maint vdev 193 unlinked
+ xCAT::zvmUtils->printSyslog("$out");
+ } else {
+ xCAT::zvmUtils->printSyslog( "$node: changeVM() Error occurred in call to offlinediskanddetach: $out" );
+ xCAT::zvmUtils->printLn( $callback, "$node: changeVM() Error occurred in call to offlinediskanddetach: $out" );
+ $error = 1;
+ }
+ # Use old code to disable and detach
+ } else {
+ xCAT::zvmUtils->disableEnableDisk( $::SUDOER, $hcp, "-d", $vdev );
+ `ssh $::SUDOER\@$hcp "$::SUDO /sbin/vmcp DETACH $vdev &> /dev/null"`;
+ xCAT::zvmUtils->printSyslog("vmcp DETACH $vdev");
+ }
}
+ if (!$error) {
+ # Add to active configuration
+ $out .= "Adding 9336 disk for $node as $addr ... Done";
+ my $power = `/opt/xcat/bin/rpower $node stat`;
+ if ($power =~ m/: on/i) {
+ $out .= "\n" . `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli Image_Disk_Create -T $userId -v $addr -m $mode"`;
+ xCAT::zvmUtils->printSyslog("smcli Image_Disk_Create -T $userId -v $addr -m $mode");
+ }
- $out = xCAT::zvmUtils->appendHostname( $node, $out );
+ $out = xCAT::zvmUtils->appendHostname( $node, $out );
+ }
}
# adddisk2pool [function] [region] [volume] [group]
@@ -1438,6 +1609,10 @@ EOF"`;
if ($useWwpnLun) {
# Store current attributes of the SCSI/FCP device in case need to roll back when something goes wrong
my $deviceRef = xCAT::zvmUtils->findzFcpDeviceAttr($::SUDOER, $hcp, $pool, $wwpn, $lun);
+ if (xCAT::zvmUtils->checkOutput( $deviceRef ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$deviceRef" );
+ return;
+ }
%zFCP = %$deviceRef;
# Check current status of the FCP device
@@ -1582,9 +1757,13 @@ EOF"`;
}
# Check if the config file already exists and contains the zFCP channel
- $cmd = $::SUDO . ' cat /etc/udev/rules.d/51-zfcp-0.0.' . $cur_device . '.rules | egrep -a -i ccw/0.0.' . $cur_device. ']online';
+ $cmd = $::SUDO . ' cat /etc/udev/rules.d/51-zfcp-0.0.' . $cur_device . '.rules';
$out = xCAT::zvmUtils->execcmdonVM($::SUDOER, $node, $cmd);
if (xCAT::zvmUtils->checkOutput( $out ) == -1) {
+ return;
+ }
+ $out = `echo "$out" | egrep -a -i 'ccw/0.0.' . $cur_device. ']online'`;
+ if (!(length $out)) {
# Configure zFCP device to be persistent
$cmd = "$::SUDO touch /etc/udev/rules.d/51-zfcp-0.0.$cur_device.rules";
$out = xCAT::zvmUtils->execcmdonVM($::SUDOER, $node, $cmd, $callback);
@@ -2022,8 +2201,12 @@ EOF"`;
next;
}
- $cmd = $::SUDO . ' /sbin/udevadm info --query=all --name=' . $srcFile . ' | grep -a "ID_SERIAL="';
- $out = xCAT::zvmUtils->execcmdonVM($::SUDOER, $node, $cmd);
+ $cmd = $::SUDO . ' /sbin/udevadm info --query=all --name=' . $srcFile;
+ $out = xCAT::zvmUtils->execcmdonVM($::SUDOER, $node, $cmd, $callback);
+ if (xCAT::zvmUtils->checkOutput( $out ) == -1) {
+ return;
+ }
+ $out = `echo "$out" | egrep -a -i "ID_SERIAL="`;
$out =~ m/ID_SERIAL=(\w+)\s*$/;
$wwid = $1;
if ($wwid) { last; }
@@ -2522,13 +2705,23 @@ EOF"`;
# Find the pool that contains the SCSI/FCP device
my $pool = xCAT::zvmUtils->findzFcpDevicePool($::SUDOER, $hcp, $wwpn, $lun);
+ if (xCAT::zvmUtils->checkOutput( $pool ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$pool" );
+ return;
+ }
if (!$pool) {
# Continue to try and remove the SCSI/FCP device even when it is not found in a storage pool
xCAT::zvmUtils->printLn( $callback, "$node: Could not find FCP device in any FCP storage pool" );
} else {
xCAT::zvmUtils->printLn( $callback, "$node: Found FCP device in $pool" );
- my $select = `ssh $::SUDOER\@$hcp "$::SUDO cat $::ZFCPPOOL/$pool.conf" | grep -a -i "$wwpn,$lun"`;
+ my $select = `ssh $::SUDOER\@$hcp "$::SUDO cat $::ZFCPPOOL/$pool.conf"`;
+ ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO cat $::ZFCPPOOL/$pool.conf\" ", $hcp, "changeVM", $select, $node );
+ if ($rc != 0) {
+ xCAT::zvmUtils->printLn( $callback, "$outmsg" );
+ return;
+ }
+ $select = `echo "$select" | egrep -a -i "$wwpn,$lun"`;
chomp($select);
my @info = split(',', $select);
@@ -2873,8 +3066,14 @@ EOF"`;
'30','31','32','33','34','35','36','37','39','39','3A','3B','3C','3D','3E','3F');
# Get current CPU count and address
- my $proc = `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli Image_Definition_Query_DM -T $userId -k CPU" | grep -a CPU=`;
- xCAT::zvmUtils->printSyslog("smcli Image_Definition_Query_DM -T $userId -k CPU | grep -a CPU=");
+ xCAT::zvmUtils->printSyslog("smcli Image_Definition_Query_DM -T $userId -k CPU");
+ my $proc = `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli Image_Definition_Query_DM -T $userId -k CPU"`;
+ ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO $::DIR/smcli Image_Definition_Query_DM -T $userId -k CPU\"", $hcp, "changeVM", $proc, $node );
+ if ($rc != 0) {
+ xCAT::zvmUtils->printLn( $callback, "$outmsg" );
+ return;
+ }
+ $proc = `echo "$proc" | egrep -a -i CPU=`;
while ( index( $proc, "CPUADDR" ) != -1) {
my $position = index($proc, "CPUADDR");
my $address = substr($proc, $position + 8, 2);
@@ -3420,8 +3619,6 @@ sub powerVM {
xCAT::zvmUtils->printLn( $callback, "$node: unreachable");
return;
}
-
-
# Create output string
if ($out) {
xCAT::zvmUtils->printLn( $callback, "$node: reachable");
@@ -3648,7 +3845,7 @@ sub scanVM {
Description : Get hardware and software inventory of a given node
Arguments : Node
Type of inventory (all|config|console [logsize]|cpumem|cpumempowerstat|--freerepospace)
- Returns : Nothing
+ Returns : Nothing, errors returned in $callback
Example : inventoryVM($callback, $node, $args);
=cut
@@ -3662,6 +3859,9 @@ sub inventoryVM {
# Output string
my $str = "";
+ my $outmsg;
+ my $rc;
+
# Check if node is pingable
if (($args->[0] ne '--consoleoutput') and ($args->[0] ne 'cpumempowerstat')){
my $ping = xCAT::zvmUtils->pingNode($node);
@@ -3752,6 +3952,10 @@ sub inventoryVM {
# Get instance CPU used time
my $cputime = xCAT::zvmUtils->getUsedCpuTime($::SUDOER, $hcp , $node);
+ if (xCAT::zvmUtils->checkOutput( $cputime ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$cputime" );
+ return;
+ }
$str .= "Total Memory: $memory\n";
$str .= "Processors: \n$proc\n";
@@ -3856,6 +4060,10 @@ sub inventoryVM {
# Get instance CPU used time
my $cputime = xCAT::zvmUtils->getUsedCpuTime($::SUDOER, $hcp , $node);
+ if (xCAT::zvmUtils->checkOutput( $cputime ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$cputime" );
+ return;
+ }
# Create output string
$str .= "z/VM UserID: $userId\n";
@@ -3914,7 +4122,13 @@ sub inventoryVM {
xCAT::zvmUtils->printSyslog( "vmcp spool c class return: $out" );
# Get console output from zhcp
- $out = `ssh $::SUDOER\@$hcp "$::SUDO /usr/sbin/vmur list | egrep -a -i $userId "`;
+ $out = `ssh $::SUDOER\@$hcp "$::SUDO /usr/sbin/vmur list"`;
+ ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO /usr/sbin/vmur list\"", $hcp, "inventoryVM", $out, $node );
+ if ($rc != 0) {
+ xCAT::zvmUtils->printLn( $callback, "$outmsg" );
+ return;
+ }
+ $out = `echo "$out" | egrep -a -i "$userId "`;
my @spoolFiles = sort(split('\n', $out));
$str = "";
foreach (@spoolFiles){
@@ -4206,6 +4420,8 @@ sub makeVM {
# Create a new user in zVM without user directory entry file
my $out;
+ my $outmsg;
+ my $rc;
my $stdin;
my $password = "";
my $memorySize = "";
@@ -4313,14 +4529,20 @@ sub makeVM {
$out = `ssh -o ConnectTimeout=5 $::SUDOER\@$hcp "/sbin/modprobe vmcp"`;
# Get USER Prefix
- my $prefix = `ssh -o ConnectTimeout=5 $::SUDOER\@$hcp "$::SUDO /sbin/vmcp q vmlan" | egrep -a -i "USER Prefix:"`;
+ my $out = `ssh -o ConnectTimeout=5 $::SUDOER\@$hcp "$::SUDO /sbin/vmcp q vmlan"`;
+ ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh -o ConnectTimeout=5 $::SUDOER\@$hcp \"$::SUDO /sbin/vmcp q vmlan\"", $hcp, "makeVM", $out, $node );
+ if ($rc != 0) {
+ xCAT::zvmUtils->printLn( $callback, "$outmsg" );
+ return;
+ }
+ my $prefix = `echo "$out" | egrep -a -i "USER Prefix:"`;
$prefix =~ s/(.*?)USER Prefix:(.*)/$2/;
$prefix =~ s/^\s+//;
$prefix =~ s/\s+$//;
# Get MACADDR Prefix instead if USER Prefix is not defined
if (!$prefix) {
- $prefix = `ssh -o ConnectTimeout=5 $::SUDOER\@$hcp "$::SUDO /sbin/vmcp q vmlan" | egrep -a -i "MACADDR Prefix:"`;
+ $prefix = `echo "$out" | egrep -a -i "MACADDR Prefix:"`;
$prefix =~ s/(.*?)MACADDR Prefix:(.*)/$2/;
$prefix =~ s/^\s+//;
$prefix =~ s/\s+$//;
@@ -4387,7 +4609,6 @@ sub makeVM {
my $oldNicDef;
my $nicDef;
my $id;
- my $rc;
my @vswId;
my $target = "$::SUDOER\@$hcp";
if ($userEntry) {
@@ -4619,6 +4840,10 @@ sub cloneVM {
my $sourceIp = xCAT::zvmUtils->getIp($sourceNode);
my @dedicates = xCAT::zvmUtils->getDedicates( $callback, $::SUDOER, $sourceNode );
+ if (xCAT::zvmUtils->checkOutput( $dedicates[0] ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$dedicates[0]" );
+ return;
+ }
if (scalar(@dedicates)) {
xCAT::zvmUtils->printLn( $callback, "$sourceNode: (Error) Dedicate statements found in source directory." );
return;
@@ -4728,6 +4953,10 @@ sub cloneVM {
# Create MAC address (target)
$targetMac = xCAT::zvmUtils->createMacAddr( $::SUDOER, $_, $macId );
+ if (xCAT::zvmUtils->checkOutput( $targetMac ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$targetMac" );
+ return;
+ }
# Save MAC address in 'mac' table
xCAT::zvmUtils->setNodeProp( 'mac', $_, 'mac', $targetMac );
@@ -4756,6 +4985,10 @@ sub cloneVM {
# $srcLinkAddr[$addr] = $type
my %srcDiskType;
my @srcDisks = xCAT::zvmUtils->getMdisks( $callback, $::SUDOER, $sourceNode );
+ if (xCAT::zvmUtils->checkOutput( $srcDisks[0] ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$srcDisks[0]" );
+ return;
+ }
# Get details about source disks
# Output is similar to:
@@ -4938,6 +5171,10 @@ sub cloneVM {
my $srcUserEntry = "/tmp/$sourceNode.txt";
$out = `rm $srcUserEntry`;
$out = xCAT::zvmUtils->getUserEntryWODisk( $callback, $::SUDOER, $sourceNode, $srcUserEntry );
+ if (xCAT::zvmUtils->checkOutput( $out ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$out" );
+ return;
+ }
# Check if user entry is valid
$out = `cat $srcUserEntry`;
@@ -5074,7 +5311,7 @@ sub cloneVM {
Root parition device address
Path to network configuration file
Path to hardware configuration file (SUSE only)
- Returns : Nothing
+ Returns : Nothing, errors returned in $callback
Example : clone($callback, $_, $args, \@srcDisks, \%srcLinkAddr, \%srcDiskSize,
$srcNicAddr, $hcpNetName, \@srcVswitch, $srcOs, $srcMac, $netEntries,
$sourceIp, $srcNetwork, $srcMask);
@@ -5162,6 +5399,7 @@ sub clone {
xCAT::zvmUtils->printSyslog("hcp:$hcp tgtUserId:$tgtUserId targetIp:$targetIp");
my $out;
+ my $outmsg;
my @lines;
my @words;
@@ -5454,8 +5692,14 @@ sub clone {
while ( $try > 0 ) {
# Get disks within user entry
- $out = `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli Image_Query_DM -T $tgtUserId" | sed '\$d' | grep -a "MDISK"`;
- xCAT::zvmUtils->printSyslog("smcli Image_Query_DM -T $tgtUserId | grep -a MDISK");
+ xCAT::zvmUtils->printSyslog("smcli Image_Query_DM -T $tgtUserId");
+ $out = `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli Image_Query_DM -T $tgtUserId"`;
+ ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO $::DIR/smcli Image_Query_DM -T $tgtUserId\"", $hcp, "clone", $out, $tgtNode );
+ if ($rc != 0) {
+ xCAT::zvmUtils->printLn( $callback, "$outmsg" );
+ return;
+ }
+ $out = `echo "$out" | sed '\$d' | grep -a -i "MDISK"`;
xCAT::zvmUtils->printSyslog("$out");
@disks = split( '\n', $out );
@@ -5795,12 +6039,24 @@ sub clone {
while (!$out && $try > 0) {
# Check if /usr/bin/file is available
if (`ssh $::SUDOER\@$hcp "$::SUDO test -f /usr/bin/file && echo Exists"`) {
- $out = `ssh $::SUDOER\@$hcp "$::SUDO /usr/bin/file -s /dev/$tgtDevNode*" | grep -a -v swap | grep -a -o "$tgtDevNode\[1-9\]"`;
+ xCAT::zvmUtils->printSyslog("ssh $::SUDOER\@$hcp \"$::SUDO /usr/bin/file -s /dev/$tgtDevNode*\"");
+ $out = `ssh $::SUDOER\@$hcp "$::SUDO /usr/bin/file -s /dev/$tgtDevNode*"`;
+ ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO /usr/bin/file -s /dev/$tgtDevNode*\"", $hcp, "clone", $out, $tgtDevNode );
+ if ($rc != 0) {
+ xCAT::zvmUtils->printLn( $callback, "$outmsg" );
+ return;
+ }
} else {
- $out = `ssh $::SUDOER\@$hcp "$::SUDO /sbin/fdisk -l /dev/$tgtDevNode* | grep -a -v swap | grep -a -o $tgtDevNode\[1-9\]"`;
+ xCAT::zvmUtils->printSyslog("ssh $::SUDOER\@$hcp \"$::SUDO /sbin/fdisk -l /dev/$tgtDevNode*\"");
+ $out = `ssh $::SUDOER\@$hcp "$::SUDO /sbin/fdisk -l /dev/$tgtDevNode*"`;
+ ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO /sbin/fdisk -l /dev/$tgtDevNode*\"", $hcp, "clone", $out, $tgtDevNode );
+ if ($rc != 0) {
+ xCAT::zvmUtils->printLn( $callback, "$outmsg" );
+ return;
+ }
}
+ $out = `echo "$out" | egrep -a -i -v swap | egrep -a -o "$tgtDevNode\[1-9\]"`;
$out = xCAT::zvmUtils->trimStr($out);
- xCAT::zvmUtils->printSyslog("fdisk -l /dev/$tgtDevNode* | grep -a -v swap | grep -a -o $tgtDevNode\[1-9\]");
xCAT::zvmUtils->printSyslog("$out");
# Wait before trying again
@@ -5868,8 +6124,14 @@ sub clone {
# If it is Red Hat - ifcfg-qeth file is in /etc/sysconfig/network-scripts
my @files;
if ( $srcOs =~ m/rhel/i ) {
- $out = `ssh $::SUDOER\@$hcp "$::SUDO grep -a -H -i -r $srcNicAddr $cloneMntPt/etc/sysconfig/network-scripts | grep -a -i 'ifcfg-eth' "`;
xCAT::zvmUtils->printSyslog("grep -a -H -i -r $srcNicAddr $cloneMntPt/etc/sysconfig/network-scripts");
+ $out = `ssh $::SUDOER\@$hcp "$::SUDO grep -a -H -i -r $srcNicAddr $cloneMntPt/etc/sysconfig/network-scripts"`;
+ ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO grep -a -H -i -r $srcNicAddr $cloneMntPt/etc/sysconfig/network-scripts\"", $hcp, "clone", $out, $tgtDevNode );
+ if ($rc != 0) {
+ xCAT::zvmUtils->printLn( $callback, "$outmsg" );
+ return;
+ }
+ $out = `echo "$out" | egrep -a -i 'ifcfg-eth'`;
xCAT::zvmUtils->printSyslog("$out");
@files = split('\n', $out);
@words = split( ':', $files[0] );
@@ -5932,15 +6194,20 @@ sub clone {
# Set MAC address
my $networkFile = $tgtNode . "NetworkConfig";
my $config;
- if ( $srcOs =~ m/rhel/i ) {
+ $config = `ssh $::SUDOER\@$hcp "$::SUDO cat $ifcfgPath"`;
+ ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO cat $ifcfgPath\"", $hcp, "clone", $config, $tgtDevNode );
+ if ($rc != 0) {
+ xCAT::zvmUtils->printLn( $callback, "$outmsg" );
+ return;
+ }
+ if ( $srcOs =~ m/rhel/i ) {
# Red Hat only
- $config = `ssh $::SUDOER\@$hcp "$::SUDO cat $ifcfgPath" | grep -a -v "MACADDR"`;
+ $config = `echo "$config" | egrep -a -i -v "MACADDR"`;
$config .= "MACADDR='" . $targetMac . "'\n";
} else {
-
# SUSE only
- $config = `ssh $::SUDOER\@$hcp "$::SUDO cat $ifcfgPath" | grep -a -v "LLADDR" | grep -a -v "UNIQUE"`;
+ $config = `echo "$config" | egrep -a -i -v "LLADDR" | egrep -a -i -v "UNIQUE"`;
# Set to MAC address (only for layer 2)
if ( $layer == 2 ) {
@@ -6033,7 +6300,7 @@ sub clone {
* Punch initrd, kernel, and parmfile to node reader
* Layer 2 and 3 VSwitch/Lan supported
Arguments : Node
- Returns : Nothing
+ Returns : Nothing, errors returned in $callback
Example : nodeSet($callback, $node, $args);
=cut
@@ -6158,6 +6425,7 @@ sub nodeSet {
# Get action
my $out;
+ my $outmsg;
if ( $action eq "install" ) {
# Get node root password
@@ -6611,7 +6879,13 @@ sub nodeSet {
my $zfcpSection = "";
foreach (@pools) {
if (!(length $_)) {next;}
- $entry = `ssh $::SUDOER\@$hcp "$::SUDO cat $::ZFCPPOOL/$_" | egrep -a -i ",$node,"`;
+ $entry = `ssh $::SUDOER\@$hcp "$::SUDO cat $::ZFCPPOOL/$_"`;
+ ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO cat $::ZFCPPOOL/$_\"", $hcp, "nodeSet", $entry, $node );
+ if ($rc != 0) {
+ xCAT::zvmUtils->printLn( $callback, "$outmsg" );
+ return;
+ }
+ $entry = `echo "$entry" | egrep -a -i ",$node,"`;
chomp($entry);
if (!$entry) {
next;
@@ -6895,7 +7169,13 @@ END
my $zfcpSection = "";
foreach (@pools) {
if (!(length $_)) {next;}
- $entry = `ssh $::SUDOER\@$hcp "$::SUDO cat $::ZFCPPOOL/$_" | egrep -a -i ",$node,"`;
+ $entry = `ssh $::SUDOER\@$hcp "$::SUDO cat $::ZFCPPOOL/$_"`;
+ ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO cat $::ZFCPPOOL/$_\"", $hcp, "nodeSet", $entry, $node );
+ if ($rc != 0) {
+ xCAT::zvmUtils->printLn( $callback, "$outmsg" );
+ return;
+ }
+ $entry = `echo "$entry" | egrep -a -i ",$node,"`;
chomp($entry);
if (!$entry) {
next;
@@ -6973,6 +7253,10 @@ END
# Get mdisk virtual address
my @mdisks = xCAT::zvmUtils->getMdisks( $callback, $::SUDOER, $node );
+ if (xCAT::zvmUtils->checkOutput( $mdisks[0] ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$mdisks[0]" );
+ return;
+ }
@mdisks = sort(@mdisks);
my $dasd = "";
my $devices = "";
@@ -6998,6 +7282,10 @@ END
# Get dedicated virtual address
my @dedicates = xCAT::zvmUtils->getDedicates( $callback, $::SUDOER, $node );
+ if (xCAT::zvmUtils->checkOutput( $dedicates[0] ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$dedicates[0]" );
+ return;
+ }
@dedicates = sort(@dedicates);
$i = 0;
foreach (@dedicates) {
@@ -7217,7 +7505,13 @@ END
my $tmpInitFile = "/tmp/$os-initrd-statelite.gz";
xCAT::zvmUtils->printLn( $callback, "$node: Looking for kernel $os-kernel." );
- if (`ssh -o ConnectTimeout=5 $::SUDOER\@$hcp "$::SUDO ls /tmp" | grep -a "$os-kernel"`) {
+ $out = `ssh -o ConnectTimeout=5 $::SUDOER\@$hcp "$::SUDO ls /tmp"`;
+ ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh -o ConnectTimeout=5 $::SUDOER\@$hcp \"$::SUDO ls /tmp\"", $hcp, "nodeSet", $out, $node );
+ if ($rc != 0) {
+ xCAT::zvmUtils->printLn( $callback, "$outmsg" );
+ return;
+ }
+ if (`echo "$out" | egrep -a -i "$os-kernel"`) {
# Do nothing
} else {
# Send kernel to reader to HCP
@@ -7225,14 +7519,14 @@ END
xCAT::zvmUtils->printLn( $callback, "sendfile $kernelFile, $tmpKernelFile" );
}
- if (`ssh -o ConnectTimeout=5 $::SUDOER\@$hcp "$::SUDO ls /tmp" | grep -a "$os-parm-statelite"`) {
+ if (`echo "$out" | egrep -a -i "$"os-parm-statelite"`) {
# Do nothing
} else {
# Send parmfile to reader to HCP
xCAT::zvmUtils->sendFile( $::SUDOER, $hcp, $parmFile, $tmpParmFile );
}
- if (`ssh -o ConnectTimeout=5 $::SUDOER\@$hcp "$::SUDO ls /tmp" | grep -a "$os-initrd-statelite.gz"`) {
+ if (`echo "$out" | egrep -a -i "$os-initrd-statelite.gz"`) {
# Do nothing
} else {
# Send initrd to reader to HCP
@@ -7314,6 +7608,10 @@ END
# Handle sysclone which can have multiple image files which MUST match each mdisk
# Get the list of mdisks
my @srcDisks = xCAT::zvmUtils->getMdisks( $callback, $::SUDOER, $node );
+ if (xCAT::zvmUtils->checkOutput( $srcDisks[0] ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$srcDisks[0]" );
+ return;
+ }
# Verify the list of images and matching disks
my $validArrayDisks = 0;
@@ -7561,7 +7859,7 @@ END
* Requires the node be online
* Saves MAC address in 'mac' table
Arguments : Node
- Returns : Nothing
+ Returns : Nothing, errors returned in $callback
Example : getMacs($callback, $node, $args);
=cut
@@ -7579,6 +7877,10 @@ sub getMacs {
GetOptions( 'f' => \$force );
}
+ my $out;
+ my $outmsg;
+ my $rc;
+
# Get node properties from 'zvm' table
my @propNames = ( 'hcp', 'userid' );
my $propVals = xCAT::zvmUtils->getNodeProps( 'zvm', $node, @propNames );
@@ -7615,7 +7917,13 @@ sub getMacs {
xCAT::zvmCPUtils->loadVmcp($::SUDOER, $node);
# Get xCat MN Lan/VSwitch name
- my $out = `ssh -o ConnectTimeout=5 $::SUDOER\@$hcp "$::SUDO /sbin/vmcp q v nic" | egrep -a -i "VSWITCH|LAN"`;
+ $out = `ssh -o ConnectTimeout=5 $::SUDOER\@$hcp "$::SUDO /sbin/vmcp q v nic"`;
+ ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh -o ConnectTimeout=5 $::SUDOER\@$hcp \"$::SUDO /sbin/vmcp q v nic\"", $hcp, "getMacs", $out, $node );
+ if ($rc != 0) {
+ xCAT::zvmUtils->printLn( $callback, "$outmsg" );
+ return;
+ }
+ $out = `echo "$out" | egrep -a -i "VSWITCH|LAN"`;
my @lines = split( '\n', $out );
my @words;
@@ -8054,6 +8362,10 @@ sub listTree {
# Find out if this z/VM belongs to an SSI cluster
$ssi{$node} = xCAT::zvmUtils->querySSI($::SUDOER, $hcp);
+ if (xCAT::zvmUtils->checkOutput( $ssi{$node} ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$ssi{$node}" );
+ return;
+ }
# Find CEC root based on LPAR
# CEC -> LPAR
@@ -8182,7 +8494,7 @@ sub listTree {
Description : Configure the virtualization hosts
Arguments : Node
Arguments
- Returns : Nothing
+ Returns : Nothing, errors returned in $callback
Example : changeHypervisor($callback, $node, $args);
=cut
@@ -8219,6 +8531,8 @@ sub changeHypervisor {
# Output string
my $out = "";
+ my $outmsg;
+ my $rc;
# adddisk2pool [function] [region] [volume] [group]
if ( $args->[0] eq "--adddisk2pool" ) {
@@ -8552,11 +8866,19 @@ sub changeHypervisor {
xCAT::zvmUtils->printLn( $callback, "$node: (Error) Failed to find FCP device in any zFCP storage pool" );
return;
} else {
+ if (xCAT::zvmUtils->checkOutput( $pool ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$pool" );
+ return;
+ }
xCAT::zvmUtils->printLn( $callback, "$node: Found FCP device in $pool" );
}
# Get source device's attributes
my $srcDiskRef = xCAT::zvmUtils->findzFcpDeviceAttr($::SUDOER, $hcp, $pool, $srcWwpn, $srcLun);
+ if (xCAT::zvmUtils->checkOutput( $srcDiskRef ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$srcDiskRef" );
+ return;
+ }
my %srcDisk = %$srcDiskRef;
if (!defined($srcDisk{'lun'}) && !$srcDisk{'lun'}) {
xCAT::zvmUtils->printLn( $callback, "$node: (Error) Source zFCP device $srcWwpn/$srcLun does not exists" );
@@ -8568,6 +8890,10 @@ sub changeHypervisor {
my $tgtSize;
if ($useWwpnLun) {
my $tgtDiskRef = xCAT::zvmUtils->findzFcpDeviceAttr($::SUDOER, $hcp, $pool, $tgtWwpn, $tgtLun);
+ if (xCAT::zvmUtils->checkOutput( $tgtDiskRef ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$tgtDiskRef" );
+ return;
+ }
my %tgtDisk = %$tgtDiskRef;
if (!defined($tgtDisk{'lun'}) && !$tgtDisk{'lun'}) {
xCAT::zvmUtils->printLn( $callback, "$node: (Error) Target zFCP device $tgtWwpn/$tgtLun does not exists" );
@@ -8793,11 +9119,19 @@ sub changeHypervisor {
xCAT::zvmUtils->printLn($callback, "$node: (Error) Failed to find FCP device in any zFCP storage pool");
return;
} else {
+ if (xCAT::zvmUtils->checkOutput( $pool ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$pool" );
+ return;
+ }
xCAT::zvmUtils->printLn($callback, "$node: Found FCP device in $pool");
}
# Get source device's attributes
my $srcDiskRef = xCAT::zvmUtils->findzFcpDeviceAttr($::SUDOER, $hcp, $pool, $wwpn, $lun);
+ if (xCAT::zvmUtils->checkOutput( $srcDiskRef ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$srcDiskRef" );
+ return;
+ }
my %srcDisk = %$srcDiskRef;
if (!defined($srcDisk{'lun'}) && !$srcDisk{'lun'}) {
xCAT::zvmUtils->printLn($callback, "$node: (Error) Source zFCP device $wwpn/$lun does not exists");
@@ -8972,6 +9306,10 @@ sub changeHypervisor {
xCAT::zvmUtils->printLn($callback, "$node: (Error) Failed to find FCP device in any zFCP storage pool");
return;
} else {
+ if (xCAT::zvmUtils->checkOutput( $pool ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$pool" );
+ return;
+ }
xCAT::zvmUtils->printLn($callback, "$node: Found FCP device in $pool");
}
@@ -9154,7 +9492,13 @@ sub changeHypervisor {
my $cur_lun = $_;
if (!(length $cur_lun)) {next;}
# Entry should contain: status, wwpn, lun, size, range, owner, channel, tag
- $entry = `ssh $::SUDOER\@$hcp "$::SUDO cat $::ZFCPPOOL/$pool.conf" | egrep -a -i $cur_lun`;
+ $entry = `ssh $::SUDOER\@$hcp "$::SUDO cat $::ZFCPPOOL/$pool.conf"`;
+ ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO cat $::ZFCPPOOL/$pool.conf\"", $hcp, "changeHypervisor", $entry, $node );
+ if ($rc != 0) {
+ xCAT::zvmUtils->printLn( $callback, "$outmsg" );
+ return;
+ }
+ $entry = `echo "$entry" | egrep -a -i "$cur_lun"`;
# Do not update if LUN does not exists, stop checking other luns if this one not found
if (!$entry) {
xCAT::zvmUtils->printLn( $callback, "$node: (Error) zFCP device $cur_lun does not exist" );
@@ -9285,6 +9629,10 @@ sub changeHypervisor {
if ($wwpn && $lun) {
# Check the status of the FCP device
my $deviceRef = xCAT::zvmUtils->findzFcpDeviceAttr($::SUDOER, $hcp, $pool, $wwpn, $lun);
+ if (xCAT::zvmUtils->checkOutput( $deviceRef ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$deviceRef" );
+ return;
+ }
my %zFCP = %$deviceRef;
if ($zFCP{'status'} eq 'used') {
xCAT::zvmUtils->printLn($callback, "$node: (Error) FCP device 0x$wwpn/0x$lun is in use.");
@@ -9386,7 +9734,7 @@ sub changeHypervisor {
Description : Get hardware and software inventory of a given hypervisor
Arguments : Node
Type of inventory (config|all)
- Returns : Nothing
+ Returns : Nothing, errors returned in $callback
Example : inventoryHypervisor($callback, $node, $args);
=cut
@@ -9404,6 +9752,8 @@ sub inventoryHypervisor {
my $str = "";
my $rc;
+ my $out;
+ my $outmsg;
# Get node properties from 'zvm' table
my @propNames = ( 'hcp' );
@@ -9422,7 +9772,7 @@ sub inventoryHypervisor {
my $hcpUserId = xCAT::zvmCPUtils->getUserId($::SUDOER, $hcp);
# Load VMCP module
- my $out = `ssh -o ConnectTimeout=5 $::SUDOER\@$hcp "$::SUDO /sbin/modprobe vmcp"`;
+ $out = `ssh -o ConnectTimeout=5 $::SUDOER\@$hcp "$::SUDO /sbin/modprobe vmcp"`;
# Get configuration
if ( $args->[0] eq 'config' ) {
@@ -9431,18 +9781,38 @@ sub inventoryHypervisor {
# Get total physical CPU in this LPAR
my $lparCpuTotal = xCAT::zvmUtils->getLparCpuTotal($::SUDOER, $hcp);
+ if (xCAT::zvmUtils->checkOutput( $lparCpuTotal ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$lparCpuTotal" );
+ return;
+ }
# Get used physical CPU in this LPAR
my $lparCpuUsed = xCAT::zvmUtils->getLparCpuUsed($::SUDOER, $hcp);
+ if (xCAT::zvmUtils->checkOutput( $lparCpuUsed ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$lparCpuUsed" );
+ return;
+ }
# Get LPAR memory total
my $lparMemTotal = xCAT::zvmUtils->getLparMemoryTotal($::SUDOER, $hcp);
+ if (xCAT::zvmUtils->checkOutput( $lparMemTotal ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$lparMemTotal" );
+ return;
+ }
# Get LPAR memory Offline
my $lparMemOffline = xCAT::zvmUtils->getLparMemoryOffline($::SUDOER, $hcp);
+ if (xCAT::zvmUtils->checkOutput( $lparMemOffline ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$lparMemOffline" );
+ return;
+ }
# Get LPAR memory Used
my $lparMemUsed = xCAT::zvmUtils->getLparMemoryUsed($::SUDOER, $hcp);
+ if (xCAT::zvmUtils->checkOutput( $lparMemUsed ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$lparMemUsed" );
+ return;
+ }
$str .= "z/VM Host: $hypname\n";
$str .= "zHCP: $hcp\n";
@@ -9458,18 +9828,38 @@ sub inventoryHypervisor {
my $hypname = xCAT::zvmCPUtils->getHost($::SUDOER, $hcp);
# Get total physical CPU in this LPAR
my $lparCpuTotal = xCAT::zvmUtils->getLparCpuTotal($::SUDOER, $hcp);
+ if (xCAT::zvmUtils->checkOutput( $lparCpuTotal ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$lparCpuTotal" );
+ return;
+ }
# Get used physical CPU in this LPAR
my $lparCpuUsed = xCAT::zvmUtils->getLparCpuUsed($::SUDOER, $hcp);
+ if (xCAT::zvmUtils->checkOutput( $lparCpuUsed ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$lparCpuUsed" );
+ return;
+ }
# Get CEC model
my $cecModel = xCAT::zvmUtils->getCecModel($::SUDOER, $hcp);
+ if (xCAT::zvmUtils->checkOutput( $cecModel ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$cecModel" );
+ return;
+ }
# Get vendor of CEC
my $cecVendor = xCAT::zvmUtils->getCecVendor($::SUDOER, $hcp);
+ if (xCAT::zvmUtils->checkOutput( $cecVendor ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$cecVendor" );
+ return;
+ }
# Get hypervisor type and version
my $hvInfo = xCAT::zvmUtils->getHypervisorInfo($::SUDOER, $hcp);
+ if (xCAT::zvmUtils->checkOutput( $hvInfo ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$hvInfo" );
+ return;
+ }
# Get processor architecture
my $arch = xCAT::zvmUtils->getArch($::SUDOER, $hcp);
@@ -9479,12 +9869,24 @@ sub inventoryHypervisor {
# Get LPAR memory total
my $lparMemTotal = xCAT::zvmUtils->getLparMemoryTotal($::SUDOER, $hcp);
+ if (xCAT::zvmUtils->checkOutput( $lparMemTotal ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$lparMemTotal" );
+ return;
+ }
# Get LPAR memory Offline
my $lparMemOffline = xCAT::zvmUtils->getLparMemoryOffline($::SUDOER, $hcp);
+ if (xCAT::zvmUtils->checkOutput( $lparMemOffline ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$lparMemOffline" );
+ return;
+ }
# Get LPAR memory Used
my $lparMemUsed = xCAT::zvmUtils->getLparMemoryUsed($::SUDOER, $hcp);
+ if (xCAT::zvmUtils->checkOutput( $lparMemUsed ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$lparMemUsed" );
+ return;
+ }
# Get IPL Time
my $ipl = xCAT::zvmCPUtils->getIplTime($::SUDOER, $hcp);
@@ -9653,8 +10055,14 @@ sub inventoryHypervisor {
}
}
} else {
- $out = `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli System_WWPN_Query -T $hcpUserId" | egrep -a -i "FCP device number|Status"`;
- xCAT::zvmUtils->printSyslog("smcli System_WWPN_Query -T $hcpUserId | egrep -a -i FCP device number|Status");
+ xCAT::zvmUtils->printSyslog("smcli System_WWPN_Query -T $hcpUserId");
+ $out = `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli System_WWPN_Query -T $hcpUserId"`;
+ ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO $::DIR/smcli System_WWPN_Query -T $hcpUserId\"", $hcp, "inventoryHypervisor", $out, $node );
+ if ($rc != 0) {
+ xCAT::zvmUtils->printLn( $callback, "$outmsg" );
+ return;
+ }
+ $out = `echo "$out" | egrep -a -i "FCP device number|Status"`;
@devices = split( "\n", $out );
for ($i = 0; $i < @devices; $i++) {
@@ -9691,8 +10099,14 @@ sub inventoryHypervisor {
return;
}
- $out = `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli System_FCP_Free_Query -T $hcpUserId -k fcp_dev=$fcp" | egrep -a -i "FCP device number:|World wide port number:|Logical unit number:|Number of bytes residing on the logical unit:"`;
- xCAT::zvmUtils->printSyslog("smcli System_FCP_Free_Query -T $hcpUserId -k fcp_dev=$fcp | egrep -a -i FCP device number:|World wide port number:|Logical unit number:|Number of bytes residing on the logical unit:");
+ xCAT::zvmUtils->printSyslog("smcli System_FCP_Free_Query -T $hcpUserId -k fcp_dev=$fcp");
+ $out = `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli System_FCP_Free_Query -T $hcpUserId -k fcp_dev=$fcp"`;
+ ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO $::DIR/smcli System_FCP_Free_Query -T $hcpUserId -k fcp_dev=$fcp\"", $hcp, "inventoryHypervisor", $out, $node );
+ if ($rc != 0) {
+ xCAT::zvmUtils->printLn( $callback, "$outmsg" );
+ return;
+ }
+ $out = `echo "$out" | egrep -a -i "FCP device number:|World wide port number:|Logical unit number:|Number of bytes residing on the logical unit:"`;
my @wwpns = split( "\n", $out );
my %map;
@@ -9908,8 +10322,14 @@ sub inventoryHypervisor {
return;
}
- $out = `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli System_FCP_Free_Query -T $hcpUserId -k fcp_dev=$fcp" | egrep -a -i "World wide port number:"`;
- xCAT::zvmUtils->printSyslog("smcli System_FCP_Free_Query -T $hcpUserId -k fcp_dev=$fcp | egrep -a -i World wide port number:");
+ xCAT::zvmUtils->printSyslog("smcli System_FCP_Free_Query -T $hcpUserId -k fcp_dev=$fcp");
+ $out = `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli System_FCP_Free_Query -T $hcpUserId -k fcp_dev=$fcp"`;
+ ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO $::DIR/smcli System_FCP_Free_Query -T $hcpUserId -k fcp_dev=$fcp\"", $hcp, "inventorHypervisor", $out, $node );
+ if ($rc != 0) {
+ xCAT::zvmUtils->printLn( $callback, "$outmsg" );
+ return;
+ }
+ $out = `echo "$out" | egrep -a -i "World wide port number:"`;
my @wwpns = split( "\n", $out );
my %uniqueWwpns;
@@ -9942,7 +10362,14 @@ sub inventoryHypervisor {
$str = `ssh $::SUDOER\@$hcp "$::SUDO cat $::ZFCPPOOL/$pool.conf"`;
} else {
$str = "#status,wwpn,lun,size,range,owner,channel,tag\n";
- $str .= `ssh $::SUDOER\@$hcp "$::SUDO cat $::ZFCPPOOL/$pool.conf" | egrep -a -i $space`;
+ $out = `ssh $::SUDOER\@$hcp "$::SUDO cat $::ZFCPPOOL/$pool.conf"`;
+ ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO cat $::ZFCPPOOL/$pool.conf\"", $hcp, "inventoryHypervisor", $out, $node );
+ if ($rc != 0) {
+ xCAT::zvmUtils->printLn( $callback, "$outmsg" );
+ return;
+ }
+ $out = `echo "$out" | egrep -a -i "$space"`;
+ $str .= $out;
}
}
@@ -10421,7 +10848,7 @@ sub eventLog {
Profile
Device information
Compression level: 0 - none, 1 thru 9 - gzip compression level
- Returns : Nothing
+ Returns : Nothing, errors returned in $callback
Example : imageCapture( $callback, $node, $os, $arch, $type, $profile, $osimg, $device, $comp );
=cut
@@ -10431,6 +10858,7 @@ sub imageCapture {
my ($class, $callback, $node, $os, $arch, $type, $profile, $osimg, $device, $comp) = @_;
my $rc;
my $out = '';
+ my $outmsg;
my $reason = "";
my $provMethod;
my $compParm = "";
@@ -10532,12 +10960,12 @@ sub imageCapture {
if ($devName eq '/dev/root') {
# Determine which Linux device is associated with the root directory
#$out = `ssh $sudoer\@$node $sudo 'cat /proc/cmdline | tr " " "\\n" | grep -a "^root=" | cut -c6-'`;
- $cmd = "$::SUDO" . ' cat /proc/cmdline | tr " " "\\n" | grep -a "^root=" | cut -c6-';
+ $cmd = "$::SUDO" . ' cat /proc/cmdline | tr " " "\\n"';
$out = xCAT::zvmUtils->execcmdonVM($sudoer, $node, $cmd, $callback);
if (xCAT::zvmUtils->checkOutput( $out ) == -1) {
return;
}
-
+ $out = `echo "$out" | egrep -a -i "^root=" | cut '-c6-'`;
my $rootDev = '';
if ($out) {
@@ -10596,6 +11024,10 @@ sub imageCapture {
# Get the list of mdisks
my @srcDisks = xCAT::zvmUtils->getMdisks( $callback, $sudoer, $node );
+ if (xCAT::zvmUtils->checkOutput( $srcDisks[0] ) == -1) {
+ xCAT::zvmUtils->printLn( $callback, "$srcDisks[0]" );
+ return;
+ }
foreach (@srcDisks) {
# Get disk address
my @words = split( ' ', $_ );
@@ -10691,11 +11123,23 @@ sub imageCapture {
# Wait (checking every 15 seconds) until user is finally logged off or maximum wait time has elapsed
my $max = 0;
- $out=`ssh $sudoer\@$hcp "$sudo /sbin/vmcp q user $targetUserId 2>/dev/null | grep -a HCPCQU045E"`;
+ $out=`ssh $sudoer\@$hcp "$sudo /sbin/vmcp q user $targetUserId 2>/dev/null"`;
+ ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $sudoer\@$hcp \"$sudo /sbin/vmcp q user $targetUserId 2>/dev/null\"", $hcp, "imageCapture", $out, $node );
+ if ($rc != 0) {
+ xCAT::zvmUtils->printLn( $callback, "$outmsg" );
+ return;
+ }
+ $out = `echo "$out" | egrep -a -i "HCPCQU045E"`;
while ( !$out && $max < 60 ) {
sleep(15); # Wait 15 seconds
$max++;
- $out=`ssh $sudoer\@$hcp "$sudo /sbin/vmcp q user $targetUserId 2>/dev/null | grep -a HCPCQU045E"`;
+ $out=`ssh $sudoer\@$hcp "$sudo /sbin/vmcp q user $targetUserId 2>/dev/null"`;
+ ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $sudoer\@$hcp \"$sudo /sbin/vmcp q user $targetUserId 2>/dev/null\"", $hcp, "imageCapture", $out, $node );
+ if ($rc != 0) {
+ xCAT::zvmUtils->printLn( $callback, "$outmsg" );
+ return;
+ }
+ $out = `echo "$out" | egrep -a -i "HCPCQU045E"`;
}
my $totalMinutes = $max * 15 / 60;
if ( $out ) {
@@ -11286,7 +11730,7 @@ sub specialcloneVM {
clone info hash from doclone.txt
Source zvm userid
Source userid directory file name
- Returns : Nothing
+ Returns : Nothing, errors returned in $callback
Example : specialClone($callback, $_, $args, \@srcMdisks, \%srcLinkAddr, \%cloneInfoHash, $sourceId, $srcUserEntry);
=cut
@@ -11348,6 +11792,7 @@ sub specialClone {
$hcpUserId =~ tr/a-z/A-Z/;
my $out;
+ my $outmsg;
my @lines;
my @words;
@@ -11551,8 +11996,14 @@ sub specialClone {
while ( $try > 0 ) {
# Get disks within user entry
- $out = `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli Image_Query_DM -T $tgtUserId" | sed '\$d' | grep -a "MDISK"`;
- xCAT::zvmUtils->printSyslog("smcli Image_Query_DM -T $tgtUserId | grep -a MDISK");
+ xCAT::zvmUtils->printSyslog("smcli Image_Query_DM -T $tgtUserId");
+ $out = `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli Image_Query_DM -T $tgtUserId"`;
+ ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO $::DIR/smcli Image_Query_DM -T $tgtUserId\"", $hcp, "specialClone", $out, $tgtNode );
+ if ($rc != 0) {
+ xCAT::zvmUtils->printLn( $callback, "$outmsg" );
+ return;
+ }
+ $out = `echo "$out" | sed '\$d' | grep -a -i "MDISK"`;
xCAT::zvmUtils->printSyslog("$out");
@disks = split( '\n', $out );
diff --git a/xCAT-server/lib/xcat/plugins/zvmdiscovery.pm b/xCAT-server/lib/xcat/plugins/zvmdiscovery.pm
index b6bc8debe..66d5e6808 100644
--- a/xCAT-server/lib/xcat/plugins/zvmdiscovery.pm
+++ b/xCAT-server/lib/xcat/plugins/zvmdiscovery.pm
@@ -1945,8 +1945,9 @@ sub startDiscovery{
'ldapsrv', 'lohcost',
'maint', 'maint630', 'maint640',
'migmaint', 'monwrite', 'mproute',
- 'operator', 'operatns', 'opersymp', 'opncloud', 'osadmin1', 'osadmin2',
- 'osadmin3', 'osamaint', 'osasf', 'ovfdev62',
+ 'operator', 'operatns', 'opersymp', 'opncloud',
+ 'osadmin1', 'osadmin2', 'osadmin3',
+ 'osamaint', 'osasf', 'ovfdev62',
'perfsvm', 'persmapi', 'pmaint', 'portmap',
'racfsmf', 'racfvm', 'racmaint', 'rexecd',
'rscs', 'rscsauth', 'rscsdns', 'rxagent1',
@@ -1955,8 +1956,8 @@ sub startDiscovery{
'tcpip', 'tcpmaint', 'tsafvm',
'uftd',
'vmnfs', 'vmrmadmn', 'vmrmsvm',
- 'vmservp', 'vmservr', 'vmservu', 'vmservs', 'vsmevsrv',
- 'vsmguard', 'vsmproxy', 'vsmreqim', 'vsmreqin', 'vsmreqiu',
+ 'vmservp', 'vmservr', 'vmservu', 'vmservs', 'vsmevsrv',
+ 'vsmguard', 'vsmproxy', 'vsmreqim', 'vsmreqin', 'vsmreqiu',
'vsmreqi6', 'vsmwork1', 'vsmwork2', 'vsmwork3', 'vsmwork4',
'vsmwork5', 'vsmwork6', 'vsmwork7', 'vsmwork8', 'vsmwork9',
'xcat', 'xcatserv', 'xchange',
diff --git a/xCAT-server/xCAT-server.spec b/xCAT-server/xCAT-server.spec
index 2013dcf11..53f239709 100644
--- a/xCAT-server/xCAT-server.spec
+++ b/xCAT-server/xCAT-server.spec
@@ -46,9 +46,8 @@ Obsoletes: atftp-xcat
%ifos linux
#
# PCM does not use or ship grub2-xcat
-Requires: grub2-xcat perl-Net-HTTPS-NB perl-HTTP-Async
%if %nots390x
-Requires: grub2-xcat
+Requires: grub2-xcat perl-Net-HTTPS-NB perl-HTTP-Async
%endif
%endif
%endif
diff --git a/xCAT-server/xCAT-wsapi/xcatws.cgi b/xCAT-server/xCAT-wsapi/xcatws.cgi
index a5e8c39dd..84701929a 100755
--- a/xCAT-server/xCAT-wsapi/xcatws.cgi
+++ b/xCAT-server/xCAT-wsapi/xcatws.cgi
@@ -1,1310 +1,35 @@
#!/usr/bin/perl
-# IBM(c) 2014 EPL license http://www.eclipse.org/legal/epl-v10.html
use strict;
-use CGI qw/:standard/; #todo: remove :standard when the code only uses object oriented interface
+use CGI qw/:standard/;
+#use JSON; # require this dynamically later on so that installations that do not use xcatws.cgi do not need perl-JSON
use Data::Dumper;
-#talk to the server
-use Socket;
-use IO::Socket::INET;
-use IO::Socket::SSL;
-
-# The hash %URIdef defines all the xCAT resources which can be access from Web Service.
-# This script will be called when a https request with the URI started with /xcatws/ is sent to xCAT Web Service
-# Inside this script:
-# 1. The main body parses the URI and parameters
-# 2. Base on the URI, go through the %URIdef to find the matched resource by the 'matcher' which is defined for each resource
-# 3. Call the 'fhandler' which is defined in the resource to communicate with xcatd and get the xml response
-# 3.1 The 'fhandler' generates the xml request base on the resource, parameters and http method 'GET|PUT|POST|DELETE', sends to xcatd and then get the xml response
-# 4. Call the 'outhdler' which is defined in the resource to parse the xml response and translate it to JSON format
-# 5. Output the http response to STDOUT
+#added the line:
+#ScriptAlias /xcatws /var/www/cgi-bin/xcatws.cgi
+#to /etc/httpd/conf/httpd.conf to hid the cgi-bin and .cgi extension in the uri
#
-# Refer to the $URIdef{node}->{allnode} and $URIdef{node}->{nodeallattr} for your new created resource definition.
-#
-# |--node - Resource Group
-# | `--allnode - Resource Name
-# | `--desc - Description for the Resource
-# | `--desc[1..10] - Additional description for the Resource
-# | `--matcher - The matcher which is used to match the URI to the Resource
-# | `--GET - The info is used to handle the GET request
-# | `--desc - Description for the GET operation
-# | `--desc[1..10] - Additional description for the GET operation
-# | `--usage - Usage message. The format must be '|Parameters for the GET request|Returns for the GET request|'. The message in the '|' can be black, but the delimiter '|' must be kept.
-# | `--example - Example message. The format must be '|Description|GET|URI PUT/POST_data|Return Msg|'. The messages in the four sections must be completed.
-# | `--cmd - The xCAT command line coammnd which will be used to complete the request. It's not a must have attribute.
-# | `--fhandler - The call back subroutine which is used to handle the GET request. Generally, it parses the parameters from request and then call xCAT command. This subroutine can be exclusive or shared.
-# | `--outhdler - The call back subroutine which is used to handle the GET request. Generally, it parses the xml output from the 'fhandler' and then format the output to JSON. This subroutine can be exclusive or shared.
-# | `--PUT - The info is used to handle the PUT request
-# | `--POST - The info is used to handle the POST request
-# | `--DELETE - The info is used to handle the DELETE request
+# also upgraded CGI to 3.52
-# The common messages which can be used in the %URIdef
-my %usagemsg = (
- objreturn => "Json format: An object which includes multiple \' : {att:value, attr:value ...}\' pairs.",
- objchparam => "Json format: An object which includes multiple \'att:value\' pairs.",
- non_getreturn => "No output when execution is successfull. Otherwise output the error information in the Standard Error Format: {error:[msg1,msg2...],errocode:errornum}."
-);
+#take the JSON or XML and put it into a data structure
+#all data input will be done from the common structure
-my %URIdef = (
- #### definition for node resources
- nodes => {
- allnode => {
- desc => "[URI:/nodes] - The node list resource.",
- desc1 => "This resource can be used to display all the nodes which have been defined in the xCAT database.",
- matcher => '^/nodes$',
- GET => {
- desc => "Get all the nodes in xCAT.",
- desc1 => "The attributes details for the node will not be displayed.",
- usage => "||Json format: An array of node names.|",
- example => "|Get all the node names from xCAT database.|GET|/nodes|[\n \"node1\",\n \"node2\",\n \"node3\",\n]|",
- cmd => "lsdef",
- fhandler => \&defhdl,
- outhdler => \&defout_remove_appended_type,
- }
- },
- nodeallattr => {
- desc => "[URI:/nodes/{noderange}] - The node resource",
- matcher => '^/nodes/[^/]*$',
- GET => {
- desc => "Get all the attibutes for the node {noderange}.",
- desc1 => "The keyword ALLRESOURCES can be used as {noderange} which means to get node attributes for all the nodes.",
- usage => "||$usagemsg{objreturn}|",
- example => "|Get all the attibutes for node \'node1\'.|GET|/nodes/node1|{\n \"node1\":{\n \"profile\":\"compute\",\n \"netboot\":\"xnba\",\n \"arch\":\"x86_64\",\n \"mgt\":\"ipmi\",\n \"groups\":\"all\",\n ...\n }\n}|",
- cmd => "lsdef",
- fhandler => \&defhdl,
- outhdler => \&defout,
- },
- PUT => {
- desc => "Change the attibutes for the node {noderange}.",
- usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|",
- example => "|Change the attributes mgt=dfm and netboot=yaboot.|PUT|/nodes/node1 {\"mgt\":\"dfm\",\"netboot\":\"yaboot\"}||",
- cmd => "chdef",
- fhandler => \&defhdl,
- outhdler => \&noout,
- },
- POST => {
- desc => "Create the node {noderange}.",
- usage => "|$usagemsg{objchparam} DataBody: {options:{opt1:v1,opt2:v2},attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|",
- example => "|Create a node with attributes groups=all, mgt=dfm and netboot=yaboot|POST|/nodes/node1 {\"options\":{\"--template\":\"x86_64kvmguest-template\"}, \"groups\":\"all\",\"mgt\":\"dfm\",\"netboot\":\"yaboot\"}||",
- cmd => "mkdef",
- fhandler => \&defhdl,
- outhdler => \&noout,
- },
- DELETE => {
- desc => "Remove the node {noderange}.",
- usage => "||$usagemsg{non_getreturn}|",
- example => "|Delete the node node1|DELETE|/nodes/node1||",
- cmd => "rmdef",
- fhandler => \&defhdl,
- outhdler => \&noout,
- },
- },
- nodeattr => {
- desc => "[URI:/nodes/{noderange}/attrs/{attr1,attr2,attr3 ...}] - The attributes resource for the node {noderange}",
- matcher => '^/nodes/[^/]*/attrs/\S+$',
- GET => {
- desc => "Get the specific attributes for the node {noderange}.",
- desc1 => "The keyword ALLRESOURCES can be used as {noderange} which means to get node attributes for all the nodes.",
- usage => "||$usagemsg{objreturn}|",
- example => "|Get the attributes {groups,mgt,netboot} for node node1|GET|/nodes/node1/attrs/groups,mgt,netboot|{\n \"node1\":{\n \"netboot\":\"xnba\",\n \"mgt\":\"ipmi\",\n \"groups\":\"all\"\n }\n}|",
- cmd => "lsdef",
- fhandler => \&defhdl,
- outhdler => \&defout,
- },
- PUT_backup => {
- desc => "Change attributes for the node {noderange}. DataBody: {attr1:v1,att2:v2,att3:v3 ...}.",
- usage => "||An array of node objects.|",
- example => "|Get the attributes {groups,mgt,netboot} for node node1|GET|/nodes/node1/attrs/groups;mgt;netboot||",
- cmd => "chdef",
- fhandler => \&defhdl,
- outhdler => \&noout,
- }
- },
- nodestat => {
- desc => "[URI:/nodes/{noderange}/nodestat}] - The attributes resource for the node {noderange}",
- matcher => '^/nodes/[^/]*/nodestat$',
- GET => {
- desc => "Get the running status for the node {noderange}.",
- usage => "||An object which includes multiple entries like: : { nodestat : }|",
- example => "|Get the running status for node node1|GET|/nodes/node1/nodestat|{\n \"node1\":{\n \"nodestat\":\"noping\"\n }\n}|",
- cmd => "nodestat",
- fhandler => \&actionhdl,
- outhdler => \&actionout,
- },
- },
- nodehost => {
- desc => "[URI:/nodes/{noderange}/host] - The mapping of ip and hostname for the node {noderange}",
- matcher => '^/nodes/[^/]*/host$',
- POST => {
- desc => "Create the mapping of ip and hostname record for the node {noderange}.",
- usage => "||$usagemsg{non_getreturn}|",
- example => "|Create the mapping of ip and hostname record for node \'node1\'.|POST|/nodes/node1/host||",
- cmd => "makehosts",
- fhandler => \&actionhdl,
- outhdler => \&noout,
- },
- },
- noderename => {
- desc => "[URI:/nodes/{noderange}/rename] - Change old_nodename into new_nodename",
- matcher => '^/nodes/[^/]*/rename$',
- PUT => {
- desc => "Change node name.",
- usage => "||$usagemsg{non_getreturn}|",
- example => "|Change nodename for node \'node1\'.|PUT|/nodes/node1/rename||",
- cmd => "chdef",
- fhandler => \&actionhdl,
- outhdler => \&defout_remove_appended_info,
- },
- },
- nodedns => {
- desc => "[URI:/nodes/{noderange}/dns] - The dns record resource for the node {noderange}",
- matcher => '^/nodes/[^/]*/dns$',
- POST => {
- desc => "Create the dns record for the node {noderange}.",
- desc1 => "The prerequisite of the POST operation is the mapping of ip and noderange for the node has been added in the /etc/hosts.",
- usage => "||$usagemsg{non_getreturn}|",
- example => "|Create the dns record for node \'node1\'.|POST|/nodes/node1/dns||",
- cmd => "makedns",
- fhandler => \&actionhdl,
- outhdler => \&noout,
- },
- DELETE => {
- desc => "Remove the dns record for the node {noderange}.",
- usage => "||$usagemsg{non_getreturn}|",
- example => "|Delete the dns record for node node1|DELETE|/nodes/node1/dns||",
- cmd => "makedns",
- fhandler => \&actionhdl,
- outhdler => \&noout,
- },
- },
- nodedhcp => {
- desc => "[URI:/nodes/{noderange}/dhcp] - The dhcp record resource for the node {noderange}",
- matcher => '^/nodes/[^/]*/dhcp$',
- POST => {
- desc => "Create the dhcp record for the node {noderange}.",
- usage => "||$usagemsg{non_getreturn}|",
- example => "|Create the dhcp record for node \'node1\'.|POST|/nodes/node1/dhcp||",
- cmd => "makedhcp",
- fhandler => \&actionhdl,
- outhdler => \&noout,
- },
- DELETE => {
- desc => "Remove the dhcp record for the node {noderange}.",
- usage => "||$usagemsg{non_getreturn}|",
- example => "|Delete the dhcp record for node node1|DELETE|/nodes/node1/dhcp||",
- cmd => "makedhcp",
- fhandler => \&actionhdl,
- outhdler => \&noout,
- },
- },
- power => {
- desc => "[URI:/nodes/{noderange}/power] - The power resource for the node {noderange}",
- matcher => '^/nodes/[^/]*/power$',
- GET => {
- desc => "Get the power status for the node {noderange}.",
- usage => "||An object which includes multiple entries like: : { power : }|",
- example => "|Get the power status.|GET|/nodes/node1/power|{\n \"node1\":{\n \"power\":\"on\"\n }\n}|",
- cmd => "rpower",
- fhandler => \&actionhdl,
- outhdler => \&actionout,
- },
- PUT => {
- desc => "Change power status for the node {noderange}.",
- usage => "|Json Formatted DataBody: {action:on/off/reset ...}.|$usagemsg{non_getreturn}|",
- example => "|Change the power status to on|PUT|/nodes/node1/power {\"action\":\"on\"}||",
- cmd => "rpower",
- fhandler => \&actionhdl,
- outhdler => \&noout,
- }
- },
- provision => {
- desc => "[URI:/nodes/{noderange}/provision] - The deployment resource for the node {noderange}",
- matcher => '^/nodes/[^/]*/provision$',
- PUT => {
- desc => "OS provision for the node {noderange}.",
- usage => "|Json Formatted DataBody: {osimage: ubuntu16.04.1-x86_64-install-compute, action: boot}.|$usagemsg{non_getreturn}|",
- example => "|Provision the node|PUT|/nodes/node1/provision {\"osimage\":\"ubuntu16.04.1-x86_64-install-compute\"}||",
- cmd => "rinstall",
- fhandler => \&actionhdl,
- outhdler => \&noout,
- }
- },
- energy => {
- desc => "[URI:/nodes/{noderange}/energy] - The energy resource for the node {noderange}",
- matcher => '^/nodes/[^/]*/energy$',
- GET => {
- desc => "Get all the energy status for the node {noderange}.",
- usage => "||$usagemsg{objreturn}|",
- example => "|Get all the energy attributes.|GET|/nodes/node1/energy|{\n \"node1\":{\n \"cappingmin\":\"272.3 W\",\n \"cappingmax\":\"354.0 W\"\n ...\n }\n}|",
- cmd => "renergy",
- fhandler => \&actionhdl,
- outhdler => \&actionout,
- },
- PUT => {
- desc => "Change energy attributes for the node {noderange}.",
- usage => "|$usagemsg{objchparam} DataBody: {powerattr:value}.|$usagemsg{non_getreturn}|",
- example => "|Turn on the cappingstatus to [on]|PUT|/nodes/node1/energy {\"cappingstatus\":\"on\"}||",
- cmd => "renergy",
- fhandler => \&actionhdl,
- outhdler => \&noout,
- }
- },
- energyattr => {
- disable => 1,
- desc => "[URI:/nodes/{noderange}/energy/{cappingmaxmin,cappingstatus,cappingvalue ...}] - The specific energy attributes resource for the node {noderange}",
- matcher => '^/nodes/[^/]*/energy/\S+$',
- GET => {
- desc => "Get the specific energy attributes cappingmaxmin,cappingstatus,cappingvalue ... for the node {noderange}.",
- usage => "||$usagemsg{objreturn}|",
- example => "|Get the energy attributes which are specified in the URI.|GET|/nodes/node1/energy/cappingmaxmin,cappingstatus|{\n \"node1\":{\n \"cappingmin\":\"272.3 W\",\n \"cappingmax\":\"354.0 W\"\n }\n}|",
- cmd => "renergy",
- fhandler => \&actionhdl,
- outhdler => \&actionout,
- },
- PUT_backup => {
- desc => "Change energy attributes for the node {noderange}. ",
- usage => "|$usagemsg{objchparam} DataBody: {powerattr:value}.|$usagemsg{non_getreturn}|",
- example => "|Turn on the cappingstatus to [on]|PUT|/nodes/node1/energy {\"cappingstatus\":\"on\"}||",
- cmd => "renergy",
- fhandler => \&actionhdl,
- outhdler => \&noout,
- }
- },
- serviceprocessor => {
- disable => 1,
- desc => "[URI:/nodes/{noderange}/sp/{community|ip|netmask|...}] - The attribute resource of service processor for the node {noderange}",
- matcher => '^/nodes/[^/]*/sp/\S+$',
- GET => {
- desc => "Get the specific attributes for service processor resource.",
- usage => "||$usagemsg{objreturn}|",
- example => "|Get the snmp community for the service processor of node1.|GET|/nodes/node1/sp/community|{\n \"node1\":{\n \"SP SNMP Community\":\"public\"\n }\n}|",
- cmd => "rspconfig",
- fhandler => \&actionhdl,
- outhdler => \&actionout,
- },
- PUT => {
- desc => "Change the specific attributes for the service processor resource. ",
- usage => "|$usagemsg{objchparam} DataBody: {community:public}.|$usagemsg{non_getreturn}|",
- example => "|Set the snmp community to [mycommunity].|PUT|/nodes/node1/sp/community {\"value\":\"mycommunity\"}||",
- cmd => "rspconfig",
- fhandler => \&actionhdl,
- outhdler => \&noout,
- }
- },
- macaddress => {
- disable => 1,
- desc => "[URI:/nodes/{noderange}/mac] - The mac address resource for the node {noderange}",
- matcher => '^/nodes/[^/]*/mac$',
- GET => {
- desc => "Get the mac address for the node {noderange}. Generally, it also updates the mac attribute of the node.",
- cmd => "getmacs",
- fhandler => \&common,
- },
- },
- nextboot => {
- desc => "[URI:/nodes/{noderange}/nextboot] - The temporary bootorder resource in next boot for the node {noderange}",
- matcher => '^/nodes/[^/]*/nextboot$',
- GET => {
- desc => "Get the next bootorder.",
- usage => "||$usagemsg{objreturn}|",
- example => "|Get the bootorder for the next boot. (It's only valid after setting.)|GET|/nodes/node1/nextboot|{\n \"node1\":{\n \"nextboot\":\"Network\"\n }\n}|",
- cmd => "rsetboot",
- fhandler => \&actionhdl,
- outhdler => \&actionout,
- },
- PUT => {
- desc => "Change the next boot order. ",
- usage => "|$usagemsg{objchparam} DataBody: {order:net/hd}.|$usagemsg{non_getreturn}|",
- example => "|Set the bootorder for the next boot.|PUT|/nodes/node1/nextboot {\"order\":\"net\"}||",
- cmd => "rsetboot",
- fhandler => \&actionhdl,
- outhdler => \&noout,
- }
- },
- bootorder => {
- desc => "[URI:/nodes/{noderange}/bootorder] - The permanent bootorder resource for the node {noderange}",
- matcher => '^/nodes/[^/]*/bootorder$',
- GET => {
- desc => "Get the permanent boot order.",
- usage => "|?|?|",
- example => "|Get the permanent bootorder for the node1.|GET|/nodes/node1/bootorder|?|",
- cmd => "rbootseq",
- fhandler => \&actionhdl,
- outhdler => \&actionout,
- },
- PUT => {
- desc => "Change the boot order. DataBody: {\"order\":\"net,hd\"}.",
- usage => "|Put data: Json formatted order:value pair.|?|",
- example => "|Set the permanent bootorder for the node1.|PUT|/nodes/node1/bootorder|?|",
- cmd => "rbootseq",
- fhandler => \&actionhdl,
- outhdler => \&noout,
- }
- },
- vitals => {
- desc => "[URI:/nodes/{noderange}/vitals] - The vitals resources for the node {noderange}",
- matcher => '^/nodes/[^/]*/vitals$',
- GET => {
- desc => "Get all the vitals attibutes.",
- usage => "||$usagemsg{objreturn}|",
- example => "|Get all the vitails attributes for the node1.|GET|/nodes/node1/vitals|{\n \"node1\":{\n \"SysBrd Fault\":\"0\",\n \"CPUs\":\"0\",\n \"Fan 4A Tach\":\"3330 RPM\",\n \"Drive 15\":\"0\",\n \"SysBrd Vol Fault\":\"0\",\n \"nvDIMM Flash\":\"0\",\n \"Progress\":\"0\"\n ...\n }\n}|",
- cmd => "rvitals",
- fhandler => \&actionhdl,
- outhdler => \&actionout,
- },
- },
- vitalsattr => {
- disable => 1,
- desc => "[URI:/nodes/{noderange}/vitals/{temp|voltage|wattage|fanspeed|power|leds...}] - The specific vital attributes for the node {noderange}",
- matcher => '^/nodes/[^/]*/vitals/\S+$',
- GET => {
- desc => "Get the specific vitals attibutes.",
- usage => "||$usagemsg{objreturn}|",
- example => "|Get the \'fanspeed\' vitals attribute.|GET|/nodes/node1/vitals/fanspeed|{\n \"node1\":{\n \"Fan 1A Tach\":\"3219 RPM\",\n \"Fan 4B Tach\":\"2688 RPM\",\n \"Fan 3B Tach\":\"2560 RPM\",\n \"Fan 4A Tach\":\"3330 RPM\",\n \"Fan 2A Tach\":\"3293 RPM\",\n \"Fan 1B Tach\":\"2592 RPM\",\n \"Fan 3A Tach\":\"3182 RPM\",\n \"Fan 2B Tach\":\"2592 RPM\"\n }\n}|",
- cmd => "rvitals",
- fhandler => \&actionhdl,
- outhdler => \&actionout,
- },
- },
- inventory => {
- desc => "[URI:/nodes/{noderange}/inventory] - The inventory attributes for the node {noderange}",
- matcher => '^/nodes/[^/]*/inventory$',
- GET => {
- desc => "Get all the inventory attibutes.",
- usage => "||$usagemsg{objreturn}|",
- example => "|Get all the inventory attributes for node1.|GET|/nodes/node1/inventory|{\n \"node1\":{\n \"DIMM 21 \":\"8GB PC3-12800 (1600 MT/s) ECC RDIMM\",\n \"DIMM 1 Manufacturer\":\"Hyundai Electronics\",\n \"Power Supply 2 Board FRU Number\":\"94Y8105\",\n \"DIMM 9 Model\":\"HMT31GR7EFR4C-PB\",\n \"DIMM 8 Manufacture Location\":\"01\",\n \"DIMM 13 Manufacturer\":\"Hyundai Electronics\",\n \"DASD Backplane 4\":\"Not Present\",\n ...\n }\n}|",
- cmd => "rinv",
- fhandler => \&actionhdl,
- outhdler => \&actionout,
- },
- },
- inventoryattr => {
- desc => "[URI:/nodes/{noderange}/inventory/{pci|model...}] - The specific inventory attributes for the node {noderange}",
- matcher => '^/nodes/[^/]*/inventory/\S+$',
- GET => {
- desc => "Get the specific inventory attibutes.",
- usage => "||$usagemsg{objreturn}|",
- example => "|Get the \'model\' inventory attribute for node1.|GET|/nodes/node1/inventory/model|{\n \"node1\":{\n \"System Description\":\"System x3650 M4\",\n \"System Model/MTM\":\"7915C2A\"\n }\n}|",
- cmd => "rinv",
- fhandler => \&actionhdl,
- outhdler => \&actionout,
- },
- },
- eventlog => {
- desc => "[URI:/nodes/{noderange}/eventlog] - The eventlog resource for the node {noderange}",
- matcher => '^/nodes/[^/]*/eventlog$',
- GET => {
- desc => "Get all the eventlog for the node {noderange}.",
- usage => "||$usagemsg{objreturn}|",
- example => "|Get all the eventlog for node1.|GET|/nodes/node1/eventlog|{\n \"node1\":{\n \"eventlog\":[\n \"03/19/2014 15:17:58 Event Logging Disabled, Log Area Reset/Cleared (SEL Fullness)\"\n ]\n }\n}|",
- cmd => "reventlog",
- fhandler => \&actionhdl,
- outhdler => \&actionout,
- },
- DELETE => {
- desc => "Clean up the event log for the node {noderange}.",
- usage => "||$usagemsg{non_getreturn}|",
- example => "|Delete all the event log for node1.|DELETE|/nodes/node1/eventlog|[\n {\n \"eventlog\":[\n \"SEL cleared\"\n ],\n \"name\":\"node1\"\n }\n]|",
- cmd => "reventlog",
- fhandler => \&actionhdl,
- outhdler => \&noout,
- },
- },
- beacon => {
- desc => "[URI:/nodes/{noderange}/beacon] - The beacon resource for the node {noderange}",
- matcher => '^/nodes/[^/]*/beacon$',
- GET_backup => {
- desc => "Get the beacon status for the node {noderange}.",
- cmd => "rbeacon",
- fhandler => \&common,
- },
- PUT => {
- desc => "Change the beacon status for the node {noderange}.",
- usage => "|$usagemsg{objchparam} DataBody: {action:on/off/blink}.|$usagemsg{non_getreturn}|",
- example => "|Turn on the beacon.|PUT|/nodes/node1/beacon {\"action\":\"on\"}|[\n {\n \"name\":\"node1\",\n \"beacon\":\"on\"\n }\n]|",
- cmd => "rbeacon",
- fhandler => \&actionhdl,
- outhdler => \&noout,
- },
- },
- vm => {
- desc => "[URI:/nodes/{noderange}/vm] - The virtualization node {noderange}.",
- desc1 => "The node should be a virtual machine of type kvm, esxi ...",
- matcher => '^/nodes/[^/]*/vm$',
- GET_backup => {
- desc => "Get the vm status for the node {noderange}.",
- cmd => "lsvm",
- fhandler => \&actionhdl,
- outhdler => \&actionout,
- },
- PUT => {
- desc => "Change the configuration for the virtual machine {noderange}.",
- usage => "|$usagemsg{objchparam} DataBody: \n Set memory size - {\"memorysize\":\"sizeofmemory(MB)\"}\n Add new disk - {\"adddisk\":\"sizeofdisk1(GB),sizeofdisk2(GB)\"}\n Purge disk - {\"purgedisk\":\"scsi_id1,scsi_id2\"}|$usagemsg{non_getreturn}|",
- example => "|Set memory to 3000MB.|PUT|/nodes/node1/vm {\"memorysize\":\"3000\"}||",
- example1 => "|Add a new 20G disk.|PUT|/nodes/node1/vm {\"adddisk\":\"20G\"}||",
- example2 => "|Purge the disk \'hdb\'.|PUT|/nodes/node1/vm {\"purgedisk\":\"hdb\"}||",
- cmd => "chvm",
- fhandler => \&actionhdl,
- outhdler => \&noout,
- },
- POST => {
- desc => "Create the vm node {noderange}.",
- usage => "|$usagemsg{objchparam} DataBody: \n Set CPU count - {\"cpucount\":\"numberofcpu\"}\n Set memory size - {\"memorysize\":\"sizeofmemory(MB)\"}\n Set disk size - {\"disksize\":\"sizeofdisk\"}\n Do it by force - {\"force\":\"yes\"}|$usagemsg{non_getreturn}|",
- example => "|Create the vm node1 with a 30G disk, 2048M memory and 2 cpus.|POST|/nodes/node1/vm {\"disksize\":\"30G\",\"memorysize\":\"2048\",\"cpucount\":\"2\"}||",
- cmd => "mkvm",
- fhandler => \&actionhdl,
- outhdler => \&noout,
- },
- DELETE => {
- desc => "Remove the vm node {noderange}.",
- usage => "|$usagemsg{objchparam} DataBody: \n Purge disk - {\"purge\":\"yes\"}\n Do it by force - {\"force\":\"yes\"}|$usagemsg{non_getreturn}|",
- example => "|Remove the vm node1 by force and purge the disk.|DELETE|/nodes/node1/vm {\"force\":\"yes\",\"purge\":\"yes\"}||",
- cmd => "rmvm",
- fhandler => \&actionhdl,
- outhdler => \&noout,
- },
- },
- vmclone => {
- desc => "[URI:/nodes/{noderange}/vmclone] - The clone resource for the virtual node {noderange}.",
- desc1 => "The node should be a virtual machine of kvm, esxi ...",
- matcher => '^/nodes/[^/]*/vmclone$',
- POST => {
- desc => "Create a clone master from node {noderange}. Or clone the node {noderange} from a clone master.",
- usage => "|$usagemsg{objchparam} DataBody: \n Clone a master named \"mastername\" - {\"tomaster\":\"mastername\"}\n Clone a node from master \"mastername\" - {\"frommaster\":\"mastername\"}\n Use Detach mode - {\"detach\":\"yes\"}\n Do it by force - {\"force\":\"yes\"}|The messages of creating Clone target.|",
- example1 => "|Create a clone master named \"vmmaster\" from the node1.|POST|/nodes/node1/vmclone {\"tomaster\":\"vmmaster\",\"detach\":\"yes\"}|{\n \"node1\":{\n \"vmclone\":\"Cloning of node1.hda.qcow2 complete (clone uses 9633.19921875 for a disk size of 30720MB)\"\n }\n}|",
- example2 => "|Clone the node1 from the clone master named \"vmmaster\".|POST|/nodes/node1/vmclone {\"frommaster\":\"vmmaster\"}||",
- cmd => "clonevm",
- fhandler => \&actionhdl,
- outhdler => \&actionout,
- },
- },
- vmmigrate => {
- desc => "[URI:/nodes/{noderange}/vmmigrate] - The virtualization resource for migration.",
- desc1 => "The node should be a virtual machine of kvm, esxi ...",
- matcher => '^/nodes/[^/]*/vmmigrate$',
- POST => {
- desc => "Migrate a node to targe node.",
- usage => "|$usagemsg{objchparam} DataBody: {\"target\":\"targethost\"}.",
- example => "|Migrate node1 to target host host2.|POST|/nodes/node1/vmmigrate {\"target\":\"host2\"}||",
- cmd => "rmigrate",
- fhandler => \&actionhdl,
- outhdler => \&actionout,
- },
- },
- updating => {
- desc => "[URI:/nodes/{noderange}/updating] - The updating resource for the node {noderange}",
- matcher => '^/nodes/[^/]*/updating$',
- POST => {
- desc => "Update the node with file syncing, software maintenance and rerun postscripts.",
- usage => "||An array of messages for performing the node updating.|",
- example => "|Initiate an updatenode process.|POST|/nodes/node2/updating|[\n \"There were no syncfiles defined to process. File synchronization has completed.\",\n \"Performing software maintenance operations. This could take a while, if there are packages to install.\n\",\n \"node2: Wed Mar 20 15:01:43 CST 2013 Running postscript: ospkgs\",\n \"node2: Running of postscripts has completed.\"\n]|",
- cmd => "updatenode",
- fhandler => \&actionhdl,
- outhdler => \&infoout,
- },
- },
- filesyncing => {
- desc => "[URI:/nodes/{noderange}/filesyncing] - The filesyncing resource for the node {noderange}",
- matcher => '^/nodes/[^/]*/filesyncing$',
- POST => {
- desc => "Sync files for the node {noderange}.",
- usage => "||An array of messages for performing the file syncing for the node.|",
- example => "|Initiate an file syncing process.|POST|/nodes/node2/filesyncing|[\n \"There were no syncfiles defined to process. File synchronization has completed.\"\n]|",
- cmd => "updatenode",
- fhandler => \&actionhdl,
- outhdler => \&infoout,
- },
- },
- software_maintenance => {
- desc => "[URI:/nodes/{noderange}/sw] - The software maintenance for the node {noderange}",
- matcher => '^/nodes/[^/]*/sw$',
- POST => {
- desc => "Perform the software maintenance process for the node {noderange}.",
- usage => "||$usagemsg{objreturn}|",
- example => "|Initiate an software maintenance process.|POST|/nodes/node2/sw|{\n \"node2\":[\n \" Wed Apr 3 09:05:42 CST 2013 Running postscript: ospkgs\",\n \" Unable to read consumer identity\",\n \" Postscript: ospkgs exited with code 0\",\n \" Wed Apr 3 09:05:44 CST 2013 Running postscript: otherpkgs\",\n \" ./otherpkgs: no extra rpms to install\",\n \" Postscript: otherpkgs exited with code 0\",\n \" Running of Software Maintenance has completed.\"\n ]\n}|",
- cmd => "updatenode",
- fhandler => \&actionhdl,
- outhdler => \&infoout,
- },
- },
- postscript => {
- desc => "[URI:/nodes/{noderange}/postscript] - The postscript resource for the node {noderange}",
- matcher => '^/nodes/[^/]*/postscript$',
- POST => {
- desc => "Run the postscripts for the node {noderange}.",
- usage => "|$usagemsg{objchparam} DataBody: {scripts:[p1,p2,p3,...]}.|$usagemsg{objreturn}|",
- example => "|Initiate an updatenode process.|POST|/nodes/node2/postscript {\"scripts\":[\"syslog\",\"remoteshell\"]}|{\n \"node2\":[\n \" Wed Apr 3 09:01:33 CST 2013 Running postscript: syslog\",\n \" Shutting down system logger: [ OK ]\",\n \" Starting system logger: [ OK ]\",\n \" Postscript: syslog exited with code 0\",\n \" Wed Apr 3 09:01:33 CST 2013 Running postscript: remoteshell\",\n \" Stopping sshd: [ OK ]\",\n \" Starting sshd: [ OK ]\",\n \" Postscript: remoteshell exited with code 0\",\n \" Running of postscripts has completed.\"\n ]\n}|",
- cmd => "updatenode",
- fhandler => \&actionhdl,
- outhdler => \&infoout,
- },
- },
- nodeshell => {
- desc => "[URI:/nodes/{noderange}/nodeshell] - The nodeshell resource for the node {noderange}",
- matcher => '^/nodes/[^/]*/nodeshell$',
- POST => {
- desc => "Run the command in the shell of the node {noderange}.",
- usage => "|$usagemsg{objchparam} DataBody: set environment {ENV:{en1:v1,en2:v2}}, raw command {raw:[op1,op2]}, direct command {command:[cmd1,cmd2]}.|$usagemsg{objreturn}|",
- example => "|Run the \'date\' command on the node2.|POST|/nodes/node2/nodeshell {\"command\":[\"date\",\"ls\"]}|{\n \"node2\":[\n \" Wed Apr 3 08:30:26 CST 2013\",\n \" testline1\",\n \" testline2\"\n ]\n}|Use ENV and raw command on the node2.|POST|/nodes/node2/nodeshell {\"ENV\":{\"DSH_REMOTE_PASSWORD\":\"cluster\",\"DSH_FROM_USERID\":\"root\",\"DSH_TO_USERID\":\"root\"},\"raw\":[\"-K\"]}|[\n \"/usr/bin/ssh setup is complete.\",\n \"return code = 0\"\n]|",
- cmd => "xdsh",
- fhandler => \&actionhdl,
- outhdler => \&infoout,
- },
- },
- nodecopy => {
- desc => "[URI:/nodes/{noderange}/nodecopy] - The nodecopy resource for the node {noderange}",
- matcher => '^/nodes/[^/]*/nodecopy$',
- POST => {
- desc => "Copy files to the node {noderange}.",
- usage => "|$usagemsg{objchparam} DataBody: {src:[file1,file2],target:dir}.|$usagemsg{non_getreturn}|",
- example => "|Copy files /tmp/f1 and /tmp/f2 from xCAT MN to the node2:/tmp.|POST|/nodes/node2/nodecopy {\"src\":[\"/tmp/f1\",\"/tmp/f2\"],\"target\":\"/tmp\"}|no output for succeeded copy.|",
- cmd => "xdcp",
- fhandler => \&actionhdl,
- outhdler => \&infoout,
- },
- },
- subnodes => {
- desc => "[URI:/nodes/{noderange}/subnodes] - The sub-nodes resources for the node {noderange}",
- matcher => '^/nodes/[^/]*/subnodes$',
- GET => {
- desc => "Return the Children nodes for the node {noderange}.",
- usage => "||$usagemsg{objreturn}|",
- example => "|Get all the children nodes for node \'node1\'.|GET|/nodes/node1/subnodes|{\n \"cmm01node09\":{\n \"mpa\":\"ngpcmm01\",\n \"parent\":\"ngpcmm01\",\n \"serial\":\"1035CDB\",\n \"mtm\":\"789523X\",\n \"cons\":\"fsp\",\n \"hwtype\":\"blade\",\n \"objtype\":\"node\",\n \"groups\":\"blade,all,p260\",\n \"mgt\":\"fsp\",\n \"nodetype\":\"ppc,osi\",\n \"slotid\":\"9\",\n \"hcp\":\"10.1.9.9\",\n \"id\":\"1\"\n },\n ...\n}|",
- cmd => "rscan",
- fhandler => \&actionhdl,
- outhdler => \&defout,
- },
+#turn on or off the debugging output
+my $DEBUGGING = 0;
+my $VERSION = "2.8";
- # the put should be implemented by customer that using GET to get all the resources and define it with PUT /nodes/
- PUT_bak => {
- desc => "Update the Children node for the node {noderange}.",
- cmd => "rscan",
- fhandler => \&common,
- },
- },
- bootstate => {
- desc => "[URI:/nodes/{noderange}/bootstate] - The boot state resource for node {noderange}.",
- matcher => '^/nodes/[^/]*/bootstate$',
- GET => {
- desc => "Get boot state.",
- usage => "||$usagemsg{objreturn}|",
- example => "|Get the next boot state for the node1.|GET|/nodes/node1/bootstate|{\n \"node1\":{\n \"bootstat\":\"boot\"\n }\n}|",
- cmd => "nodeset",
- fhandler => \&actionhdl,
- outhdler => \&actionout,
- },
- PUT => {
- desc => "Set the boot state.",
- usage => "|$usagemsg{objchparam} DataBody: {osimage:xxx}/{state:offline}.|$usagemsg{non_getreturn}|",
- example => "|Set the next boot state for the node1.|PUT|/nodes/node1/bootstate {\"osimage\":\"rhels6.4-x86_64-install-compute\"}||",
- cmd => "nodeset",
- fhandler => \&actionhdl,
- outhdler => \&noout,
- },
- },
+my $q = CGI->new;
+my $url = $q->url;
+my $pathInfo = $q->path_info;
+my $requestType = $ENV{'REQUEST_METHOD'};
+my $queryString = $ENV{'QUERY_STRING'};
+my %queryhash;
+my @path = split(/\//, $pathInfo);
+shift(@path);
+my $resource = $path[0];
+my $pageContent = '';
+my $request = {clienttype => 'ws'};
- # TODO: rflash
- },
-
- #### definition for group resources
- groups => {
- all_groups => {
- desc => "[URI:/groups] - The group list resource.",
- desc1 => "This resource can be used to display all the groups which have been defined in the xCAT database.",
- matcher => '^/groups$',
- GET => {
- desc => "Get all the groups in xCAT.",
- desc1 => "The attributes details for the group will not be displayed.",
- usage => "||Json format: An array of group names.|",
- example => "|Get all the group names from xCAT database.|GET|/groups|[\n \"__mgmtnode\",\n \"all\",\n \"compute\",\n \"ipmi\",\n \"kvm\",\n]|",
- cmd => "lsdef",
- fhandler => \&defhdl,
- outhdler => \&defout_remove_appended_type,
- }
- },
- group_allattr => {
- desc => "[URI:/groups/{groupname}] - The group resource",
- matcher => '^/groups/[^/]*$',
- GET => {
- desc => "Get all the attibutes for the group {groupname}.",
- usage => "||$usagemsg{objreturn}|",
- example => "|Get all the attibutes for group \'all\'.|GET|/groups/all|{\n \"all\":{\n \"members\":\"zxnode2,nodexxx,node1,node4\"\n }\n}|",
- cmd => "lsdef",
- fhandler => \&defhdl,
- outhdler => \&defout,
- },
- PUT => {
- desc => "Change the attibutes for the group {groupname}.",
- usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|",
- example => "|Change the attributes mgt=dfm and netboot=yaboot.|PUT|/groups/all {\"mgt\":\"dfm\",\"netboot\":\"yaboot\"}||",
- cmd => "chdef",
- fhandler => \&defhdl,
- outhdler => \&noout,
- },
- },
- group_attr => {
- desc => "[URI:/groups/{groupname}/attrs/{attr1,attr2,attr3 ...}] - The attributes resource for the group {groupname}",
- matcher => '^/groups/[^/]*/attrs/\S+$',
- GET => {
- desc => "Get the specific attributes for the group {groupname}.",
- usage => "||$usagemsg{objreturn}|",
- example => "|Get the attributes {mgt,netboot} for group all|GET|/groups/all/attrs/mgt,netboot|{\n \"all\":{\n \"netboot\":\"yaboot\",\n \"mgt\":\"dfm\"\n }\n}|",
- cmd => "lsdef",
- fhandler => \&defhdl,
- outhdler => \&defout,
- },
- },
- },
-
- #### definition for services resources: dns, dhcp, hostname
- services => {
- host => {
- desc => "[URI:/services/host] - The hostname resource.",
- matcher => '^/services/host$',
- POST => {
- desc => "Create the ip/hostname records for all the nodes to /etc/hosts.",
- usage => "||$usagemsg{non_getreturn}|",
- example => "|Create the ip/hostname records for all the nodes to /etc/hosts.|POST|/services/host||",
- cmd => "makehosts",
- fhandler => \&nonobjhdl,
- outhdler => \&noout,
- }
- },
- dns => {
- desc => "[URI:/services/dns] - The dns service resource.",
- matcher => '^/services/dns$',
- POST => {
- desc => "Initialize the dns service.",
- usage => "||$usagemsg{non_getreturn}|",
- example => "|Initialize the dns service.|POST|/services/dns||",
- cmd => "makedns",
- fhandler => \&nonobjhdl,
- outhdler => \&noout,
- }
- },
- bmcdiscover => {
- desc => "[URI:/services/bmcdiscover] - The bmc which does support nmap in the xCAT cluster.",
- matcher => '^/services/bmcdiscover/[^/]+$',
- GET => {
- desc => "Get all the bmc alive.",
- usage => "||$usagemsg{objreturn}|",
- example => "|Get all the bmc which do not support slp in the network.|",
- cmd => "bmcdiscover",
- fhandler => \&bmclisthdl,
- outhdler => \&defout_remove_appended_info,
-
- }
- },
- checkbmcauth => {
- desc => "[URI:/services/checkbmcauth] - Check if bmc user or password is correct.",
- matcher => '^/services/checkbmcauth/[^/]*/[^/]+$',
- GET => {
- desc => "Check if bmc user or password is correct.",
- usage => "||$usagemsg{objreturn}|",
- example => "|Check bmc user or password.|GET|/services/checkbmcauth||",
- cmd => "bmcdiscover",
- fhandler => \&bmccheckhdl,
- outhdler => \&defout_remove_appended_info,
-
- }
- },
- getbmcipsource => {
- desc => "[URI:/services/getbmcipsource] - Get BMC IP Address source.",
- matcher => '^/services/getbmcipsource/[^/]*/[^/]+$',
- GET => {
- desc => "Get BMC IP Address source.",
- usage => "||$usagemsg{objreturn}|",
- example => "|Get BMC IP Address source.|GET|/services/getbmcipsource||",
- cmd => "bmcdiscover",
- fhandler => \&bmccheckhdl,
- outhdler => \&defout_remove_appended_info,
-
- }
- },
-
- dhcp => {
- desc => "[URI:/services/dhcp] - The dhcp service resource.",
- matcher => '^/services/dhcp$',
- POST => {
- desc => "Create the dhcpd.conf for all the networks which are defined in the xCAT Management Node.",
- usage => "||$usagemsg{non_getreturn}|",
- example => "|Create the dhcpd.conf and restart the dhcpd.|POST|/services/dhcp||",
- cmd => "makedhcp",
- fhandler => \&nonobjhdl,
- outhdler => \&noout,
- }
- },
-
- # todo: for slpnode, we need use the query attribute to specify the network parameter for lsslp command
- slpnodes => {
- desc => "[URI:/services/slpnodes] - The nodes which support SLP in the xCAT cluster",
- matcher => '^/services/slpnodes',
- GET => {
- desc => "Get all the nodes which support slp protocol in the network.",
- usage => "||$usagemsg{objreturn}|",
- example => "|Get all the nodes which support slp in the network.|GET|/services/slpnodes|{\n \"ngpcmm01\":{\n \"mpa\":\"ngpcmm01\",\n \"otherinterfaces\":\"10.1.9.101\",\n \"serial\":\"100037A\",\n \"mtm\":\"789392X\",\n \"hwtype\":\"cmm\",\n \"side\":\"2\",\n \"objtype\":\"node\",\n \"nodetype\":\"mp\",\n \"groups\":\"cmm,all,cmm-zet\",\n \"mgt\":\"blade\",\n \"hidden\":\"0\",\n \"mac\":\"5c:f3:fc:25:da:99\"\n },\n ...\n}|",
- cmd => "lsslp",
- fhandler => \&nonobjhdl,
- outhdler => \&defout,
- },
- PUT_bakcup => {
- desc => "Update the discovered nodes to database.",
- cmd => "lsslp",
- fhandler => \&common,
- },
- },
- specific_slpnodes => {
- desc => "[URI:/services/slpnodes/{CEC|FRAME|MM|IVM|RSA|HMC|CMM|IMM2|FSP...}] - The slp nodes with specific service type in the xCAT cluster",
- matcher => '^/services/slpnodes/[^/]*$',
- GET => {
- desc => "Get all the nodes with specific slp service type in the network.",
- usage => "||$usagemsg{objreturn}|",
- example => "|Get all the CMM nodes which support slp in the network.|GET|/services/slpnodes/CMM|{\n \"ngpcmm01\":{\n \"mpa\":\"ngpcmm01\",\n \"otherinterfaces\":\"10.1.9.101\",\n \"serial\":\"100037A\",\n \"mtm\":\"789392X\",\n \"hwtype\":\"cmm\",\n \"side\":\"2\",\n \"objtype\":\"node\",\n \"nodetype\":\"mp\",\n \"groups\":\"cmm,all,cmm-zet\",\n \"mgt\":\"blade\",\n \"hidden\":\"0\",\n \"mac\":\"5c:f3:fc:25:da:99\"\n },\n \"Server--SNY014BG27A01K\":{\n \"mpa\":\"Server--SNY014BG27A01K\",\n \"otherinterfaces\":\"10.1.9.106\",\n \"serial\":\"100CF0A\",\n \"mtm\":\"789392X\",\n \"hwtype\":\"cmm\",\n \"side\":\"1\",\n \"objtype\":\"node\",\n \"nodetype\":\"mp\",\n \"groups\":\"cmm,all,cmm-zet\",\n \"mgt\":\"blade\",\n \"hidden\":\"0\",\n \"mac\":\"34:40:b5:df:0a:be\"\n }\n}|",
- cmd => "lsslp",
- fhandler => \&nonobjhdl,
- outhdler => \&defout,
- },
- PUT_backup => {
- desc => "Update the discovered nodes to database.",
- cmd => "lsslp",
- fhandler => \&common,
- },
- },
- #### definition for mknb [-c]
- nbimage => {
- desc => "[URI:/services/nbimage] - Create netboot root image for specified arch.",
- matcher => '^/services/nbimage/arch/[ppc64|x86_64]',
- POST => {
- desc => "creates a network boot root image",
- usage => "|$usagemsg{objchparam} DataBody: {\"onlyconfigfile\":\"[true|yes|Y|1]|[false|no|N|0]\"}.|$usagemsg{non_getreturn}|",
- example => "|Create a network boot root iamge for the specified arch|",
- cmd => "mknb",
- fhandler => \&actionhdl,
- },
- },
- console => {
- desc => "[URI:/services/console] - Conserver configuration on management node.",
- matcher => '^/services/console$',
- PUT => {
- desc => "Update conserver configuration",
- usage => "|Json Formatted DataBody: {nodes: [node1, node2], action: on/off trust_host: }.|$usagemsg{non_getreturn}|",
- example => "|Enable the console capability for node1|PUT|/services/console {\"nodes\":\n[\"node1\", \"node2\"]\"\n, \"action\": \"on\", \n\"trust_host\": \"host\"}||",
- cmd => "makeconservercf",
- fhandler => \&actionhdl,
- outhdler => \&noout,
- }
- },
- },
-
- #### definition for network resources
- networks => {
- allnetwork => {
- desc => "[URI:/networks] - The network list resource.",
- desc1 => "This resource can be used to display all the networks which have been defined in the xCAT database.",
- matcher => '^\/networks$',
- GET => {
- desc => "Get all the networks in xCAT.",
- desc1 => "The attributes details for the networks will not be displayed.",
- usage => "||Json format: An array of networks names.|",
- example => "|Get all the networks names from xCAT database.|GET|/networks|[\n \"network1\",\n \"network2\",\n \"network3\",\n]|",
- cmd => "lsdef",
- fhandler => \&defhdl,
- outhdler => \&defout_remove_appended_type,
- },
- POST => {
- desc => "Create the networks resources base on the network configuration on xCAT MN.",
- usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|",
- example => "|Create the networks resources base on the network configuration on xCAT MN.|POST|/networks||",
- cmd => "makenetworks",
- fhandler => \&actionhdl,
- outhdler => \&noout,
- },
- },
- network_allattr => {
- desc => "[URI:/networks/{netname}] - The network resource",
- matcher => '^\/networks\/[^\/]*$',
- GET => {
- desc => "Get all the attibutes for the network {netname}.",
- desc1 => "The keyword ALLRESOURCES can be used as {netname} which means to get network attributes for all the networks.",
- usage => "||$usagemsg{objreturn}|",
- example => "|Get all the attibutes for network \'network1\'.|GET|/networks/network1|{\n \"network1\":{\n \"gateway\":\"\",\n \"mask\":\"255.255.255.0\",\n \"mgtifname\":\"eth2\",\n \"net\":\"10.0.0.0\",\n \"tftpserver\":\"10.0.0.119\",\n ...\n }\n}|",
- cmd => "lsdef",
- fhandler => \&defhdl,
- outhdler => \&defout,
- },
- PUT => {
- desc => "Change the attibutes for the network {netname}.",
- usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|",
- example => "|Change the attributes mgtifname=eth0 and net=10.1.0.0.|PUT|/networks/network1 {\"mgtifname\":\"eth0\",\"net\":\"10.1.0.0\"}||",
- cmd => "chdef",
- fhandler => \&defhdl,
- outhdler => \&noout,
- },
- POST => {
- desc => "Create the network {netname}. DataBody: {attr1:v1,att2:v2...}.",
- usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|",
- example => "|Create a network with attributes gateway=10.1.0.1, mask=255.255.0.0 |POST|/networks/network1 {\"gateway\":\"10.1.0.1\",\"mask\":\"255.255.0.0\"}||",
- cmd => "mkdef",
- fhandler => \&defhdl,
- outhdler => \&noout,
- },
- DELETE => {
- desc => "Remove the network {netname}.",
- usage => "||$usagemsg{non_getreturn}|",
- example => "|Delete the network network1|DELETE|/networks/network1||",
- cmd => "rmdef",
- fhandler => \&defhdl,
- outhdler => \&noout
- },
- },
- network_attr => {
- desc => "[URI:/networks/{netname}/attrs/attr1,attr2,...] - The attributes resource for the network {netname}",
- matcher => '^\/networks\/[^\/]*/attrs/\S+$',
- GET => {
- desc => "Get the specific attributes for the network {netname}.",
- desc1 => "The keyword ALLRESOURCES can be used as {netname} which means to get network attributes for all the networks.",
- usage => "||$usagemsg{objreturn}|",
- example => "|Get the attributes {groups,mgt,netboot} for network network1|GET|/networks/network1/attrs/gateway,mask,mgtifname,net,tftpserver|{\n \"network1\":{\n \"gateway\":\"9.114.34.254\",\n \"mask\":\"255.255.255.0\",\n }\n}|",
- cmd => "lsdef",
- fhandler => \&defhdl,
- outhdler => \&defout,
- },
- PUT__backup => {
- desc => "Change attributes for the network {netname}. DataBody: {attr1:v1,att2:v2,att3:v3 ...}.",
- usage => "||An array of network objects.|",
- example => "|Get the attributes {gateway,mask,mgtifname,net,tftpserver} for networks network1|GET|/networks/network1/attrs/gateway;mask;net||",
- cmd => "chdef",
- fhandler => \&noout,
- }
- },
-
- },
-
- #### definition for osimage resources
- osimages => {
- osimage => {
- desc => "[URI:/osimages] - The osimage resource.",
- matcher => '^\/osimages$',
- GET => {
- desc => "Get all the osimage in xCAT.",
- usage => "||Json format: An array of osimage names.|",
- example => "|Get all the osimage names.|GET|/osimages|[\n \"sles11.2-x86_64-install-compute\",\n \"sles11.2-x86_64-install-iscsi\",\n \"sles11.2-x86_64-install-iscsiibft\",\n \"sles11.2-x86_64-install-service\"\n]|",
-
- cmd => "lsdef",
- fhandler => \&defhdl,
- outhdler => \&defout_remove_appended_type,
- },
- POST => {
- desc => "Create the osimage resources base on the parameters specified in the Data body.",
-
- #usage => "|$usagemsg{objchparam} DataBody: {iso:isoname\\file:filename\\node:noderange,params:[{attr1:value1,attr2:value2}]}|$usagemsg{non_getreturn}|",
- usage => "|$usagemsg{objchparam} DataBody: {iso:isoname\\file:filename,params:[{attr1:value1,attr2:value2}]}|$usagemsg{non_getreturn}|",
- example1 => "|Create osimage resources based on the ISO specified|POST|/osimages {\"iso\":\"/iso/RHEL6.4-20130130.0-Server-ppc64-DVD1.iso\"}||",
- example2 => "|Create osimage resources based on an xCAT image or configuration file|POST|/osimages {\"file\":\"/tmp/sles11.2-x86_64-install-compute.tgz\"}||",
-
- # TD: the imgcapture need to be moved to nodes/.*/osimages
- # example3 => "|Create a image based on the specified Linux diskful node|POST|/osimages {\"node\":\"rhcn1\"}||",
- cmd => "copycds",
- fhandler => \&imgophdl,
- outhdler => \&noout,
- },
- },
- osimage_allattr => {
- desc => "[URI:/osimages/{imgname}] - The osimage resource",
- matcher => '^\/osimages\/[^\/]*$',
- GET => {
- desc => "Get all the attibutes for the osimage {imgname}.",
- desc1 => "The keyword ALLRESOURCES can be used as {imgname} which means to get image attributes for all the osimages.",
- usage => "||$usagemsg{objreturn}|",
- example => "|Get the attributes for the specified osimage.|GET|/osimages/sles11.2-x86_64-install-compute|{\n \"sles11.2-x86_64-install-compute\":{\n \"provmethod\":\"install\",\n \"profile\":\"compute\",\n \"template\":\"/opt/xcat/share/xcat/install/sles/compute.sles11.tmpl\",\n \"pkglist\":\"/opt/xcat/share/xcat/install/sles/compute.sles11.pkglist\",\n \"osvers\":\"sles11.2\",\n \"osarch\":\"x86_64\",\n \"osname\":\"Linux\",\n \"imagetype\":\"linux\",\n \"otherpkgdir\":\"/install/post/otherpkgs/sles11.2/x86_64\",\n \"osdistroname\":\"sles11.2-x86_64\",\n \"pkgdir\":\"/install/sles11.2/x86_64\"\n }\n}|",
- cmd => "lsdef",
- fhandler => \&defhdl,
- outhdler => \&defout,
- },
-
- POST => {
- desc => "Create the osimage {imgname}.",
- usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,attr2:v2]|$usagemsg{non_getreturn}|",
- example => "|Create a osimage obj with the specified parameters.|POST|/osimages/sles11.3-ppc64-install-compute {\"osvers\":\"sles11.3\",\"osarch\":\"ppc64\",\"osname\":\"Linux\",\"provmethod\":\"install\",\"profile\":\"compute\"}||",
- cmd => "mkdef",
- fhandler => \&defhdl,
- outhdler => \&noout,
- },
- PUT => {
- desc => "Change the attibutes for the osimage {imgname}.",
- usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,attr2:v2...}|$usagemsg{non_getreturn}|",
- example => "|Change the 'osvers' and 'osarch' attributes for the osiamge.|PUT|/osimages/sles11.2-ppc64-install-compute/ {\"osvers\":\"sles11.3\",\"osarch\":\"x86_64\"}||",
- cmd => "chdef",
- fhandler => \&defhdl,
- outhdler => \&noout,
- },
- DELETE => {
- desc => "Remove the osimage {imgname}.",
- usage => "||$usagemsg{non_getreturn}|",
- example => "|Delete the specified osimage.|DELETE|/osimages/sles11.3-ppc64-install-compute||",
- cmd => "rmdef",
- fhandler => \&defhdl,
- outhdler => \&noout,
- },
- },
- osimage_attr => {
- desc => "[URI:/osimages/{imgname}/attrs/attr1,attr2,attr3 ...] - The attributes resource for the osimage {imgname}",
- matcher => '^\/osimages\/[^\/]*/attrs/\S+$',
- GET => {
- desc => "Get the specific attributes for the osimage {imgname}.",
- desc1 => "The keyword ALLRESOURCES can be used as {imgname} which means to get image attributes for all the osimages.",
- usage => "||Json format: An array of attr:value pairs for the specified osimage.|",
- example => "|Get the specified attributes.|GET|/osimages/sles11.2-ppc64-install-compute/attrs/imagetype,osarch,osname,provmethod|{\n \"sles11.2-ppc64-install-compute\":{\n \"provmethod\":\"install\",\n \"osname\":\"Linux\",\n \"osarch\":\"ppc64\",\n \"imagetype\":\"linux\"\n }\n}|",
- cmd => "lsdef",
- fhandler => \&defhdl,
- outhdler => \&defout,
- },
-
- # TD, the implementation may need to be change.
- PUT_backup => {
- desc => "Change the attibutes for the osimage {imgname}.",
- usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,attr2:v2...}|$usagemsg{non_getreturn}|",
- example => "|Change the 'osvers' and 'osarch' attributes for the osiamge.|PUT|/osimages/sles11.2-ppc64-install-compute/attrs/osvers;osarch {\"osvers\":\"sles11.3\",\"osarch\":\"x86_64\"}||",
- cmd => "chdef",
- fhandler => \&defhdl,
- outhdler => \&noout,
- },
-
- },
- osimage_op => {
- desc => "[URI:/osimages/{imgname}/instance] - The instance for the osimage {imgname}",
- matcher => '^\/osimages\/[^\/]*/instance$',
- POST => {
- desc => "Operate the instance of the osimage {imgname}.",
- usage => "|$usagemsg{objchparam} DataBody: {action:gen\\pack\\export,params:[{attr1:value1,attr2:value2...}]}|$usagemsg{non_getreturn}|",
- example1 => "|Generates a stateless image based on the specified osimage|POST|/osimages/sles11.2-x86_64-install-compute/instance {\"action\":\"gen\"}||",
- example2 => "|Packs the stateless image from the chroot file system based on the specified osimage|POST|/osimages/sles11.2-x86_64-install-compute/instance {\"action\":\"pack\"}||",
- example3 => "|Exports an xCAT image based on the specified osimage|POST|/osimages/sles11.2-x86_64-install-compute/instance {\"action\":\"export\"}||",
- cmd => "",
- fhandler => \&imgophdl,
- },
- DELETE => {
- desc => "Delete the stateless or statelite image instance for the osimage {imgname} from the file system",
- usage => "||$usagemsg{non_getreturn}",
- example => "|Delete the stateless image for the specified osimage|DELETE|/osimages/sles11.2-x86_64-install-compute/instance||",
- cmd => "rmimage",
- fhandler => \&imgophdl,
- },
- },
-
- # todo: genimage, packimage, imagecapture, imgexport, imgimport
- },
-
- #### definition for policy resources
- policy => {
- policy => {
- desc => "[URI:/policy] - The policy resource.",
- matcher => '^\/policy$',
- GET => {
- desc => "Get all the policies in xCAT.",
- desc1 => "It will dislplay all the policy resource.",
- usage => "||$usagemsg{objreturn}|",
- example => "|Get all the policy objects.|GET|/policy|[\n \"1\",\n \"1.2\",\n \"2\",\n \"4.8\"\n]|",
- cmd => "lsdef",
- fhandler => \&defhdl,
- outhdler => \&defout_remove_appended_type,
- },
- },
- policy_allattr => {
- desc => "[URI:/policy/{policy_priority}] - The policy resource",
- matcher => '^\/policy\/[^\/]*$',
- GET => {
- desc => "Get all the attibutes for a policy {policy_priority}.",
- desc1 => "It will display all the policy attributes for one policy resource.",
- desc2 => "The keyword ALLRESOURCES can be used as {policy_priority} which means to get policy attributes for all the policies.",
- usage => "||$usagemsg{objreturn}|",
- example => "|Get all the attribute for policy 1.|GET|/policy/1|{\n \"1\":{\n \"name\":\"root\",\n \"rule\":\"allow\"\n }\n}|",
- cmd => "lsdef",
- fhandler => \&defhdl,
- outhdler => \&defout,
- },
- PUT => {
- desc => "Change the attibutes for the policy {policy_priority}.",
- desc1 => "It will change one or more attributes for a policy.",
- usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|",
- example => "|Set the name attribute for policy 3.|PUT|/policy/3 {\"name\":\"root\"}||",
- cmd => "chdef",
- fhandler => \&defhdl,
- outhdler => \&noout,
- },
- POST => {
- desc => "Create the policy {policyname}. DataBody: {attr1:v1,att2:v2...}.",
- desc1 => "It will creat a new policy resource.",
- usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|",
- example => "|Create a new policy 10.|POST|/policy/10 {\"name\":\"root\",\"commands\":\"rpower\"}||",
- cmd => "chdef",
- fhandler => \&defhdl,
- outhdler => \&noout,
- },
- DELETE => {
- desc => "Remove the policy {policy_priority}.",
- desc1 => "Remove one or more policy resource.",
- usage => "||$usagemsg{non_getreturn}|",
- example => "|Delete the policy 10.|DELETE|/policy/10||",
- cmd => "rmdef",
- fhandler => \&defhdl,
- outhdler => \&noout,
- },
- },
- policy_attr => {
- desc => "[URI:/policy/{policyname}/attrs/{attr1,attr2,attr3,...}] - The attributes resource for the policy {policy_priority}",
- matcher => '^\/policy\/[^\/]*/attrs/\S+$',
- GET => {
- desc => "Get the specific attributes for the policy {policy_priority}.",
- desc1 => "It will get one or more attributes of a policy.",
- desc2 => "The keyword ALLRESOURCES can be used as {policy_priority} which means to get policy attributes for all the policies.",
- usage => "||$usagemsg{objreturn}|",
- example => "|Get the name and rule attributes for policy 1.|GET|/policy/1/attrs/name,rule|{\n \"1\":{\n \"name\":\"root\",\n \"rule\":\"allow\"\n }\n}|",
- cmd => "lsdef",
- fhandler => \&defhdl,
- outhdler => \&defout,
- },
- },
- },
- #### definition for global setting resources
- globalconf => {
- all_site => {
- desc => "[URI:/globalconf] - The global configuration resource.",
- desc1 => "This resource can be used to display all the global configuration which have been defined in the xCAT database.",
- matcher => '^\/globalconf$',
- GET => {
- desc => "Get all the xCAT global configuration.",
- desc1 => "It will display all the global attributes.",
- usage => "||$usagemsg{objreturn}|",
- example => "|Get all the global configuration|GET|/globalconf|{\n \"clustersite\":{\n \"xcatconfdir\":\"/etc/xcat\",\n \"tftpdir\":\"/tftpboot\",\n ...\n }\n}|",
- cmd => "lsdef",
- fhandler => \&sitehdl,
- outhdler => \&defout,
- },
- POST_backup => {
- desc => "Add the site attributes. DataBody: {attr1:v1,att2:v2...}.",
- desc1 => "One or more global attributes could be added/modified.",
- usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|",
- example => "|Add one or more attributes to xCAT database|POST|/globalconf {\"domain\":\"cluster.com\",\"mydomain\":\"mycluster.com\"}||",
- cmd => "chdef",
- fhandler => \&sitehdl,
- },
- },
- site => {
- desc => "[URI:/globalconf/attrs/{attr1,attr2 ...}] - The specific global configuration resource.",
- matcher => '^\/globalconf/attrs/\S+$',
- GET => {
- desc => "Get the specific configuration in global.",
- desc1 => "It will display one or more global attributes.",
- usage => "||$usagemsg{objreturn}|",
- example => "|Get the \'master\' and \'domain\' configuration.|GET|/globalconf/attrs/master,domain|{\n \"clustersite\":{\n \"domain\":\"cluster.com\",\n \"master\":\"192.168.1.15\"\n }\n}|",
- cmd => "lsdef",
- fhandler => \&sitehdl,
- outhdler => \&defout,
- },
- PUT => {
- desc => "Change the global attributes.",
- desc1 => "It can be used for changing/adding global attributes.",
- usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|",
- example => "|Change/Add the domain attribute.|PUT|/globalconf/attrs/domain {\"domain\":\"cluster.com\"}||",
- cmd => "chdef",
- fhandler => \&sitehdl,
- outhdler => \&noout,
- },
- POST_backup => {
- desc => "Create the global configuration entry. DataBody: {name:value}.",
- usage => "||$usagemsg{non_getreturn}|",
- example => "|Create the domain attribute|POST|/globalconf/attrs/domain {\"domain\":\"cluster.com\"}|?|",
- cmd => "chdef",
- fhandler => \&sitehdl,
- outhdler => \&noout,
- },
- DELETE => {
- desc => "Remove the site attributes.",
- desc1 => "Used for femove one or more global attributes.",
- usage => "||$usagemsg{non_getreturn}|",
- example => "|Remove the domain configure.|DELETE|/globalconf/attrs/domain||",
- cmd => "chdef",
- fhandler => \&sitehdl,
- outhdler => \&noout,
- },
- },
- },
-
- #### definition for database/table resources
- tables => {
- table_nodes => {
- desc => "[URI:/tables/{tablelist}/nodes/{noderange}] - The node table resource",
- desc1 => "For a large number of nodes, this API call can be faster than using the corresponding nodes resource. The disadvantage is that you need to know the table names the attributes are stored in.",
- matcher => '^/tables/[^/]+/nodes/[^/]+$',
- GET => {
- desc => "Get attibutes of tables for a noderange.",
- usage => "||An object containing each table. Within each table object is an array of node objects containing the attributes.|",
- example1 => qq(|Get all the columns from table nodetype for node1 and node2.|GET|/tables/nodetype/nodes/node1,node2|{\n \"nodetype\":[\n {\n \"provmethod\":\"rhels6.4-x86_64-install-compute\",\n \"profile\":\"compute\",\n \"arch\":\"x86_64\",\n \"name\":\"node1\",\n \"os\":\"rhels6.4\"\n },\n {\n \"provmethod\":\"rhels6.3-x86_64-install-compute\",\n \"profile\":\"compute\",\n \"arch\":\"x86_64\",\n \"name\":\"node2\",\n \"os\":\"rhels6.3\"\n }\n ]\n}|),
- example2 => qq(|Get all the columns from tables nodetype and noderes for node1 and node2.|GET|/tables/nodetype,noderes/nodes/node1,node2|{\n \"noderes\":[\n {\n \"installnic\":\"mac\",\n \"netboot\":\"xnba\",\n \"name\":\"node1\",\n \"nfsserver\":\"192.168.1.15\"\n },\n {\n \"installnic\":\"mac\",\n \"netboot\":\"pxe\",\n \"name\":\"node2\",\n \"proxydhcp\":\"no\"\n }\n ],\n \"nodetype\":[\n {\n \"provmethod\":\"rhels6.4-x86_64-install-compute\",\n \"profile\":\"compute\",\n \"arch\":\"x86_64\",\n \"name\":\"node1\",\n \"os\":\"rhels6.4\"\n },\n {\n \"provmethod\":\"rhels6.3-x86_64-install-compute\",\n \"profile\":\"compute\",\n \"arch\":\"x86_64\",\n \"name\":\"node2\",\n \"os\":\"rhels6.3\"\n }\n ]\n}|),
- fhandler => \&tablenodehdl,
- outhdler => \&tableout,
- },
- PUT => {
- desc => "Change the node table attibutes for {noderange}.",
- usage => "|A hash of table names and attribute objects. DataBody: {table1:{attr1:v1,att2:v2,...}}.|$usagemsg{non_getreturn}|",
- example => '|Change the nodetype.arch and noderes.netboot attributes for nodes node1,node2.|PUT|/tables/nodetype,noderes/nodes/node1,node2 {"nodetype":{"arch":"x86_64"},"noderes":{"netboot":"xnba"}}||',
- fhandler => \&tablenodeputhdl,
- outhdler => \&noout,
- },
- },
- table_nodes_attrs => {
- desc => "[URI:/tables/{tablelist}/nodes/nodes/{noderange}/{attrlist}] - The node table attributes resource",
- desc1 => "For a large number of nodes, this API call can be faster than using the corresponding nodes resource. The disadvantage is that you need to know the table names the attributes are stored in.",
- matcher => '^/tables/[^/]+/nodes/[^/]+/[^/]+$',
- GET => {
- desc => "Get table attibutes for a noderange.",
- usage => "||An object containing each table. Within each table object is an array of node objects containing the attributes.|",
- example => qq(|Get OS and ARCH attributes from nodetype table for node1 and node2.|GET|/tables/nodetype/nodes/node1,node2/os,arch|{\n \"nodetype\":[\n {\n \"arch\":\"x86_64\",\n \"name\":\"node1\",\n \"os\":\"rhels6.4\"\n },\n {\n \"arch\":\"x86_64\",\n \"name\":\"node2\",\n \"os\":\"rhels6.3\"\n }\n ]\n}|),
- fhandler => \&tablenodehdl,
- outhdler => \&tableout,
- },
- PUT_backup => {
- desc => "[URI:/tables/nodes/{noderange}] - Change the node table attibutes for the {noderange}.",
- usage => "|A hash of table names and attribute objects. DataBody: {table1:{attr1:v1,att2:v2,...}}.|$usagemsg{non_getreturn}|",
- example => '|Change the nodehm.mgmt and noderes.netboot attributes for nodes node1-node5.|PUT|/tables/nodes/node1-node5 {"nodehm":{"mgmt":"ipmi"},"noderes":{"netboot":"xnba"}}||',
- fhandler => \&tablenodeputhdl,
- outhdler => \&noout,
- },
- },
- table_all_rows => {
- desc => "[URI:/tables/{tablelist}/rows] - The non-node table resource",
- desc1 => "Use this for tables that don't have node name as the key of the table, for example: passwd, site, networks, polciy, etc.",
- matcher => '^/tables/[^/]+/rows$',
- GET => {
- desc => "Get all rows from non-node tables.",
- usage => "||An object containing each table. Within each table object is an array of row objects containing the attributes.|",
- example => qq(|Get all rows from networks table.|GET|/tables/networks/rows|{\n \"networks\":[\n {\n \"netname\":\"192_168_13_0-255_255_255_0\",\n \"gateway\":\"192.168.13.254\",\n \"staticrangeincrement\":\"1\",\n \"net\":\"192.168.13.0\",\n \"mask\":\"255.255.255.0\"\n },\n {\n \"netname\":\"192_168_12_0-255_255_255_0\",\n \"gateway\":\"192.168.12.254\",\n \"staticrangeincrement\":\"1\",\n \"net\":\"192.168.12.0\",\n \"mask\":\"255.255.255.0\"\n },\n ]\n}|),
- fhandler => \&tablerowhdl,
- outhdler => \&tableout,
- },
- },
- table_rows => {
- desc => "[URI:/tables/{tablelist}/rows/{keys}] - The non-node table rows resource",
- desc1 => "Use this for tables that don't have node name as the key of the table, for example: passwd, site, networks, polciy, etc.",
- desc2 => "{keys} should be the name=value pairs which are used to search table. e.g. {keys} should be [net=192.168.1.0,mask=255.255.255.0] for networks table query since the net and mask are the keys of networks table.",
- matcher => '^/tables/[^/]+/rows/[^/]+$',
- GET => {
- desc => "Get attibutes for rows from non-node tables.",
- usage => "||An object containing each table. Within each table object is an array of row objects containing the attributes.|",
- example => qq(|Get row which net=192.168.1.0,mask=255.255.255.0 from networks table.|GET|/tables/networks/rows/net=192.168.1.0,mask=255.255.255.0|{\n \"networks\":[\n {\n \"mgtifname\":\"eth0\",\n \"netname\":\"192_168_1_0-255_255_255_0\",\n \"tftpserver\":\"192.168.1.15\",\n \"gateway\":\"192.168.1.100\",\n \"staticrangeincrement\":\"1\",\n \"net\":\"192.168.1.0\",\n \"mask\":\"255.255.255.0\"\n }\n ]\n}|),
- fhandler => \&tablerowhdl,
- outhdler => \&tableout,
- },
- PUT => {
- desc => "Change the non-node table attibutes for the row that matches the {keys}.",
- usage => "|A hash of attribute names and values. DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|",
- example => '|Create a route row in the routes table.|PUT|/tables/routes/rows/routename=privnet {"net":"10.0.1.0","mask":"255.255.255.0","gateway":"10.0.1.254","ifname":"eth1"}||',
- fhandler => \&tablerowputhdl,
- outhdler => \&noout,
- },
- DELETE => {
- desc => "Delete rows from a non-node table that have the attribute values specified in {keys}.",
- usage => "||$usagemsg{non_getreturn}|",
- example => '|Delete a route row which routename=privnet in the routes table.|DELETE|/tables/routes/rows/routename=privnet||',
- fhandler => \&tablerowdelhdl,
- outhdler => \&noout,
- },
- },
- table_rows_attrs => {
- desc => "[URI:/tables/{tablelist}/rows/{keys}/{attrlist}] - The non-node table attributes resource",
- desc1 => "Use this for tables that don't have node name as the key of the table, for example: passwd, site, networks, polciy, etc.",
- matcher => '^/tables/[^/]+/rows/[^/]+/[^/]+$',
- GET => {
- desc => "Get specific attibutes for rows from non-node tables.",
- usage => "||An object containing each table. Within each table object is an array of row objects containing the attributes.|",
- example => qq(|Get attributes mgtifname and tftpserver which net=192.168.1.0,mask=255.255.255.0 from networks table.|GET|/tables/networks/rows/net=192.168.1.0,mask=255.255.255.0/mgtifname,tftpserver|{\n \"networks\":[\n {\n \"mgtifname\":\"eth0\",\n \"tftpserver\":\"192.168.1.15\"\n }\n ]\n}|),
- fhandler => \&tablerowhdl,
- outhdler => \&tableout,
- },
- },
- },
-
- #### definition for tokens resources
- tokens => {
- tokens => {
- desc => "[URI:/tokens] - The authentication token resource.",
- matcher => '^\/tokens',
- POST => {
- desc => "Create a token.",
- usage => "||An array of all the global configuration list.|",
- example => "|Aquire a token for user \'root\'.|POST|/tokens {\"userName\":\"root\",\"userPW\":\"cluster\"}|{\n \"token\":{\n \"id\":\"a6e89b59-2b23-429a-b3fe-d16807dd19eb\",\n \"expire\":\"2014-3-8 14:55:0\"\n }\n}|",
- fhandler => \&nonobjhdl,
- outhdler => \&tokenout,
- },
- POST_backup => {
- desc => "Add the site attributes. DataBody: {attr1:v1,att2:v2...}.",
- usage => "|?|?|",
- example => "|?|?|?|?|",
- cmd => "chdef",
- fhandler => \&sitehdl,
- },
- },
- },
-
- ### interface to access local system resource which is not managed by xcat directly
- ### localres can be looked as a top level non-xcat resource pool
- ### rest operation will trasfer the target resource to xcatd plugin to handle the non-xcat resource
- localres => {
- localres => {
- desc => "[URI:/localres/*] - The local non-xcat resource.",
- matcher => '^/localres(/[^/]*)+$',
- GET => {
- desc => "List information for the target system resource.",
- usage => "||For target resource can match any resource type which can be proccssed by the resthelper plugin.|",
- example => qq(|List adapters on MN machine|GET|/localres/interface/|{\n \"interfaces\":[\n\"eth0\",\n \"eth1\",\n]"|),
- cmd => "localrest",
- fhandler => \&localreshdl,
- outhdler => \&localresout,
- },
- }
- },
-
- templates => {
- node => {
- desc =>
- "[URI:/templates/node] - The template information of nodes.",
- matcher => '^/templates/node$',
- GET => {
- desc => "Show attributes of a node template.",
- usage => "||$usagemsg{objreturn}|",
- example => "|GET all the attibutes of node template \'x86_64kvmguest-template\'.|GET|/templates/node {\"options\":{\"--template\":\"x86_64kvmguest-template\"}} |{\n \"arch\":{\n \"x86_64\":\"compute\",\n \"bmc\":\"MANDATORY:The hostname or ip address of the BMC adapater\",\n \bmcpassword\":\"MANDATORY:the password of the BMC\",\n \"mgt\":\"ipmi\",\n \"groups\":\"all\",\n ...\n }\n}",
- cmd => "lsdef",
- fhandler => \&defhdl,
- outhdler => \&defout,
- },
- },
- # Generally, the 'oprions' json filed could be used to support different argument of the command.
- # As limited by the different outhdler, a new resource name 'all' has to be added here.
- all => {
- desc => "[URI:/templates/node/all] - The template information of node.",
- matcher => '^/templates/node/all$',
- GET => {
- desc => "List template items of node.",
- usage => "||$usagemsg{objreturn}|",
- example => "|List all the templates. |GET /templates/node/all {\"options\":{\"--template\":\"\"}}| [cec-template,hmc-template,ppc64le-template,x86_64-template,x86_64kvmguest-template]",
- cmd => "lsdef",
- fhandler => \&defhdl,
- outhdler => \&defout_remove_appended_type,
- },
- },
- },
-);
-
-# supported formats
-my %formatters = (
- 'json' => \&wrapJson,
-
- #'html' => \&wrapHtml,
- #'xml' => \&wrapXml
-);
-
-# error status codes
+#error status codes
my $STATUS_BAD_REQUEST = "400 Bad Request";
my $STATUS_UNAUTH = "401 Unauthorized";
my $STATUS_FORBIDDEN = "403 Forbidden";
@@ -1316,1845 +41,21 @@ my $STATUS_EXPECT_FAILED = "417 Expectation Failed";
my $STATUS_TEAPOT = "418 I'm a teapot";
my $STATUS_SERVICE_UNAVAILABLE = "503 Service Unavailable";
-# good status codes
+#good status codes
my $STATUS_OK = "200 OK";
my $STATUS_CREATED = "201 Created";
-# Development notes:
-# - added this line to /etc/httpd/conf/httpd.conf to hide the cgi-bin and .cgi extension in the uri:
-# ScriptAlias /xcatws /var/www/cgi-bin/xcatws.cgi
-# - also upgraded CGI to 3.52
-# - If "Internal Server Error" is returned, look at /var/log/httpd/ssl_error_log
-# - can run your cgi script from the cli: http://perldoc.perl.org/CGI.html#DEBUGGING
+#default format
+my $format = 'html';
-# This is how the parameters come in:
-# GET: url parameters come $q->url_param. There is no put/post data.
-# PUT: url parameters come $q->url_param. Put data comes in q->param(PUTDATA).
-# POST: url parameters come $q->url_param. Post data comes in q->param(POSTDATA).
-# DELETE: ??
-
-# Notes from http://perldoc.perl.org/CGI.html:
-# %params = $q->Vars; # same as $q->param() except put it in a hash
-# @foo = split("\0",$params{'foo'});
-# my $error = $q->cgi_error; #todo: check for errors that occurred while processing user input
-# print $q->end_html; #todo: add the tags
-# $q->url_param() # gets url options, even when there is put/post data (unlike q->param)
-
-
-
-#### Main procedure to handle the REST request
-
-# To get the HTTP elements through perl CGI module
-my $q = CGI->new;
-my $pathInfo = $q->path_info; # the resource specification, i.e. everything in the url after xcatws
-my $requestType = $q->request_method(); # GET, PUT, POST, PATCH, DELETE
-my $userAgent = $q->user_agent(); # the client program: curl, etc.
-my @path = split(/\//, $pathInfo); # The uri path like /nodes/node1/...
-
-# Define the golbal variables which will be used through the handling process
-my $pageContent = ''; # Global var containing the ouptut back to the rest client
-my %header_info; #Global var containing the extra info to the http header
-my $request = { clienttype => 'ws' }; # Global var that holds the request to send to xcatd
-my $format = 'json'; # The output format for a request invoke
-my $xmlinstalled; # Global var to speicfy whether the xml modules have been loaded
-
-# To easy the perl debug, this script can be run directly with 'perl -d'
-# This script also support to generate the rest api doc automatically.
-# Following part of code will not be run when this script is called by http server
-my $dbgdata;
-sub dbgusage { print "Usage:\n $0 -h\n $0 -g rst > ../../docs/source/advanced/restapi/restapi_resource/restapi_reference.rst (generate document)\n $0 {GET|PUT|POST|DELETE} URI user:password \'{data}\'\n"; }
-
-if ($ARGV[0] eq "-h") {
- dbgusage();
- exit 0;
-} elsif ($ARGV[0] eq "-g") {
-
- # generate the document
- require genrestapidoc;
- if (defined($ARGV[1])) {
- genrestapidoc::gendoc(\%URIdef, $ARGV[1]);
- } else {
- genrestapidoc::gendoc(\%URIdef);
- }
- exit 0;
-} elsif ($ARGV[0] eq "-d") {
- displayUsage();
- exit 0;
-} elsif ($ARGV[0] =~ /(GET|PUT|POST|DELETE)/) {
-
- # parse the parameters when run this script locally
- $requestType = $ARGV[0];
- $pathInfo = $ARGV[1];
-
- unless ($pathInfo) { dbgusage(); exit 1; }
-
- if ($ARGV[2] =~ /(.*):(.*)/) {
- $ENV{userName} = $1;
- $ENV{password} = $2;
- } else {
- dbgusage();
- exit 0;
- }
- $dbgdata = $ARGV[3] if defined($ARGV[3]);
-} elsif (defined($ARGV[0])) {
- dbgusage();
- exit 1;
-}
-
-my $JSON; # global ptr to the json object. Its set by loadJSON()
-
-# Since the json is the only supported format, load it at beginning
-# need to do this early, so we can fetch the PUT/POST params
-loadJSON();
-
-# the input parameters from both the url and put/post data will be combined and then
-# separated into the general params (not specific to the api call) and params specific to the call
-# Note: some of the values of the params in the hash can be arrays
-# $generalparams - the general parameters like 'debug=1', 'pretty=1'
-# $paramhash - all parameters that come from the url or put/post data except the ones that are put in $generalparams
-my ($generalparams, $paramhash) = fetchParameters();
-
-my $DEBUGGING = $generalparams->{debug}; # turn on or off the debugging output by setting debug=1 (or 2) in the url string
-if ($DEBUGGING) {
- displaydebugmsg();
-}
-
-# The filter flag is used to group the nodes which have the same output
-my $XCOLL = $generalparams->{xcoll};
-
-# Process the format requested
-$format = $generalparams->{format} if (defined($generalparams->{format}));
-
-# Remove the last '/' in the pathInfo
-$pathInfo =~ s/\/$//;
-
-# Get the payload format from the end of URI
-#if ($pathInfo =~ /\.json$/) {
-# $format = "json";
-# $pathInfo =~ s/\.json$//;
-#} elsif ($pathInfo =~ /\.json.pretty$/) {
-# $format = "json";
-# $pretty = 1;
-# $pathInfo =~ s/\.json.pretty$//;
-#} elsif ($pathInfo =~ /\.xml$/) {
-# $format = "xml";
-# $pathInfo =~ s/\.xml$//;
-#} elsif ($pathInfo =~ /\.html$/) {
-# $format = "html";
-# $pathInfo =~ s/\.html$//;
-#}
-
-#if (!exists $formatters{$format}) {
-# error("The format '$format' is not supported",$STATUS_BAD_REQUEST);
-#}
-
-if ($format eq 'json') {
-
- # make the output to be readable if 'pretty=1' is specified
- if ($generalparams->{pretty}) { $JSON->indent(1); }
-}
-
-# we need XML all the time to send request to xcat, even if thats not the return format requested by the user
-loadXML();
-
-# The first layer of resource URI. It should be 'nodes' for URI '/nodes/node1'
-my $uriLayer1;
-
-# Get all the layers in the URI
-my @layers = split('\/', $pathInfo);
-shift(@layers);
-
-if ($#layers < 0) {
-
- # If no resource was specified, list all the resource groups which have been defined in the %URIdef
- my $json;
- foreach (sort keys %URIdef) {
- push @{$json}, $_;
- }
- if ($json) {
- addPageContent($JSON->encode($json));
- }
- sendResponseMsg($STATUS_OK); # this will also exit
-} else {
- $uriLayer1 = $layers[0];
-}
-
-# set the user and password to access xcatd
-$request->{becomeuser}->[0]->{username}->[0] = $ENV{userName} if (defined($ENV{userName}));
-$request->{becomeuser}->[0]->{username}->[0] = $generalparams->{userName} if (defined($generalparams->{userName}));
-$request->{becomeuser}->[0]->{password}->[0] = $ENV{password} if (defined($ENV{password}));
-$request->{becomeuser}->[0]->{password}->[0] = $generalparams->{userPW} if (defined($generalparams->{userPW}));
-
-# use the token if it is specified with X_AUTH_TOKEN head
-$request->{tokens}->[0]->{tokenid}->[0] = $ENV{'HTTP_X_AUTH_TOKEN'} if (defined($ENV{'HTTP_X_AUTH_TOKEN'}));
-
-# find and invoke the correct handler and output handler functions
-my $outputdata;
-my $handled;
-if (defined($URIdef{$uriLayer1})) {
-
- # Make sure the resource has been defined
- foreach my $res (keys %{ $URIdef{$uriLayer1} }) {
- my $matcher = $URIdef{$uriLayer1}->{$res}->{matcher};
- if ($pathInfo =~ m|$matcher|) {
-
- # matched to a resource
- unless (defined($URIdef{$uriLayer1}->{$res}->{$requestType})) {
- error("request method '$requestType' is not supported on resource '$pathInfo'", $STATUS_NOT_ALLOWED);
- }
- if (defined($URIdef{$uriLayer1}->{$res}->{$requestType}->{fhandler})) {
- my $params;
-
- $params->{'cmd'} = $URIdef{$uriLayer1}->{$res}->{$requestType}->{cmd} if (defined($URIdef{$uriLayer1}->{$res}->{$requestType}->{cmd}));
- $params->{'outputhdler'} = $URIdef{$uriLayer1}->{$res}->{$requestType}->{outhdler} if (defined($URIdef{$uriLayer1}->{$res}->{$requestType}->{outhdler}));
- $params->{'layers'} = \@layers;
- $params->{'resourcegroup'} = $uriLayer1;
- $params->{'resourcename'} = $res;
-
- # Call the handler subroutine which specified in 'fhandler' to send request to xcatd and get the response
- $outputdata = $URIdef{$uriLayer1}->{$res}->{$requestType}->{fhandler}->($params);
-
- # Filter the output data from the response
- $outputdata = filterData($outputdata);
-
- # Restructure the output data with the subroutine which is specified in 'outhdler'
- if (defined($URIdef{$uriLayer1}->{$res}->{$requestType}->{outhdler})) {
- $outputdata = $URIdef{$uriLayer1}->{$res}->{$requestType}->{outhdler}->($outputdata, $params);
- } else {
-
- # Call the appropriate formatting function stored in the formatters hash as default output handler
- if (exists $formatters{$format}) {
- $formatters{$format}->($outputdata);
- }
- }
-
- $handled = 1;
- last;
- }
- }
- }
-} else {
-
- # not matches to any resource group. Check the 'resource group' to improve the performance
- error("Unspported resource.", $STATUS_NOT_FOUND);
-}
-
-# the URI cannot match to any resources which are defined in %URIdef
-unless ($handled) {
- error("Unspported resource.", $STATUS_NOT_FOUND);
-}
-
-
-# all output has been added into the global varibale pageContent, call the response funcion to generate HTTP reply and exit
-
-if (isPost()) {
- sendResponseMsg($STATUS_CREATED);
-}
-else {
- sendResponseMsg($STATUS_OK);
-}
-
-#### End of the Main Program
-
-
-
-
-
-#===========================================================
-# Subrutines
-sub isGET { return uc($requestType) eq "GET"; }
-sub isPost { return uc($requestType) eq "POST"; }
-sub isPut { return uc($requestType) eq "PUT"; }
-sub isPatch { return uc($requestType) eq "PATCH"; }
-sub isDelete { return uc($requestType) eq "DELETE"; }
-
-
-#handle the output for def command and rscan
-#handle the input like
-# ===raw xml input
-# $d->{info}->[msg list] - each msg could be mulitple msg which split with '\n'
-# $d->{data}->[msg list]
-#
-# ===msg format
-# Object name:
-# attr=value
-#OR
-# :
-# attr=value
-# ---
-#TO
-# ---
-# { : {
-# attr : value
-# ...
-# } ... }
-sub defout {
- my $data = shift;
-
- my $json;
- foreach my $d (@$data) {
- my $nodename;
- my $lines;
- my @alldata;
- if (defined($d->{info})) {
- foreach (@{ $d->{info} }) {
- push @alldata, split('\n', $_);
- }
- $lines = \@alldata;
- } elsif (defined($d->{data})) {
- foreach (@{ $d->{data} }) {
- push @alldata, split('\n', $_);
- }
- $lines = \@alldata;
- }
- foreach my $l (@$lines) {
- if ($l =~ /No responses/) { # handle the case that no output from lsslp command
- return;
- } elsif ($l =~ /Could not find any object definitions/) {
- $json->{info} = $l;
- last;
- }
- if ($l =~ /^Object name: / || $l =~ /^\S+:$/) { # start new node
- if ($l =~ /^Object name:\s+(\S+)/) { # handle the output of lsdef -t
- $nodename = $1;
- }
- if ($l =~ /^(\S+):$/) { # handle the output for stanza format '-z'
- $nodename = $1;
- }
- }
- else { # just an attribute of the current node
- if (!$nodename) { error('improperly formatted lsdef output from xcatd', $STATUS_TEAPOT); }
- my ($attr, $val) = $l =~ /^\s*(\S+?)=(.*)$/;
- if (!defined($attr)) { error('improperly formatted lsdef output from xcatd', $STATUS_TEAPOT); }
- $json->{$nodename}->{$attr} = $val;
- }
- }
- }
- if ($json) {
- addPageContent($JSON->encode($json), 1);
- }
-}
-
-#handle the output for lsdef -t command
-#handle the input like
-# ===raw xml input
-# $d->{info}->[msg list] - each msg could be mulitple msg which split with '\n'
-#
-# ===msg format
-# node1 (node)
-# node2 (node)
-# node3 (node)
-# ---
-#TO
-# ---
-# node1
-# node2
-# node3
-sub defout_remove_appended_type {
- my $data = shift;
-
- my $json;
- foreach my $d (@$data) {
- my $jsonnode;
- my $lines = $d->{info};
- foreach my $l (@$lines) {
- if ($l =~ /^(\S*)\s+\(.*\)$/) { # start new node
- push @{$json}, $1;
- } elsif ($l =~ /Could not find any object definitions/) {
- push @{$json}, $l;
- last;
- }
- }
- }
- if ($json) {
- addPageContent($JSON->encode($json), 1);
- }
-}
-
-#handle the output for bmcdiscover command
-#handle the input like
-#
-#$VAR1 = [
-# {
-# 'info' => [
-# 'bmc_1'
-# ]
-# },
-# {
-# 'info' => [
-# 'bmc_2'
-# ]
-# },
-# {
-# 'info' => [
-# 'bmc_3'
-# ]
-# }
-# ];
-#
-# ===msg format
-# bmc_1
-# bmc_2
-# bmc_3
-# ---
-#
-#TO
-# ---
-# [
-# "bmc_1",
-# "bmc_2",
-# "bmc_3"
-# ]
-
-#
-sub defout_remove_appended_info {
- my $data = shift;
-
- my $json;
- foreach my $d (@$data) {
- my $jsonnode;
- my $lines = $d->{info};
- foreach my $l (@$lines) {
-
- # if ($l =~ /^(\S*)\s+\(.*\)$/) { # start new node
- push(@{$json}, $l);
-
- # }
- }
- }
- if ($json) {
- addPageContent($JSON->encode($json), 1);
- }
-}
-
-
-sub localresout {
- my $data = shift;
- my $json;
- if ($data->[0]->{info}->[0] eq 'stream') {
- $format = 'stream';
- $header_info{'attachment'} = $data->[0]->{info}->[1];
- addPageContent($data->[0]->{info}->[2]);
- } elsif ($data->[0]->{info}->[0] eq 'json') {
- addPageContent($data->[0]->{info}->[1]);
- }
-}
-
-# hanlde the output which has the node irrelevant message (e.g. the output for updatenode command)
-# handle the input like
-# ===raw xml input
-# $d->{info}->[msg list] - each msg could be mulitple msg which split with '\n'
-# $d->{data}->[msg list]
-# $d->{data}->{contents}->[msg list]
-#
-# ===msg format
-# "There were no syncfiles defined to process. File synchronization has completed.",
-# "Performing software maintenance operations. This could take a while, if there are packages to install.",
-# "node2: Tue Apr 2 15:55:57 CST 2013 Running postscript: ospkgs",
-# ---
-#TO
-# ---
-# [
-# "There were no syncfiles defined to process. File synchronization has completed.",
-# "Performing software maintenance operations. This could take a while, if there are packages to install.",
-# "node2: Tue Apr 2 15:55:57 CST 2013 Running postscript: ospkgs",
-# ]
-#
-# An exception is to handle the output of 'xdsh'(nodeshell). Since each msg has a : head, split the head out and group
-# the msg with the name in the head.
-
-sub infoout {
- my $data = shift;
- my $param = shift;
-
- my $json;
- foreach my $d (@$data) {
- if (defined($d->{info})) {
- foreach (@{ $d->{info} }) {
- push @{$json}, split('\n', $_);
- }
- }
- if (defined($d->{data})) {
- if (ref($d->{data}->[0]) ne "HASH") {
- foreach (@{ $d->{data} }) {
- push @{$json}, split('\n', $_);
- }
- } else {
- if (defined($d->{data}->[0]->{contents})) {
- push @{$json}, @{ $d->{data}->[0]->{contents} };
- }
- }
- }
- if (defined($d->{error})) {
- push @{$json}, @{ $d->{error} };
- }
- }
-
- # for nodeshell (xdsh), group msg with node name
- if ($param->{'resourcename'} =~ /(nodeshell|postscript|software_maintenance)/) {
- my $jsonnode;
- foreach (@{$json}) {
- if (/^(\S+):(.*)$/) {
- push @{ $jsonnode->{$1} }, $2 if ($2 !~ /^\s*$/);
- }
- }
- if (!$jsonnode && $json)
- {
- push(@{$jsonnode}, @{$json});
- }
- addPageContent($JSON->encode($jsonnode), 1);
- return;
- }
- if ($json) {
- addPageContent($JSON->encode($json), 1);
- }
-}
-
-# hanlde the output which is node relevant (rpower, rinv, rvitals ...)
-# the output must be grouped with 'node' as key
-# handle the input like
-# ===raw xml input
-# $d->{node}->{name}->[name] # this is must have, otherwise ignore the msg
-# $d->{node}->{data}->[msg]
-#OR
-# $d->{node}->{name}->[name] # this is must have, otherwise ignore the msg
-# $d->{node}->{data}->{contents}->[msg]
-#OR
-# $d->{node}->{name}->[name] # this is must have, otherwise ignore the msg
-# $d->{node}->{data}->{contents}->[msg]
-# $d->{node}->{data}->{desc}->[msg]
-#
-# Note: if does not have '$d->{node}->{data}->{desc}', use the resource name as the name of attribute.
-# e.g. Get /node/node1/power, the record is '"power":"off"'
-#
-# ===msg format
-#
-#
-# 1.41 (VVE128GUS 2013/07/22)
-# UEFI Version
-#
-# node1
-#
-# ---
-#TO
-# ---
-# {
-# "node1":{
-# "UEFI Version":"1.41 (VVE128GUS 2013/07/22)",
-# }
-# }
-sub actionout {
- my $data = shift;
- my $param = shift;
-
- my $jsonnode;
- foreach my $d (@$data) {
- unless (defined($d->{node}->[0]->{name})) {
- next;
- }
- if (defined($d->{node}->[0]->{data}) && (ref($d->{node}->[0]->{data}->[0]) ne "HASH" || !defined($d->{node}->[0]->{data}->[0]->{contents}))) {
-
- # no $d->{node}->{data}->{contents} or $d->{node}->[0]->{data} is not hash
- $jsonnode->{ $d->{node}->[0]->{name}->[0] }->{ $param->{'resourcename'} } = $d->{node}->[0]->{data}->[0];
- } elsif (defined($d->{node}->[0]->{data}->[0]->{contents})) {
- if (defined($d->{node}->[0]->{data}->[0]->{desc})) {
-
- # has $d->{node}->{data}->{desc}
- $jsonnode->{ $d->{node}->[0]->{name}->[0] }->{ $d->{node}->[0]->{data}->[0]->{desc}->[0] } = $d->{node}->[0]->{data}->[0]->{contents}->[0];
- } else {
-
- # use resourcename as the record name
- if ($param->{'resourcename'} eq "eventlog") {
- push @{ $jsonnode->{ $d->{node}->[0]->{name}->[0] }->{ $param->{'resourcename'} } }, $d->{node}->[0]->{data}->[0]->{contents}->[0];
- } elsif ($param->{'resourcename'} =~ /(vitals|inventory)/) {
-
- # handle output of rvital and rinv for ppc node
- #push @{$jsonnode->{$d->{node}->[0]->{name}->[0]}}, $d->{node}->[0]->{data}->[0]->{contents}->[0];
- push @{ $jsonnode->{ $d->{node}->[0]->{name}->[0] }->{Message} }, $d->{node}->[0]->{data}->[0]->{contents}->[0];
- } else {
- $jsonnode->{ $d->{node}->[0]->{name}->[0] }->{ $param->{'resourcename'} } = $d->{node}->[0]->{data}->[0]->{contents}->[0];
- }
- }
- }
- }
-
- addPageContent($JSON->encode($jsonnode), 1) if ($jsonnode);
-}
-
-# hanlde the output which has the token id
-# handle the input like
-# ===raw xml input
-# $d->{data}->{token}->{id}
-# $d->{data}->{token}->{expire}
-sub tokenout {
- my $data = shift;
-
- my $json;
- foreach my $d (@$data) {
- if (defined($d->{data}) && defined($d->{data}->[0]->{token})) {
- $json->{token}->{id} = $d->{data}->[0]->{token}->[0]->{id}->[0];
- $json->{token}->{expire} = $d->{data}->[0]->{token}->[0]->{expire}->[0];
- }
- }
-
- if ($json) {
- addPageContent($JSON->encode($json));
- }
-}
-
-# This is the general callback subroutine for PUT/POST/DELETE methods
-# when this subroutine is called, that means the operation has been done successfully
-# The correct output is 'null'
-sub noout {
- return;
-### for debugging
- my $data = shift;
-
- addPageContent(qq(\n\n\n=======================================================\nDebug: Following message is just for debugging. It will be removed in the GAed version.\n));
-
- my $json;
- if ($data) {
- addPageContent($JSON->encode($data));
- }
-
- addPageContent(qq(["Debug: the operation has been done successfully"]));
-### finish the debugging
-}
-
-# The operation callback subroutine for def related resource (lsdef, chdef ...)
-# assembe the xcat request, send it to xcatd and get response
-sub defhdl {
- my $params = shift;
-
- my @args;
- my @urilayers = @{ $params->{'layers'} };
-
- # set the command name
- $request->{command} = $params->{'cmd'};
-
- # push the -t args for *def command
- my $resrctype = $params->{'resourcegroup'};
- $resrctype =~ s/s$//; # remove the last 's' as the type of object
- push @args, ('-t', $resrctype) if $resrctype ne 'template';
-
- # push the object name - node/noderange
- if (defined($urilayers[1]) && $resrctype ne 'template') {
- if ($urilayers[1] eq "ALLRESOURCES") {
- unless (isGET()) {
- error("Keyword ALLRESOURCES is only supported for GET Action.", $STATUS_NOT_FOUND);
- }
- push @args, '-l';
- } else {
- push @args, ('-o', $urilayers[1]);
- }
- }
-
- # For template only.
- if ($resrctype eq 'template') {
- if ($params->{'resourcename'} eq "all") {
- $paramhash->{'options'}->{'-a'} = "";
- }
- }
- # For the put/post which specifies attributes like mgt=ipmi groups=all
- foreach my $k (keys(%$paramhash)) {
- next if (!$k);
- # NOTE: The json field 'options' may be confilict with the attibute
- # name called 'options', but it does not happen currently. A better
- # solution is to add a new json field called attributes like this
- # {options:{}, attributes:{}} to avoid of the ambiguity.
- if ($k eq 'options') {
- my $options = $paramhash->{$k};
- my ($opt_key, $opt_val);
- while(($opt_key, $opt_val) = each(%{$options})) {
- next if (!$opt_key || grep (/^$opt_key$/, ('-o','-l','-t')));
- push @args, $opt_key;
- push @args, $opt_val if $opt_val;
- }
- next;
- }
- push @args, "$k=$paramhash->{$k}" if $paramhash->{$k};
- }
-
- if ($params->{'resourcename'} eq "allnode") {
- push @args, '-s';
- } elsif ($params->{'resourcename'} =~ /(nodeattr|osimage_attr|group_attr|policy_attr|network_attr)/) {
-
- # if /nodes/node1/attrs/attr1,att2 is specified, for get request,
- # use 'lsdef -i' to specify the attribute list
- my $attrs = $urilayers[3];
- $attrs =~ s/;/,/g;
-
- if (isGET()) {
- push @args, ('-i', $attrs);
- }
- }
-
- push @{ $request->{arg} }, @args;
- my $req = genRequest();
- my $responses = sendRequest($req);
-
- return $responses;
-}
-
-# The operation callback subroutine for any node related resource (power, energy ...)
-# assembe the xcat request, send it to xcatd and get response
-sub actionhdl {
- my $params = shift;
-
- my @args;
- my @urilayers = @{ $params->{'layers'} };
-
- # set the command name
- $request->{command} = $params->{'cmd'};
-
- # push the object name - node/noderange
- if (defined($urilayers[1])) {
- $request->{noderange} = $urilayers[1];
- }
-
- if ($params->{'resourcename'} eq "power") {
- if (isGET()) {
- push @args, 'stat';
- } elsif ($paramhash->{'action'}) {
-
- #my @v = keys(%$paramhash);
- push @args, $paramhash->{'action'};
- } else {
- error("Missed Action.", $STATUS_NOT_FOUND);
- }
- } elsif ($params->{'resourcename'} =~ /(energy|energyattr)/) {
- if (isGET()) {
- if ($params->{'resourcename'} eq "energy") {
- push @args, 'all';
- } elsif ($params->{'resourcename'} eq "energyattr") {
- my @attrs = split(',', $urilayers[3]);
- push @args, @attrs;
- }
- } elsif ($paramhash) {
- my @params = keys(%$paramhash);
- push @args, "$params[0]=$paramhash->{$params[0]}";
- } else {
- error("Missed Action.", $STATUS_NOT_FOUND);
- }
- } elsif ($params->{'resourcename'} eq "bootstate") {
- if (isGET()) {
- push @args, 'stat';
- } elsif ($paramhash->{'action'}) {
- push @args, $paramhash->{'action'};
- } elsif ($paramhash) {
- my @params = keys(%$paramhash);
- if ($params[0] eq "state") {
-
- # hanlde the {state:offline}
- push @args, $paramhash->{ $params[0] };
- } else {
-
- # handle the {osimage:imagename}
- push @args, "$params[0]=$paramhash->{$params[0]}";
- }
- } else {
- error("Missed Action.", $STATUS_NOT_FOUND);
- }
- } elsif ($params->{'resourcename'} eq "nextboot") {
- if (isGET()) {
- push @args, 'stat';
- } elsif ($paramhash->{'order'}) {
- push @args, $paramhash->{'order'};
- } else {
- error("Missed Action.", $STATUS_NOT_FOUND);
- }
- } elsif ($params->{'resourcename'} =~ /(vitals|vitalsattr|inventory|inventoryattr)/) {
- if (defined($urilayers[3])) {
- my @attrs = split(';', $urilayers[3]);
- push @args, @attrs;
- } else { # default, get all attrs
- push @args, "all";
- }
- } elsif ($params->{'resourcename'} eq "serviceprocessor") {
- if (isGET()) {
- push @args, $urilayers[3];
- } elsif (isPut() or isPost()) {
- if ($paramhash->{'value'} and defined($urilayers[3])) {
- push @args, $urilayers[3] . "=" . $paramhash->{'value'};
- } else {
- foreach my $key (keys %$paramhash) {
- if (($key ne '') and (exists($paramhash->{$key}))) {
- push @args, $key . "=" . $paramhash->{$key};
- }
- }
- }
- }
- } elsif ($params->{'resourcename'} eq "eventlog") {
- if (isGET()) {
- push @args, 'all';
- } elsif (isDelete()) {
- push @args, 'clear';
- }
- } elsif ($params->{'resourcename'} eq "beacon") {
- if (isPut()) {
- push @args, $paramhash->{'action'};
- }
- } elsif ($params->{'resourcename'} eq "filesyncing") {
- push @args, '-F';
- } elsif ($params->{'resourcename'} eq "software_maintenance") {
- push @args, '-S';
- } elsif ($params->{'resourcename'} eq "postscript") {
- push @args, '-P';
- if (defined($paramhash->{'scripts'})) {
- push @args, join(',', @{ $paramhash->{'scripts'} });
- }
- } elsif ($params->{'resourcename'} eq "nodeshell") {
- if (%$paramhash)
- {
- foreach my $key1 (keys %$paramhash) {
- if ($key1 eq "ENV" && defined($paramhash->{'ENV'})) {
- foreach my $key (keys %{ $paramhash->{'ENV'} }) {
- if (($key ne '') and (exists($paramhash->{'ENV'}->{$key}))) {
- push(@{ $request->{env} }, "$key=$paramhash->{'ENV'}->{$key}");
- }
- }
- next;
- }
- elsif ($key1 eq "raw" && defined($paramhash->{'raw'})) {
- if (ref($paramhash->{'raw'}) eq "ARRAY") {
- push @args, join(';', @{ $paramhash->{'raw'} });
- } else {
- push @args, $paramhash->{'raw'};
- }
- next;
- }
- elsif ($key1 eq "command" && defined($paramhash->{'command'})) {
- if (ref($paramhash->{'command'}) eq "ARRAY") {
- push @args, join(';', @{ $paramhash->{'command'} });
- } else {
- push @args, $paramhash->{'command'};
- }
- next;
- }
- }
- }
- else {
- error("Lack of operation data.", $STATUS_BAD_REQUEST, 3);
- }
-
- } elsif ($params->{'resourcename'} eq "nodecopy") {
- if (defined($paramhash->{'src'})) {
- push @args, @{ $paramhash->{'src'} };
- }
- if (defined($paramhash->{'target'})) {
- push @args, $paramhash->{'target'};
- }
- } elsif ($params->{'resourcename'} =~ /(dns|dhcp)/) {
- if (isDelete()) {
- push @args, '-d';
- }
- } elsif ($params->{'resourcename'} eq "subnodes") {
- if (isGET()) {
- push @args, '-z';
- }
- } elsif ($params->{'resourcename'} eq "vm") {
-
- # handle the virtual machine
- if (isGET()) {
-
- # do nothing for kvm and esxi
- } elsif (isPut()) { # change the configuration of vm
- if (defined($paramhash->{'adddisk'})) { #add new disk
- push @args, ('-a', $paramhash->{'adddisk'});
- }
-
- #if (defined ($paramhash->{'rmdisk'})) { #remove disk
- # push @args, ('-d', $paramhash->{'rmdisk'});
- #}
- if (defined($paramhash->{'purgedisk'})) { #purge disk
- push @args, ('-p', $paramhash->{'purgedisk'});
- }
- if (defined($paramhash->{'resizedisk'})) { #change the disk size
- $paramhash->{'resizedisk'} =~ s/\:/=/; # replace : to be = in the param
- push @args, ('--resize', $paramhash->{'resizedisk'});
- }
- if (defined($paramhash->{'memorysize'})) { #change the memory size
- push @args, ('--mem', $paramhash->{'memorysize'});
- }
- if (defined($paramhash->{'cpucount'})) { #change the cpu size
- push @args, ('--cpus', $paramhash->{'cpucount'});
- }
- } elsif (isPost()) { # create virtual machine
- if (defined($paramhash->{'master'})) { # specify the master node for clone
- push @args, ('-m', $paramhash->{'master'});
- }
- if (defined($paramhash->{'disksize'})) { # specify disk size
- push @args, ('-s', $paramhash->{'disksize'});
- }
- if (defined($paramhash->{'memorysize'})) { #specify the memory size
- push @args, ('--mem', $paramhash->{'memorysize'});
- }
- if (defined($paramhash->{'cpucount'})) { #specify the cpu size
- push @args, ('--cpus', $paramhash->{'cpucount'});
- }
- if (defined($paramhash->{'force'}) && $paramhash->{'force'} eq "yes") { # force the recreate
- push @args, "-f";
- }
- } elsif (isDelete()) {
- if (defined($paramhash->{'force'}) && $paramhash->{'force'} eq "yes") { # force the recreate
- push @args, "-f";
- }
- if (defined($paramhash->{'purge'}) && $paramhash->{'purge'} eq "yes") { # purge disk when remove the vm
- push @args, "-p";
- }
- }
- } elsif ($params->{'resourcename'} eq "vmclone") {
-
- # handle the clone of virtual machine
- if (isPost()) {
- if (defined($paramhash->{'tomaster'})) {
- push @args, ("-t", $paramhash->{'tomaster'});
- } elsif (defined($paramhash->{'frommaster'})) {
- push @args, ("-b", $paramhash->{'frommaster'});
- } else {
- error("Lack of operation data.", $STATUS_BAD_REQUEST, 3);
- }
-
- if (defined($paramhash->{'detach'}) && $paramhash->{'detach'} eq "yes") {
- push @args, "-d";
- }
- if (defined($paramhash->{'force'}) && $paramhash->{'force'} eq "yes") { # force the recreate
- push @args, "-f";
- }
- }
- } elsif (($params->{'resourcename'} eq "vmmigrate")) {
-
- # handle the migration of virtual machine
- if (isPost()) {
- if (defined($paramhash->{'target'})) {
- push @args, $paramhash->{'target'};
- } else {
- error("Lack of operation data.", $STATUS_BAD_REQUEST, 3);
- }
- }
- } elsif ($params->{'resourcename'} eq "noderename") {
-
- if (isPut()) {
- if (defined($paramhash->{'newNode'})) { #specify the new name for node
- push @args, ('-t', "node");
- push @args, ('-o', $urilayers[1]);
- push @args, ('-n', $paramhash->{'newNode'});
- }
- }
- } elsif ($params->{'resourcename'} eq "nbimage") {
- delete $request->{noderange};
- push @args, $urilayers[3];
- if (isPost()) {
- if (defined($paramhash->{'onlyconfigfile'})) {
- my $tmp_value = $paramhash->{'onlyconfigfile'};
- if ($tmp_value =~ /true|yes|Y|1/i) {
- push @args, "-c";
- } elsif ($tmp_value !~ /false|no|N|0/i) {
- error("Option value \"$tmp_value\" invalid.", $STATUS_BAD_REQUEST, 3);
- }
- }
- }
-
- } elsif ($params->{'resourcename'} eq "console") {
- delete $request->{noderange};
- if ($paramhash->{'action'}) {
- my %action = ('on' => '', 'off' => '-d');
- push @args, $action{$paramhash->{'action'}};
- if ($paramhash->{'nodes'}) {
- $request->{noderange} = join(',', @{$paramhash->{'nodes'}});
- } else {
- error("Missed node.")
- }
- }
- if ($paramhash->{'trust_host'}) {
- push @args, '-t';
- push @args, $paramhash->{'trust_host'};
- }
- } elsif ($params->{'resourcename'} eq "provision") {
- if ($paramhash->{'osimage'}) {
- push @args, 'osimage='.$paramhash->{'osimage'};
- } elsif ($paramhash->{'action'}) {
- push @args, $paramhash->{'action'};
- }
- }
-
- push @{ $request->{arg} }, @args;
- my $req = genRequest();
- my $responses = sendRequest($req);
-
- return $responses;
-}
-
-sub localreshdl {
- my $params = shift;
- my @args;
- my @urilayers = @{ $params->{'layers'} };
-
- # set the command name
- $request->{command} = $params->{'cmd'};
-
- if (isGET() && scalar(@urilayers) > 1 && $urilayers[-1] eq "detail") {
- push @args, "show";
- } elsif (isGET() && scalar(@urilayers) > 1 && $urilayers[-1] eq "file") {
- push @args, "download";
- } elsif (isGET()) {
- push @args, "list";
- } elsif (isPost()) {
- push @args, "create";
- } elsif (isPut()) {
- push @args, "update";
- } elsif (isDelete()) {
- push @args, "delete";
- }
- shift @urilayers;
- foreach my $item (@urilayers) {
- push @args, $item if $item ne 'detail' && $item ne 'file';
- }
- push @{ $request->{arg} }, @args;
-
- # localrest is single plugin handler, use sequntial to avoid of multi-level processes
- $request->{'sequential'}->[0] = 1;
- my $req = genRequest();
- my $responses = sendRequest($req);
- return $responses;
-}
-
-# The operation callback subroutine for node irrelevant commands like makedns -n and makedhcp -n
-# assembe the xcat request, send it to xcatd and get response
-sub nonobjhdl {
- my $params = shift;
-
- my @args;
- my @urilayers = @{ $params->{'layers'} };
-
- # set the command name
- $request->{command} = $params->{'cmd'};
- if ($params->{'resourcename'} =~ /(dns|dhcp)/) {
- push @args, '-n';
- } elsif ($params->{'resourcename'} eq "slpnodes") {
- if (isGET()) {
- push @args, '-z';
- }
- } elsif ($params->{'resourcename'} eq "specific_slpnodes") {
- if (isGET()) {
- push @args, "-z";
- push @args, "-s";
- push @args, $urilayers[2];
- }
- } elsif ($params->{'resourcename'} eq "tokens") {
- $request->{gettoken}->[0]->{username}->[0] = $generalparams->{userName} if (defined($generalparams->{userName}));
- $request->{gettoken}->[0]->{password}->[0] = $generalparams->{userPW} if (defined($generalparams->{userPW}));
- }
-
- push @{ $request->{arg} }, @args;
- my $req = genRequest();
- my $responses = sendRequest($req);
-
- return $responses;
-}
-
-
-# operate image instance for a osimage
-sub imgophdl {
- my $params = shift;
- my @args = ();
- if (isPost()) {
- if ($params->{'resourcename'} eq "osimage_op") {
- my $action = $paramhash->{'action'};
- unless ($action) {
- error("Missed Action.", $STATUS_NOT_FOUND);
- } elsif ($action eq "gen") {
- $params->{'cmd'} = "genimage";
- } elsif ($action eq "pack") {
- $params->{'cmd'} = "packimage";
- } elsif ($action eq "export") {
- $params->{'cmd'} = "imgexport";
- } else {
- error("Incorrect action:$action.", $STATUS_BAD_REQUEST);
- }
- } elsif ($params->{'resourcename'} eq "osimage") {
- if (exists($paramhash->{'iso'})) {
- $params->{'cmd'} = "copycds";
- push @{ $params->{layers} }, $paramhash->{'iso'};
- } elsif (exists($paramhash->{'file'})) {
- $params->{'cmd'} = "imgimport";
- push @{ $params->{layers} }, $paramhash->{'file'};
- } elsif (exists($paramhash->{'node'})) {
- $params->{'cmd'} = "imgcapture";
-
- #push @{$params->{layers}}, $paramhash->{'node'};
- push @{ $request->{noderange} }, $paramhash->{'node'};
- } else {
- error("Invalid source.", $STATUS_NOT_FOUND);
- }
- }
- }
- $request->{command} = $params->{'cmd'};
- push @args, $params->{layers}->[1];
- if (exists($paramhash->{'params'})) {
- foreach (keys %{ $paramhash->{'params'}->[0] }) {
- push @args, ($_, $paramhash->{'params'}->[0]->{$_});
- }
- }
- push @{ $request->{arg} }, @args;
- my $req = genRequest();
- my $responses = sendRequest($req);
- return $responses;
-}
-
-sub sitehdl {
- my $params = shift;
- my @args;
- my @urilayers = @{ $params->{'layers'} };
-
- # set the command name
- $request->{command} = $params->{'cmd'};
-
- # push the -t args
- push @args, '-t';
- push @args, 'site';
- if (isGET()) {
- push @args, 'clustersite';
- }
- if (defined($urilayers[2])) {
- if (isGET()) {
- push @args, ('-i', $urilayers[2]);
- }
- }
- if (isDelete()) {
- if (defined($urilayers[2])) {
- push @args, "$urilayers[2]=";
- }
- }
- foreach my $k (keys(%$paramhash)) {
- push @args, "$k=$paramhash->{$k}" if ($k);
- }
- push @{ $request->{arg} }, @args;
- my $req = genRequest();
- my $responses = sendRequest($req);
-
- return $responses;
-}
-
-
-# get attrs of tables for a noderange
-sub tablenodehdl {
- my $params = shift;
-
- my @args;
- my @urilayers = @{ $params->{'layers'} };
-
- # the array elements for @urilayers are:
- # 0 - 'table'
- # 1 -
- # 2 - 'nodes'
- # 3 - (optional)
- # 4 - (optional)
-
- # set the command name
- my @tables = split(/,/, $urilayers[1]);
-
- if (!defined($urilayers[3]) || $urilayers[3] eq 'ALLNODES') {
- $request->{command} = 'getTablesAllNodeAttribs';
- } else {
- $request->{command} = 'getTablesNodesAttribs';
- $request->{noderange} = $urilayers[3];
- }
-
- # For both getTablesAllNodeAttribs and getTablesNodesAttribs, the rest of the request strucutre looks like this:
- # table => [
- # {
- # tablename => nodehm,
- # attr => [
- # mgmt,
- # cons
- # ]
- # },
- # {
- # tablename => ipmi,
- # attr => [
- # ALL
- # ]
- # }
- # ]
-
- # if they specified attrs, sort/group them by table
- my $attrlist = $urilayers[4];
- if (!defined($attrlist)) { $attrlist = 'ALL'; } # attr=ALL means get all non-blank attributes
- my @attrs = split(/,/, $attrlist);
- my %attrhash;
- foreach my $a (@attrs) {
- if ($a =~ /\./) {
- my ($table, $attr) = split(/\./, $a);
- push @{ $attrhash{$table} }, $attr;
- }
- else { # the attr doesn't have a table qualifier so apply to all tables
- foreach my $t (@tables) { push @{ $attrhash{$t} }, $a; }
- }
- }
-
- # deal with all of the tables and the attrs for each table
- foreach my $tname (@tables) {
- my $table = { tablename => $tname };
- if (defined($attrhash{$tname})) { $table->{attr} = $attrhash{$tname}; }
- else { $table->{attr} = 'ALL'; }
- push @{ $request->{table} }, $table;
- }
-
-
- my $req = genRequest();
-
- # disabling the KeyAttr option is important in this case, so xmlin doesn't pull the name attribute
- # out of the node hash and make it the key
- my $responses = sendRequest($req, { SuppressEmpty => undef, ForceArray => 0, KeyAttr => [] });
-
- return $responses;
-}
-
-#get bmc ip address source
-#check if bmc user or password is correct
-sub bmccheckhdl {
-
- my $params = shift;
-
- my @args;
- my @urilayers = @{ $params->{'layers'} };
- my $bmc_ip;
- my $bmc_user;
- my $bmc_pw;
-
- # set the command name
- $request->{command} = $params->{'cmd'};
-
- # get bmc ip
- if (defined($urilayers[2]))
- {
- $bmc_ip = $urilayers[2];
- }
-
- # get bmc user and password
- if (defined($urilayers[3]))
- {
- my @keyvals = split(/,/, $urilayers[3]);
- foreach my $kv (@keyvals)
- {
- my ($key, $value) = split(/\s*=\s*/, $kv, 2);
- if ($key eq "bmcuser")
- {
- $bmc_user = $value;
- }
- elsif ($key eq "bmcpw")
- {
- $bmc_pw = $value;
- }
- }
- }
-
- if ($params->{'resourcename'} eq "checkbmcauth") {
- if (isGET()) {
-
- push @args, "-i";
- push @args, $bmc_ip;
- if (defined($bmc_user) && $bmc_user ne "none")
- {
- push @args, "-u";
- push @args, $bmc_user;
-
- }
- push @args, "-p";
- push @args, $bmc_pw;
- push @args, "-c";
- }
- }
-
- if ($params->{'resourcename'} eq "getbmcipsource") {
- if (isGET()) {
- push @args, "-i";
- push @args, $bmc_ip;
- if (defined($bmc_user) && $bmc_user ne "none")
- {
- push @args, "-u";
- push @args, $bmc_user;
- }
- push @args, "-p";
- push @args, $bmc_pw;
- push @args, "--ipsource";
- }
- }
-
- push @{ $request->{arg} }, @args;
- my $req = genRequest();
- my $responses = sendRequest($req);
-
- return $responses;
-
-
-}
-
-
-#get bmc list for bmcdiscover
-sub bmclisthdl {
-
- my $params = shift;
-
- my @args;
- my @urilayers = @{ $params->{'layers'} };
- my $m_value;
- my $ip_range;
-
- # the array elements for @urilayers are:
- # 0 - 'bmcdiscover'
- # 1 - (optional)
-
- # set the command name
- $request->{command} = $params->{'cmd'};
-
- # get method and ip_range
- if (defined($urilayers[2]))
- {
- my @keyvals = split(/,/, $urilayers[2]);
- foreach my $kv (@keyvals)
- {
- my ($key, $value) = split(/\s*=\s*/, $kv, 2);
- if ($key eq "method")
- {
- $m_value = $value;
- }
- elsif ($key eq "iprange")
- {
- $ip_range = $value;
- }
- }
- }
-
-
- if ($params->{'resourcename'} eq "bmcdiscover") {
- if (isGET()) {
- if (defined($m_value))
- {
- push @args, "-s";
- push @args, $m_value;
- }
- push @args, "--range";
- push @args, $ip_range;
- }
-
- }
-
- push @{ $request->{arg} }, @args;
- my $req = genRequest();
- my $responses = sendRequest($req);
-
- return $responses;
-
-}
-
-# get attrs of tables for keys
-sub tablerowhdl {
- my $params = shift;
-
- my @args;
- my @urilayers = @{ $params->{'layers'} };
-
- # the array elements for @urilayers are:
- # 0 - 'table'
- # 1 -
- # 2 - 'rows'
- # 3 - (optional)
- # 4 - (optional)
-
- # do stuff that is common between getAttribs and getTablesAllRowAttribs
- my @tables = split(/,/, $urilayers[1]);
- my $attrlist = $urilayers[4];
- if (!defined($attrlist)) { $attrlist = 'ALL'; } # attr=ALL means get all non-blank attributes
- my @attrs = split(/,/, $attrlist);
-
- # get all rows for potentially multiple tables
- if (!defined($urilayers[3]) || $urilayers[3] eq 'ALLROWS') {
- $request->{command} = 'getTablesAllRowAttribs';
-
- # For getTablesAllRowAttribs, the rest of the request strucutre needs to look like this:
- # table => [
- # {
- # tablename => nodehm,
- # attr => [
- # mgmt,
- # cons
- # ]
- # },
- # {
- # tablename => ipmi,
- # attr => [
- # ALL
- # ]
- # }
- # ]
-
- # if they specified attrs, sort/group them by table
- my %attrhash;
- foreach my $a (@attrs) {
- if ($a =~ /\./) {
- my ($table, $attr) = split(/\./, $a);
- push @{ $attrhash{$table} }, $attr;
- }
- else { # the attr doesn't have a table qualifier so apply to all tables
- foreach my $t (@tables) { push @{ $attrhash{$t} }, $a; }
- }
- }
-
- # deal with all of the tables and the attrs for each table
- foreach my $tname (@tables) {
- my $table = { tablename => $tname };
- if (defined($attrhash{$tname})) { $table->{attr} = $attrhash{$tname}; }
- else { $table->{attr} = 'ALL'; }
- push @{ $request->{table} }, $table;
- }
- }
-
- # for 1 table, get just one row based on the keys given
- else {
- if (scalar(@tables) > 1) { error('currently you can only specify keys for a single table.', $STATUS_BAD_REQUEST); }
- $request->{command} = 'getAttribs';
-
- # For getAttribs, the rest of the request strucutre needs to look like this:
- # {
- # table => networks,
- # keys => {
- # net => 11.35.0.0,
- # mask => 255.255.0.0
- # }
- # attr => [
- # netname,
- # dhcpserver
- # ]
- # },
- $request->{table} = $tables[0];
- if (defined($urilayers[3])) {
- my @keyvals = split(/,/, $urilayers[3]);
- foreach my $kv (@keyvals) {
- my ($key, $value) = split(/\s*=\s*/, $kv, 2);
- $request->{keys}->{$key} = $value;
- }
- }
- foreach my $a (@attrs) { push @{ $request->{attr} }, $a; }
- }
-
- my $req = genRequest();
-
- # disabling the KeyAttr option is important in this case, so xmlin doesn't pull the name attribute
- # out of the node hash and make it the key
- my $responses = sendRequest($req, { SuppressEmpty => undef, ForceArray => 0, KeyAttr => [] });
-
- return $responses;
-}
-
-# parse the output of all attrs of tables for the GET calls. This is used for both node-oriented tables
-# and non-node-oriented tables.
-#todo: investigate a converter straight from xml to json
-sub tableout {
- my $data = shift;
- my $json = {};
-
- # For the table get calls, we turned off ForceArray and KeyAttr for XMLin(), so the output is a little
- # different than usual. Each element is a hash with key "table" that is either a hash or array of hashes.
- # Each element of that is a hash with 2 keys called "tablename" and "node". The latter has either: an array of node hashes,
- # or (if there is only 1 node returned) the node hash directly.
- # We are producing json that is a hash of table name keys that each have an array of node objects.
- foreach my $d (@$data) {
- my $table = $d->{table};
- if (!defined($table)) { # special case for the getAttribs cmd
- $json->{ $request->{table} }->[0] = $d;
- last;
- }
-
- #debug(Dumper($d)); debug (Dumper($jsonnode));
- if (ref($table) eq 'HASH') { $table = [$table]; } # if a single table, make it a 1 element array of tables
- foreach my $t (@$table) {
- my $jsonnodes = []; # start an array of node objects for this table
- my $tabname = $t->{tablename};
- if (!defined($tabname)) { $tabname = 'unknown' . $::i++; } #todo: have lissa fix this bug
- $json->{$tabname} = $jsonnodes; # add it into the top level hash
- my $node = $t->{node};
- if (!defined($node)) { $node = $t->{row}; }
-
- #debug(Dumper($d)); debug (Dumper($jsonnode));
- if (ref($node) eq 'HASH') { $node = [$node]; } # if a single node, make it a 1 element array of nodes
- foreach my $n (@$node) { push @$jsonnodes, $n; }
- }
- }
- addPageContent($JSON->encode($json));
-}
-
-# set attrs of nodes in tables
-sub tablenodeputhdl {
- my $params = shift;
-
- # from the %URIdef:
- # desc => "[URI:/tables/nodes/{noderange}] - Change the table attibutes for the {noderange}.",
- # usage => "|An array of table objects. Each table object contains the table name and an object of attribute values. DataBody: {table1:{attr1:v1,att2:v2,...}}.|$usagemsg{non_getreturn}|",
- # example => '|Change the nodehm.mgmt and noderes.netboot attributes for nodes node1-node5.|PUT|/tables/nodes/node1-node5 {"nodehm":{"mgmt":"ipmi"},"noderes":{"netboot":"xnba"}}||',
-
- my @args;
- my @urilayers = @{ $params->{'layers'} };
-
- # the array elements for @urilayers are:
- # 0 - 'table'
- # 1 -
- # 2 - 'nodes'
- # 3 -
-
- # set the command name
- $request->{command} = 'setNodesAttribs';
- $request->{noderange} = $urilayers[3];
-
- # For setNodesAttribs, the rest of the request strucutre looks like this:
- # arg => {
- # table => [
- # {
- # name => nodehm,
- # attr => {
- # mgmt => ipmi
- # }
- # },
- # {
- # name => noderes,
- # attr => {
- # netboot => xnba
- # }
- # }
- # ]
- # }
-
- # Get table list in the URI
- my @uritbs = split(/,/, $urilayers[1]);
-
- # Go thru the list of tables (which are the top level keys in paramhash)
- my $tables = [];
- $request->{arg}->{table} = $tables;
- foreach my $k (keys(%$paramhash)) {
- my $intable = $k;
-
- # Check the validity of tables
- if (!grep(/^$intable$/, @uritbs)) {
- error("The table $intable is NOT in the URI.", $STATUS_BAD_REQUEST);
- }
- my $attrhash = $paramhash->{$k};
- my $outtable = { name => $intable, attr => $attrhash };
- push @$tables, $outtable;
- }
-
- my $req = genRequest();
-
- # disabling the KeyAttr option is important in this case, so xmlin doesn't pull the name attribute
- # out of the node hash and make it the key
- my $responses = sendRequest($req, { SuppressEmpty => undef, ForceArray => 1, KeyAttr => [] });
-
- return $responses;
-}
-
-# set attrs of a row in a non-node table
-sub tablerowputhdl {
- my $params = shift;
-
- # from %URIdef:
- # desc => "[URI:/tables/{table}/rows/{keys}] - Change the non-node table attibutes for the row that matches the {keys}.",
- # usage => "|A hash of attribute names and values. DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|",
- # example => '|Creat a route row in the routes table.|PUT|/tables/routes/rows/routename=privnet {"net":"10.0.1.0","mask":"255.255.255.0","gateway":"10.0.1.254","ifname":"eth1"}||',
-
- my @args;
- my @urilayers = @{ $params->{'layers'} };
-
- # the array elements for @urilayers are:
- # 0 - 'table'
- # 1 -
- # 2 - 'rows'
- # 3 -
-
- # set the command name
- $request->{command} = 'setAttribs';
-
- # For setAttribs, the rest of the xml request strucutre looks like this:
- #
- #
- # foo
- #
- #
- # 10.0.1.0
- # This is a test
- #
-
- # set the table name and keys
- $request->{table} = $urilayers[1];
- my @keyvals = split(/,/, $urilayers[3]);
- foreach my $kv (@keyvals) {
- my ($key, $value) = split(/\s*=\s*/, $kv, 2);
- $request->{keys}->{$key} = $value;
- }
-
- # the attribute/value hash is already in paramhash
- $request->{attr} = $paramhash;
-
- my $req = genRequest();
-
- # disabling the KeyAttr option is important in this case, so xmlin doesn't pull the name attribute
- # out of the node hash and make it the key
- my $responses = sendRequest($req, { SuppressEmpty => undef, ForceArray => 1, KeyAttr => [] });
-
- return $responses;
-}
-
-# delete rows in a non-node table
-sub tablerowdelhdl {
- my $params = shift;
-
- # from %URIdef:
- # desc => "[URI:/tables/{table}/rows/{attrvals}] - Delete rows from a non-node table that have the attribute values specified in {attrvals}.",
- # usage => "||$usagemsg{non_getreturn}|",
- # example => '|Delete a route row in the routes table.|PUT|/tables/routes/rows/routename=privnet||',
-
- my @args;
- my @urilayers = @{ $params->{'layers'} };
-
- # the array elements for @urilayers are:
- # 0 - 'table'
- # 1 -
- # 2 - 'rows'
- # 3 -
-
- # set the command name
- $request->{command} = 'delEntries';
-
- # For delEntries, the rest of the xml request strucutre looks like this:
- #
- # nodelist
- #
- # compute1,lissa
- # down
- #
- #
-
- # set the table name and attr/vals
- my $table = {}; # will hold the name and attr/vals
- $request->{table}->[0] = $table; #todo: the xcat delEntries cmd supports multiple tables in 1 request. We could support this if the attr names were table.attr
- $table->{name} = $urilayers[1];
- my @attrvals = split(/,/, $urilayers[3]);
- foreach my $av (@attrvals) {
- my ($attr, $value) = split(/\s*=\s*/, $av, 2);
- $table->{attr}->{$attr} = $value;
- }
-
- my $req = genRequest();
-
- # disabling the KeyAttr option is important in this case, so xmlin doesn't pull the name attribute
- # out of the node hash and make it the key
- my $responses = sendRequest($req, { SuppressEmpty => undef, ForceArray => 1, KeyAttr => [] });
-
- return $responses;
-}
-
-
-# display the resource list when run 'xcatws.cgi -d'
-sub displayUsage {
- foreach my $group (keys %URIdef) {
- print "Resource Group: $group\n";
- foreach my $res (keys %{ $URIdef{$group} }) {
- print " Resource: $res\n";
- print " $URIdef{$group}->{$res}->{desc}\n";
- if (defined($URIdef{$group}->{$res}->{GET})) {
- print " GET: $URIdef{$group}->{$res}->{GET}->{desc}\n";
- }
- if (defined($URIdef{$group}->{$res}->{PUT})) {
- print " PUT: $URIdef{$group}->{$res}->{PUT}->{desc}\n";
- }
- if (defined($URIdef{$group}->{$res}->{POST})) {
- print " POST: $URIdef{$group}->{$res}->{POST}->{desc}\n";
- }
- if (defined($URIdef{$group}->{$res}->{DELETE})) {
- print " DELETE: $URIdef{$group}->{$res}->{DELETE}->{desc}\n";
- }
- }
- }
-}
-
-
-# This handles and removes serverdone and error tags in the perl data structure that is from the xml that xcatd returned
-#bmp: is there a way to avoid make a copy of the whole response? For big output that could be time consuming.
-# For the error tag, you don't have to bother copying the response, because you are going to exit anyway.
-# Maybe this function could just verify there is a serverdone and handle any error, and then
-# let each specific output handler ignore the serverdone tag?
-
-# Filter out the error message
-# If has 'error' message in the output data, push them all to one list
-# If has 'errorcode' in the output data, set it to be the errorcode of response. Otherwise, the errorcode to '1'
-# When get the 'serverdone' identifer
-# If 'errorcode' has been set, return the error message and error code like {error:[msg1,msg2...], errorcode:num}
-# Otherwise, pass the output to the outputhandler for the specific resource
-
-sub filterData {
- my $data = shift;
-
- #debugandexit(Dumper($data));
-
- my $outputdata;
- my $outputerror;
- my @errmsgindata; # put the out->{data} for error message output
-
- #trim the serverdone message off
- foreach (@{$data}) {
- if (defined($_->{error})) {
- if (ref($_->{error}) eq 'ARRAY') {
- foreach my $msg (@{ $_->{error} }) {
- if ($msg =~ /(Permission denied|Authentication failure)/) {
-
- # return 401 Unauthorized
- error("Authentication failure", $STATUS_UNAUTH);
- } else {
- push @{ $outputerror->{error} }, $msg;
- }
- }
- } else {
- push @{ $outputerror->{error} }, $_->{error};
- }
-
- if (defined($_->{errorcode})) {
- if (ref($_->{errorcode}) eq 'ARRAY') {
- $outputerror->{errorcode} = $_->{errorcode}->[0];
- } else {
- $outputerror->{errorcode} = $_->{errorcode};
- }
- } else {
-
- # set the default errorcode to '1'
- $outputerror->{errorcode} = '1';
- }
- } elsif (defined($_->{errorcode}) && $_->{errorcode}->[0] ne "0") { # defined errorcode, but not define the error msg
- $outputerror->{errorcode} = $_->{errorcode}->[0];
- if (defined($_->{data}) && ref($_->{data}->[0]) ne "HASH") {
-
- # to get the message in data for the case that errorcode is set but no 'error' attr
- push @errmsgindata, $_->{data}->[0];
- }
- if (@errmsgindata) {
- push @{ $outputerror->{error} }, @errmsgindata;
- } else {
- push @{ $outputerror->{error} }, "Failed with unknown reason.";
- }
- }
-
- # handle the output like
- #
- # node1
- # Unable to identify plugin for this command, check relevant tables: nodehm.power,mgt;nodehm.mgt
- # 1
- #
- if (defined($_->{node}) && defined($_->{node}->[0]->{error})) {
- if (defined($_->{node}->[0]->{name})) {
- push @{ $outputerror->{error} }, "$_->{node}->[0]->{name}->[0]: " . $_->{node}->[0]->{error}->[0];
- }
- if (defined($_->{node}->[0]->{errorcode})) {
- $outputerror->{errorcode} = $_->{node}->[0]->{errorcode}->[0];
- } else {
-
- # set the default errorcode to '1'
- $outputerror->{errorcode} = '1';
- }
- }
-
-
- if (exists($_->{serverdone})) {
- if (defined($outputerror->{error}) || defined($outputerror->{error})) {
- addPageContent($JSON->encode($outputerror));
-
- #return the default http error code to be 403 forbidden
- sendResponseMsg($STATUS_FORBIDDEN);
-
- #} else {
- #otherwise, ignore the 'servicedone' data
- # next;
- } else {
- delete($_->{serverdone});
- if (scalar(keys %{$_}) > 0) {
- push @{$outputdata}, $_;
- }
- }
- } else {
- if (defined($_->{data}) && ref($_->{data}->[0]) ne "HASH") {
-
- # to get the message in data for the case that errorcode is set but no 'error' attr
- push @errmsgindata, $_->{data}->[0];
- }
- push @{$outputdata}, $_;
- }
- }
-
- return $outputdata;
-}
-
-# Structure the response perl data structure into well-formed json. Since the structure of the
-# xml output that comes from xcatd is inconsistent and not very structured, we have a lot of work to do.
-sub wrapJson {
-
- # this is an array of responses from xcatd. Often all the output comes back in 1 response, but not always.
- my $data = shift;
-
- addPageContent($JSON->encode($data));
- return;
-
-
- # put, delete, and patch usually just give a short msg, if anything
- if (isPut() || isDelete() || isPatch()) {
- addPageContent($JSON->encode($data));
- return;
- }
-}
-
-# Append content to the global var holding the output to go back to the rest client
-# 1st param - The output message
-# 2nd param - A flag to specify the format of 1st param: 1 - json formatted standard xcat output data
sub addPageContent {
my $newcontent = shift;
- my $userdata = shift;
-
- if ($userdata && $XCOLL) {
- my $group;
- my $hash = $JSON->decode($newcontent);
- if (ref($hash) eq "HASH") {
- foreach my $node (keys %{$hash}) {
- if (ref($hash->{$node}) eq "HASH") {
- my $value;
- foreach (sort (keys %{ $hash->{$node} })) {
- $value .= "$_$hash->{$node}->{$_}";
- }
- push @{ $group->{$value}->{node} }, $node;
- $group->{$value}->{orig} = $hash->{$node};
- } elsif (ref($hash->{$node}) eq "ARRAY") {
- my $value;
- foreach (sort (@{ $hash->{$node} })) {
- $value .= "$_";
- }
- push @{ $group->{$value}->{node} }, $node;
- $group->{$value}->{orig} = $hash->{$node};
- }
- }
- }
- my $groupout;
- foreach my $value (keys %{$group}) {
- if (defined $group->{$value}->{node}) {
- my $nodes = join(',', @{ $group->{$value}->{node} });
- if (defined($group->{$value}->{orig})) {
- $groupout->{$nodes} = $group->{$value}->{orig};
- }
- }
- }
- $newcontent = $JSON->encode($groupout) if ($groupout);
- }
-
$pageContent .= $newcontent;
}
-# send the response to client side, then exit
-# with http there is only one return for each request, so all content should be in pageContent global variable when you call this
-# create the response header by status code and format
+#send the response to client side
+#the http only return once in each request, so all content shoudl save in a global variable,
+#create the response header by status
sub sendResponseMsg {
my $code = shift;
my $tempFormat = '';
@@ -3164,44 +65,2334 @@ sub sendResponseMsg {
elsif ('xml' eq $format) {
$tempFormat = 'text/xml';
}
- elsif ('stream' eq $format) {
- $tempFormat = 'application/octet-stream';
- }
else {
$tempFormat = 'text/html';
}
-
- if ($header_info{attachment}) {
- print $q->header(-status => $code,
- -type => $tempFormat,
- -attachment => $header_info{attachment},
- -Content_length => length($pageContent));
- } else {
- print $q->header(-status => $code, -type => $tempFormat);
- if ($pageContent) { $pageContent .= "\n"; } # if there is any content, append a newline
- }
+ print $q->header(-status => $code, -type => $tempFormat);
print $pageContent;
exit(0);
}
-# Convert xcat request to xml for sending to xcatd
-sub genRequest {
- my $xml = XML::Simple::XMLout($request, RootName => 'xcatrequest', NoAttr => 1, KeyAttr => []);
+sub unsupportedRequestType {
+ addPageContent("request method '$requestType' is not supported on resource '$resource'");
+ sendResponseMsg($STATUS_NOT_ALLOWED);
}
-# Send the request to xcatd and read the response. The request passed in has already been converted to xml.
-# The response returned to the caller of this function has already been converted from xml to perl structure.
+use XML::Simple;
+$XML::Simple::PREFERRED_PARSER = 'XML::Parser';
+
+sub genRequest {
+ if ($DEBUGGING) {
+ addPageContent($q->p("request " . Dumper($request)));
+ }
+ my $xml = XMLout($request, RootName => 'xcatrequest', NoAttr => 1, KeyAttr => []);
+}
+
+#data formatters. To add one simple copy the format of an existing one
+# and add it to this hash
+my %formatters = (
+ 'html' => \&wrapHtml,
+ 'json' => \&wrapJson,
+ 'xml' => \&wrapXml,);
+
+fetchParameter($queryString);
+
+if ($queryhash{'format'}) {
+ $format = $queryhash{'format'}->[0];
+ if (!exists $formatters{$format}) {
+ addPageContent("The format '$format' is not valid");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+
+ if ($format eq 'json') {
+ # require JSON dynamically and let them know if it is not installed
+ my $jsoninstalled = eval { require JSON; };
+ unless ($jsoninstalled) {
+ addPageContent('{"data":"JSON perl module missing. Install perl-JSON before using the xCAT REST web services API."}');
+ sendResponseMsg($STATUS_SERVICE_UNAVAILABLE);
+ }
+ }
+}
+
+my $XCAT_PATH = '/opt/xcat/bin';
+
+#resource handlers
+my %resources = (
+ groups => \&groupsHandler,
+ images => \&imagesHandler,
+ logs => \&logsHandler,
+ monitors => \&monitorsHandler,
+ networks => \&networksHandler,
+ nodes => \&nodesHandler,
+ notifications => \¬ificationsHandler,
+ policies => \&policiesHandler,
+ site => \&siteHandler,
+ tables => \&tablesHandler,
+ accounts => \&accountsHandler,
+ objects => \&objectsHandler,
+ vms => \&vmsHandler,
+ debug => \&debugHandler,
+ hypervisor => \&hypervisorHandler,
+ version => \&versionHandler);
+
+#if no resource was specified
+if ($pathInfo =~ /^\/$/ || $pathInfo =~ /^$/) {
+ addPageContent($q->p("This is the root page for the xCAT Rest Web Service. Available resources are:"));
+ foreach (sort keys %resources) {
+ addPageContent($q->p($_));
+ }
+ sendResponseMsg($STATUS_OK);
+}
+
+sub doesResourceExist {
+ my $res = shift;
+ return exists $resources{$res};
+}
+
+if ($DEBUGGING) {
+ if (defined $q->param('PUTDATA')) {
+ addPageContent("put data " . $q->p($q->param('PUTDATA') . "\n"));
+ } elsif (isPut()) {
+ my $entries = JSON::decode_json($q->param('PUTDATA'));
+ if (scalar(@$entries) >= 1) {
+ addPageContent("put data \n");
+ foreach (@$entries) {
+ addPageContent("$_\n");
+ }
+ }
+ }
+
+ if (defined $q->param('POSTDATA')) {
+ addPageContent("post data " . $q->p($q->param('POSTDATA') . "\n"));
+ } elsif (isPost()) {
+ my $entries = JSON::decode_json($q->param('POSTDATA'));
+ if (scalar(@$entries) >= 1) {
+ addPageContent("post data \n");
+ foreach (@$entries) {
+ addPageContent("$_\n");
+ }
+ }
+ }
+
+ addPageContent($q->p("Parameters "));
+ my @params = $q->param;
+ foreach (@params) {
+ addPageContent("$_ = " . join(',', $q->param($_)) . "\n");
+ }
+ addPageContent($q->p("Query String $queryString" . "\n"));
+ addPageContent($q->p("Query parameters from the Query String" . Dumper(\%queryhash) . "\n"));
+ addPageContent($q->p("HTTP Method $requestType" . "\n"));
+ addPageContent($q->p("URI $url" . "\n"));
+ addPageContent($q->p("path " . Dumper(@path) . "\n"));
+}
+
+#when use put and post, can not fetch the url-parameter, so add this sub to support all kinks of method
+sub fetchParameter {
+ my $parstr = shift;
+ unless ($parstr) {
+ return;
+ }
+
+ my @pairs = split(/&/, $parstr);
+ foreach my $pair (@pairs) {
+ my ($key, $value) = split(/=/, $pair, 2);
+ $value =~ tr/+/ /;
+ $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/chr(hex($1))/eg;
+ push @{$queryhash{$key}}, $value;
+ }
+}
+
+#extract the put data or post data into perl hash, easy for retrieve
+sub extractData {
+ my $temphash = shift;
+ my $parArray = shift;
+ my $key;
+ my $value;
+ my $position;
+
+ #traversal all element in the array
+ foreach (@$parArray) {
+ $position = index($_, '=');
+ if ($position < 0) {
+ $key = $_;
+ $value = 1;
+ }
+ else {
+ $key = substr $_, 0, $position;
+ $value = substr $_, $position + 1;
+ }
+ $temphash->{$key} = $value;
+
+ if ($DEBUGGING) {
+ addPageContent($q->p("The parameter extract from put/post data: " . Dumper($temphash)));
+ }
+ }
+}
+
+my $userName=http('userName');
+my $password=http('password');
+
+sub handleRequest {
+ if (defined $queryhash{'userName'}) {
+ $userName = $queryhash{'userName'}->[0];
+ }
+ if (defined $queryhash{'password'}) {
+ $password = $queryhash{'password'}->[0];
+ }
+ if ($userName && $password) {
+ $request->{becomeuser}->[0]->{username}->[0] = $userName;
+ $request->{becomeuser}->[0]->{password}->[0] = $password;
+ }
+ my @data = $resources{$resource}->();
+ wrapData(\@data);
+}
+
+my @groupFields = ('groupname', 'grouptype', 'members', 'wherevals', 'comments', 'disable');
+
+#get is done
+#post and delete are done but not tested
+#groupfiles4dsh is done but not tested
+sub groupsHandler {
+ my @responses;
+ my @args;
+ my $groupName;
+
+ #is the group name in the URI?
+ if (defined $path[1]) {
+ $groupName = $path[1];
+ }
+
+ #in the query string?
+ else {
+ $groupName = $q->param('groupName');
+ }
+
+ if (isGet()) {
+ if (defined $groupName) {
+ $request->{command} = 'gettab';
+ push @args, "groupname=$groupName";
+ if (defined $q->param('field')) {
+ foreach ($q->param('field')) {
+ push @args, "nodegroup.$_";
+ }
+ }
+ else {
+ foreach (@groupFields) {
+ push @args, "nodegroup.$_";
+ }
+ }
+ }
+ else {
+ $request->{command} = 'tabdump';
+ push @args, 'nodegroup';
+ }
+ }
+
+ #does it make sense to even have this?
+ elsif (isPost()) {
+ my $nodeRange = $q->param('nodeRange');
+ if ((defined $groupName) && (defined $nodeRange)) {
+ $request->{command} = 'mkdef';
+ push @args, '-t';
+ push @args, 'group';
+ push @args, '-o';
+ push @args, $groupName;
+ push @args, "members=$nodeRange";
+ }
+ else {
+ addPageContent("A node range and group name must be specified for creating a group");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ }
+ elsif (isPut()) {
+
+ #handle groupfiles4dsh -p /tmp/nodegroupfiles
+ if ($q->param('command') eq "4dsh") {
+ if ($q->param('path')) {
+ $request->{command} = 'groupfiles4dsh';
+ push @args, "p=$q->param('path')";
+ }
+ else {
+ addPageContent("The path must be specified for creating directories for dsh");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ }
+ else {
+ if (defined $groupName && defined $q->param('fields')) {
+ $request->{command} = 'nodegrpch';
+ push @args, $groupName;
+ push @args, $q->param('field');
+ }
+ else {
+ addPageContent("The group and fields must be specified to update groups");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ }
+ }
+ elsif (isDelete()) {
+ if (defined $groupName) {
+ $request->{command} = 'rmdef';
+ push @args, '-t';
+ push @args, 'group';
+ push @args, '-o';
+ push @args, $groupName;
+ }
+ else {
+ addPageContent("The group must be specified to delete a group");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ }
+ else {
+ unsupportedRequestType();
+ exit();
+ }
+
+ push @{$request->{arg}}, @args;
+ my $req = genRequest();
+ @responses = sendRequest($req);
+
+ return @responses;
+}
+
+my @imageFields = (
+ 'imagename', 'profile', 'imagetype', 'provmethod', 'osname', 'osvers',
+ 'osdistro', 'osarch', 'synclists', 'comments', 'disable');
+
+#get is done, nothing else
+sub imagesHandler {
+ my @responses;
+ my @args;
+ my $image;
+ my $subResource;
+
+ if (defined($path[1])) {
+ $image = $path[1];
+ }
+
+ if (isGet()) {
+ $request->{command} = 'lsdef';
+ push @args, '-t', 'osimage';
+ if (defined $image) {
+ push @args, '-o', $image;
+ }
+ if (defined($q->param('field'))) {
+ push @args, '-i';
+ push @args, join(',', $q->param('field'));
+ }
+ if (defined($q->param('criteria'))) {
+ foreach ($q->param('criteria')) {
+ push @args, '-w', "$_";
+ }
+ }
+ }
+ elsif (isPost()) {
+ my $operationname = $image;
+ my $entries;
+ my %entryhash;
+
+ #check the post data
+ unless (defined($q->param('POSTDATA'))) {
+ addPageContent("Invalid Parameters");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ $entries = JSON::decode_json($q->param('POSTDATA'));
+ if (scalar(@$entries) < 1) {
+ addPageContent("No set attribute was supplied.");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+
+ extractData(\%entryhash, $entries);
+
+ #for image capture
+ if ($operationname eq 'capture') {
+ $request->{command} = 'imgcapture';
+ if (defined($entryhash{'nodename'})) {
+ $request->{noderange} = $entryhash{'nodename'};
+ }
+ else {
+ addPageContent('No node range.');
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+
+ if (defined($entryhash{'profile'})) {
+ push @args, '-p';
+ push @args, $entryhash{'profile'};
+ }
+ if (defined($entryhash{'osimage'})) {
+ push @args, '-o';
+ push @args, $entryhash{'osimage'};
+ }
+ if (defined($entryhash{'bootinterface'})) {
+ push @args, '-i';
+ push @args, $entryhash{'bootinterface'};
+ }
+ if (defined($entryhash{'netdriver'})) {
+ push @args, '-n';
+ push @args, $entryhash{'netdriver'};
+ }
+ if (defined($entryhash{'device'})) {
+ push @args, '-d';
+ push @args, $entryhash{'device'};
+ }
+ if (defined($entryhash{'compress'})) {
+ push @args, '-c';
+ push @args, $entryhash{'compress'};
+ }
+ }
+ elsif ($operationname eq 'export') {
+ $request->{command} = 'imgexport';
+ if (defined($entryhash{'osimage'})) {
+ push @args, $entryhash{'osimage'};
+ }
+ else {
+ addPageContent('No image specified');
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+
+ if (defined($entryhash{'destination'})) {
+ push @args, $entryhash{'destination'};
+ }
+ if (defined($entryhash{'postscripts'})) {
+ push @args, '-p';
+ push @args, $entryhash{'postscripts'};
+ }
+ if (defined($entryhash{'extra'})) {
+ push @args, '-e';
+ push @args, $entryhash{'extra'};
+ }
+ if (defined($entryhash{'remotehost'})) {
+ push @args, '-R';
+ push @args, $entryhash{'remotehost'};
+ }
+ if (defined($entryhash{'verbose'})) {
+ push @args, '-v';
+ }
+ }
+ elsif ($operationname eq 'import') {
+ $request->{command} = 'imgimport';
+ if (defined($entryhash{'osimage'})) {
+ push @args, $entryhash{'osimage'};
+ }
+ else {
+ addPageContent('No image specified');
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+
+ if (defined($entryhash{'profile'})) {
+ push @args, '-f';
+ push @args, $entryhash{'profile'};
+ }
+ if (defined($entryhash{'remotehost'})) {
+ push @args, '-R';
+ push @args, $entryhash{'remotehost'};
+ }
+ if (defined($entryhash{'postscripts'})) {
+ push @args, '-p';
+ push @args, $entryhash{'postscripts'};
+ }
+ if (defined($entryhash{'nozip'})) {
+ push @args, '-n';
+ }
+
+ if (defined($entryhash{'verbose'})) {
+ push @args, '-v';
+ }
+ }
+ }
+ elsif (isPut()) {
+
+ #check the operation type
+ unless (defined $path[2]) {
+ addPageContent("The subResource $subResource does not exist");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+
+ $subResource = $path[2];
+
+ #check the image name
+ unless (defined $image) {
+ addPageContent("The image name is required to clean an os image");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+
+ if ($subResource eq 'check') {
+ $request->{command} = 'chkosimage';
+ if (defined($q->param('PUTDATA'))) {
+ push @args, '-c';
+ }
+ push @args, $image;
+ }
+ else {
+ addPageContent("The subResource $subResource does not exist");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ }
+ elsif (isDelete()) {
+ if (defined $image) {
+ $request->{command} = 'rmimage';
+ if (defined $q->param('verbose')) {
+ push @args, '-v';
+ }
+ push @args, $image;
+ }
+ elsif (defined $q->param('os') && defined $q->param('arch') && defined $q->param('profile')) {
+ push @args, '-o';
+ push @args, $q->param('os');
+ push @args, '-a';
+ push @args, $q->param('arch');
+ push @args, '-p';
+ push @args, $q->param('profile');
+ }
+ else {
+ addPageContent(
+ "Either the image name or the os, architecture and profile must be specified to remove an image");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ }
+ else {
+ unsupportedRequestType();
+ exit();
+ }
+
+ push @{$request->{arg}}, @args;
+ my $req = genRequest();
+ @responses = sendRequest($req);
+
+ return @responses;
+}
+
+#complete
+sub logsHandler {
+ my @responses;
+ my @args;
+ my $logType;
+
+ if (defined $path[1]) {
+ $logType = $path[1];
+ }
+
+ #in the query string?
+ else {
+ $logType = $q->param('logType');
+ }
+ my $nodeRange = $q->param('nodeRange');
+
+ #no real output unless the log type is defined
+ if (!defined $logType) {
+ addPageContent("Current logs available are auditlog, eventlog, and diagnostics");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+
+ if (isGet()) {
+ if ($logType eq "reventLog") {
+ if (defined $nodeRange) {
+ $request->{command} = 'reventlog';
+ push @args, $nodeRange;
+ if (defined $q->param('count')) {
+ push @args, $q->param('count');
+ }
+ }
+ else {
+ addPageContent("nodeRange must be specified to GET remote event logs");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ }
+ elsif ($logType eq "diagnostics") {
+ addPageContent(uc($requestType) . " remote diagnostic logs is not supported");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ else {
+ $request->{command} = 'tabdump';
+ push @args, $logType;
+ }
+ }
+
+ #this clears the log
+ elsif (isPut()) {
+ if ($logType eq "reventlog") {
+ if (defined $nodeRange) {
+ $request->{command} = 'reventlog';
+ push @args, $nodeRange;
+ push @args, 'clear';
+ }
+ else {
+ addPageContent("nodeRange must be specified to clean remote event logs");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ }
+ elsif ($logType eq "diagnostics") {
+ addPageContent(uc($requestType) . " remote diagnostic logs is not supported");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ else {
+
+ #should it return the removed entries?
+ if (defined $q->param('showRemoved')) {
+ push @args, '-V';
+ }
+ if (defined $q->param('count') || defined $q->param('percent') || defined $q->param('lastRecord')) {
+
+ #remove some of the entries
+ $request->{command} = 'tabprune';
+
+ #remove a certain number of records
+ if (defined $q->param('count')) {
+ push @args, ('-n', $q->param('count'));
+ }
+
+ #remove a percentage of the records
+ if (defined $q->param('percent')) {
+ push @args, ('-p', $q->param('percent'));
+ }
+
+ #remove all records before this record
+ if (defined $q->param('lastRecord')) {
+ push @args, ('-i', $q->param('lastRecord'));
+ }
+ }
+ else {
+ $request->{command} = 'tabprune';
+
+ #-a removes all
+ push @args, '-a';
+ }
+ }
+ }
+ # Currently, only diagnostic logs can be created
+ elsif (isPost()) {
+ if ($logType eq "diagnostics") {
+
+ # Potential base bug on the reventlog and auditlog paths:
+ # $q->param('nodeRange') != $queryhash{'nodeRange'}
+ # The base code uses the first, which is undef even when a URL
+ # query parameter named nodeRange was passed by the caller (e.g. is
+ # found in the nova-compute.log traces).
+ # Re-assigning nodeRange on this new path since it does return
+ # a value.
+
+ $nodeRange = $queryhash{'nodeRange'};
+ if (defined $nodeRange) {
+ $request->{command} = 'diagnostics';
+ $request->{noderange} = $nodeRange;
+
+ my $parameter;
+ # Parse the optional upstream request ID, e.g. an OpenStack request UUID
+ $parameter = 'requestid';
+ if (defined $queryhash{$parameter}) {
+ push @args, '--'.$parameter;
+ push @args, $queryhash{$parameter}->[0];
+ }
+
+ # Parse the optional upstream object ID, e.g. an OpenStack nova instance UUID
+ $parameter = 'objectid';
+ if (defined $queryhash{$parameter}) {
+ push @args, '--'.$parameter;
+ push @args, $queryhash{$parameter}->[0];
+ }
+
+ unless ($q->param('POSTDATA')) {
+ addPageContent("A request body containing parameters is required");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+
+ # Collect all parameters from the postdata
+ my %entryhash;
+ my $entries = JSON::decode_json($q->param('POSTDATA'));
+ if (scalar(@$entries) < 1) {
+ addPageContent("No request parameters were supplied in the message body.");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+
+ extractData(\%entryhash, $entries);
+ # TODO: add parameter parsing back in to pass through all body parameters.
+ # How to handle duplicate property names? Perhaps prefix them with upstream_ , and pass the prefix too ;-)
+
+ # Parse the optional body parameters from the caller (NOT URL query parameters)
+ # TODO: this is early code that hard-codes a single key passed by the
+ # z/VM OpenStack nova plugin. It will be replaced later with more
+ # general code that behaves similarly.
+ $parameter = 'reason';
+ if (defined $entryhash{$parameter}) {
+ push @args, '--upstream-'.$parameter;
+ push @args, $entryhash{$parameter};
+ }
+
+ }
+ else {
+ addPageContent("nodeRange must be specified to collect diagnostics");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ }
+ else {
+ addPageContent("POST is only valid for logType(s): diagnostics. It is not valid with the supplied logType: $logType");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ }
+ else {
+ unsupportedRequestType();
+ exit();
+ }
+
+ push @{$request->{arg}}, @args;
+ my $req = genRequest();
+ @responses = sendRequest($req);
+
+ return @responses;
+}
+
+#complete
+sub monitorsHandler {
+ my @responses;
+ my @args;
+ my $monitor;
+
+ if (defined $path[1]) {
+ $monitor = $path[1];
+ }
+
+ #in the query string?
+ elsif (defined $q->param('monitor')) {
+ push @args, $q->param('monitor');
+ }
+ if (defined $monitor) {
+ push @args, $monitor;
+ }
+
+ if (isGet()) {
+ $request->{command} = 'monls';
+ }
+ elsif (isPost()) {
+ $request->{command} = 'monadd';
+ if ($q->param('nodeStatMon')) {
+ push @args, '-n';
+ }
+
+ #get the plug-in specific settings array
+ foreach ($q->param('pluginSetting')) {
+ push @args, '-s';
+ push @args, $_;
+ }
+ }
+ elsif (isDelete()) {
+ $request->{command} = 'monrm';
+ }
+ elsif (isPut() || isPatch()) {
+ my $action = $q->param('action');
+ if ($action eq "start") {
+ $request->{command} = 'monstart';
+ }
+ elsif ($action eq "stop") {
+ $request->{command} = 'monstop';
+ }
+ elsif ($action eq "config") {
+ $request->{command} = 'moncfg';
+ }
+ elsif ($action eq "deconfig") {
+ $request->{command} = 'mondeconfig';
+ }
+ else {
+ unsupportedRequestType();
+ }
+ if (!defined $q->param('nodeRange')) {
+
+ #error
+ }
+ else {
+ push @args, $q->param('nodeRange');
+ }
+ if (defined $q->param('remote')) {
+ push @args, '-r';
+ }
+ }
+ else {
+ unsupportedRequestType();
+ exit();
+ }
+
+ push @{$request->{arg}}, @args;
+ my $req = genRequest();
+ @responses = sendRequest($req);
+
+ return @responses;
+}
+
+sub networksHandler {
+ my @responses;
+ my @args;
+ my $netname = '';
+
+ if (isGet()) {
+ $request->{command} = 'lsdef';
+ push @{$request->{arg}}, '-t', 'network';
+ if (defined($path[1])) {
+ push @{$request->{arg}}, '-o', $path[1];
+ }
+ my @temparray = $q->param('field');
+
+ #add the field name to get
+ if (scalar(@temparray) > 0) {
+ push @{$request->{arg}}, '-i';
+ push @{$request->{arg}}, join(',', @temparray),;
+ }
+ }
+ elsif (isPut() || isPost()) {
+ my $entries;
+ my $iscommand = 0;
+ if (isPut()) {
+ $request->{command} = 'chdef';
+ if (defined($path[1])) {
+ if ($path[1] eq "makehosts" || $path[1] eq "makedns") {
+ # Issue makehost/makedns directly
+ $request->{command} = $path[1];
+ $iscommand = 1;
+ }
+ }
+ }
+ else {
+ $request->{command} = 'mkdef';
+ }
+
+ if (!$iscommand) {
+ if (defined $path[1]) {
+ $netname = $path[1];
+ }
+
+ if ($netname eq '') {
+ addPageContent('A network name must be specified.');
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+
+ push @{$request->{arg}}, '-t', 'network', '-o', $netname;
+
+ if (defined($q->param('PUTDATA'))) {
+ $entries = JSON::decode_json($q->param('PUTDATA'));
+ }
+ elsif (defined($q->param('POSTDATA'))) {
+ $entries = JSON::decode_json($q->param('POSTDATA'));
+ }
+ else {
+ addPageContent("No Field and Value map was supplied.");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+
+ if (scalar($entries) < 1) {
+ addPageContent("No Field and Value map was supplied.");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ foreach (@$entries) {
+ push @{$request->{arg}}, $_;
+ }
+ }
+ }
+ elsif (isDelete()) {
+ $request->{command} = 'rmdef';
+
+ if (defined $path[1]) {
+ $netname = $path[1];
+ }
+ if ($netname eq '') {
+ addPageContent('A network name must be specified.');
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ push @{$request->{arg}}, '-t', 'network', '-o', $netname;
+ }
+ else {
+ unsupportedRequestType();
+ exit(0);
+ }
+ @responses = sendRequest(genRequest());
+
+ return @responses;
+}
+
+sub nodesHandler {
+ my @responses;
+ my @args;
+ my $noderange;
+ my @envs;
+
+ if (defined $path[1]) {
+ $noderange = $path[1];
+ }
+
+ if (isGet()) {
+ my $subResource;
+ if (defined $path[2]) {
+ $subResource = $path[2];
+ unless (defined($noderange)) {
+ addPageContent("Invalid nodes and/or groups in noderange");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ $request->{noderange} = $noderange;
+
+ #use the corresponding command by the subresource name
+ if ($subResource eq "power") {
+ $request->{command} = 'rpower';
+
+ #no fields will default to 'stat'
+ if (defined $q->param('field')) {
+ push @args, $q->param('field');
+ }
+ else {
+ push @args, 'stat';
+ }
+ }
+ elsif ($subResource eq "energy") {
+ $request->{command} = 'renergy';
+
+ #no fields will default to 'all'
+ if (defined $q->param('field')) {
+ push @args, $q->param('field');
+ }
+ else {
+ push @args, 'all';
+ }
+ }
+ elsif ($subResource eq "status") {
+ $request->{command} = 'nodestat';
+ }
+ elsif ($subResource eq "inventory") {
+ $request->{command} = 'rinv';
+ if (defined $q->param('field')) {
+ push @args, $q->param('field');
+ }
+ else {
+ push @args, 'all';
+ }
+ }
+ elsif ($subResource eq "vitals") {
+ $request->{command} = 'rvitals';
+ if (defined $q->param('field')) {
+ push @args, $q->param('field');
+ }
+ else {
+ push @args, 'all';
+ }
+ }
+ elsif ($subResource eq "scan") {
+ $request->{command} = 'rscan';
+ if (defined $q->param('field')) {
+ push @args, $q->param('field');
+ }
+ }
+ else {
+ addPageContent("Unspported operation on nodes object.");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ }
+ else {
+ $request->{command} = 'lsdef';
+ push @args, "-t", "node";
+
+ #add the nodegroup into args
+ if (defined($noderange)) {
+ push @args, "-o", $noderange;
+ }
+
+ #maybe it's specified in the parameters
+ my @temparray = $q->param('field');
+ if (scalar(@temparray) > 0) {
+ push @args, "-i";
+ push @args, join(',', @temparray);
+ }
+ }
+ }
+ elsif (isPut()) {
+ my $subResource;
+ my @entries;
+ my $entrydata;
+
+ unless (defined($noderange)) {
+ addPageContent("Invalid nodes and/or groups in noderange");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ $request->{noderange} = $noderange;
+
+ unless ($q->param('PUTDATA')) {
+ #temporary allowance for the put data to be contained in the queryString
+ unless ($queryhash{'putData'}) {
+ addPageContent("No set attribute was supplied.");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ else {
+ foreach my $put (@{$queryhash{'putData'}}) {
+ my ($key, $value) = split(/=/, $put, 2);
+ if ($key eq 'field' && $value) {
+ push @entries, $value;
+ }
+ }
+ }
+ }
+ else {
+ @entries = JSON::decode_json($q->param('PUTDATA'));
+ if (scalar(@entries) < 1) {
+ addPageContent("No set attribute was supplied.");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ }
+
+ if (defined $path[2]) {
+ $subResource = $path[2];
+
+ if (($subResource ne "dsh") && ($subResource ne "dcp")) {
+ # For any function other than "dsh" or "dcp",
+ # move all operands to the argument list.
+ foreach (@entries) {
+ if (ref($_) eq 'ARRAY') {
+ foreach (@$_) {
+ push @args, $_;
+ }
+ } else {
+ push @args, $_;
+ }
+ }
+ }
+ if ($subResource eq "power") {
+ $request->{command} = "rpower";
+ my %elements;
+ extractData(\%elements, @entries);
+
+ unless (scalar(%elements)) {
+ addPageContent("No power operands were supplied.");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ }
+ elsif ($subResource eq "energy") {
+ $request->{command} = "renergy";
+ }
+ elsif ($subResource eq "bootstat" or $subResource eq "bootstate") {
+ $request->{command} = "nodeset";
+ }
+ elsif ($subResource eq "bootseq") {
+ $request->{command} = "rbootseq";
+ }
+ elsif ($subResource eq "setboot") {
+ $request->{command} = "rsetboot";
+ }
+ elsif ($subResource eq "migrate") {
+ $request->{command} = "rmigrate";
+ }
+ elsif ($subResource eq "execcmdonvm") {
+ $request->{command} = "execcmdonvm";
+ }
+ elsif ($subResource eq "dsh") {
+ $request->{command} = "xdsh";
+ my %elements;
+ extractData(\%elements, @entries);
+ if (defined($elements{'devicetype'})) {
+ push @args, '--devicetype';
+ push @args, $elements{'devicetype'};
+ }
+ if (defined($elements{'execute'})) {
+ push @args, '-e';
+ }
+ if (defined($elements{'environment'})) {
+ push @args, '-E';
+ push @args, $elements{'environment'};
+ }
+ if (defined($elements{'fanout'})) {
+ push @args, '-f';
+ push @args, $elements{'fanout'};
+ }
+ if (defined($elements{'nolocale'})) {
+ push @args, '-L';
+ }
+ if (defined($elements{'userid'})) {
+ push @args, '-l';
+ push @args, $elements{'userid'};
+ }
+ if (defined($elements{'monitor'})) {
+ push @args, '-m';
+ }
+ if (defined($elements{'options'})) {
+ push @args, '-o';
+ push @args, $elements{'options'};
+ }
+ if (defined($elements{'showconfig'})) {
+ push @args, '-q';
+ }
+ if (defined($elements{'silent'})) {
+ push @args, '-Q';
+ }
+ if (defined($elements{'remoteshell'})) {
+ push @args, '-r';
+ push @args, $elements{'remoteshell'};
+ }
+ if (defined($elements{'syntax'})) {
+ push @args, '-S';
+ push @args, $elements{'syntax'};
+ }
+ if (defined($elements{'timeout'})) {
+ push @args, '-t';
+ push @args, $elements{'timeout'};
+ }
+ if (defined($elements{'envlist'})) {
+ push @args, '-X';
+ push @args, $elements{'envlist'};
+ }
+ if (defined($elements{'sshsetup'})) {
+ push @args, '-K';
+ push @args, $elements{'sshsetup'};
+ }
+ if (defined($elements{'rootimg'})) {
+ push @args, '-i';
+ push @args, $elements{'rootimg'};
+ }
+ if (defined($elements{'command'})) {
+ push @args, $elements{'command'};
+ }
+ if (defined($elements{'remotepasswd'})) {
+ push @envs, 'DSH_REMOTE_PASSWORD=' . $elements{'remotepasswd'};
+ push @envs, 'DSH_FROM_USERID=root';
+ push @envs, 'DSH_TO_USERID=root';
+ }
+ }
+ elsif ($subResource eq "dcp") {
+ $request->{command} = "xdcp";
+ my %elements;
+ extractData(\%elements, @entries);
+ if (defined($elements{'fanout'})) {
+ push @args, '-f';
+ push @args, $elements{'fanout'};
+ }
+ if (defined($elements{'rootimg'})) {
+ push @args, '-i';
+ push @args, $elements{'rootimg'};
+ }
+ if (defined($elements{'options'})) {
+ push @args, '-o';
+ push @args, $elements{'options'};
+ }
+ if (defined($elements{'rsyncfile'})) {
+ push @args, '-F';
+ push @args, $elements{'rsyncfile'};
+ }
+ if (defined($elements{'preserve'})) {
+ push @args, '-p';
+ }
+ if (defined($elements{'pull'})) {
+ push @args, '-P';
+ }
+ if (defined($elements{'showconfig'})) {
+ push @args, '-q';
+ }
+ if (defined($elements{'remotecopy'})) {
+ push @args, '-r';
+ push @args, $elements{'remotecopy'};
+ }
+ if (defined($elements{'recursive'})) {
+ push @args, '-R';
+ }
+ if (defined($elements{'timeout'})) {
+ push @args, '-t';
+ push @args, $elements{'timeout'};
+ }
+ if (defined($elements{'source'})) {
+ push @args, $elements{'source'};
+ }
+ if (defined($elements{'target'})) {
+ push @args, $elements{'target'};
+ }
+ }
+ }
+ else {
+ my %elements;
+ my $name;
+ my $val;
+
+ $request->{command} = "tabch";
+ push @args, "node=" . $request->{noderange};
+
+ extractData(\%elements, @entries);
+ while (($name, $val) = each (%elements)) {
+ push @args, $name . "=" . $val;
+ }
+ }
+ }
+ elsif (isPost()) {
+ $request->{command} = 'mkdef';
+ push @args, "-t", "node";
+
+ unless (defined($noderange)) {
+ addPageContent("No nodename was supplied.");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+
+ push @args, "-o", $noderange;
+
+ if ($q->param('POSTDATA')) {
+ my $entries = JSON::decode_json($q->param('POSTDATA'));
+ if (scalar($entries) < 1) {
+ addPageContent("No Field and Value map was supplied.");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ foreach (@$entries) {
+ push @args, $_;
+ }
+ }
+ }
+ elsif (isDelete()) {
+
+ #FYI: the nodeRange for delete has to be specified in the URI
+ $request->{command} = 'rmdef';
+ push @args, "-t", "node";
+ unless (defined($noderange)) {
+ addPageContent("No nodename was supplied.");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ push @args, "-o", $noderange;
+ }
+ else {
+ unsupportedRequestType();
+ exit();
+ }
+
+ push @{$request->{arg}}, @args;
+ if (@envs) {
+ push @{$request->{env}}, @envs;
+ }
+ my $req = genRequest();
+ @responses = sendRequest($req);
+
+ return @responses;
+}
+
+my @notificationFields = ('filename', 'tables', 'tableops', 'comments', 'disable');
+
+#complete, unless there is some way to alter existing notifications
+sub notificationsHandler {
+ my @responses;
+ my @args;
+
+ #does not support using the notification fileName in the URI
+
+ if (isGet()) {
+ if (defined $q->param('fileName')) {
+ $request->{command} = 'gettab';
+ push @args, "filename" . $q->param('fileName');
+
+ #if they specified the fields, just get those
+ if (defined $q->param('field')) {
+ foreach ($q->param('field')) {
+ push @args, $_;
+ }
+ }
+
+ #else show all of the fields
+ else {
+ foreach (@notificationFields) {
+ push @args, "notification.$_";
+ }
+ }
+ }
+ else {
+ $request->{command} = 'tabdump';
+ push @args, "notification";
+ }
+ }
+ elsif (isPost()) {
+ $request->{command} = 'regnotif';
+ if (!defined $q->param('fileName') || !defined $q->param('table') || !defined $q->param('operation')) {
+ addPageContent("fileName, table and operation must be specified for a POST on /notifications");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ else {
+ push @args, $q->param('fileName');
+ my $tables;
+ foreach ($q->param('table')) {
+ $tables .= "$_,";
+ }
+
+ #get rid of the extra comma
+ chop($tables);
+ push @args, $tables;
+ push @args, '-o';
+ my $operations;
+ foreach ($q->param('operation')) {
+ $operations .= "$_,";
+ }
+
+ #get rid of the extra comma
+ chop($operations);
+ push @args, $q->param('operation');
+ }
+ }
+ elsif (isDelete()) {
+ $request->{command} = 'unregnotif';
+ if (defined $q->param('fileName')) {
+ push @args, $q->param('fileName');
+ }
+ else {
+ addPageContent("fileName must be specified for a DELETE on /notifications");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ }
+ else {
+ unsupportedRequestType();
+ exit();
+ }
+
+ push @{$request->{arg}}, @args;
+ addPageContent("request is " . Dumper($request));
+ my $req = genRequest();
+ @responses = sendRequest($req);
+
+ return @responses;
+}
+
+my @policyFields =
+ ('priority', 'name', 'host', 'commands', 'noderange', 'parameters', 'time', 'rule', 'comments', 'disable');
+
+#complete
+sub policiesHandler {
+ my @responses;
+ my @args;
+ my $priority;
+
+ #does it specify the prioirty in the URI?
+ if (defined $path[1]) {
+ $priority = $path[1];
+ }
+
+ #in the query string?
+ elsif (defined $q->param('priority')) {
+ $priority = $q->param('priority');
+ }
+
+ if (isGet()) {
+ if (defined $priority) {
+ $request->{command} = 'gettab';
+ push @args, "priority=$priority";
+ my @fields = $q->param('field');
+
+ #if they specified fields to retrieve
+ if (@fields) {
+ push @args, @fields;
+ }
+
+ #give them everything if nothing is specified
+ else {
+ foreach (@policyFields) {
+ push @args, "policy.$_";
+ }
+ }
+ }
+ else {
+ $request->{command} = 'tabdump';
+ push @args, 'policy';
+ }
+ }
+ elsif (isPost()) {
+ if (defined $priority) {
+ $request->{command} = 'tabch';
+ push @args, "priority=$priority";
+ for ($q->param) {
+ if ($_ ne /priority/) {
+ push @args, "policy.$_=" . $q->param($_);
+ }
+ }
+ }
+
+ #some response about the priority being required
+ else {
+ addPageContent("The priority must be specified when creating a policy");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ }
+ elsif (isDelete()) {
+
+ #just allowing a delete by priority at the moment, could expand this to anything
+ if (defined $priority) {
+ $request->{command} = 'tabch';
+ push @args, '-d';
+ push @args, "priority=$priority";
+ push @args, "policy";
+ }
+ }
+ elsif (isPut() || isPatch()) {
+ if (defined $priority) {
+ $request->{command} = 'tabch';
+ push @args, "priority=$priority";
+ for ($q->param) {
+ if ($_ ne /priority/) {
+ push @args, "policy.$_=" . $q->param($_);
+ }
+ }
+ }
+
+ #some response about the priority being required
+ else {
+ addPageContent("The priority must be specified when updating a policy");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ }
+ else {
+ unsupportedRequestType();
+ exit();
+ }
+
+ push @{$request->{arg}}, @args;
+ addPageContent("request is " . Dumper($request));
+ my $req = genRequest();
+ @responses = sendRequest($req);
+
+ return @responses;
+}
+
+#complete
+sub siteHandler {
+ my @data;
+ my @responses;
+ my @args;
+
+ if (isGet()) {
+ $request->{command} = 'lsdef';
+ push @{$request->{arg}}, '-t', 'site', '-o', 'clustersite';
+ my @temparray = $q->param('field');
+
+ #add the field name to get
+ if (scalar(@temparray) > 0) {
+ push @{$request->{arg}}, '-i';
+ push @{$request->{arg}}, join(',', @temparray);
+ }
+ }
+ elsif (isPut()) {
+ $request->{command} = 'chdef';
+ push @{$request->{arg}}, '-t', 'site', '-o', 'clustersite';
+ unless ($q->param('PUTDATA')) {
+ #temporary allowance for the put data to be contained in the queryString
+ unless ($queryhash{'putData'}) {
+ addPageContent("No set attribute was supplied.");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ else {
+ foreach my $put (@{$queryhash{'putData'}}) {
+ my ($key, $value) = split(/=/, $put, 2);
+ if ($key eq 'field' && $value) {
+ push @{$request->{arg}}, $value;
+ }
+ }
+ }
+ } else {
+ if ($q->param('PUTDATA')) {
+ my $entries = JSON::decode_json($q->param('PUTDATA'));
+ foreach (@$entries) {
+ push @{$request->{arg}}, $_;
+ }
+ }
+ else {
+ addPageContent("No Field and Value map was supplied.");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ }
+ }
+ else {
+ unsupportedRequestType();
+ }
+
+ my $req = genRequest();
+ @responses = sendRequest($req);
+ return @responses;
+}
+
+my $formatType;
+
+#provide direct table access
+#complete and tested on the site table
+#use of the actual DELETE doesn't seem to fit here, since a resource would not be deleted
+#using PUT or PATCH instead, though it doesn't feel all that correct either
+sub tablesHandler {
+ my @responses;
+ my $table;
+ my @args;
+
+ #is the table name specified in the URI?
+ if (defined $path[1]) {
+ $table = $path[1];
+ }
+
+ #handle all gets
+ if (isGet()) {
+
+ #table was specified
+ if (defined $table) {
+ if (defined($q->param('col'))) {
+ $request->{command} = 'gettab';
+ push @args, $q->param('col') . '=' . $q->param('value');
+ my @temparray = $q->param('attribute');
+ foreach (@temparray) {
+ push @args, $table . '.' . $_;
+ }
+ }
+ else {
+ $request->{command} = 'tabdump';
+ push @args, $table;
+ if (!defined $q->param('desc')) {
+ $formatType = 'splitCommas';
+ }
+ }
+ }
+ else {
+ $request->{command} = 'tabdump';
+ }
+ }
+ elsif (isPut() || isPatch()) {
+ my $condition = $q->param('condition');
+ my @vals;
+ my $entries;
+ if (!defined $condition) {
+ unless ($q->param('PUTDATA')) {
+ foreach my $put (@{$queryhash{'putData'}}) {
+ my ($key, $value) = split(/=/, $put, 2);
+ if ($key eq 'condition' && $value) {
+ $condition = $value;
+ }
+ }
+ foreach my $put (@{$queryhash{'putData'}}) {
+ my ($key, $value) = split(/=/, $put, 2);
+ if ($key eq 'value') {
+ push(@vals, $value);
+ }
+ }
+ }
+ else {
+ $entries = JSON::decode_json($q->param('PUTDATA'));
+ if (scalar(@$entries) < 1) {
+ addPageContent("No set attribute was supplied.");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ }
+ }
+
+ if (!defined $table || !defined $condition) {
+ if (scalar(@$entries) < 1) {
+ addPageContent("The table and condition must be specified when adding, changing or deleting an entry");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ }
+ $request->{command} = 'tabch';
+ my $del;
+ if (!defined $q->param('delete')) {
+ foreach my $put (@{$queryhash{'putData'}}) {
+ my ($key, $value) = split(/=/, $put, 2);
+ if ($key eq 'delete') {
+ $del = 1;
+ }
+ }
+ }
+
+ if (defined $q->param('delete') || defined $del) {
+ push @args, '-d';
+ push @args, $condition;
+ push @args, $table;
+ }
+ elsif (defined $condition) {
+ push @args, $condition;
+ if ($q->param('value')) {
+ for ($q->param('value')) {
+ push @args, "$table.$_";
+ }
+ }
+ else {
+ @args = (@args, @vals);
+ }
+ }
+ else {
+ foreach (@$entries) {
+ push @args, split(/ /,$_);
+ }
+ }
+ }
+ else {
+ unsupportedRequestType();
+ exit();
+ }
+
+ push @{$request->{arg}}, @args;
+ my $req = genRequest();
+ @responses = sendRequest($req);
+ return @responses;
+}
+
+my @accountFields = ('key', 'username', 'password', 'cryptmethod', 'comments', 'disable');
+
+#done aside from being able to change cluster users, which xcat can't do yet
+sub accountsHandler {
+ my @responses;
+ my @args;
+ my $key = $q->param('key');
+
+ if (isGet()) {
+
+ #passwd table
+ if (!defined $q->param('clusterUser')) {
+ if (defined $key) {
+ $request->{command} = 'gettab';
+ push @args, "key=$key";
+ if (defined $q->param('field')) {
+ foreach ($q->param('field')) {
+ push @args, "passwd.$_";
+ }
+ }
+ else {
+ foreach (@accountFields) {
+ push @args, "passwd.$_";
+ }
+ }
+ }
+ else {
+ $request->{command} = 'tabdump';
+ push @args, 'passwd';
+ }
+ }
+
+ #cluster user list
+ else {
+ $request->{command} = 'xcatclientnnr';
+ push @args, 'clusteruserlist';
+ push @args, '-p';
+ }
+ }
+ elsif (isPost()) {
+ if (!defined $q->param('clusterUser')) {
+ if (defined $key) {
+ $request->{command} = 'tabch';
+ push @args, "key=$key";
+ for ($q->param) {
+ if ($_ !~ /key/) {
+ push @args, "passwd.$_=" . $q->param($_);
+ }
+ }
+ }
+ else {
+ addPageContent("The key must be specified when creating a non-cluster user");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ }
+
+ #active directory user
+ else {
+ if (defined $q->param('userName') && defined $q->param('userPass')) {
+ $request->{command} = 'xcatclientnnr';
+ push @args, 'clusteruseradd';
+ push @args, $q->param('userName');
+ push @{$request->{arg}}, @args;
+ $request->{environment} = {XCAT_USERPASS => $q->param('userPass')};
+ }
+ else {
+ addPageContent("The key must be specified when creating a cluster user");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ }
+ }
+ elsif (isDelete()) {
+ if (!defined $q->param('clusterUser')) {
+
+ #just allowing a delete by key at the moment, could expand this to anything
+ if (defined $key) {
+ $request->{command} = 'tabch';
+ push @args, '-d';
+ push @args, "key=$key";
+ push @args, "passwd";
+ }
+ else {
+ addPageContent("The key must be specified when deleting a non-cluster user");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ }
+ else {
+ if (defined $q->param('userName')) {
+ $request->{command} = 'xcatclientnnr';
+ push @args, 'clusteruserdel';
+ push @args, $q->param('userName');
+ }
+ else {
+ addPageContent("The userName must be specified when deleting a cluster user");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ }
+ }
+ elsif (isPut() || isPatch()) {
+ if (!defined $q->param('clusterUser')) {
+ if (defined $key) {
+ $request->{command} = 'tabch';
+ push @args, "key=$key";
+ for ($q->param) {
+ if ($_ !~ /key/) {
+ push @args, "passwd.$_=" . $q->param($_);
+ }
+ }
+ }
+ else {
+ addPageContent("The key must be specified when updating a non-cluster user");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ }
+
+ #TODO: there isn't currently a way to update cluster users
+ else {
+
+ }
+ }
+ else {
+ unsupportedRequestType();
+ exit(0);
+ }
+
+ push @{$request->{arg}}, @args;
+ my $req = genRequest();
+ @responses = sendRequest($req);
+ return @responses;
+}
+
+sub objectsHandler {
+ my @responses;
+ my @args;
+ my @objectTypeList = (
+ "auditlog", "boottarget", "eventlog", "firmware", "group", "monitoring",
+ "network", "node", "notification", "osimage", "policy", "route",
+ "site");
+
+ #my %objectTypes;
+ #foreach my $item (@objectTypeList) { $objectTypes{$item} = 1 }
+ my @objectTypes;
+ my @objects;
+ if (defined $path[1]) {
+ $objectTypes[0] = $path[1];
+ if (defined $path[2]) {
+ $objects[0] = $path[2];
+ }
+ }
+ if (defined $q->param('objectType')) {
+ @objectTypes = $q->param('objectType');
+ }
+ if (defined $q->param('object')) {
+ @objects = $q->param('object');
+ }
+
+ if ($q->param('verbose')) {
+ push @args, '-v';
+ }
+
+ if (isGet()) {
+ if (defined $objectTypes[0]) {
+ $request->{command} = 'lsdef';
+ push @args, '-l';
+ push @args, '-t';
+ push @args, join(',', @objectTypes);
+ if (defined $objects[0]) {
+ push @args, '-o';
+ push @args, join(',', @objects);
+ }
+ if ($q->param('info')) {
+ push @args, '-h';
+ }
+ }
+ else {
+ if ($q->param('info')) {
+ push @args, '-h';
+ }
+ else {
+
+ #couldn't find a way to do this through xcatd, so shortcutting the request
+ my %resp = (data => \@objectTypeList);
+ return (\%resp);
+ }
+ }
+ }
+ elsif (isPut()) {
+ $request->{command} = 'chdef';
+ if ($q->param('verbose')) {
+ push @args, '-v';
+ }
+ if (!defined $q->param('objectType')) {
+ addPageContent("The object must be specified.");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ else {
+ push @args, '-t';
+ push @args, join(',', $q->param('objectType'));
+ }
+ if ($q->param('objectName')) {
+ push @args, join(',', $q->param('objectName'));
+ }
+ if ($q->param('dynamic')) {
+ push @args, '-d';
+ }
+ if ($q->param('minus')) {
+ push @args, '-m';
+ }
+ if ($q->param('plus')) {
+ push @args, '-p';
+ }
+ if (defined $q->param('field')) {
+ foreach ($q->param('field')) {
+
+ #if it has ==, !=. =~ or !~ operators in the field, use the -w option
+ if (/==|!=|=~|!~/) {
+ push @args, '-w';
+ }
+ push @args, $_;
+ }
+ }
+ if ($q->param('nodeRange')) {
+ push @args, $q->param('nodeRange');
+ }
+
+ }
+ elsif (isPost()) {
+ $request->{command} = 'mkdef';
+ if ($q->param('verbose')) {
+ push @args, '-v';
+ }
+ if (!defined $q->param('objectType')) {
+ addPageContent("The object must be specified.");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ else {
+ push @args, '-t';
+ push @args, join(',', $q->param('objectType'));
+ }
+ if ($q->param('objectName')) {
+ push @args, join(',', $q->param('objectName'));
+ }
+ if ($q->param('dynamic')) {
+ push @args, '-d';
+ }
+ if ($q->param('force')) {
+ push @args, '-f';
+ }
+ if (defined $q->param('field')) {
+ foreach ($q->param('field')) {
+
+ #if it has ==, !=. =~ or !~ operators in the field, use the -w option
+ if (/==|!=|=~|!~/) {
+ push @args, '-w';
+ }
+ push @args, $_;
+ }
+ }
+ if ($q->param('nodeRange')) {
+ push @args, $q->param('nodeRange');
+ }
+
+ }
+ elsif (isDelete()) {
+ $request->{command} = 'rmdef';
+ if (defined $q->param('info')) {
+ push @args, '-h';
+ }
+ elsif (defined $q->param('all')) {
+ push @args, '-a';
+ }
+ elsif (defined $objectTypes[0]) {
+ push @args, '-t';
+ push @args, join(',', @objectTypes);
+ if (defined $objects[0]) {
+ push @args, '-o';
+ push @args, join(',', @objects);
+ }
+ }
+ else {
+ addPageContent(
+"Either the help info must be requested or the object must be specified or the flag that indicates everything should be removed."
+ );
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ if (defined $q->param('nodeRange')) {
+ push @args, $q->param('nodeRange');
+ }
+ }
+ else {
+ unsupportedRequestType();
+ exit();
+ }
+
+ push @{$request->{arg}}, @args;
+ my $req = genRequest();
+ @responses = sendRequest($req);
+ return @responses;
+}
+
+#complete i think, tho chvm could handle args better
+sub vmsHandler {
+ my @args;
+ my $noderange;
+ my $subResource;
+ if (defined $path[1]) {
+ $noderange = $path[1];
+ $request->{noderange} = $noderange;
+ }
+ else {
+ addPageContent("Invalid nodes and/or groups in noderange");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+
+ if (isGet()) {
+ $request->{command} = 'lsvm';
+ if (defined $q->param('all')) {
+ push @args, '-a';
+ }
+
+ # for z/VM
+ if (defined $q->param('networknames')) {
+ push @args, '--getnetworknames';
+ }
+
+ if (defined $q->param('network')) {
+ push @args, '--getnetwork';
+ push @args, $q->param('getnetwork');
+ }
+
+ if (defined $q->param('diskpoolnames')) {
+ push @args, '--diskpoolnames';
+ }
+
+ if (defined $q->param('diskpool')) {
+ push @args, '--diskpool';
+ push @args, $q->param('diskpool');
+ }
+
+ if (defined $q->param('checknics')) {
+ push @args, '--checknics';
+ push @args, $q->param('checknics');
+ }
+ }
+ elsif (isPost()) {
+ my $entries;
+ my %entryhash;
+ my $position;
+ $request->{command} = 'mkvm';
+ unless ($q->param('POSTDATA')) {
+ addPageContent("Invalid Parameters");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+
+ #collect all parameters from the postdata
+ $entries = JSON::decode_json($q->param('POSTDATA'));
+ if (scalar(@$entries) < 1) {
+ addPageContent("No set attribute was supplied.");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+
+ extractData(\%entryhash, $entries);
+
+ # For zVM; clonefrom must be first so that the mkvm call
+ # has the clone from node in correct spot in makeVM args
+ if (defined $entryhash{'clonefrom'}) {
+ push @args, $entryhash{'clonefrom'};
+ }
+
+ #for system p
+ if (defined $entryhash{'cec'}) {
+ push @args, '-c';
+ push @args, $entryhash{'cec'};
+ }
+
+ if (defined $entryhash{'startId'}) {
+ push @args, '-i';
+ push @args, $entryhash{'startId'};
+ }
+
+ if (defined $entryhash{'source'}) {
+ push @args, '-l';
+ push @args, $entryhash{'source'};
+ }
+
+ if (defined $entryhash{'profile'}) {
+ push @args, '-p';
+ push @args, $entryhash{'profile'};
+ }
+
+ if (defined $entryhash{'full'}) {
+ push @args, '--full';
+ }
+
+ #for KVM & Vmware
+ if (defined $entryhash{'master'}) {
+ push @args, '-m';
+ push @args, $entryhash{'master'};
+ }
+
+ if (defined $entryhash{'disksize'}) {
+ push @args, '-s';
+ push @args, $entryhash{'disksize'};
+ }
+
+ if (defined $entryhash{'memory'}) {
+ push @args, '--mem';
+ push @args, $entryhash{'memory'};
+ }
+
+ if (defined $entryhash{'cpu'}) {
+ push @args, '--cpus';
+ push @args, $entryhash{'cpu'};
+ }
+
+ if (defined $entryhash{'force'}) {
+ push @args, '-f';
+ }
+
+ # for z/VM
+ if (defined $entryhash{'userid'}) {
+ push @args, '--userid';
+ push @args, $entryhash{'userid'};
+ }
+
+ if (defined $entryhash{'size'}) {
+ push @args, '--size';
+ push @args, $entryhash{'size'};
+ }
+
+ if (defined $entryhash{'password'}) {
+ push @args, '--password';
+ push @args, $entryhash{'password'};
+ }
+
+ if (defined $entryhash{'privilege'}) {
+ push @args, '--privilege';
+ push @args, $entryhash{'privilege'};
+ }
+
+ if (defined $entryhash{'diskpool'}) {
+ push @args, '--diskpool';
+ push @args, $entryhash{'diskpool'};
+ }
+
+ if (defined $entryhash{'diskvdev'}) {
+ push @args, '--diskVdev';
+ push @args, $entryhash{'diskvdev'};
+ }
+ if (defined $entryhash{'imagename'}) {
+ push @args, '--imagename';
+ push @args, $entryhash{'imagename'};
+ }
+ if (defined $entryhash{'osimage'}) {
+ push @args, '--osimage';
+ push @args, $entryhash{'osimage'};
+ }
+ if (defined $entryhash{'ipl'}) {
+ push @args, '--ipl';
+ push @args, $entryhash{'ipl'};
+ }
+ # For the mkvm call the zvm.pm code is looking for key=value
+ # for pool and pw; rather than a "--key value"
+ if ( defined $entryhash{'pool'} ) {
+ push @args, "pool=$entryhash{'pool'}";
+ }
+ if ( defined $entryhash{'pw'} ) {
+ push @args, "pw=$entryhash{'pw'}";
+ }
+ }
+ elsif (isPut()) {
+ $request->{command} = 'chvm';
+ if ($q->param('PUTDATA')) {
+ my $entries = JSON::decode_json($q->param('PUTDATA'));
+ if (scalar(@$entries) < 1) {
+ addPageContent("No Field and Value map was supplied.");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ foreach (@$entries) {
+ # Handle blank delimited parameters
+ push @args, split(/ /,$_);
+ }
+ }
+ else {
+ addPageContent("No Field and Value map was supplied.");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+ }
+ elsif (isDelete()) {
+ $request->{command} = 'rmvm';
+ if (defined $q->param('retain')) {
+ push @args, '-r';
+ }
+ if (defined $q->param('service')) {
+ push @args, '--service';
+ }
+ }
+ else {
+ unsupportedRequestType();
+ exit();
+ }
+
+ # Note: MUST parse these parameters after all others if we want to avoid
+ # duplicating this code on each if branch, since
+ # lsvm depends on its "subcommand" being the first parameter.
+ # TODO if we add these parameters to other paths, could we use a subroutine instead? only 2 inputs.
+
+ # Parse the optional upstream object ID, e.g. an OpenStack nova instance UUID
+ if (defined $queryhash{'objectid'}) {
+ push @args, '--objectid';
+ push @args, $queryhash{'objectid'}->[0];
+ }
+
+ # Parse the optional upstream request ID, e.g. an OpenStack request UUID
+ if (defined $queryhash{'requestid'}) {
+ push @args, '--requestid';
+ push @args, $queryhash{'requestid'}->[0];
+ }
+
+ push @{$request->{arg}}, @args;
+ my $req = genRequest();
+ my @responses = sendRequest($req);
+ return @responses;
+}
+
+sub versionHandler {
+ $request->{command} = "lsxcatd";
+ push @{$request->{arg}}, "-v";
+ my $req = genRequest();
+ my @responses = sendRequest($req);
+ return @responses;
+}
+
+#for operations that take a 'long' time to finish, this will provide the interface to check their status
+sub jobsHandler {
+
+}
+
+sub hypervisorHandler {
+ my @responses;
+ my @args;
+ if (isPut()) {
+ my %entryhash;
+ if (defined $path[1]) {
+ $request->{noderange} = $path[1];
+ }
+ else {
+ addPageContent("Invalid nodes and/or groups in node in noderange");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+
+ if (defined $path[2]) {
+ $request->{command} = $path[2];
+ }
+ else {
+ $request->{command} = 'chhypervisor';
+ }
+ my $entries = JSON::decode_json( $q->param('PUTDATA') );
+ if (scalar(@$entries) < 1) {
+ addPageContent("No set attribute was supplied.");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+
+ foreach (@$entries) {
+ push @args, split(/ /,$_);
+ }
+
+ push @{$request->{arg}}, @args;
+ my $req = genRequest();
+ @responses = sendRequest($req);
+ return @responses;
+ }
+}
+
+sub debugHandler {
+ my @responses;
+ my @args;
+ if (isPut()) {
+ my %entryhash;
+ $request->{command} = 'xcatclientnnr xcatdebug';
+
+ #push @args, 'xcatdebug';
+ my $entries = JSON::decode_json( $q->param('PUTDATA') );
+ if (scalar(@$entries) < 1) {
+ addPageContent("No set attribute was supplied.");
+ sendResponseMsg($STATUS_BAD_REQUEST);
+ }
+
+ foreach (@$entries) {
+ push @{$request->{arg}}, $_;
+ }
+
+ push @{$request->{arg}}, @args;
+ my $req = genRequest();
+ @responses = sendRequest($req);
+ return @responses;
+ }
+}
+
+#all data wrapping and writing is funneled through here
+sub wrapData {
+ my $data = shift;
+ my $errorInformation = '';
+
+ #trim the serverdone message off
+ if (exists $data->[0]->{serverdone} && exists $data->[0]->{error}) {
+ $errorInformation = $data->[0]->{error}->[0];
+ addPageContent($q->p($errorInformation));
+ if (($errorInformation =~ /Permission denied/) || ($errorInformation =~ /Authentication failure/)) {
+ sendResponseMsg($STATUS_UNAUTH);
+ }
+ else {
+ sendResponseMsg($STATUS_FORBIDDEN);
+ }
+ exit 1;
+ }
+ else {
+ pop @{$data};
+ }
+ if (exists $formatters{$format}) {
+ $formatters{$format}->($data);
+ }
+
+ #all information were add into the global varibale, call the response funcion
+ if (exists $data->[0]->{info} && $data->[0]->{info}->[0] =~ /Could not find an object/) {
+ sendResponseMsg($STATUS_NOT_FOUND);
+ }
+ elsif (isPost()) {
+ sendResponseMsg($STATUS_CREATED);
+ }
+ else {
+ sendResponseMsg($STATUS_OK);
+ }
+}
+
+sub wrapJson {
+ my $data = shift;
+ my $json;
+ $json->{'data'} = $data;
+ addPageContent(JSON::to_json($json));
+}
+
+sub wrapHtml {
+ my $item;
+ my $response = shift;
+ my $baseUri = $url . $pathInfo;
+ if ($baseUri !~ /\/^/) {
+ $baseUri .= "/";
+ }
+
+ foreach my $element (@$response) {
+
+ #foreach my $element (@$data){
+ #if($element->{error}){
+ if ($element->{node}) {
+ addPageContent("");
+ foreach $item (@{$element->{node}}) {
+
+ #my $url = $baseUri.$item->{name}[0];
+ addPageContent("$item->{name}[0] ");
+ if (exists $item->{data} && exists $item->{data}[0]) {
+ if (ref($item->{data}[0]) eq 'HASH') {
+ if (exists $item->{data}[0]->{desc} && exists $item->{data}[0]->{desc}[0]) {
+ addPageContent("$item->{data}[0]->{desc}[0] ");
+ }
+ if (ref($item->{data}[0]) eq 'HASH' && exists $item->{data}[0]->{contents}[0]) {
+ addPageContent("$item->{data}[0]->{contents}[0] ");
+ }
+ }
+ else {
+ addPageContent("$item->{data}[0] ");
+ }
+ }
+ elsif (exists $item->{error}) {
+ addPageContent("$item->{error}[0] ");
+ }
+ addPageContent(" ");
+ }
+ addPageContent("
");
+ }
+ if ($element->{data}) {
+ addPageContent("");
+ foreach $item (@{$element->{data}}) {
+ my @values = split(/:/, $item, 2);
+ addPageContent("");
+ foreach (@values) {
+ if ($formatType =~ /splitCommas/) {
+ my @fields = split(/,/, $_, -1);
+ foreach (@fields) {
+ addPageContent("$_ ");
+ }
+ }
+ else {
+ addPageContent("$_ ");
+ }
+ }
+ addPageContent(" \n");
+ }
+ addPageContent("
");
+ }
+ if ($element->{info}) {
+ addPageContent("");
+ foreach $item (@{$element->{info}}) {
+ addPageContent("");
+ my $fieldname = '';
+ my $fieldvalue = '';
+
+ #strip whitespace in the string
+ $item =~ s/^\s+//;
+ $item =~ s/\s+$//;
+ if ($item =~ /Object/) {
+ ($fieldname, $fieldvalue) = split(/:/, $item);
+ }
+ elsif ($item =~ /.*=.*/) {
+ my $position = index $item, '=';
+ $fieldname = substr $item, 0, $position;
+ $fieldvalue = substr $item, $position + 1;
+ }
+ else {
+ $fieldname = $item;
+ }
+ addPageContent("" . $fieldname . " ");
+ if ($fieldvalue ne '') {
+ addPageContent("" . $fieldvalue . " ");
+ }
+ addPageContent(" \n");
+ }
+ addPageContent("
");
+ }
+ if ($element->{error}) {
+ addPageContent("");
+ foreach $item (@{$element->{error}}) {
+ addPageContent("" . $item . " ");
+ }
+ addPageContent("
");
+ }
+ }
+}
+
+sub wrapXml {
+ my @data = shift;
+ foreach (@data) {
+ foreach (@$_) {
+ addPageContent(XMLout($_, RootName => '', NoAttr => 1, KeyAttr => []));
+ }
+ }
+}
+
+#general tests for valid requests and responses with HTTP codes here
+if (!doesResourceExist($resource)) {
+ addPageContent("Resource '$resource' does not exist");
+ sendResponseMsg($STATUS_NOT_FOUND);
+}
+else {
+ if ($DEBUGGING) {
+ addPageContent($q->p("resource is $resource"));
+ }
+ handleRequest();
+}
+
+#talk to the server
+use Socket;
+use IO::Socket::INET;
+use IO::Socket::SSL;
+
+# The database initialization may take some time in the system boot scenario
+# wait for a while for the database initialization
+#do we really need to do this for the web service?
sub sendRequest {
my $request = shift;
- my $xmlinoptions = shift; # optional arg to not set ForceArray on the XMLin() call
my $sitetab;
my $retries = 0;
- if ($DEBUGGING == 2) {
+ if ($DEBUGGING) {
my $preXml = $request;
- $preXml =~ s/ < /g;
- $preXml =~ s/>/> /g;
- addPageContent($q->p("DEBUG: request XML: " . $request . "\n"));
+
+ #$preXml =~ s/ < /g;
+ #$preXml =~ s/>/> /g;
+ addPageContent($q->p("request XML " . $preXml));
}
#hardcoded port for now
@@ -3217,60 +2408,53 @@ sub sendRequest {
my $client;
if (-r $keyfile and -r $certfile and -r $cafile) {
$client = IO::Socket::SSL->new(
- PeerAddr => $xcatHost,
- SSL_key_file => $keyfile,
- SSL_cert_file => $certfile,
- SSL_ca_file => $cafile,
- SSL_verify_mode => SSL_VERIFY_PEER,
- SSL_verifycn_scheme => "none",
- SSL_use_cert => 1,
- Timeout => 15,);
+ PeerAddr => $xcatHost,
+ SSL_key_file => $keyfile,
+ SSL_cert_file => $certfile,
+ SSL_ca_file => $cafile,
+ SSL_use_cert => 1,
+ Timeout => 15,);
}
else {
$client = IO::Socket::SSL->new(
- PeerAddr => $xcatHost,
- SSL_verify_mode => 0,
- Timeout => 15,);
+ PeerAddr => $xcatHost,
+ SSL_verify_mode => 'SSL_VERIFY_NONE',
+ Timeout => 15,);
}
unless ($client) {
if ($@ =~ /SSL Timeout/) {
- error("Connection failure: SSL Timeout or incorrect certificates in ~/.xcat", $STATUS_TIMEOUT);
+ addPageContent("Connection failure: SSL Timeout or incorrect certificates in ~/.xcat");
+ sendResponseMsg($STATUS_TIMEOUT);
}
else {
- error("Connection failurexx: $@", $STATUS_SERVICE_UNAVAILABLE);
+ addPageContent("Connection failurexx: $@");
+ sendResponseMsg($STATUS_SERVICE_UNAVAILABLE);
}
}
- debug("request xml=$request");
print $client $request;
my $response;
my $rsp;
- my $fullResponse = [];
- my $cleanexit = 0;
+ my @fullResponse;
+ my $cleanexit = 0;
while (<$client>) {
$response .= $_;
if (m/<\/xcatresponse>/) {
#replace ESC with xxxxESCxxx because XMLin cannot handle it
if ($DEBUGGING) {
-
- #addPageContent("DEBUG: response from xcatd: " . $response . "\n");
+ addPageContent($response . "\n");
}
$response =~ s/\e/xxxxESCxxxx/g;
- debug("response xml=$response");
- #bmp: i added the $xmlinoptions var because for the table output it saved me processing if everything
- # wasn't forced into arrays. Consider if that could save you processing on other api calls too.
- if (!$xmlinoptions) { $xmlinoptions = { SuppressEmpty => undef, ForceArray => 1 }; }
- $rsp = XML::Simple::XMLin($response, %$xmlinoptions);
-
- #debug(Dumper($rsp));
+ #print "responseXML is ".$response;
+ $rsp = XMLin($response, SuppressEmpty => undef, ForceArray => 1);
#add ESC back
foreach my $key (keys %$rsp) {
if (ref($rsp->{$key}) eq 'ARRAY') {
- foreach my $text (@{ $rsp->{$key} }) {
+ foreach my $text (@{$rsp->{$key}}) {
next unless defined $text;
$text =~ s/xxxxESCxxxx/\e/g;
}
@@ -3281,175 +2465,57 @@ sub sendRequest {
}
$response = '';
- push(@$fullResponse, $rsp);
- if (exists($rsp->{serverdone})) {
+ push(@fullResponse, $rsp);
+ if ($rsp->{serverdone}) {
$cleanexit = 1;
last;
}
}
}
unless ($cleanexit) {
- error("communication with the xCAT server seems to have been ended prematurely", $STATUS_SERVICE_UNAVAILABLE);
+ addPageContent("ERROR/WARNING: communication with the xCAT server seems to have been ended prematurely");
+ sendResponseMsg($STATUS_SERVICE_UNAVAILABLE);
+ exit(0);
}
- if ($DEBUGGING == 2) {
- addPageContent($q->p("DEBUG: full response from xcatd: " . Dumper($fullResponse)));
+ if ($DEBUGGING) {
+ addPageContent($q->p("response " . Dumper(@fullResponse)));
}
- return $fullResponse;
+ return @fullResponse;
}
-# Put input parameters from both $q->url_param and put/post data (if it exists) into generalparams and paramhash for all to use
-# 1st output param - The params which are listed in @generalparamlis as a general parameters like 'debug=1, pretty=1'
-# 2nd output param - All the params from url params and 'PUTDATA'/'POSTDATA' except the ones in @generalparamlis
-sub fetchParameters {
- my @generalparamlist = qw(userName userPW pretty debug xcoll);
-
- # 1st check for put/post data and put that in the hash
- my $pdata;
- if (isPut()) {
- $pdata = $q->param('PUTDATA');
-
- # in the sles 11.x, the 'PUTDATA' param is not supported for PUT method
- # so we have to work around it by getting it by myself
- unless ($pdata) {
- if (-f "/etc/SuSE-release") { # SUSE os
- if ($ENV{'CONTENT_TYPE'} =~ /json/) {
- $q->read_from_client(\$pdata, $ENV{'CONTENT_LENGTH'});
- }
- }
- }
- } elsif (isPost()) {
- $pdata = $q->param('POSTDATA');
- } elsif (isDelete() || isGET()) {
- if ($ENV{'CONTENT_TYPE'} =~ /json/) {
- $q->read_from_client(\$pdata, $ENV{'CONTENT_LENGTH'});
- }
- }
-
- if ($dbgdata) {
- $pdata = $dbgdata;
- }
-
- my $genparms = {};
- my $phash;
- if ($pdata) {
- $phash = eval { $JSON->decode($pdata); };
- if ($@) {
-
- # remove the code location information to make the output looks better
- if ($@ =~ m/ at \//) {
- $@ =~ s/ at \/.*$//;
- }
- error("$@", $STATUS_BAD_REQUEST);
- }
-
- #debug("phash=" . Dumper($phash));
- if (ref($phash) ne 'HASH') { error("put or post data must be a json object (hash/dict).", $STATUS_BAD_REQUEST); }
-
- # if any general parms are in the put/post data, move them to genparms
- foreach my $k (keys %$phash) {
- if (grep(/^$k$/, @generalparamlist)) {
- $genparms->{$k} = $phash->{$k};
- delete($phash->{$k});
- }
- }
- }
- else { $phash = {}; }
-
- # now get params from the url (if any of the keys overlap, the url value will overwrite the put/post value)
- foreach my $p ($q->url_param) {
- my @a = $q->url_param($p); # this could be a single value or an array, have to figure it out
- my $value;
- if (scalar(@a) > 1) { $value = [@a]; } # convert it to a reference to an array
- else { $value = $a[0]; }
- if (grep(/^$p$/, @generalparamlist)) { $genparms->{$p} = $value; }
- else { $phash->{$p} = $value; }
- }
-
- return ($genparms, $phash);
+sub isGet {
+ return uc($requestType) eq "GET";
}
-# Load the XML::Simple module
-sub loadXML {
- if ($xmlinstalled) { return; }
-
- $xmlinstalled = eval { require XML::Simple; };
- unless ($xmlinstalled) {
- error('The XML::Simple perl module is missing. Install perl-XML-Simple before using the xCAT REST web services API with this format."}', $STATUS_SERVICE_UNAVAILABLE);
- }
- $XML::Simple::PREFERRED_PARSER = 'XML::Parser';
+sub isPut {
+ return uc($requestType) eq "PUT";
}
-# Load the JSON perl module, if not already loaded. Sets the $JSON global var.
-sub loadJSON {
- if ($JSON) { return; } # already loaded
- # require JSON dynamically and let them know if it is not installed
- my $jsoninstalled = eval { require JSON; };
- unless ($jsoninstalled) {
- error("JSON perl module missing. Install perl-JSON before using the xCAT REST web services API.", $STATUS_SERVICE_UNAVAILABLE);
- }
- $JSON = JSON->new();
+sub isPost {
+ return uc($requestType) eq "POST";
}
-# add a error msg to the output in the correct format and end this request
-sub error {
- my ($errmsg, $httpcode, $errorcode) = @_;
- my $json;
- $json->{error} = $errmsg;
- $json->{errorcode} = '2';
- if ($errorcode) {
- $json->{errorcode} = $errorcode;
+sub isPatch {
+ return uc($requestType) eq "PATCH";
+}
+
+sub isDelete {
+ return uc($requestType) eq "DELETE";
+}
+
+#check to see if this is a valid user. userName and password are already set
+sub isAuthenticUser {
+ $request->{command} = 'authcheck';
+ my $req = genRequest();
+ my @responses = sendRequest($req);
+ if ($responses[0]->{data}[0] eq "Authenticated") {
+
+ #user is authenticated
+ return 1;
}
- addPageContent($JSON->encode($json));
- sendResponseMsg($httpcode);
+ #authentication failure
+ addPageContent($responses[0]->{error}[0]);
+ sendResponseMsg($STATUS_UNAUTH);
}
-
-
-# if debugging, output the given string
-sub debug {
- if (!$DEBUGGING) { return; }
- addPageContent($q->p("DEBUG: $_[0]\n"));
-}
-
-# when having bugs that cause this cgi to not produce any output, output something and then exit.
-sub debugandexit {
- debug("$_[0]\n");
- sendResponseMsg($STATUS_OK);
-}
-
-sub displaydebugmsg {
- addPageContent($q->p("DEBUG: generalparams:" . Dumper($generalparams)));
- addPageContent($q->p("DEBUG: paramhash:" . Dumper($paramhash)));
- addPageContent($q->p("DEBUG: q->request_method: $requestType\n"));
-
- #addPageContent($q->p("DEBUG: q->user_agent: $userAgent\n"));
- addPageContent($q->p("DEBUG: pathInfo: $pathInfo\n"));
-
- #addPageContent($q->p("DEBUG: path " . Dumper(@path) . "\n"));
- #foreach (keys(%ENV)) { addPageContent($q->p("DEBUG: ENV{$_}: $ENV{$_}\n")); }
- #addPageContent($q->p("DEBUG: userName=".$paramhash->{userName}.", password=".$paramhash->{password}."\n"));
- #addPageContent($q->p("DEBUG: http() values:\n" . http() . "\n"));
- #if ($pdata) { addPageContent($q->p("DEBUG: pdata: $pdata\n")); }
- addPageContent("\n");
- if ($DEBUGGING == 3) {
- sendResponseMsg($STATUS_OK); # this will also exit
- }
-}
-
-
-# push flags (options) onto the xcatd request. Arguments: request args array, flags array.
-# Format of flags array:
-# Use this function for cmds with a lot of flags like xdcp and xdsh
-sub pushFlags {
- my ($args, $flags) = @_;
- foreach my $f (@$flags) {
- my ($key, $flag, $arg) = @$f;
- if (defined($paramhash->{$key})) {
- push @$args, $flag;
- if ($arg) { push @$args, $paramhash->{$key}; }
- }
- }
-}
-
-
diff --git a/xCAT/xCAT.spec b/xCAT/xCAT.spec
index 2b30241c5..eb28babd9 100644
--- a/xCAT/xCAT.spec
+++ b/xCAT/xCAT.spec
@@ -28,9 +28,12 @@ Conflicts: xCATsn
Requires: perl-DBD-SQLite
Requires: xCAT-client = 4:%{version}-%{release}
Requires: xCAT-server = 4:%{version}-%{release}
+
+%ifnarch s390x
Requires: xCAT-probe = 4:%{version}-%{release}
Requires: xCAT-genesis-scripts-x86_64 = 1:%{version}-%{release}
Requires: xCAT-genesis-scripts-ppc64 = 1:%{version}-%{release}
+%endif
%define pcm %(if [ "$pcm" = "1" ];then echo 1; else echo 0; fi)
%define notpcm %(if [ "$pcm" = "1" ];then echo 0; else echo 1; fi)
@@ -86,8 +89,10 @@ Requires: ipmitool-xcat >= 1.8.17-1
%if %notpcm
# PCM does not need or ship syslinux-xcat
+%ifnarch s390x
Requires: syslinux-xcat
%endif
+%endif
%description
xCAT is a server management package intended for at-scale management, including