mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-10-31 11:22:27 +00:00 
			
		
		
		
	git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@11265 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
		
			
				
	
	
		
			3351 lines
		
	
	
		
			85 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			3351 lines
		
	
	
		
			85 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /**
 | |
|  * Global variables
 | |
|  */
 | |
| // Node tabs
 | |
| var nodesTab;
 | |
| // Original node attributes
 | |
| var origAttrs = new Object();
 | |
| // Node attributes
 | |
| var nodeAttrs;
 | |
| // Node list
 | |
| var nodesList;
 | |
| // Nodes datatable ID
 | |
| var nodesTableId = 'nodesDatatable';
 | |
| 
 | |
| /**
 | |
|  * Set node tab
 | |
|  * 
 | |
|  * @param tab
 | |
|  *            Tab object
 | |
|  * @return Nothing
 | |
|  */
 | |
| function setNodesTab(tab) {
 | |
| 	nodesTab = tab;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Get node tab
 | |
|  * 
 | |
|  * @return Tab object
 | |
|  */
 | |
| function getNodesTab() {
 | |
| 	return nodesTab;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * 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
 | |
|  * 
 | |
|  * @return Nothing
 | |
|  */
 | |
| function loadNodesPage() {
 | |
| 	// If groups are not already loaded
 | |
| 	if (!$('#groups').length) {
 | |
| 		// Create a groups division
 | |
| 		var groups = $('<div id="groups"></div>');
 | |
| 		var nodes = $('<div id="nodes"></div>');
 | |
| 		$('#content').append(groups);
 | |
| 		$('#content').append(nodes);
 | |
| 
 | |
| 		// Create loader and info bar
 | |
| 		groups.append(createLoader());
 | |
| 		$('#nodes').append(createInfoBar('Select a group to view its nodes.'));
 | |
| 
 | |
| 		// 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('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
 | |
|  * @return Nothing
 | |
|  */
 | |
| function loadPieSummary(groupName){
 | |
|     var summaryTable = '<table style="border: 0px none;">' +
 | |
|                        '<tr>' +
 | |
|                        		'<td><div id="statuspie" class="summarypie"></div></td>' +
 | |
|                        		'<td><div id="ospie" class="summarypie"></div></td>' +
 | |
|                        		'<td><div id="archpie" class="summarypie"></div></td>' +
 | |
|                        '</tr>' +
 | |
|                        '<tr>' +
 | |
|                        		'<td><div id="provmethodpie" class="summarypie"></td>' +
 | |
|                        		'<td><div id="nodetypepie" class="summarypie"></div></td>' +
 | |
|                        '</tr></table>';
 | |
|     $('#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
 | |
|  * @return Nothing
 | |
|  */
 | |
| 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
 | |
|  * @return Nothing
 | |
|  */
 | |
| 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('<div class="grouplabel">Groups</div>');
 | |
| 	var grouplist= $('<div class="groupdiv"></div>');
 | |
| 	// Create a link for each group
 | |
| 	for (var i = 0; i < groups.length; i++) {
 | |
| 	    grouplist.append('<div>' + groups[i] + '</div>');
 | |
| 	}
 | |
| 	
 | |
| 	$('#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('selectgrouponnodes', thisGroup, { expires: 7 });
 | |
| 	    
 | |
| 	    drawNodesArea(thisGroup,'',thisGroup);
 | |
| 	});
 | |
| 	
 | |
| 	// Make a link to add nodes
 | |
| 	$('#groups').append('<div class="actionDiv" id="adddiv"></div>');
 | |
| 	$('#groups #adddiv').append(mkAddNodeLink());
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Empty the nodes area and add two 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
 | |
|  * @return Nothing
 | |
|  */
 | |
| 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);
 | |
|     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($('<center></center>').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
 | |
|                  * @return Nothing
 | |
|                  */
 | |
|                 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 (!$('#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('tabindex_history')) {
 | |
| 	    var order = $.cookie('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 = $('<a title="Add a node or a node range to xCAT">+ Add Node</a>');
 | |
| 	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 = $('<div class="form"></div>');
 | |
| 		addNodeForm.append(info);
 | |
| 		addNodeForm.append('<div><label for="mgt">Hardware management:</label>'
 | |
|     		+ '<select id="mgt" name="mgt">'
 | |
|     			+ '<option value="esx">ESX</option>'
 | |
|     			+ '<option value="kvm">KVM</option>'
 | |
|     			+ '<option value="zvm">z\/VM</option>'
 | |
|     			+ '<option value="ipmi">iDataPlex</option>' 
 | |
|     			+ '<option value="blade">BladeCenter</option>'
 | |
|     			+ '<option value="hmc">System p</option>'	// Documentation refers to 'IBM System p' (where p is NOT capitalized)
 | |
|     		+ '</select>'
 | |
|     	+ '</div>');
 | |
| 		
 | |
| 		// Create advanced link to set advanced node properties
 | |
| 		var advanced = $('<div></div>');
 | |
| 		var advancedLnk = $('<a>Advanced</a>').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
 | |
| 				 * @return Nothing
 | |
| 				 */
 | |
| 				success : function(data) {
 | |
| 					// Save node attributes
 | |
| 					setNodeAttrs(data);
 | |
| 					// Open a dialog to set node attributes
 | |
| 					openSetAttrsDialog();
 | |
| 				}
 | |
| 			});
 | |
| 			
 | |
| 			// Close dialog
 | |
| 			addNodeForm.dialog('close');
 | |
| 		});
 | |
| 		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;
 | |
| 			    	}
 | |
| 					
 | |
| 					plugin.addNode();
 | |
| 					$(this).dialog('close');
 | |
| 				},
 | |
| 				'Cancel': function(){
 | |
|         			$(this).dialog('close');
 | |
|         		}
 | |
| 			}
 | |
| 		});
 | |
