integrate ganglia into xcat gui
git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@10247 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
This commit is contained in:
		| @@ -713,11 +713,16 @@ table a:hover { | ||||
|  | ||||
| .monitorsumdiv { | ||||
| 	width: 300px; | ||||
| 	height: 150px; | ||||
| 	height: 180px; | ||||
| 	float: left; | ||||
| 	margin: 0px 0px 10px 0px; | ||||
| 	margin: 0px 0px 10px 10px; | ||||
| } | ||||
|  | ||||
| .monitorsumdiv td{ | ||||
| 	padding: 0; | ||||
| 	border-style: none; | ||||
| 	font-size: 10px; | ||||
| } | ||||
| .monitornodediv { | ||||
| 	width: 240px; | ||||
| 	height: 120px; | ||||
|   | ||||
							
								
								
									
										83
									
								
								xCAT-UI/ganglianode.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								xCAT-UI/ganglianode.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | ||||
| <?php | ||||
| echo <<<EEE | ||||
| <html> | ||||
| 	<head> | ||||
| 	    <title>Node {$_GET['n']} Ganglia Report</title> | ||||
| 	    <meta content="600" http-equiv="refresh"> | ||||
| 	    <meta http-equiv="content-type" content="text/html; charset=UTF-8"/> | ||||
| 	    <link href="css/style.css" rel=stylesheet type="text/css"> | ||||
| 	    <link href="css/jquery.jqplot.css" rel=stylesheet type="text/css"> | ||||
| 	    <script type="text/javascript" src="js/jquery/jquery-1.4.4.min.js"></script> | ||||
| 	    <script type="text/javascript" src="js/jquery/jquery-ui-1.8.12.start.min.js"></script> | ||||
| 	    <script type="text/javascript" src="js/ui.js"></script> | ||||
| EEE; | ||||
| ?> | ||||
| <script type="text/javascript"> | ||||
| window.onload=function() { | ||||
|     var nodepath = $('#nodepath').val(); | ||||
|     includeJs("js/jquery/jquery.jqplot.min.js"); | ||||
|     includeJs("js/jquery/jqplot.dateAxisRenderer.min.js"); | ||||
|     includeJs("js/jquery/jqplot.dateAxisRenderer.min.js"); | ||||
|     includeJs("js/monitor/gangliamon.js"); | ||||
|     $.ajax({ | ||||
|         url : 'lib/cmd.php', | ||||
|         dataType : 'json', | ||||
|         data : { | ||||
|             cmd : 'webrun', | ||||
|             tgt : '', | ||||
|             args : 'gangliashow;' + nodepath + ';hour;_summary_', | ||||
|             msg : '' | ||||
|         }, | ||||
|          | ||||
|         success: function(data){ | ||||
|             drawNodesummary(data.rsp[0]); | ||||
|         } | ||||
|     }); | ||||
|  | ||||
| }; | ||||
|  | ||||
| function drawNodesummary(summaryString){ | ||||
| 	var nodename = $('#nodename').val(); | ||||
| 	var nodeData = new Object(); | ||||
| 	var metricArray = summaryString.split(';'); | ||||
|     var metricname = ''; | ||||
|     var valueArray = ''; | ||||
|     var position = 0; | ||||
|     var tempLength = 0; | ||||
|     for (var index = 0; index < metricArray.length; index++){ | ||||
|         position = metricArray[index].indexOf(':'); | ||||
|  | ||||
|         metricname = metricArray[index].substr(0, position); | ||||
|         nodeData[metricname] = new Array(); | ||||
|         valueArray = metricArray[index].substr(position + 1).split(','); | ||||
|         tempLength = valueArray.length; | ||||
|  | ||||
|         for (var i = 0; i < tempLength; i++){ | ||||
|             nodeData[metricname].push(Number(valueArray[i])); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     drawLoadFlot('ganglianodeload', nodename, nodeData['load_one'], nodeData['cpu_num']); | ||||
|     drawCpuFlot('ganglianodecpu', nodename, nodeData['cpu_idle']); | ||||
|     drawMemFlot('ganglianodemem', nodename, nodeData['mem_free'], nodeData['mem_total']); | ||||
| } | ||||
| </script> | ||||
| <?php | ||||
| echo <<<EEE | ||||
| 	</head> | ||||
| 	<body> | ||||
| 		<input id="nodename" type="hidden" value="{$_GET['n']}"></input> | ||||
| 		<input id="nodepath" type="hidden" value="{$_GET['p']}"></input> | ||||
| 		<div style="background-color:white;" class="tab"> | ||||
| 			<table style="border-style:none;"> | ||||
| 				<tr> | ||||
| 					<td style="padding:0;border-style:none;"><div id="ganglianodeload" class="monitorsumdiv"></div></td> | ||||
| 					<td style="padding:0;border-style:none;"><div id="ganglianodecpu" class="monitorsumdiv"></div></td> | ||||
| 					<td style="padding:0;border-style: none;"><div id="ganglianodemem" class="monitorsumdiv"></div></td> | ||||
| 				</tr> | ||||
| 			</table> | ||||
| 		</div> | ||||
| 	</body> | ||||
| </html> | ||||
| EEE; | ||||
| ?> | ||||
| @@ -1,8 +1,19 @@ | ||||
| /** | ||||
|  * Global variables | ||||
|  */ | ||||
| var gangliaTableId = 'nodesDatatable'; | ||||
| var gangliaData; | ||||
| //save grid summary data, update every one minute | ||||
| var gridData; | ||||
|  | ||||
| //save nodes path, used for getting detail from rrd file | ||||
| var nodePath = new Object(); | ||||
|  | ||||
| //save nodes current status,  | ||||
| //unknown-> -2, error->-1, warning->0 ,normal->1   which is used for sorting  | ||||
| var nodeStatus = new Object(); | ||||
|  | ||||
| //update timer | ||||
| var gangliaTimer; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Load Ganglia monitoring tool | ||||
| @@ -11,61 +22,33 @@ var gangliaData; | ||||
|  */ | ||||
| function loadGangliaMon() { | ||||
| 	// Get Ganglia tab | ||||
| 	var gangliaTab = $('#gangliamon'); | ||||
| 	$('#gangliamon').append(createInfoBar('Checking RPMs.')); | ||||
| 	 | ||||
| 	//should get the groups first | ||||
| 	if (!$.cookie('groups')){ | ||||
| 	    $.ajax( { | ||||
|             url : 'lib/cmd.php', | ||||
|             dataType : 'json', | ||||
|             data : { | ||||
|                 cmd : 'extnoderange', | ||||
|                 tgt : '/.*', | ||||
|                 args : 'subgroups', | ||||
|                 msg : '' | ||||
|             }, | ||||
|  | ||||
|             success : setGroupsCookies | ||||
|         }); | ||||
| 	} | ||||
| 	// Check whether Ganglia RPMs are installed on the xCAT MN | ||||
| 	$.ajax({ | ||||
| 		url : 'lib/systemcmd.php', | ||||
| 		dataType : 'json', | ||||
| 		data : { | ||||
| 			cmd : 'rpm -q rrdtool ganglia-gmetad ganglia-gmond ganglia-web' | ||||
| 			cmd : 'rpm -q rrdtool ganglia-gmetad ganglia-gmond' | ||||
| 		}, | ||||
|  | ||||
| 		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 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>'); | ||||
| 	info.append('<span class="ui-icon ui-icon-info" style="display: inline-block; margin: 10px 5px;"></span>'); | ||||
| 	var msg = $('<p style="display: inline-block; width: 95%;"></p>'); | ||||
| 	msg.append('Select a group to view the nodes summary. '); | ||||
| 	msg.append(gangliaLnk); | ||||
| 	msg.append(' to open the Ganglia page.'); | ||||
| 	info.append(msg); | ||||
| 	info.css('margin-bottom', '10px'); | ||||
| 	nodes.append(info); | ||||
|  | ||||
| 	// Get groups | ||||
| 	$.ajax( { | ||||
| 		url : 'lib/cmd.php', | ||||
| 		dataType : 'json', | ||||
| 		data : { | ||||
| 			cmd : 'extnoderange', | ||||
| 			tgt : '/.*', | ||||
| 			args : 'subgroups', | ||||
| 			msg : '' | ||||
| 		}, | ||||
|  | ||||
| 		success : loadGroups4Ganglia | ||||
| 	}); | ||||
|  | ||||
| 	return; | ||||
| } | ||||
|  | ||||
| @@ -78,10 +61,10 @@ function loadGangliaMon() { | ||||
|  */ | ||||
| function checkGangliaRPMs(data) { | ||||
| 	var gangliaTab = $('#gangliamon'); | ||||
|  | ||||
| 	gangliaTab.empty(); | ||||
| 	// Get the list of Ganglia RPMs installed | ||||
| 	var status = data.rsp.split(/\n/); | ||||
| 	var gangliaRPMs = [ "rrdtool", "ganglia-gmetad", "ganglia-gmond", "ganglia-web" ]; | ||||
| 	var gangliaRPMs = [ "rrdtool", "ganglia-gmetad", "ganglia-gmond"]; | ||||
| 	var warningMsg = 'Before continuing, please install the following packages: '; | ||||
| 	var missingRPMs = false; | ||||
| 	for ( var i in status) { | ||||
| @@ -99,6 +82,7 @@ function checkGangliaRPMs(data) { | ||||
| 		warningBar.css('margin-bottom', '10px'); | ||||
| 		warningBar.prependTo(gangliaTab); | ||||
| 	} else { | ||||
| 	    gangliaTab.append(createInfoBar('Checking Running status.')); | ||||
| 		// Check if ganglia is running on the xCAT MN | ||||
| 		$.ajax( { | ||||
| 			url : 'lib/cmd.php', | ||||
| @@ -110,255 +94,598 @@ function checkGangliaRPMs(data) { | ||||
| 				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); | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			success : checkGangliaRunning | ||||
| 		}); | ||||
| 	} | ||||
| 	 | ||||
| 	return; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Load groups | ||||
|  *  | ||||
|  * @param data | ||||
|  *            Data returned from HTTP request | ||||
|  * @return | ||||
|  */ | ||||
| function loadGroups4Ganglia(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 = groups.length; i--;) { | ||||
| 	    grouplist.append('<div><a href="#">' + groups[i] + '</a></div>'); | ||||
| 	} | ||||
| 	 | ||||
| 	$('#groups').append(grouplist); | ||||
| 	 | ||||
| 	// Bind the click event | ||||
| 	$('#groups .groupdiv div').bind('click', function(){ | ||||
| 		$('#nodes .jqplot-target').remove(); | ||||
| 		 | ||||
| 		// Create loader | ||||
| 		var loader = createLoader(); | ||||
| 		loader.css('padding', '5px'); | ||||
| 		$('#nodes').append(loader); | ||||
| 		 | ||||
| 	    var thisGroup = $(this).text(); | ||||
| 	    $('#groups .groupdiv div').removeClass('selectgroup'); | ||||
| 	    $(this).addClass('selectgroup'); | ||||
| 	     | ||||
| 	    $.ajax( { | ||||
| 			url : 'lib/cmd.php', | ||||
| 			dataType : 'json', | ||||
| 			data : { | ||||
| 				cmd : 'nodels', | ||||
| 				tgt : thisGroup, | ||||
| 				args : '', | ||||
| 				msg : thisGroup | ||||
| 			}, | ||||
|  | ||||
| 			/** | ||||
| 			 * Get node definitions | ||||
| 			 *  | ||||
| 			 * @param data | ||||
| 			 *            Data returned from HTTP request | ||||
| 			 * @return Nothing | ||||
| 			 */ | ||||
| 			success : function(data) { | ||||
| 				var group = data.msg; | ||||
| 									 | ||||
| 				// Get nodes definitions | ||||
| 				$.ajax( { | ||||
| 					url : 'lib/cmd.php', | ||||
| 					dataType : 'json', | ||||
| 					data : { | ||||
| 						cmd : 'nodestat', | ||||
| 						tgt : group, | ||||
| 						args : '', | ||||
| 						msg : group | ||||
| 					}, | ||||
|  | ||||
| 					success : loadGangliaSummary | ||||
| 				}); | ||||
| 			} | ||||
| 		}); | ||||
| 	}); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Load Ganglia summary page | ||||
|  * Check whether Ganglia is running | ||||
|  *  | ||||
|  * @param data | ||||
|  *            Data returned from HTTP request | ||||
|  * @return Nothing | ||||
|  */ | ||||
| function loadGangliaSummary(data) {	 | ||||
| 	// Data returned | ||||
| 	var rsp = data.rsp; | ||||
| 	// Group name | ||||
| 	var group = data.msg; | ||||
| 	// Node attributes hash | ||||
| 	var attrs = new Object(); | ||||
| 	 | ||||
| 	var node, status, args; | ||||
| 	for ( var i in rsp) { | ||||
| 		// Get key and value | ||||
| 		args = rsp[i].split(':', 2); | ||||
| 		node = jQuery.trim(args[0]); | ||||
| 		status = jQuery.trim(args[1]); | ||||
| 		 | ||||
| 		// Create a hash table | ||||
| 		attrs[node] = new Object(); | ||||
| 		attrs[node]['status'] = status;		 | ||||
| 	} | ||||
| 	 | ||||
| 	// Save node attributes hash | ||||
| 	gangliaData = attrs; | ||||
| 	 | ||||
| 	// Get the status of Ganglia | ||||
| 	// Then create pie chart for node and Ganglia status | ||||
| 	$.ajax( { | ||||
| 		url : 'lib/cmd.php', | ||||
| 		dataType : 'json', | ||||
| 		data : { | ||||
| 			cmd : 'webrun', | ||||
| 			tgt : '', | ||||
| 			args : 'gangliastatus;' + group, | ||||
| 			msg : '' | ||||
| 		}, | ||||
| function checkGangliaRunning(data){ | ||||
|     var gangliaTab = $('#gangliamon'); | ||||
|     var groupsSelectStr = ''; | ||||
|     var groupsArray = $.cookie('groups').split(','); | ||||
|     gangliaTab.empty(); | ||||
|     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'); | ||||
|         }); | ||||
|  | ||||
| 		success : loadGangliaStatus | ||||
| 	}); | ||||
| } | ||||
|         // 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'); | ||||
|  | ||||
| /** | ||||
|  * Load the status of Ganglia for a given group | ||||
|  *  | ||||
|  * @param data | ||||
|  *            Data returned from HTTP request | ||||
|  * @return Nothing | ||||
|  */ | ||||
| function loadGangliaStatus(data) { | ||||
| 	// Remove loader | ||||
| 	$('#nodes').find('img').remove(); | ||||
| 	 | ||||
| 	// Get datatable | ||||
| 	var ganglia = data.rsp; | ||||
| 	var node, ping, monitored; | ||||
|         // If there are any warning messages, append this warning after it | ||||
|         var curWarnings = $('#gangliamon').find('.ui-state-error'); | ||||
|          | ||||
|         if (curWarnings.length) { | ||||
|             curWarnings.after(warningBar); | ||||
|         } else { | ||||
|             warningBar.prependTo(gangliaTab); | ||||
|         } | ||||
|          | ||||
|         return; | ||||
|     } | ||||
|  | ||||
| 	// Count nodes that are pingable and not pingable | ||||
| 	// and nodes that are pingable and monitored by Ganglia | ||||
| 	var pingWGanglia = 0; | ||||
| 	var pingWOGanglia = 0; | ||||
| 	var noping = 0; | ||||
| 	for ( var i in ganglia) { | ||||
| 		// ganglia[0] = nodeName and ganglia[1] = state | ||||
| 		node = jQuery.trim(ganglia[i][0]); | ||||
| 		if (node) { | ||||
| 			monitored = jQuery.trim(ganglia[i][1]); | ||||
| 			ping = gangliaData[node]['status']; | ||||
| 			 | ||||
| 			// If the node is monitored, increment count | ||||
| 			if (ping == 'sshd' && monitored == 'on') { | ||||
| 				pingWGanglia++; | ||||
| 			} else if (ping == 'sshd' && monitored == 'off') { | ||||
| 				pingWOGanglia++; | ||||
| 			} else { | ||||
| 				noping++; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 		 | ||||
| 	// Create pie chart | ||||
| 	var summary = $('<div id="ganglia_sum"></div>'); | ||||
| 	$('#nodes').append(summary); | ||||
| 	 | ||||
| 	// Create pie details | ||||
| 	var details = $('<div id="ganglia_details"></div>'); | ||||
| 	$('#nodes').append(details); | ||||
| 		 | ||||
| 	var pie = [['Ping + monitored', pingWGanglia], ['Ping + not monitored', pingWOGanglia], ['Noping', noping]]; | ||||
| 	var plot = $.jqplot('ganglia_sum', | ||||
| 		[pie], { | ||||
| 	        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' | ||||
|     groupsSelectStr = '<select style="padding:0px;" id="gangliagroup">'; | ||||
|     for (var i in groupsArray){ | ||||
|         groupsSelectStr += '<option value="' + groupsArray[i] + '">' + groupsArray[i] + '</option>'; | ||||
|     } | ||||
|     groupsSelectStr += '</select>'; | ||||
|      | ||||
|     //help info | ||||
|     var helpStr = '<div class="tooltip">aaa</div>'; | ||||
|      | ||||
|     //pass checking | ||||
|     var showStr = '<h3>Grid Overview</h3><hr>' + | ||||
|                   '<div id="gangliaGridSummary"></div>' + | ||||
|                   '<h3 style="display:inline;">Nodes Current Status</h3>' + | ||||
|                   '<sup style="cursor: pointer;color:blue"> ?</sup>' + | ||||
|                   '<hr>Nodes in Group:' + groupsSelectStr + | ||||
|                   ' order by: <select id="gangliaorder" style="padding:0px;"><option value="name">Name</option>' + | ||||
|                   '<option value="asc">Ascending</option><option value="des">Descending</option></select>' + | ||||
|                   '<div id="gangliaNodes"></div>'; | ||||
|      | ||||
|     //ganglia help information | ||||
|      | ||||
|     gangliaTab.append(showStr); | ||||
|  | ||||
|     //get summary data and draw on the page | ||||
|     $('#gangliaGridSummary').append('Getting Grid summary Data.<img src="images/loader.gif"></img>'); | ||||
|     sendGridSummaryAjax(); | ||||
|      | ||||
|     //get nodes current status and draw on the page | ||||
|     $('#gangliaNodes').append('Getting ' + $('#gangliagroup').val() + ' nodes Status.<img src="images/loader.gif"></img>'); | ||||
|     sendNodeCurrentAjax(); | ||||
|      | ||||
|     //start the timer to update page per minute. | ||||
|     gangliaTimer = window.setTimeout('updateGangliaPage()', 60000); | ||||
|      | ||||
|     //bind the group select change event | ||||
|     $('#gangliagroup').bind('change', function(){ | ||||
|         var groupname = $(this).val(); | ||||
|         $('#gangliaNodes').html('Getting ' + groupname + ' nodes Status.<img src="images/loader.gif"></img>'); | ||||
|         sendNodeCurrentAjax(); | ||||
|     }); | ||||
|      | ||||
|     //bind the order select change event | ||||
|     $('#gangliaorder').bind('change', function(){ | ||||
|         drawGangliaNodesArea($(this).val()); | ||||
|     }); | ||||
|      | ||||
|     //bind the info click enent | ||||
|     $('#gangliamon sup').bind('click', function(){ | ||||
|         var helpStr = '<table>' + | ||||
|                       '<tr><td style="background:#66CD00;" width="16px"> </td><td>Normal</td></tr>' + | ||||
|                       '<tr><td style="background:#FFD700;" width="16px"> </td><td>Heavy Load</td></tr>' + | ||||
|                       '<tr><td style="background:#FF3030;" width="16px"> </td><td>Can not get status longer than 3 minutes</td></tr>' + | ||||
|                       '<tr><td style="background:#8B8B7A;" width="16px"> </td><td>Unknown</td></tr>' + | ||||
|                       '</table>'; | ||||
|         var helpDia = $('<div></div>'); | ||||
|         helpDia.append(helpStr); | ||||
|         helpDia.dialog({ | ||||
|             modal: true, | ||||
|             width: 350, | ||||
|             title: 'Node Status Help Info', | ||||
|             close: function(){$(this).remove();}, | ||||
|             buttons: { | ||||
|                 'Close': function(){ | ||||
|                     $(this).dialog('close'); | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
| 	 | ||||
| 	// Change CSS styling for legend | ||||
| 	summary.find('table').css({ | ||||
| 		'border-style': 'none' | ||||
| 	}).find('td').css({ | ||||
| 		'border-style': 'none' | ||||
| 	}); | ||||
|     }); | ||||
| } | ||||
|  | ||||
| 	// Open nodes page on-click | ||||
| 	$('#ganglia_sum').bind('jqplotDataClick', function(env, srIndex, ptIndex, data) { | ||||
| 		window.open('../xcat/index.php'); | ||||
| 	}); | ||||
| 	 | ||||
| 	// Special note | ||||
| 	// To redraw pie chart:  | ||||
| 	//     - Use chart.series[0].data[i] to reference existing data | ||||
| 	//     - Use chart.redraw() to redraw chart | ||||
| /** | ||||
|  * send ajax request to get grid summary information | ||||
|  *  | ||||
|  * @param  | ||||
|  *         | ||||
|  * @return Nothing | ||||
|  */ | ||||
| function sendGridSummaryAjax(){ | ||||
|   //get the summary data | ||||
|     $.ajax({ | ||||
|         url : 'lib/cmd.php', | ||||
|         dataType : 'json', | ||||
|         data : { | ||||
|             cmd : 'webrun', | ||||
|             tgt : '', | ||||
|             args : 'gangliashow;_grid_;hour;_summary_', | ||||
|             msg : '' | ||||
|         }, | ||||
|          | ||||
|         success: function(data){ | ||||
|             createGridSummaryData(data.rsp[0]); | ||||
|             drawGridSummary(); | ||||
|         } | ||||
|     }); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * send ajax request to get nodes current load information | ||||
|  *  | ||||
|  * @param which group name want to get | ||||
|  *         | ||||
|  * @return Nothing | ||||
|  */ | ||||
| function sendNodeCurrentAjax(){ | ||||
|     var groupname = $('#gangliagroup').val(); | ||||
|   //get all nodes current status | ||||
|     $.ajax({ | ||||
|         url : 'lib/cmd.php', | ||||
|         dataType : 'json', | ||||
|         data : { | ||||
|             cmd : 'webrun', | ||||
|             tgt : '', | ||||
|             args : 'gangliacurrent;node;' + groupname, | ||||
|             msg : '' | ||||
|         }, | ||||
|          | ||||
|         success: function(data){ | ||||
|             createNodeStatusData(data.rsp[0]); | ||||
|             drawGangliaNodesArea($('#gangliaorder').val()); | ||||
|         } | ||||
|     }); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * send ajax request to get grid current summary information for update the page | ||||
|  *  | ||||
|  * @param  | ||||
|  *         | ||||
|  * @return Nothing | ||||
|  */ | ||||
| function sendGridCurrentAjax(){ | ||||
|     //get the summary data | ||||
|     $.ajax({ | ||||
|         url : 'lib/cmd.php', | ||||
|         dataType : 'json', | ||||
|         data : { | ||||
|             cmd : 'webrun', | ||||
|             tgt : '', | ||||
|             args : 'gangliacurrent;grid', | ||||
|             msg : '' | ||||
|         }, | ||||
|          | ||||
|         success: function(data){ | ||||
|             updateGridSummaryData(data.rsp[0]); | ||||
|             drawGridSummary(); | ||||
|         } | ||||
|     }); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * save the grid summary data to local global variable | ||||
|  *  | ||||
|  * @param data structure | ||||
|  *            metric1:time11,val11,time12,val12....;metric2:time21,val21,time22,val22,...;.... | ||||
|  * @return Nothing | ||||
|  */ | ||||
| function createGridSummaryData(summaryString){ | ||||
|     //empty the global data | ||||
|     gridData = new Object(); | ||||
|      | ||||
|     var metricArray = summaryString.split(';'); | ||||
|     var metricname = ''; | ||||
|     var valueArray = ''; | ||||
|     var position = 0; | ||||
|     var tempLength = 0; | ||||
|     for (var index = 0; index < metricArray.length; index++){ | ||||
|         position = metricArray[index].indexOf(':'); | ||||
|         //get the metric name and init its global array to save timestamp and value pair | ||||
|         metricname = metricArray[index].substr(0, position); | ||||
|         gridData[metricname] = new Array(); | ||||
|         valueArray = metricArray[index].substr(position + 1).split(','); | ||||
|         tempLength = valueArray.length; | ||||
|         //save timestamp and value into global array | ||||
|         for (var i = 0; i < tempLength; i++){ | ||||
|             gridData[metricname].push(Number(valueArray[i])); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * update the grid summary data to local global variable | ||||
|  *  | ||||
|  * @param data structure | ||||
|  *            metric1:time11,val11;metric2:time21,val21,time22;.... | ||||
|  * @return Nothing | ||||
|  */ | ||||
| function updateGridSummaryData(currentString){ | ||||
|     var metricArray = currentString.split(';'); | ||||
|     var metricname = ''; | ||||
|     var position = 0; | ||||
|     var tempLength = 0; | ||||
|     var index = 0; | ||||
|     var tempArray; | ||||
|      | ||||
|     tempLength = metricArray.length; | ||||
|     for (index = 0; index < tempLength; index++){ | ||||
|         position = metricArray[index].indexOf(':'); | ||||
|         metricname = metricArray[index].substr(0, position); | ||||
|         tempArray = metricArray[index].substr(position + 1).split(','); | ||||
|         if (gridData[metricname]){ | ||||
|             gridData[metricname].shift(); | ||||
|             gridData[metricname].shift(); | ||||
|             gridData[metricname].push(Number(tempArray[0])); | ||||
|             gridData[metricname].push(Number(tempArray[1])); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| /** | ||||
|  * draw the Grid summay area by global data | ||||
|  *  | ||||
|  * @param data | ||||
|  *            Data returned from HTTP request | ||||
|  * @return Nothing | ||||
|  */ | ||||
| function drawGridSummary() { | ||||
|     var gridDrawArea = $('#gangliaGridSummary'); | ||||
|     var showStr = ''; | ||||
|     var tempStr = $('#gangliamon').attr('class'); | ||||
|      | ||||
|     //jqflot only draw on the area visiable, if the tab is hide, return directly | ||||
|     if (-1 != tempStr.indexOf('hide')){ | ||||
|         return; | ||||
|     }; | ||||
|     gridDrawArea.empty(); | ||||
|     showStr = '<table style="border-style:none;"><tr><td style="padding:0;border-style:none;"><div id="gangliasummaryload" class="monitorsumdiv"></div></td>' +  | ||||
|               '<td style="padding:0;border-style:none;"><div id="gangliasummarycpu" class="monitorsumdiv"></div></td>' + | ||||
|               '<td style="padding:0;border-style: none;"><div id="gangliasummarymem" class="monitorsumdiv"></div></td></tr></table>'; | ||||
|     gridDrawArea.append(showStr); | ||||
|     drawLoadFlot('gangliasummaryload', 'Grid', gridData['load_one'], gridData['cpu_num']); | ||||
|     drawCpuFlot('gangliasummarycpu', 'Grid', gridData['cpu_idle']); | ||||
|     drawMemFlot('gangliasummarymem', 'Grid', gridData['mem_free'], gridData['mem_total']); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * draw the load flot by data(maybe summary data, or one node's data) | ||||
|  *  | ||||
|  * @param areaid: which div draw this flot | ||||
|  *        loadpair: the load timestamp and value pair | ||||
|  *        cpupair: the cpu number and value pair | ||||
|  *             | ||||
|  * @return Nothing | ||||
|  */ | ||||
| function drawLoadFlot(areaid, titleprefix, loadpair, cpupair){ | ||||
|     var load = new Array(); | ||||
|     var cpunum = new Array(); | ||||
|     var index = 0; | ||||
|     var templength = 0; | ||||
|     var yaxismax = 0; | ||||
|     var interval = 1; | ||||
|      | ||||
|     $('#' + areaid).empty(); | ||||
|     //parse load pair, the timestamp must mutiply 1000, javascript time stamp is millisecond | ||||
|     templength = loadpair.length; | ||||
|     for (index = 0; index < templength; index += 2){ | ||||
|         load.push([loadpair[index] * 1000, loadpair[index + 1]]); | ||||
|         if (loadpair[index + 1] > yaxismax){ | ||||
|             yaxismax = loadpair[index + 1]; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     //parse cpu pair | ||||
|     templength = cpupair.length; | ||||
|     for (index = 0; index < templength; index += 2){ | ||||
|         cpunum.push([cpupair[index] * 1000, cpupair[index + 1]]); | ||||
|         if (cpupair[index + 1] > yaxismax){ | ||||
|             yaxismax = cpupair[index + 1]; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     interval = parseInt(yaxismax / 3); | ||||
|     if (interval < 1){ | ||||
|         interval = 1; | ||||
|     } | ||||
|     $.jqplot(areaid, [load, cpunum],{ | ||||
|         title: titleprefix + ' Loads/Procs Last Hour', | ||||
|         axes:{ | ||||
|             xaxis:{ | ||||
|                 renderer : $.jqplot.DateAxisRenderer, | ||||
|                 numberTicks: 4, | ||||
|                 tickOptions : { | ||||
|                     formatString : '%R', | ||||
|                     show : true | ||||
|                 } | ||||
|             }, | ||||
|             yaxis: { | ||||
|                 min : 0, | ||||
|                 tickInterval : interval | ||||
|             } | ||||
|         }, | ||||
|         legend : { | ||||
|             show: true, | ||||
|             location: 'nw' | ||||
|         }, | ||||
|         series:[{label:'Load'}, {label: 'CPU Number'}], | ||||
|         seriesDefaults : {showMarker: false} | ||||
|     }  | ||||
|     ); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * draw the cpu usage flot by data(maybe summary data, or one node's data) | ||||
|  *  | ||||
|  * @param areaid: which div draw this flot | ||||
|  *        titleprefix : title used name | ||||
|  *        cpupair: the cpu timestamp and value pair | ||||
|  *             | ||||
|  * @return Nothing | ||||
|  */ | ||||
| function drawCpuFlot(areaid, titleprefix, cpupair){ | ||||
|     var cpu = new Array(); | ||||
|     var index = 0; | ||||
|     var tempLength = 0; | ||||
|      | ||||
|     $('#' + areaid).empty(); | ||||
|     tempLength = cpupair.length; | ||||
|     // time stamp should mutiply 1000 | ||||
|     // we get the cpu idle from server, we should use 1 subtract the idle. | ||||
|     for(index = 0; index < tempLength; index +=2){ | ||||
|         cpu.push([(cpupair[index] * 1000), (100 - cpupair[index + 1])]); | ||||
|     } | ||||
|      | ||||
|     $.jqplot(areaid, [cpu],{ | ||||
|         title: titleprefix + ' Cpu Use Last Hour', | ||||
|         axes:{ | ||||
|             xaxis:{ | ||||
|                 renderer : $.jqplot.DateAxisRenderer, | ||||
|                 numberTicks: 4, | ||||
|                 tickOptions : { | ||||
|                     formatString : '%R', | ||||
|                     show : true | ||||
|                 } | ||||
|             }, | ||||
|             yaxis: { | ||||
|                 min : 0, | ||||
|                 max : 100, | ||||
|                 tickOptions:{formatString : '%d\%'} | ||||
|             } | ||||
|         }, | ||||
|         seriesDefaults : {showMarker: false} | ||||
|     }  | ||||
|     ); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * draw the memory usage flot by data(maybe summary data, or one node's data) | ||||
|  *  | ||||
|  * @param areaid: which div draw this flot | ||||
|  *        titleprefix : title used name | ||||
|  *        cpupair: the cpu timestamp and value pair | ||||
|  *             | ||||
|  * @return Nothing | ||||
|  */ | ||||
| function drawMemFlot(areaid, titleprefix, freepair, totalpair){ | ||||
|     var use = new Array(); | ||||
|     var total = new Array(); | ||||
|     var tempsize = 0; | ||||
|     var index = 0; | ||||
|      | ||||
|     $('#' + areaid).empty(); | ||||
|     if(freepair.length < totalpair.length){ | ||||
|         tempsize = freepair.length; | ||||
|     } | ||||
|     else{ | ||||
|         tempsize = freepair.length; | ||||
|     } | ||||
|      | ||||
|     for(index = 0; index < tempsize; index += 2){ | ||||
|         var temptotal = totalpair[index + 1]; | ||||
|         var tempuse = temptotal - freepair[index + 1]; | ||||
|         temptotal = temptotal / 1000000; | ||||
|         tempuse = tempuse / 1000000; | ||||
|         total.push([totalpair[index] * 1000, temptotal]); | ||||
|         use.push([freepair[index] * 1000, tempuse]); | ||||
|     } | ||||
|      | ||||
|     $.jqplot(areaid, [use, total],{ | ||||
|         title: titleprefix + ' Memory Use Last Hour', | ||||
|         axes:{ | ||||
|             xaxis:{ | ||||
|                 renderer : $.jqplot.DateAxisRenderer, | ||||
|                 numberTicks: 4, | ||||
|                 tickOptions : { | ||||
|                     formatString : '%R', | ||||
|                     show : true | ||||
|                 } | ||||
|             }, | ||||
|             yaxis: { | ||||
|                 min : 0, | ||||
|                 tickOptions:{formatString : '%.2fG'} | ||||
|             } | ||||
|         }, | ||||
|         legend : { | ||||
|             show: true, | ||||
|             location: 'nw' | ||||
|         }, | ||||
|         series:[{label:'Used'}, {label: 'Total'}], | ||||
|         seriesDefaults : {showMarker: false} | ||||
|     }  | ||||
|     ); | ||||
| } | ||||
|  | ||||
| function createNodeStatusData(nodesStatus){ | ||||
|     var index; | ||||
|     var nodesArray = nodesStatus.split(';'); | ||||
|     var position = 0; | ||||
|     var nodename = ''; | ||||
|     var index = 0; | ||||
|     var tempArray; | ||||
|     var tempStr = ''; | ||||
|     var templength = nodesArray.length; | ||||
|      | ||||
|     for (index in nodePath){ | ||||
|         delete(nodePath[index]); | ||||
|     } | ||||
|      | ||||
|     for (index in nodeStatus){ | ||||
|         delete(nodeStatus[index]); | ||||
|     } | ||||
|      | ||||
|     for (index = 0; index < templength; index++){ | ||||
|         tempStr = nodesArray[index]; | ||||
|         position = tempStr.indexOf(':'); | ||||
|         nodename = tempStr.substring(0, position); | ||||
|         tempArray = tempStr.substring(position + 1).split(','); | ||||
|          | ||||
|         switch(tempArray[0]){ | ||||
|             case 'UNKNOWN':{ | ||||
|                 nodeStatus[nodename] = -2; | ||||
|             } | ||||
|             break; | ||||
|             case 'ERROR':{ | ||||
|                 nodeStatus[nodename] = -1; | ||||
|             } | ||||
|             break; | ||||
|             case 'WARNING':{ | ||||
|                 nodeStatus[nodename] = 0; | ||||
|                 nodePath[nodename] = tempArray[1]; | ||||
|             } | ||||
|             break; | ||||
|             case 'NORMAL':{ | ||||
|                 nodeStatus[nodename] = 1; | ||||
|                 nodePath[nodename] = tempArray[1]; | ||||
|             } | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| /** | ||||
|  * draw nodes current status, there are four type: | ||||
|  *  a. unknown(gray): can not find save data for this node | ||||
|  *  b. error(red): get status sometime early, but can not get now | ||||
|  *  c. warning(orange): node are heavy load | ||||
|  *  d. normal(green):  | ||||
|  *  | ||||
|  * @param  | ||||
|  *             | ||||
|  * @return Nothing | ||||
|  */ | ||||
| function drawGangliaNodesArea(ordertype){ | ||||
|     var index = 0; | ||||
|     var templength = 0; | ||||
|     var showStr = ''; | ||||
|     var nodename = ''; | ||||
|     var sortarray = new Array(); | ||||
|     $('#gangliaNodes').html('<ul style="margin:0px;padding:0px;"></ul>'); | ||||
|     //empty the hash | ||||
|     for (index in nodeStatus){ | ||||
|         sortarray.push([index, nodeStatus[index]]); | ||||
|     } | ||||
|      | ||||
|     if ('asc' == ordertype){ | ||||
|         sortarray.sort(statusAsc); | ||||
|     } | ||||
|     else if('des' == ordertype){ | ||||
|         sortarray.sort(statusDes); | ||||
|     } | ||||
|     else{ | ||||
|         //do nothing | ||||
|     } | ||||
|      | ||||
|     templength = sortarray.length; | ||||
|     for (index = 0; index < templength; index++){ | ||||
|         nodename = sortarray[index][0]; | ||||
|         switch(sortarray[index][1]){ | ||||
|             case -2:{ | ||||
|                 showStr = '<li class="monitorunknown ui-corner-all monitornodeli" ' +  | ||||
|                         'title="' + nodename + '"></li>'; | ||||
|             } | ||||
|             break; | ||||
|             case -1:{ | ||||
|                 showStr = '<li class="monitorerror ui-corner-all monitornodeli" ' +  | ||||
|                         'title="' + nodename + '"></li>'; | ||||
|             } | ||||
|             break; | ||||
|             case 0:{ | ||||
|                 showStr = '<li class="mornitorwarning ui-corner-all monitornodeli" ' +  | ||||
|                         'title="' + nodename + '"></li>'; | ||||
|             } | ||||
|             break; | ||||
|             case 1:{ | ||||
|                 showStr = '<li class="monitornormal ui-corner-all monitornodeli" ' +  | ||||
|                         'title="' + nodename + '"></li>'; | ||||
|             } | ||||
|             break; | ||||
|         } | ||||
|         $('#gangliaNodes ul').append(showStr); | ||||
|     } | ||||
|      | ||||
|     //bind all normal and warning nodes' click event | ||||
|     $('.monitornormal,.monitorwarning').bind('click', function(){ | ||||
|         var nodename = $(this).attr('title'); | ||||
|         window.open('ganglianode.php?n=' + nodename + '&p=' + nodePath[nodename], | ||||
|                 'nodedetail','height=250,width=950,scrollbars=yes,status =no'); | ||||
|     }); | ||||
|      | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * update all tab per minute. | ||||
|  *  | ||||
|  * @param  | ||||
|  *             | ||||
|  * @return Nothing | ||||
|  */ | ||||
| function updateGangliaPage(){ | ||||
|     if ($('#gangliaNodes').size() < 1){ | ||||
|         return; | ||||
|     } | ||||
|      | ||||
|     sendGridCurrentAjax(); | ||||
|     sendNodeCurrentAjax(); | ||||
|      | ||||
|     gangliaTimer = window.setTimeout('updateGangliaPage()', 60000); | ||||
| } | ||||
|  | ||||
| function statusAsc(a, b){ | ||||
|     return a[1] - b[1]; | ||||
| } | ||||
|  | ||||
| function statusDes(a, b){ | ||||
|     return b[1] - a[1]; | ||||
| } | ||||
| @@ -14,12 +14,13 @@ use strict; | ||||
| require xCAT::Utils; | ||||
| require xCAT::MsgUtils; | ||||
| require xCAT::DBobjUtils; | ||||
| require IO::Socket::INET; | ||||
| use Getopt::Long; | ||||
| use Data::Dumper; | ||||
| use LWP::Simple; | ||||
| use xCAT::Table; | ||||
| use xCAT::NodeRange; | ||||
|  | ||||
| require XML::Parser; | ||||
| sub handled_commands { | ||||
| 	return { webrun => "web", }; | ||||
| } | ||||
| @@ -51,7 +52,9 @@ sub process_request { | ||||
| 		'updatevpd'     => \&web_updatevpd, | ||||
| 		'createimage'   => \&web_createimage, | ||||
|         'provision'     => \&web_provision, | ||||
|         'summary'       => \&web_summay | ||||
|         'summary'       => \&web_summay, | ||||
| 	    'gangliashow'  => \&web_gangliaShow, | ||||
| 	    'gangliacurrent' => \&web_gangliaLatest | ||||
| 	); | ||||
|  | ||||
| 	#check whether the request is authorized or not | ||||
| @@ -586,6 +589,287 @@ sub web_installganglia() { | ||||
| 	return; | ||||
| } | ||||
|  | ||||
| #get ganglia data from rrd file.  | ||||
| #args :  | ||||
| #	nodeRange : the nodes' name which want to get | ||||
| #	time range : which period want to get, like last hour, last day, last week ..... | ||||
| #	metric : which monitor attribute want to get, like load_one, bytes_in, bytes_out ...... | ||||
| # | ||||
| #output: (till now there are 6 metic to get at one time at most) | ||||
| #   metric1:timestamp1,value1,timestamp2,value2,.....;metric2:timestamp1,value1,timestamp2,value2,.....;.... | ||||
| sub web_gangliaShow{ | ||||
| 	my ( $request, $callback, $sub_req ) = @_; | ||||
| 	my $nodename = $request->{arg}->[1]; | ||||
| 	my $timeRange = 'now-1h'; | ||||
| 	my $resolution = 60; | ||||
| 	my $metric = $request->{arg}->[3]; | ||||
| 	my @nodes = (); | ||||
| 	my $retStr = ''; | ||||
| 	my $runInfo; | ||||
| 	my $cmd = ''; | ||||
| 	my $dirname = '/var/lib/ganglia/rrds/__SummaryInfo__/'; | ||||
| 	#get the summary for this grid(the meaning of grid is referenced from ganglia ) | ||||
| 	if ('_grid_' ne $nodename){ | ||||
| 		$dirname = '/var/lib/ganglia/rrds/' . $nodename . '/'; | ||||
| 	} | ||||
|  | ||||
| 	if ('hour' eq $request->{arg}->[2]){ | ||||
| 		$timeRange = 'now-1h'; | ||||
| 		$resolution = 60; | ||||
| 	} | ||||
| 	elsif('day' eq $request->{arg}->[2]){ | ||||
| 		$timeRange = 'now-1d'; | ||||
| 		$resolution = 1800; | ||||
| 	} | ||||
| 	 | ||||
| 	if ('_summary_' eq $metric){ | ||||
| 		my @metricArray = ('load_one', 'cpu_num', 'cpu_idle', 'mem_free', 'mem_total',); | ||||
| 		my $filename = ''; | ||||
| 		my $step = 1; | ||||
| 		my $index = 0; | ||||
| 		my $size = 0; | ||||
| 		foreach my $tempmetric (@metricArray){ | ||||
| 			my $temp = ''; | ||||
| 			my $line = ''; | ||||
| 			$retStr .= $tempmetric . ':'; | ||||
| 			$filename = $dirname . $tempmetric . '.rrd'; | ||||
| 			$cmd = "rrdtool fetch $filename -s $timeRange -r $resolution AVERAGE"; | ||||
| 			$runInfo = xCAT::Utils->runcmd($cmd, -1, 1); | ||||
| 			if (scalar(@$runInfo) < 3){ | ||||
| 				$callback->({data=>'error.'}); | ||||
| 				return; | ||||
| 			} | ||||
| 			#delete the first 2 lindes | ||||
| 			shift(@$runInfo); | ||||
| 			shift(@$runInfo); | ||||
|  | ||||
| 			#we only support 60 lines for one metric, in order to reduce the data load for web gui | ||||
| 			$size = scalar(@$runInfo); | ||||
| 			if ($size > 60){ | ||||
| 				$step = int($size / 60) + 1; | ||||
| 			} | ||||
| 			 | ||||
| 			if (($tempmetric eq 'cpu_idle') && ('_grid_' eq $nodename)){ | ||||
| 				my $cpuidle = 0; | ||||
| 				my $cpunum = 0; | ||||
| 				for($index = 0; $index < $size; $index += $step){ | ||||
| 					if ($runInfo->[$index] =~ /^(\S+): (\S+) (\S+)/){ | ||||
| 						if (($2 eq 'NaNQ') || ($2 eq 'nan')){ | ||||
| 							#the rrdtool fetch last outline line always nan, so no need to add into return string | ||||
| 							if ($index == ($size - 1)){ | ||||
| 								next; | ||||
| 							} | ||||
| 							$temp .= $1 . ',0,'; | ||||
| 						} | ||||
| 						else{ | ||||
| 							$cpuidle = sprintf "%.2f", $2; | ||||
| 							$cpunum = sprintf "%.2f", $3; | ||||
| 							$temp .= $1 . ',' . (sprintf "%.2f", $cpuidle/$cpunum) . ','; | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			else{ | ||||
| 				for($index = 0; $index < $size; $index += $step){ | ||||
| 					if ($runInfo->[$index] =~ /^(\S+): (\S+).*/){ | ||||
| 						if (($2 eq 'NaNQ') || ($2 eq 'nan')){ | ||||
| 							#the rrdtool fetch last outline line always nan, so no need to add into return string | ||||
| 							if ($index == ($size - 1)){ | ||||
| 								next; | ||||
| 							} | ||||
| 							$temp .= $1 . ',0,'; | ||||
| 						} | ||||
| 						else{ | ||||
| 							$temp .= $1 . ',' . (sprintf "%.2f", $2) . ','; | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			$retStr .= substr($temp, 0, -1) . ';'; | ||||
| 		} | ||||
| 		$retStr = substr($retStr, 0, -1); | ||||
| 		$callback->({data=>$retStr}); | ||||
| 		return; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| my $ganglia_return_flag = 0; | ||||
| my %gangliaHash; | ||||
| my $gangliaclustername; | ||||
| my $ganglianodename; | ||||
| #use socket to connect ganglia port to get the latest value/status | ||||
| sub web_gangliaLatest{ | ||||
| 	my ( $request, $callback, $sub_req ) = @_; | ||||
| 	my $type = $request->{arg}->[1]; | ||||
| 	my $groupname = ''; | ||||
| 	my $xmlparser; | ||||
| 	my $telnetcmd = ''; | ||||
| 	my $connect; | ||||
| 	my $xmloutput = ''; | ||||
|  | ||||
| 	$ganglia_return_flag = 0; | ||||
| 	$gangliaclustername = ''; | ||||
| 	$ganglianodename = ''; | ||||
| 	undef(%gangliaHash); | ||||
|  | ||||
| 	if($request->{arg}->[2]){ | ||||
| 		$groupname = $request->{arg}->[2]; | ||||
| 	} | ||||
| 	if ('grid' eq $type){ | ||||
| 		$xmlparser = XML::Parser->new(Handlers=>{Start=>\&web_gangliaGridXmlStart, End=>\&web_gangliaXmlEnd}); | ||||
| 		$telnetcmd = "/?filter=summary\n"; | ||||
| 	} | ||||
| 	elsif('node' eq $type){ | ||||
| 		$xmlparser = XML::Parser->new(Handlers=>{Start=>\&web_gangliaNodeXmlStart, End=>\&web_gangliaXmlEnd}); | ||||
| 		$telnetcmd = "/\n"; | ||||
| 	} | ||||
|  | ||||
| 	#use socket to telnet 127.0.0.1 8652(ganglia's interactive port) | ||||
| 	$connect = IO::Socket::INET->new('127.0.0.1:8652'); | ||||
| 	unless($connect){ | ||||
| 		$callback->({'data'=>'error: connect local port failed.'}); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	print $connect $telnetcmd; | ||||
| 	while(<$connect>){ | ||||
| 		$xmloutput .= $_; | ||||
| 	} | ||||
| 	close($connect); | ||||
|  | ||||
| 	$xmlparser->parse($xmloutput); | ||||
|  | ||||
| 	if ('grid' eq $type){ | ||||
| 		web_gangliaGridLatest($callback); | ||||
| 	} | ||||
| 	elsif('node' eq $type){ | ||||
| 		web_gangliaNodeLatest($callback, $groupname); | ||||
| 	} | ||||
| 	return; | ||||
| } | ||||
|  | ||||
| #create return data for grid current status | ||||
| sub web_gangliaGridLatest{ | ||||
| 	my $callback = shift; | ||||
| 	my $retStr = ''; | ||||
| 	my $timestamp = time(); | ||||
| 	if ($gangliaHash{'load_one'}){ | ||||
| 		$retStr .= 'load_one:' . $timestamp . ',' . $gangliaHash{'load_one'}->{'SUM'} . ';'; | ||||
| 	} | ||||
| 	if ($gangliaHash{'cpu_num'}){ | ||||
| 		$retStr .= 'cpu_num:' . $timestamp . ',' . $gangliaHash{'cpu_num'}->{'SUM'} . ';'; | ||||
| 	} | ||||
| 	if ($gangliaHash{'cpu_idle'}){ | ||||
| 		my $sum = $gangliaHash{'cpu_idle'}->{'SUM'}; | ||||
| 		my $num = $gangliaHash{'cpu_idle'}->{'NUM'}; | ||||
| 		$retStr .= 'cpu_idle:' . $timestamp . ',' . (sprintf("%.2f", $sum/$num )) . ';'; | ||||
| 	} | ||||
| 	if ($gangliaHash{'mem_total'}){ | ||||
| 		$retStr .= 'mem_total:' . $timestamp . ',' . $gangliaHash{'mem_total'}->{'SUM'} . ';'; | ||||
| 	} | ||||
| 	if ($gangliaHash{'mem_free'}){ | ||||
| 		$retStr .= 'mem_free:' . $timestamp . ',' . $gangliaHash{'mem_free'}->{'SUM'} . ';'; | ||||
| 	} | ||||
|  | ||||
| 	$retStr = substr($retStr, 0, -1); | ||||
| 	$callback->({data=>$retStr}); | ||||
| } | ||||
|  | ||||
| #create return data for node current status | ||||
| sub web_gangliaNodeLatest{ | ||||
| 	my ($callback, $groupname) = @_; | ||||
| 	my $node = ''; | ||||
| 	my $retStr = ''; | ||||
| 	my $timestamp = time() - 180; | ||||
| 	my @nodes; | ||||
| 	#get all nodes by group | ||||
| 	if ($groupname){ | ||||
| 		@nodes = xCAT::NodeRange::noderange($groupname, 1); | ||||
| 	} | ||||
| 	else{ | ||||
| 		@nodes = xCAT::DBobjUtils->getObjectsOfType('node'); | ||||
| 	} | ||||
| 	foreach $node(@nodes){ | ||||
| 		#if the node install the ganglia | ||||
| 		if ($gangliaHash{$node}){ | ||||
| 			my $lastupdate = $gangliaHash{$node}->{'timestamp'}; | ||||
| 			#can not get the monitor data for too long time | ||||
| 			if ($lastupdate < $timestamp){ | ||||
| 				$retStr .= $node . ':ERROR,Can not get monitor data more than 3 minutes!;'; | ||||
| 				next; | ||||
| 			} | ||||
| 			 | ||||
| 			if ($gangliaHash{$node}->{'load_one'} > $gangliaHash{$node}->{'cpu_num'}){ | ||||
| 				$retStr .= $node . ':WARNING,'; | ||||
| 			} | ||||
| 			else{ | ||||
| 				$retStr .= $node . ':NORMAL,'; | ||||
| 			} | ||||
| 			$retStr .= $gangliaHash{$node}->{'path'} . ';' | ||||
| 		} | ||||
| 		else{ | ||||
| 			$retStr .= $node . ':UNKNOWN,;' ; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	$retStr = substr($retStr, 0, -1); | ||||
| 	$callback->({data=>$retStr}); | ||||
| } | ||||
| #xml parser end function, do noting here | ||||
| sub web_gangliaXmlEnd{ | ||||
| } | ||||
|  | ||||
| #xml parser start function for grid latest value | ||||
| sub web_gangliaGridXmlStart{ | ||||
| 	my( $parseinst, $elementname, %attrs ) = @_; | ||||
| 	my $metricname = ''; | ||||
|  | ||||
| 	#only parser grid infomation | ||||
| 	if ($ganglia_return_flag){ | ||||
| 		return; | ||||
| 	} | ||||
| 	if ('METRICS' eq $elementname){ | ||||
| 		$metricname = $attrs{'NAME'}; | ||||
| 		$gangliaHash{$metricname}->{'SUM'} = $attrs{'SUM'}; | ||||
| 		$gangliaHash{$metricname}->{'NUM'} = $attrs{'NUM'}; | ||||
| 	} | ||||
| 	elsif ('CLUSTER' eq $elementname){ | ||||
| 		$ganglia_return_flag = 1; | ||||
| 		return; | ||||
| 	} | ||||
| 	else{ | ||||
| 		return; | ||||
| 	} | ||||
| 	#only need the grid summary info, if receive cluster return directly | ||||
| } | ||||
|  | ||||
| #xml parser start function for node current status | ||||
| sub web_gangliaNodeXmlStart{ | ||||
| 	my( $parseinst, $elementname, %attrs ) = @_; | ||||
| 	my $metricname = ''; | ||||
| 	#save the cluster name | ||||
| 	if('CLUSTER' eq $elementname){ | ||||
| 		$gangliaclustername = $attrs{'NAME'}; | ||||
| 		return; | ||||
| 	} | ||||
| 	elsif('HOST' eq $elementname){ | ||||
| 		if ($attrs{'NAME'} =~ /(\S+?)\.(.*)/){ | ||||
| 			$ganglianodename = $1; | ||||
| 		} | ||||
| 		else{ | ||||
| 			$ganglianodename = $attrs{'NAME'}; | ||||
| 		} | ||||
| 		$gangliaHash{$ganglianodename}->{'path'} = $gangliaclustername . '/' . $attrs{'NAME'}; | ||||
| 		$gangliaHash{$ganglianodename}->{'timestamp'} = $attrs{'REPORTED'}; | ||||
| 	} | ||||
| 	elsif('METRIC' eq $elementname){ | ||||
| 		$metricname = $attrs{'NAME'}; | ||||
| 		if (('load_one' eq $metricname) || ('cpu_num' eq $metricname)){ | ||||
| 			$gangliaHash{$ganglianodename}->{$metricname} = $attrs{'VAL'}; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| sub web_rmcmonStart { | ||||
| 	my ( $request, $callback, $sub_req ) = @_; | ||||
| 	my $nodeRange = $request->{arg}->[1]; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user