/**
 * Global variables
 */
var gangliaTableId = 'nodesDatatable';
var gangliaNodesList;

/**
 * Load Ganglia monitoring tool
 * 
 * @return Nothing
 */
function loadGangliaMon() {
	// Get Ganglia tab
	var gangliaTab = $('#gangliamon');

	// Check whether Ganglia RPMs are installed on the xCAT MN
	$.ajax({
		url : 'lib/systemcmd.php',
		dataType : 'json',
		data : {
			cmd : 'rpm -q rrdtool ganglia-gmetad ganglia-gmond ganglia-web'
		},

		success : checkGangliaRPMs
	});

	// Create groups and nodes DIV
	var groups = $('<div id="groups"></div>');
	var nodes = $('<div id="nodes"></div>');
	gangliaTab.append(groups);
	gangliaTab.append(nodes);

	// Create info bar
	var info = createInfoBar('Select a group to view its nodes');
	nodes.append(info);

	// Get groups
	$.ajax( {
		url : 'lib/cmd.php',
		dataType : 'json',
		data : {
			cmd : 'extnoderange',
			tgt : '/.*',
			args : 'subgroups',
			msg : ''
		},

		success : loadGroups4Ganglia
	});

	return;
}

/**
 * Check whether Ganglia RPMs are installed
 * 
 * @param data
 *            Data returned from HTTP request
 * @return Nothing
 */
function checkGangliaRPMs(data) {
	var gangliaTab = $('#gangliamon');

	// Get the list of Ganglia RPMs installed
	var status = data.rsp.split(/\n/);
	var gangliaRPMs = [ "rrdtool", "ganglia-gmetad", "ganglia-gmond", "ganglia-web" ];
	var warningMsg = 'Before continuing, please install the following packages: ';
	var missingRPMs = false;
	for ( var i in status) {
		if (status[i].indexOf("not installed") > -1) {
			warningMsg += gangliaRPMs[i] + ' ';
			missingRPMs = true;
		}
	}

	// Append Ganglia PDF
	if (missingRPMs) {
		warningMsg += ". Refer to <a href='http://xcat.svn.sourceforge.net/viewvc/xcat/xcat-core/trunk/xCAT-client/share/doc/xCAT2-Monitoring.pdf'>xCAT2-Monitoring.pdf</a> for more information.";

		var warningBar = createWarnBar(warningMsg);
		warningBar.css('margin-bottom', '10px');
		warningBar.prependTo(gangliaTab);
	} else {
		// Check if ganglia is running on the xCAT MN
		$.ajax( {
			url : 'lib/cmd.php',
			dataType : 'json',
			data : {
				cmd : 'monls',
				tgt : '',
				args : 'gangliamon',
				msg : ''
			},

			/**
			 * Append warning message
			 * 
			 * @param data
			 *            Data returned from HTTP request
			 * @return Nothing
			 */
			success : function(data) {
				if (data.rsp[0].indexOf("not-monitored") > -1) {
					// Create link to start Ganglia
					var startLnk = $('<a href="#">Click here</a>');
					startLnk.css( {
						'color' : 'blue',
						'text-decoration' : 'none'
					});
					startLnk.click(function() {
						// Turn on Ganglia for all nodes
						monitorNode('', 'on');
					});
		
					// Create warning bar
					var warningBar = $('<div class="ui-state-error ui-corner-all"></div>');
					var msg = $('<p></p>');
					msg.append('<span class="ui-icon ui-icon-alert"></span>');
					msg.append('Please start Ganglia Monitoring on xCAT. ');
					msg.append(startLnk);
					msg.append(' to start Ganglia Monitoring.');
					warningBar.append(msg);
					warningBar.css('margin-bottom', '10px');
		
					// If there are any warning messages, append this warning after it
					var curWarnings = $('#gangliamon').find('.ui-state-error');
					var gangliaTab = $('#gangliamon');
					if (curWarnings.length) {
						curWarnings.after(warningBar);
					} else {
						warningBar.prependTo(gangliaTab);
					}
				}
			}
		});
	}
	return;
}