| 
 | |
| 	});
 | |
| 	
 | |
| 	// 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
 | |
|  * @return Nothing
 | |
|  */
 | |
| 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, rsp[i].length));
 | |
| 		
 | |
| 		// 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('<input type="checkbox" onclick="selectAllCheckbox(event, $(this))">', 
 | |
| 		'node', 
 | |
| 		'<span><a>status</a></span><img src="images/loader.gif"></img>', 
 | |
| 		'<span><a>power</a></span><img src="images/loader.gif" style="display: none;"></img>',
 | |
| 		'<span><a>monitor</a></span><img src="images/loader.gif" style="display: none;"></img>',
 | |
| 		'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 = '<input type="checkbox" name="' + node + '"/>';
 | |
| 		var nodeLink = $('<a class="node" id="' + node + '">' + node + '</a>').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 = $('<img id="' + tipID + '" src="' + iconSrc + '"></img>').css({
 | |
| 				'width': '18px',
 | |
| 				'height': '18px'
 | |
| 			});
 | |
| 			
 | |
| 			// Create tooltip
 | |
| 			var tip = createCommentsToolTip(comments);
 | |
| 			var col = $('<span></span>').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);
 | |
| 
 | |
| 	// Create action bar
 | |
| 	var actionBar = $('<div class="actionBar"></div>');
 | |
| 
 | |
| 	/**
 | |
| 	 * Create menu for actions to perform against a given node
 | |
| 	 */
 | |
| 
 | |
| 	// Power on
 | |
| 	var powerOnLnk = $('<a>Power on</a>');
 | |
| 	powerOnLnk.click(function() {
 | |
| 		var tgtNodes = getNodesChecked(nodesTableId);
 | |
| 		if (tgtNodes) {
 | |
| 			powerNode(tgtNodes, 'on');
 | |
| 		}
 | |
| 	});
 | |
| 	
 | |
| 	// Power off
 | |
| 	var powerOffLnk = $('<a>Power off</a>');
 | |
| 	powerOffLnk.click(function() {
 | |
| 		var tgtNodes = getNodesChecked(nodesTableId);
 | |
| 		if (tgtNodes) {
 | |
| 			powerNode(tgtNodes, 'off');
 | |
| 		}
 | |
| 	});
 | |
| 	
 | |
| 	// Turn monitoring on
 | |
| 	var monitorOnLnk = $('<a>Monitor on</a>');
 | |
| 	monitorOnLnk.click(function() {
 | |
| 		var tgtNodes = getNodesChecked(nodesTableId);
 | |
| 		if (tgtNodes) {
 | |
| 			monitorNode(tgtNodes, 'on');
 | |
| 		}
 | |
| 	});
 | |
| 
 | |
| 	// Turn monitoring off
 | |
| 	var monitorOffLnk = $('<a>Monitor off</a>');
 | |
| 	monitorOffLnk.click(function() {
 | |
| 		var tgtNodes = getNodesChecked(nodesTableId);
 | |
| 		if (tgtNodes) {
 | |
| 			monitorNode(tgtNodes, 'off');
 | |
| 		}
 | |
| 	});
 | |
| 
 | |
| 	// Clone
 | |
| 	var cloneLnk = $('<a>Clone</a>');
 | |
| 	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 "blade":
 | |
| 		    		plugin = new bladePlugin();
 | |
| 		    		break;
 | |
| 				case "fsp":
 | |
| 					plugin = new fspPlugin();
 | |
| 					break;
 | |
| 				case "hmc":
 | |
| 					plugin = new hmcPlugin();
 | |
| 					break;
 | |
| 				case "ipmi":
 | |
| 					plugin = new ipmiPlugin();
 | |
| 					break;		
 | |
| 				case "ivm":
 | |
| 					plugin = new ivmPlugin();
 | |
| 					break;
 | |
| 				case "zvm":
 | |
| 					plugin = new zvmPlugin();
 | |
| 					break;
 | |
| 			}
 | |
| 			
 | |
| 			plugin.loadClonePage(tgtNodes[i]);
 | |
| 		}
 | |
| 	});
 | |
| 
 | |
| 	// Delete
 | |
| 	var deleteLnk = $('<a>Delete</a>');
 | |
| 	deleteLnk.click(function() {
 | |
| 		var tgtNodes = getNodesChecked(nodesTableId);
 | |
| 		if (tgtNodes) {
 | |
| 			loadDeletePage(tgtNodes);
 | |
| 		}
 | |
| 	});
 | |
