git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/branches/2.7@11853 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
		
			
				
	
	
		
			3348 lines
		
	
	
		
			85 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			3348 lines
		
	
	
		
			85 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/**
 | 
						|
 * Global variables
 | 
						|
 */
 | 
						|
var nodesTab; // Nodes tabs
 | 
						|
var origAttrs = new Object(); // Original node attributes
 | 
						|
var nodeAttrs; // Node attributes
 | 
						|
var nodesList; // Node list
 | 
						|
var nodesTableId = 'nodesDatatable'; // Nodes datatable ID
 | 
						|
 | 
						|
/**
 | 
						|
 * 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());
 | 
						|
 | 
						|
		// 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 three tabs for nodes result
 | 
						|
 * 
 | 
						|
 * @param targetgroup
 | 
						|
 * 			The name range for nodels command
 | 
						|
 * @param cmdargs
 | 
						|
 * 			Filter arguments for nodels command
 | 
						|
 * @param message
 | 
						|
 * 			The useful information from the HTTP request
 | 
						|
 * @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));
 | 
						|
		
 | 
						|
		// 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;
 | 
						|
 | 
						|
	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);
 | 
						|
			}
 | 
						|
		}
 | 
						|
		
 | 
						|
		// Adjust column size
 | 
						|
		adjustColumnSize(nodesTableId);
 | 
						|
	} 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 += 'rcons.php';
 | 
						|
	
 | 
						|
	// Open the rcons page
 | 
						|
	window.open(redirectUrl + "?rconsnd=" + tgtNodes, '', "toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=no,width=590,height=436");
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Create a tool tip for comments
 | 
						|
 * 
 | 
						|
 * @param comment
 | 
						|
 *            Comments to be placed in a tool tip
 | 
						|
 * @return Tool tip
 | 
						|
 */
 | 
						|
function createCommentsToolTip(comment) {
 | 
						|
	// Create tooltip container
 | 
						|
	var toolTip = $('<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 on-click
 | 
						|
 * 
 | 
						|
 * @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" 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 (index == 0) {
 | 
						|
            archType = origAttrs[nodeName]['arch'];
 | 
						|
        }
 | 
						|
        
 | 
						|
        // Skip if nodes do not have same arch
 | 
						|
        if (archType != origAttrs[nodeName]['arch']){
 | 
						|
            errorMsg = 'Nodes should belong to the same arch!<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;
 | 
						|
} |