/**
 * Load groups
 * 
 * @param data
 *            Data returned from HTTP request
 * @return
 */
function loadGroups4Ganglia(data) {
	// Remove loader
	$('#groups').find('img').remove();

	var groups = data.rsp;
	setGroupsCookies(data);

	// Create a list of groups
	var ul = $('<ul></ul>');
	var item = $('<li id="root"><h3>Groups</h3></li>');
	ul.append(item);
	var subUL = $('<ul></ul>');
	item.append(subUL);

	// Create a link for each group
	for ( var i = groups.length; i--;) {
		var subItem = $('<li id="' + groups[i] + '"></li>');
		var link = $('<a>' + groups[i] + '</a>');
		subItem.append(link);
		subUL.append(subItem);
	}

	// Turn groups list into a tree
	$('#groups').append(ul);
	$('#groups').jstree( {
		core : {
			"initially_open" : [ "root" ]
		},
		themes : {
			"theme" : "default",
			"dots" : false, // No dots
			"icons" : false // No icons
		}
	});

	// Load nodes onclick
	$('#groups').bind('select_node.jstree', function(event, data) {
			// If there are subgroups, remove them
			data.rslt.obj.children('ul').remove();
			var thisGroup = jQuery.trim(data.rslt.obj.text());
			if (thisGroup) {
				// Clear nodes division
			$('#nodes').children().remove();

			// Create link to Ganglia
			var gangliaLnk = $('<a href="#">click here</a>');
			gangliaLnk.css( {
				'color' : 'blue',
				'text-decoration' : 'none'
			});
			gangliaLnk.click(function() {
				// Open a new window for Ganglia
				window.open('../ganglia/');
			});

			// Create info bar
			var info = $('<div class="ui-state-highlight ui-corner-all"></div>');
			var msg = $('<p></p>');
			msg.append('<span class="ui-icon ui-icon-info"></span>');
			msg.append('Review the nodes that are monitored by Ganglia.  You can turn on Ganglia monitoring on a node by selecting it and clicking on Monitor. If you are satisfied with the nodes you want to monitor, ');
			msg.append(gangliaLnk);
			msg.append(' to open Ganglia page.');
			info.append(msg);
			info.css('margin-bottom', '10px');
			$('#nodes').append(info);

			// Create loader
			var loader = $('<center></center>').append(createLoader());

			// Create a tab for this group
			var tab = new Tab();
			setNodesTab(tab);
			tab.init();
			$('#nodes').append(tab.object());
			tab.add('nodesTab', 'Nodes', loader, false);

			// 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 : thisGroup,
					args : '',
					msg : thisGroup
				},

				/**
				 * 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 : group
						},

						success : loadNodes4Ganglia
					});
				}
			});
						
			// Get subgroups within selected group
			// only when this is the parent group and not a subgroup
			if (data.rslt.obj.attr('id').indexOf('Subgroup') < 0) {
    			$.ajax( {
    				url : 'lib/cmd.php',
    				dataType : 'json',
    				data : {
    					cmd : 'extnoderange',
    					tgt : thisGroup,
    					args : 'subgroups',
    					msg : thisGroup
    				},
    
    				success : loadSubgroups
    			});
			}
		} // End of if (thisGroup)
	});
}

/**
 * Load nodes belonging to a given group
 * 
 * @param data
 *            Data returned from HTTP request
 * @return Nothing
 */
function loadNodes4Ganglia(data) {
	// Data returned
	var rsp = data.rsp;
	// Group name
	var group = data.msg;
	// Node attributes hash
	var attrs = new Object();
	// Node attributes
	var headers = new Object();

	// Variable to send command and request node status
	var getNodeStatus = true;
	
	var node, args;
	for ( var i in rsp) {
		// Get the node
		var pos = rsp[i].indexOf('Object name:');
		if (pos > -1) {
			var temp = rsp[i].split(': ');
			node = jQuery.trim(temp[1]);

			// Create a hash for the node attributes
			attrs[node] = new Object();
			i++;
		}

		// Get key and value
		args = rsp[i].split('=', 2);
		var key = jQuery.trim(args[0]);
		var val = jQuery.trim(rsp[i].substring(rsp[i].indexOf('=') + 1, rsp[i].length));
		
		// Create a hash table
		attrs[node][key] = val;
		headers[key] = 1;
		
		// If the node status is available
		if (key == 'status') {
			// Do not send command to 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];
		}
	}
	
	// Sort headers
	var sorted = new Array();
	for ( var key in headers) {
		// Do not put comments and status in
		if (key != 'usercomment' && key != 'status' && key.indexOf('statustime') < 0) {
			sorted.push(key);
		}
	}
	sorted.sort();

	// Add column for check box, node, ping, and power
	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>', 
		'<a>ganglia</a><img src="images/loader.gif"></img>');

	// Create a datatable
	var gangliaTable = new DataTable(gangliaTableId);
	gangliaTable.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, and power
		row.push(checkBx, nodeLink, status, '', '');

		// Go through each header
		for ( var i = 5; i < sorted.length; i++) {
			// Add the node attributes to the row
			var key = sorted[i];
			
			// Do not put comments and status in
			if (key != 'usercomment' && key != 'status' && key.indexOf('statustime') < 0) {
    			var val = attrs[node][key];
    			if (val) {
    				row.push(val);
    			} else {
    				row.push('');
    			}
			}
		}

		// Add the row to the table
		gangliaTable.add(row);
	}
	
	// Clear the tab before inserting the table
	$('#nodesTab').children().remove();

	// Create action bar
	var actionBar = $('<div class="actionBar"></div>');

	/**
	 * The following actions are available to perform against a given node:
	 * power and monitor
	 */

	/*
	 * Power
	 */
	var powerLnk = $('<a>Power</a>');

	// Power on
	var powerOnLnk = $('<a>Power on</a>');
	powerOnLnk.click(function() {
		var tgtNodes = getNodesChecked(gangliaTableId);
		if (tgtNodes) {
			powerNode(tgtNodes, 'on');
		}
	});

	// Power off
	var powerOffLnk = $('<a>Power off</a>');
	powerOffLnk.click(function() {
		var tgtNodes = getNodesChecked(gangliaTableId);
		if (tgtNodes) {
			powerNode(tgtNodes, 'off');
		}
	});

	// Power actions
	var powerActions = [ powerOnLnk, powerOffLnk ];
	var powerActionMenu = createMenu(powerActions);

	/*
	 * Monitor
	 */
	var monitorLnk = $('<a>Monitor</a>');

	// Turn monitoring on
	var monitorOnLnk = $('<a>Monitor on</a>');
	monitorOnLnk.click(function() {
		var tgtNodes = getNodesChecked(gangliaTableId);
		if (tgtNodes) {
			monitorNode(tgtNodes, 'on');
		}
	});

	// Turn monitoring off
	var monitorOffLnk = $('<a>Monitor off</a>');
	monitorOffLnk.click(function() {
		var tgtNodes = getNodesChecked(gangliaTableId);
		if (tgtNodes) {
			monitorNode(tgtNodes, 'off');
		}
	});

	// Power actions
	var monitorActions = [ monitorOnLnk, monitorOffLnk ];
	var monitorActionMenu = createMenu(monitorActions);

	// Create an action menu
	var actionsDIV = $('<div></div>');
	var actions = [ [ powerLnk, powerActionMenu ], [ monitorLnk, monitorActionMenu ] ];
	var actionMenu = createMenu(actions);
	actionMenu.superfish();
	actionsDIV.append(actionMenu);
	actionBar.append(actionsDIV);
	$('#nodesTab').append(actionBar);

	// Insert table
	$('#nodesTab').append(gangliaTable.object());

	// Turn table into a datatable
	var gangliaDataTable = $('#' + gangliaTableId).dataTable({
		'iDisplayLength': 50
	});
	
	// Filter table when enter key is pressed
	$('#' + gangliaTableId + '_filter input').unbind();
	$('#' + gangliaTableId + '_filter input').bind('keyup', function(e){
		if (e.keyCode == 13) {
			var table = $('#' + gangliaTableId).dataTable();
			table.fnFilter($(this).val());
			
			// If there are nodes found, get the node attributes
			if (!$('#' + gangliaTableId + ' .dataTables_empty').length) {
				getNodeAttrs4Ganglia(group);
			}
		}
	});
	
	// Load node definitions when next or previous buttons are clicked
	$('#' + gangliaTableId + '_next, #' + gangliaTableId + '_previous').click(function() {
		getNodeAttrs4Ganglia(group);
	});

	// Do not sort ping, power, and comment column
	var cols = $('#' + gangliaTableId + ' thead tr th').click(function() {		
		getNodeAttrs4Ganglia(group);
	});
	var pingCol = $('#' + gangliaTableId + ' thead tr th').eq(2);
	var powerCol = $('#' + gangliaTableId + ' thead tr th').eq(3);
	var gangliaCol = $('#' + gangliaTableId + ' thead tr th').eq(4);
	pingCol.unbind('click');
	powerCol.unbind('click');
	gangliaCol.unbind('click');

	// Create enough space for loader to be displayed
	var style = {'min-width': '60px', 'text-align': 'center'};
	$('#' + gangliaTableId + ' tbody tr td:nth-child(3)').css(style);
	$('#' + gangliaTableId + ' tbody tr td:nth-child(4)').css(style);
	$('#' + gangliaTableId + ' tbody tr td:nth-child(5)').css(style);

	// Instead refresh the ping status and power status
	pingCol.find('span a').bind('click', function(event) {
		refreshNodeStatus(group, gangliaTableId);
	});
	powerCol.find('span a').bind('click', function(event) {
		refreshPowerStatus(group, gangliaTableId);
	});
	gangliaCol.bind('click', function(event) {
		refreshGangliaStatus(group);
	});
	
	// Create tooltip for status 
	var pingTip = createStatusToolTip();
	pingCol.find('span').append(pingTip);
	pingCol.find('span a').tooltip({
		position: "center right",
		offset: [-2, 10],
		effect: "fade",	
		opacity: 0.8,
		relative: true,
		predelay: 800
	});
	
	// Create tooltip for power 
	var powerTip = createPowerToolTip();
	powerCol.find('span').append(powerTip);
	powerCol.find('span a').tooltip({
		position: "center right",
		offset: [-2, 10],
		effect: "fade",	
		opacity: 0.8,
		relative: true,
		predelay: 800
	});

	/**
	 * Get node and ganglia status
	 */
	
	// If request to get node status is made
	if (getNodeStatus) {
    	// Get the node status
    	$.ajax( {
    		url : 'lib/cmd.php',
    		dataType : 'json',
    		data : {
    			cmd : 'nodestat',
    			tgt : group,
    			args : '',
    			msg : ''
    		},
    
    		success : loadNodeStatus
    	});
	} else {
		// Hide status loader
		var statCol = $('#' + gangliaTableId + ' thead tr th').eq(2);
		statCol.find('img').hide();
	}

	// Get the status of Ganglia
	var nodes = getNodesShown(gangliaTableId);
	$.ajax( {
		url : 'lib/cmd.php',
		dataType : 'json',
		data : {
			cmd : 'webrun',
			tgt : '',
			args : 'gangliastatus;' + nodes,
			msg : ''
		},

		success : loadGangliaStatus
	});
}

/**
 * Load the status of Ganglia for a given group
 * 
 * @param data
 *            Data returned from HTTP request
 * @return Nothing
 */
function loadGangliaStatus(data) {
	// Get datatable
	var datatable = $('#' + gangliaTableId).dataTable();
	var ganglia = data.rsp;
	var rowNum, node, status, args;

	for ( var i in ganglia) {
		// ganglia[0] = nodeName and ganglia[1] = state
		node = jQuery.trim(ganglia[i][0]);
		status = jQuery.trim(ganglia[i][1]);

		// Get the row containing the node
		rowNum = findRow(node, '#' + gangliaTableId, 1);

		// Update the power status column
		datatable.fnUpdate(status, rowNum, 4);
	}

	// Hide Ganglia loader
	var gangliaCol = $('#' + gangliaTableId + ' thead tr th').eq(4);
	gangliaCol.find('img').hide();
}

/**
 * Refresh the status of Ganglia for each node
 * 
 * @param group
 *            Group name
 * @return Nothing
 */
function refreshGangliaStatus(group) {
	// Show ganglia loader
	var gangliaCol = $('#' + gangliaTableId + ' thead tr th').eq(4);
	gangliaCol.find('img').show();
	
	// Get power status for nodes shown
	var nodes = getNodesShown(gangliaTableId);

	// Get the status of Ganglia
	$.ajax( {
		url : 'lib/cmd.php',
		dataType : 'json',
		data : {
			cmd : 'webrun',
			tgt : '',
			args : 'gangliastatus;' + nodes,
			msg : ''
		},

		success : loadGangliaStatus
	});
}

/**
 * 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) {
	if (monitor == 'on') {
		// Append loader to warning bar
		var gangliaLoader = createLoader('');
		var warningBar = $('#gangliamon').find('.ui-state-error p');
		if (warningBar.length) {
			warningBar.append(gangliaLoader);
		}

		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($('#nodes'));
					} else {
						$.ajax( {
							url : 'lib/cmd.php',
							dataType : 'json',
							data : {
								cmd : 'webrun',
								tgt : '',
								args : 'gangliastart;' + data.msg,
								msg : ''
							},

							success : function(data) {
								// Remove any warnings
								$('#nodes').find('.ui-state-error').remove();
								$('#gangliamon').find('.ui-state-error').remove();
							}
						});
					} // 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
					$('#gangliamon').find('.ui-state-error').remove();
				}
			});
		} // End of if (node)
	} else {
		var args;
		if (node) {
			args = 'gangliastop;' + node;
		} else {
			args = 'gangliastop';
		}

		$.ajax( {
			url : 'lib/cmd.php',
			dataType : 'json',
			data : {
				cmd : 'webrun',
				tgt : '',
				args : args,
				msg : ''
			},

			success : function(data) {
				// Do nothing
			}
		});
	}
}

/**
 * Get attributes for nodes not yet initialized
 * 
 * @param group
 *            Group name
 * @return Nothing
 */
function getNodeAttrs4Ganglia(group) {	
	// Get datatable headers and rows
	var headers = $('#' + gangliaTableId + ' thead tr th');
	var nodes = $('#' + gangliaTableId + ' 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 : addNodes2GangliaTable
		});
		
		// 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 addNodes2GangliaTable(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 = $('#' + gangliaTableId + ' 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;
		
		// 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['ganglia'] = 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 = $('#' + gangliaTableId).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('statustime') < 0) {
    			var val = attrs[node][key];
    			if (val) {
    				rows[nodeRowPos][headersCol[key]] = val;
    			}
			}
		}
		
		// Update row
		datatable.fnUpdate(rows[nodeRowPos], nodeRowPos, 0, false);
	}

	// Enable node link
	$('.node').bind('click', loadNode);

	// Close dialog for updating table
	$('.ui-dialog-content').dialog('close');
	
	// If request to get node status is made
	if (getNodeStatus) {
    	// Get the node status
    	$.ajax( {
    		url : 'lib/cmd.php',
    		dataType : 'json',
    		data : {
    			cmd : 'nodestat',
    			tgt : group,
    			args : '',
    			msg : ''
    		},
    
    		success : loadNodeStatus
    	});
	} else {
		// Hide status loader
		var statCol = $('#' + gangliaTableId + ' thead tr th').eq(2);
		statCol.find('img').hide();
	}

	// Get the status of Ganglia
	var nodes = getNodesShown(gangliaTableId);
	$.ajax( {
		url : 'lib/cmd.php',
		dataType : 'json',
		data : {
			cmd : 'webrun',
			tgt : '',
			args : 'gangliastatus;' + nodes,
			msg : ''
		},

		success : loadGangliaStatus
	});
}