| 
 | |
| 	// Unlock
 | |
| 	var unlockLnk = $('<a>Unlock</a>');
 | |
| 	unlockLnk.click(function() {
 | |
| 		var tgtNodes = getNodesChecked(nodesTableId);
 | |
| 		if (tgtNodes) {
 | |
| 			loadUnlockPage(tgtNodes);
 | |
| 		}
 | |
| 	});
 | |
| 
 | |
| 	// Run script
 | |
| 	var scriptLnk = $('<a>Run script</a>');
 | |
| 	scriptLnk.click(function() {
 | |
| 		var tgtNodes = getNodesChecked(nodesTableId);
 | |
| 		if (tgtNodes) {
 | |
| 			loadScriptPage(tgtNodes);
 | |
| 		}
 | |
| 	});
 | |
| 
 | |
| 	// Update
 | |
| 	var updateLnk = $('<a>Update</a>');
 | |
| 	updateLnk.click(function() {
 | |
| 		var tgtNodes = getNodesChecked(nodesTableId);
 | |
| 		if (tgtNodes) {
 | |
| 			loadUpdatenodePage(tgtNodes);
 | |
| 		}
 | |
| 	});
 | |
| 
 | |
| 	// Set boot state
 | |
| 	var setBootStateLnk = $('<a>Set boot state</a>');
 | |
| 	setBootStateLnk.click(function() {
 | |
| 		var tgtNodes = getNodesChecked(nodesTableId);
 | |
| 		if (tgtNodes) {
 | |
| 			loadNodesetPage(tgtNodes);
 | |
| 		}
 | |
| 	});
 | |
| 
 | |
| 	// Boot to network
 | |
| 	var boot2NetworkLnk = $('<a>Boot to network</a>');
 | |
| 	boot2NetworkLnk.click(function() {
 | |
| 		var tgtNodes = getNodesChecked(nodesTableId);
 | |
| 		if (tgtNodes) {
 | |
| 			loadNetbootPage(tgtNodes);
 | |
| 		}
 | |
| 	});
 | |
| 	
 | |
| 	// Provision node
 | |
| 	var provisionLnk = $('<a>Provision</a>');
 | |
| 	provisionLnk.click(function() {
 | |
| 	    var tgtNodes = getNodesChecked(nodesTableId);
 | |
| 	    if (tgtNodes){
 | |
| 	        // Jump directly to the provision page
 | |
| 	        jump2Provision(tgtNodes);
 | |
| 	    }
 | |
| 	});
 | |
| 
 | |
| 	// Remote console
 | |
| 	var rcons = $('<a>Open console</a>');
 | |
| 	rcons.bind('click', function(event){
 | |
| 		var tgtNodes = getNodesChecked(nodesTableId);
 | |
| 		if (tgtNodes) {
 | |
| 			loadRconsPage(tgtNodes);
 | |
| 		}
 | |
| 	});
 | |
| 	
 | |
| 	// Edit properties
 | |
| 	var editProps = $('<a>Edit properties</a>');
 | |
| 	editProps.bind('click', function(event){
 | |
| 		var tgtNodes = getNodesChecked(nodesTableId).split(',');
 | |
| 		for (var i in tgtNodes) {
 | |
| 			editNodeProps(tgtNodes[i]);
 | |
| 		}
 | |
| 	});
 | |
| 	
 | |
| 	// Install Ganglia
 | |
| 	var installMonLnk = $('<a>Install monitoring</a>');
 | |
| 	installMonLnk.click(function() {
 | |
| 		var tgtNodes = getNodesChecked(nodesTableId);
 | |
| 		if (tgtNodes) {
 | |
| 			installGanglia(tgtNodes);
 | |
| 		}
 | |
| 	});
 | |
| 	
 | |
| 	// Actions
 | |
| 	var actionsLnk = '<a>Actions</a>';
 | |
| 	var actsMenu = createMenu([cloneLnk, deleteLnk, monitorOnLnk, monitorOffLnk, powerOnLnk, powerOffLnk, scriptLnk]);
 | |
| 
 | |
| 	// Configurations
 | |
| 	var configLnk = '<a>Configuration</a>';
 | |
| 	var configMenu = createMenu([unlockLnk, updateLnk, editProps, installMonLnk]);
 | |
| 
 | |
| 	// Provision
 | |
| 	var provLnk = '<a>Provision</a>';
 | |
| 	var provMenu = createMenu([boot2NetworkLnk, setBootStateLnk, rcons, provisionLnk]);
 | |
| 
 | |
| 	// Create an action menu
 | |
| 	var actionsMenu = createMenu([ [ actionsLnk, actsMenu ], [ configLnk, configMenu ],  [ provLnk, provMenu ] ]);
 | |
| 	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));
 | |
| 	});
 | |
| 
 | |
| 	// Insert action bar and nodes datatable
 | |
| 	$('#nodesTab').append(nodesTable.object());
 | |
| 		
 | |
| 	// Turn table into a datatable
 | |
| 	var nodesDatatable = $('#' + nodesTableId).dataTable({
 | |
| 		'iDisplayLength': 50,
 | |
| 		'bLengthChange': false,
 | |
| 		"sScrollX": "100%",
 | |
| 		"bAutoWidth": true,
 | |
| 		"fnInitComplete": function() {
 | |
| 			adjustColumnSize(nodesTableId);
 | |
| 		}
 | |
| 	});
 | |
| 	
 | |
| 	// 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 = $('<div id="' + nodesTableId + '_menuDiv" class="menuDiv"></div>');
 | |
| 	$('#' + nodesTableId + '_wrapper').prepend(menuDiv);
 | |
| 	menuDiv.append(actionBar);	
 | |
| 	$('#' + nodesTableId + '_filter').appendTo(menuDiv);
 | |
| 	
 | |
| 	// Create tooltip for status
 | |
| 	var tooltipConf = {
 | |
| 			position: "center right",
 | |
| 			offset: [-2, 10],
 | |
| 			effect: "fade",	
 | |
| 			opacity: 0.8,
 | |
| 			relative: true,
 | |
| 			predelay: 800
 | |
| 		};
 | |
| 
 | |
| 	var pingTip = createStatusToolTip();
 | |
| 	pingCol.find('span').append(pingTip);
 | |
| 	pingCol.find('span a').tooltip(tooltipConf);
 | |
| 	
 | |
| 	// Create tooltip for power
 | |
| 	var powerTip = createPowerToolTip();
 | |
| 	powerCol.find('span').append(powerTip);
 | |
| 	powerCol.find('span a').tooltip(tooltipConf);
 | |
| 	
 | |
| 	// Create tooltip for monitor
 | |
| 	var monitorTip = createMonitorToolTip();
 | |
| 	monitorCol.find('span').append(monitorTip);
 | |
| 	monitorCol.find('span a').tooltip(tooltipConf);
 | |
| 	
 | |
| 	/**
 | |
| 	 * 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 make changes, return the value directly
 | |
| 		    // jeditable saves 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).parents('.dataTables_scroll').find('.dataTables_scrollHead thead tr:eq(0) 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
 | |
|         	});
 | |
|         	
 | |
|         	// Save the data into global origAttrs
 | |
|         	origAttrs[node][attrName] = value;
 | |
| 
 | |
| 			return value;
 | |
| 		}, {
 | |
| 			onblur : 'submit', 	// Clicking outside editable area submits changes
 | |
| 			type : 'textarea',
 | |
| 			placeholder: ' ',
 | |
| 			event : "dblclick", // Double click and edit
 | |
| 			height : '30px' 	// The height of the text area
 | |
| 		});
 | |
| 	
 | |
| 	/**
 | |
| 	 * Get the node status and definable node attributes
 | |
| 	 */
 | |
| 
 | |
| 	// If request to get node status is made
 | |
| 	if (getNodeStatus) {
 | |
| 		var tgt = getNodesShown(nodesTableId);
 | |
| 		
 | |
|     	// Get node status
 | |
|     	$.ajax( {
 | |
|     		url : 'lib/cmd.php',
 | |
|     		dataType : 'json',
 | |
|     		data : {
 | |
|     			cmd : 'nodestat',
 | |
|     			tgt : tgt,
 | |
|     			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();
 | |
| 		adjustColumnSize(nodesTableId);
 | |
| 	}
 | |
| 	
 | |
| 	if (undefined == nodeAttrs){
 | |
| 		// Get definable node attributes
 | |
| 		$.ajax( {
 | |
| 			url : 'lib/cmd.php',
 | |
| 			dataType : 'json',
 | |
| 			data : {
 | |
| 				cmd : 'lsdef',
 | |
| 				tgt : '',
 | |
| 				args : '-t;node;-h',
 | |
| 				msg : ''
 | |
| 			},
 | |
| 
 | |
| 			success : setNodeAttrs
 | |
| 		});
 | |
| 	}
 | |
| 	
 | |
| 	/**
 | |
|      * Additional ajax requests need to be made for zVM
 | |
|      * load advanced information based on hardware architecture 
 | |
|      */
 | |
| 	advancedLoad(group);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Get nodes currently shown in datatable
 | |
|  * 
 | |
|  * @param tableId
 | |
|  *            Datatable ID
 | |
|  * @return String of nodes shown
 | |
|  */
 | |
| function getNodesShown(tableId) {
 | |
| 	// String of nodes shown
 | |
| 	var shownNodes = '';
 | |
| 	
 | |
| 	// Get rows of shown nodes
 | |
| 	var nodes = $('#' + tableId + ' tbody tr');
 | |
| 				
 | |
| 	// Go through each row
 | |
| 	var cols;
 | |
| 	for (var i = 0; i < nodes.length; i++) {
 | |
| 		// Get second column containing node name
 | |
| 		cols = nodes.eq(i).find('td');
 | |
| 		shownNodes += cols.eq(1).text() + ',';
 | |
| 	}
 | |
| 	
 | |
| 	// Remove last comma
 | |
| 	shownNodes = shownNodes.substring(0, shownNodes.length-1);
 | |
| 	return shownNodes;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Get attributes for nodes not yet initialized
 | |
|  * 
 | |
|  * @param group
 | |
|  *            Group name
 | |
|  * @return Nothing
 | |
|  */
 | |
| function getNodeAttrs(group) {	
 | |
| 	// Get datatable headers and rows
 | |
| 	var headers = $('#' + nodesTableId).parents('.dataTables_scroll').find('.dataTables_scrollHead thead tr:eq(0) th');
 | |
| 	var nodes = $('#' + nodesTableId + ' tbody tr');
 | |
| 	
 | |
| 	// Find group column
 | |
| 	var head, groupsCol;
 | |
| 	for (var i = 0; i < headers.length; i++) {
 | |
| 		head = headers.eq(i).html();
 | |
| 		if (head == 'groups') {
 | |
| 			groupsCol = i;
 | |
| 			break;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	// Check if groups definition is set
 | |
| 	var node, cols;
 | |
| 	var tgtNodes = '';
 | |
| 	for (var i = 0; i < nodes.length; i++) {
 | |
| 		cols = nodes.eq(i).find('td');
 | |
| 		if (!cols.eq(groupsCol).html()) {
 | |
| 			node = cols.eq(1).text();
 | |
| 			tgtNodes += node + ',';
 | |
| 		}
 | |
| 	}
 | |
| 		
 | |
| 	// If there are node definitions to load
 | |
| 	if (tgtNodes) {
 | |
| 		// Remove last comma
 | |
| 		tgtNodes = tgtNodes.substring(0, tgtNodes.length-1);
 | |
| 				
 | |
| 		// Get node definitions
 | |
| 		$.ajax( {
 | |
| 			url : 'lib/cmd.php',
 | |
| 			dataType : 'json',
 | |
| 			data : {
 | |
| 				cmd : 'lsdef',
 | |
| 				tgt : '',
 | |
| 				args : tgtNodes,
 | |
| 				msg : group
 | |
| 			},
 | |
| 	
 | |
| 			success : addNodes2Table
 | |
| 		});
 | |
| 		
 | |
| 		// Create dialog to indicate table is updating
 | |
| 		var update = $('<div id="updatingDialog" class="ui-state-highlight ui-corner-all">' 
 | |
| 				+ '<p><span class="ui-icon ui-icon-info"></span> Updating table <img src="images/loader.gif"/></p>'
 | |
| 			+'</div>');
 | |
| 		update.dialog({
 | |
| 			modal: true,
 | |
| 			width: 300,
 | |
| 			position: 'center'
 | |
| 		});
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Add nodes to datatable
 | |
|  * 
 | |
|  * @param data
 | |
|  *            Data returned from HTTP request
 | |
|  * @return Nothing
 | |
|  */
 | |
| 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 + ' 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 four headers
 | |
| 	var headersCol = new Object();
 | |
| 	headersCol['node'] = 1;
 | |
| 	headersCol['status'] = 2;
 | |
| 	headersCol['power'] = 3;
 | |
| 	headersCol['comments'] = 4;
 | |
| 	
 | |
| 	// Go through each header
 | |
| 	for (var i = 5; 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;
 | |
| 		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], nodeRowPos, 0, 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(4);
 | |
| 		
 | |
| 		// Create tooltip
 | |
| 		var icon = $('<img id="' + tipID + '" src="' + iconSrc + '"></img>').css({
 | |
| 			'width': '18px',
 | |
| 			'height': '18px'
 | |
| 		});
 | |
| 		
 | |
| 		var tip = createCommentsToolTip(comments);
 | |
| 		var span = $('<span></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('close');
 | |
| 	
 | |
| 	/**
 | |
| 	 * 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
 | |
|  * @return Nothing
 | |
|  */
 | |
| function loadGangliaStatus(data) {
 | |
| 	// Get datatable
 | |
| 	var datatable = $('#' + nodesTableId).dataTable();
 | |
| 	var ganglia = data.rsp;
 | |
| 	var rowNum, node, status, args;
 | |
| 
 | |
| 	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
 | |
|  * @return Nothing
 | |
|  */
 | |
| 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
 | |
|  * @return Nothing
 | |
|  */
 | |
| 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, false);
 | |
| 	}
 | |
| 	
 | |
| 	// 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
 | |
|  * @return Nothing
 | |
|  */
 | |
| 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
 | |
|  * @return Nothing
 | |
|  */
 | |
| 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
 | |
|  * @return Nothing
 | |
|  */
 | |
| 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
 | |
|  * @return Nothing
 | |
|  */
 | |
| 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 "blade":
 | |
|     		plugin = new bladePlugin();
 | |
|     		break;
 | |
| 		case "fsp":
 | |
| 			plugin = new fspPlugin();
 | |
| 			break;
 | |
| 		case "hmc":
 | |
| 			plugin = new hmcPlugin();
 | |
| 			break;
 | |
| 		case "ipmi":
 | |
| 			plugin = new ipmiPlugin();
 | |
| 			break;		
 | |
| 		case "ivm":
 | |
| 			plugin = new ivmPlugin();
 | |
| 			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(node + 'Processes', 0);
 | |
| 
 | |
| 	// Add new tab, only if one does not exist
 | |
| 	var loader = createLoader(newTabId + 'TabLoader');
 | |
| 	loader = $('<center></center>').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
 | |
|  * @return Nothing
 | |
|  */
 | |
| 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;
 | |
| 	}
 | |
| 
 | |
| 	var unlockForm = $('<div class="form"></div>');
 | |
| 
 | |
| 	// Create status bar, hide on load
 | |
| 	var statBarId = 'unlockStatusBar' + instance;
 | |
| 	var statusBar = createStatusBar(statBarId).hide();
 | |
| 	unlockForm.append(statusBar);
 | |
| 
 | |
| 	// Create loader
 | |
| 	var loader = createLoader('');
 | |
| 	statusBar.find('div').append(loader);
 | |
| 
 | |
| 	// Create info bar
 | |
| 	var infoBar = createInfoBar('Give the root password for this node range to setup its SSH keys.');
 | |
| 	unlockForm.append(infoBar);
 | |
| 
 | |
| 	unlockForm.append('<div><label>Target node range:</label><input type="text" id="node" name="node" readonly="readonly" value="' + tgtNodes + '" title="The node or node range to unlock"/></div>');
 | |
| 	unlockForm.append('<div><label>Password:</label><input type="password" id="password" name="password" title="The root password to unlock this node"/></div>');
 | |
| 
 | |
| 	// 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 okBtn = createButton('Ok');
 | |
| 	okBtn.click(function() {
 | |
| 		// Remove any warning messages
 | |
| 		$(this).parent().parent().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
 | |
|     		statusBar.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).parent().parent());
 | |
| 			password.css('border', 'solid #FF0000 1px');
 | |
|     	}
 | |
|     });
 | |
| 
 | |
| 	unlockForm.append(okBtn);
 | |
| 	tab.add(newTabId, 'Unlock', unlockForm, true);
 | |
| 	tab.select(newTabId);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Load script page
 | |
|  * 
 | |
|  * @param tgtNodes
 | |
|  *            Targets to run script against
 | |
|  * @return Nothing
 | |
|  */
 | |
| 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;
 | |
| 	}
 | |
| 
 | |
| 	// Open new tab
 | |
| 	// Create remote script form
 | |
| 	var scriptForm = $('<div class="form"></div>');
 | |
| 
 | |
| 	// Create status bar
 | |
| 	var barId = 'scriptStatusBar' + inst;
 | |
| 	var statBar = createStatusBar(barId);
 | |
| 	statBar.hide();
 | |
| 	scriptForm.append(statBar);
 | |
| 
 | |
| 	// Create loader
 | |
| 	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);
 | |
| 
 | |
| 	// Target node or group
 | |
| 	var tgt = $('<div><label for="target">Target node range:</label><input type="text" name="target" value="' + tgtNodes + '" title="The node or node range to run a given script against"/></div>');
 | |
| 	scriptForm.append(tgt);
 | |
| 
 | |
| 	// Upload file
 | |
| 	var upload = $('<form action="lib/upload.php" method="post" enctype="multipart/form-data"></form>');
 | |
| 	var label = $('<label for="file">Remote file:</label>');
 | |
| 	var file = $('<input type="file" name="file" id="file"/>');
 | |
| 	var subBtn = createButton('Load');
 | |
| 	upload.append(label);
 | |
| 	upload.append(file);
 | |
| 	upload.append(subBtn);
 | |
| 	scriptForm.append(upload);
 | |
| 	
 | |
| 	// Generate tooltips
 | |
| 	scriptForm.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"
 | |
| 		}
 | |
| 	});
 | |
| 
 | |
| 	// Script
 | |
| 	var script = $('<div><label>Script:</label><textarea/>');
 | |
| 	scriptForm.append(script);
 | |
| 
 | |
| 	// Ajax form options
 | |
| 	var options = {
 | |
| 		// Output to text area
 | |
| 		target : '#' + newTabId + ' textarea'
 | |
| 	};
 | |
| 	upload.ajaxForm(options);
 | |
| 
 | |
| 	/**
 | |
| 	 * Run
 | |
| 	 */
 | |
| 	var runBtn = createButton('Run');
 | |
| 	runBtn.click(function() {
 | |
| 		// Remove any warning messages
 | |
| 		$(this).parent().parent().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).parent().parent());
 | |
| 			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
 | |
|  * @return Nothing
 | |
|  */
 | |
| 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
 | |
|  * @return Nothing
 | |
|  */
 | |
| 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 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();
 | |
| 
 | |
| 	// 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 = $('<div class="form"></div>');
 | |
| 	deleteForm.append(statBar);
 | |
| 	deleteForm.append(statBar);
 | |
| 	
 | |
| 	// Confirm delete
 | |
| 	var instr = $('<p>Are you sure you want to delete ' + tgtNodesStr + '?</p>').css('word-wrap', 'break-word');
 | |
| 	deleteForm.append(instr);
 | |
| 
 | |
| 	/**
 | |
| 	 * Delete
 | |
| 	 */
 | |
| 	var deleteBtn = createButton('Delete');
 | |
| 	deleteBtn.click(function() {
 | |
| 		// Delete the virtual server
 | |
| 		$.ajax( {
 | |
| 			url : 'lib/cmd.php',
 | |
| 			dataType : 'json',
 | |
| 			data : {
 | |
| 				cmd : 'rmvm',
 | |
| 				tgt : tgtNodes,
 | |
| 				args : '',
 | |
| 				msg : 'out=' + statBarId + ';cmd=rmvm;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);
 | |
| 	deleteForm.append(cancelBtn);
 | |
| 	myTab.add(newTabId, 'Delete', deleteForm, true);
 | |
| 
 | |
| 	myTab.select(newTabId);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Update status bar of a given tab
 | |
|  * 
 | |
|  * @param data
 | |
|  *            Data returned from HTTP request
 | |
|  * @return Nothing
 | |
|  */
 | |
| 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;
 | |
| 		}
 | |
| 
 | |
| 		// 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], '#' + nodesTableId, 1);
 | |
| 				dTable.fnDeleteRow(rowPos);
 | |
| 			}
 | |
| 		}
 | |
| 	} else if (cmd == 'xdsh') {
 | |
| 		// Hide loader
 | |
| 		$('#' + statBarId).find('img').hide();
 | |
| 		
 | |
| 		// Write ajax response to status bar
 | |
| 		var prg = $('<pre></pre>');
 | |
| 		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('<br>');	
 | |
| 		}
 | |
| 		$('#' + statBarId).find('div').append(prg);	
 | |
| 		
 | |
| 		// Enable fields
 | |
| 		$('#' + statBarId).parent().find('input').removeAttr('disabled');
 | |
| 		$('#' + statBarId).parent().find('textarea').removeAttr('disabled');
 | |
| 		
 | |
| 		// Enable buttons
 | |
| 		$('#' + statBarId).parent().find('button').removeAttr('disabled');
 | |
| 	} else {
 | |
| 		// Hide loader
 | |
| 		$('#' + statBarId).find('img').hide();
 | |
| 		
 | |
| 		// Write ajax response to status bar
 | |
| 		var prg = writeRsp(rsp, '[A-Za-z0-9._-]+:');	
 | |
| 		$('#' + statBarId).find('div').append(prg);	
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Update power status of a node in the datatable
 | |
|  * 
 | |
|  * @param data
 | |
|  *            Data from HTTP request
 | |
|  * @return Nothing
 | |
|  */
 | |
| 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
 | |
|  * @return Nothing
 | |
|  */
 | |
| 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;
 | |
| 	$('#' + 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
 | |
|  * @return Nothing
 | |
|  */
 | |
| 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('imagenames', imageNames);
 | |
| 
 | |
| 	// Save profiles in a cookie
 | |
| 	var tmp = new Array;
 | |
| 	for (var key in profilesHash) {
 | |
| 		tmp.push(key);
 | |
| 	}
 | |
| 	$.cookie('profiles', tmp);
 | |
| 
 | |
| 	// Save OS versions in a cookie
 | |
| 	tmp = new Array;
 | |
| 	for (var key in osVersHash) {
 | |
| 		tmp.push(key);
 | |
| 	}
 | |
| 	$.cookie('osvers', tmp);
 | |
| 
 | |
| 	// Save OS architectures in a cookie
 | |
| 	tmp = new Array;
 | |
| 	for (var key in osArchsHash) {
 | |
| 		tmp.push(key);
 | |
| 	}
 | |
| 	$.cookie('osarchs', tmp);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Set a cookie for the groups
 | |
|  * 
 | |
|  * @param data
 | |
|  *            Data from HTTP request
 | |
|  * @return Nothing
 | |
|  */
 | |
| function setGroupsCookies(data) {
 | |
| 	var rsp = data.rsp;
 | |
| 	$.cookie('groups', rsp);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * 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;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * 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){
 | |
| 	var dTable, rows, cols;
 | |
| 	
 | |
| 	// Get datatable
 | |
| 	dTable = $(table).dataTable();
 | |
| 	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 i;
 | |
| 		}
 | |
| 	}
 | |
| 	
 | |
| 	return -1;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Select all checkboxes in the datatable
 | |
|  * 
 | |
|  * @param event
 | |
|  *            Event on element
 | |
|  * @param obj
 | |
|  *            Object triggering event
 | |
|  * @return Nothing
 | |
|  */
 | |
| function selectAllCheckbox(event, obj) {
 | |
| 	// Get datatable ID
 | |
| 	// This will ascend from <input> <td> <tr> <thead> <table>
 | |
| 	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
 | |
|  * @return Nothing
 | |
|  */
 | |
| 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 += 'rconsShow.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=670,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 = $('<div class="tooltip"></div>');
 | |
| 	// Create textarea to hold comment
 | |
| 	var txtArea = $('<textarea>' + comment + '</textarea>').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 = $('<a>Save</a>').css(lnkStyle).hide();
 | |
| 	var cancelLnk = $('<a>Cancel</a>').css(lnkStyle).hide();
 | |
| 	var infoSpan = $('<span>Click to edit</span>').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 = $('<div class="tooltip"></div>').css({
 | |
| 		'width': '150px',
 | |
| 		'font-weight': 'normal'
 | |
| 	});
 | |
| 	
 | |
| 	// Create info text
 | |
| 	var info = $('<p></p>').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 = $('<a>click here</a>').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 = $('<div class="tooltip">Click here to refresh the power status</div>').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 = $('<div class="tooltip">Click here to refresh the monitoring status</div>').css({
 | |
| 		'width': '150px',
 | |
| 		'white-space': 'normal',
 | |
| 		'font-weight': 'normal'
 | |
| 	});	
 | |
| 	return toolTip;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Open dialog to configure xCAT monitor
 | |
|  * 
 | |
|  * @param data
 | |
|  *            Data returned from HTTP request
 | |
|  * @return Nothing
 | |
|  */
 | |
| function openConfXcatMon(data) {
 | |
| 	// Create info bar
 | |
| 	var info = createInfoBar('Configure the xCAT monitor. Select to enable or disable the monitor below.');
 | |
| 	var dialog = $('<div></div>');
 | |
| 	dialog.append(info);
 | |
| 	
 | |
| 	// Create status area
 | |
| 	var statusArea = $('<div></div>').css('padding-top', '10px');
 | |
| 	var label = $('<label>Status:</label>');
 | |
| 	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 = $('<span>Disabled</span>').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 = $('<span>Enabled</span>').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
 | |
|  * @return Nothing
 | |
|  */
 | |
| 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 = $('<p></p>');
 | |
| 	for (var i in out) {
 | |
| 		prg.append(tgt + ': ' + out[i] + '<br>');
 | |
| 	}
 | |
| 	
 | |
| 	info.append(prg);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Set node attributes
 | |
|  * 
 | |
|  * @param data
 | |
|  *            Data returned from HTTP request
 | |
|  * @return Nothing
 | |
|  */
 | |
| 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 set node properties page
 | |
|  * 
 | |
|  * @param tgtNode
 | |
|  *            Target node to set properties
 | |
|  * @return Nothing
 | |
|  */
 | |
| 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 = $('<div class="form"></div>');
 | |
| 
 | |
| 	// Create info bar
 | |
| 	var infoBar = createInfoBar('Choose the properties you wish to change on the node. When you are finished, click Save.');
 | |
| 	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 = $('<div></div>').css('display', 'inline-table');		
 | |
| 		label = $('<label>' + key + ':</label>').css('vertical-align', 'middle');
 | |
| 		input = $('<input type="text" value="' + value + '" title="' + nodeAttrs[key] + '"/>').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
 | |
|  * 
 | |
|  * @return Nothing
 | |
|  */
 | |
| function openSetAttrsDialog() {
 | |
| 	// Open new tab
 | |
| 	// Create set properties form
 | |
| 	var setPropsForm = $('<div class="form"></div>');
 | |
| 
 | |
| 	// Create info bar
 | |
| 	var infoBar = createInfoBar('Choose the properties you wish to change on the node. When you are finished, click Save.');
 | |
| 	setPropsForm.append(infoBar);
 | |
| 	
 | |
| 	// Create an input for each definable attribute
 | |
| 	var div, label, input, descr, value;
 | |
| 	for (var key in nodeAttrs) {
 | |
| 		value = '';
 | |
| 		
 | |
| 		// Create label and input for attribute
 | |
| 		div = $('<div></div>').css('display', 'inline');
 | |
| 		label = $('<label>' + key + ':</label>').css('vertical-align', 'middle');
 | |
| 		input = $('<input type="text" value="' + value + '" title="' + nodeAttrs[key] + '"/>').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,
 | |
| 		height: 400,
 | |
| 		width: 700,
 | |
| 		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 += '<br>' + 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
 | |
|  * @return Nothing
 | |
|  */
 | |
| 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
 | |
| 				 * @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 += '<br>' + 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
 | |
|  * @return Nothing
 | |
|  */
 | |
| 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
 | |
|  * @return Nothing
 | |
|  */
 | |
| 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;
 | |
|     }
 | |
| 
 | |
|     var args;
 | |
|     for (var h in hcps) {
 | |
|         // Get node without domain name
 | |
|         args = h.split('.');
 | |
|         
 | |
|         // If there are no disk pools or network names cookie for this hcp
 | |
|         if (!$.cookie(args[0] + 'diskpools') || !$.cookie(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
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Jump to provision page onclick
 | |
|  * 
 | |
|  * @param tgtNodes
 | |
|  * 			Target nodes
 | |
|  * @return Nothing
 | |
|  */
 | |
| function jump2Provision(tgtNodes){
 | |
|     var nodeArray = tgtNodes.split(',');
 | |
|     var nodeName = '';
 | |
|     var index = 0;
 | |
|     var archType = '';
 | |
|     var errorMsg = '';
 | |
|     var master = '';
 | |
|     var tftpserver = '';
 | |
|     var nfsserver = '';
 | |
|     var diaDiv = $('<div title="Provision (only supported for Linux)" class="form" id="deployDiv"></div>');
 | |
|     
 | |
|     // 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 (0 == index) {
 | |
|             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!<br/>';
 | |
|             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!<br/>';
 | |
|             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,
 | |
|             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;
 | |
| } |