.
[corvix.git] / var / deb-package / meta / corvix-cluster / opt / cluster / lib / www / ganglia / functions.php
blob94d092bcdd90098adb70d63c951c94ee3fd5f564
1 <?php
4 # Some common functions for the Ganglia PHP website.
5 # Assumes the Gmeta XML tree has already been parsed,
6 # and the global variables $metrics, $clusters, and $hosts
7 # have been set.
10 #-------------------------------------------------------------------------------
11 # Allows a form of inheritance for template files.
12 # If a file does not exist in the chosen template, the
13 # default is used. Cuts down on code duplication.
14 function template ($name)
16 global $template_name;
18 $fn = "./templates/$template_name/$name";
19 $default = "./templates/default/$name";
21 if (file_exists($fn)) {
22 return $fn;
24 else {
25 return $default;
29 #-------------------------------------------------------------------------------
30 # Creates a hidden input field in a form. Used to save CGI variables.
31 function hiddenvar ($name, $var)
34 $hidden = "";
35 if ($var) {
36 #$url = rawurlencode($var);
37 $hidden = "<input type=\"hidden\" name=\"$name\" value=\"$var\">\n";
39 return $hidden;
42 #-------------------------------------------------------------------------------
43 # Gives a readable time string, from a "number of seconds" integer.
44 # Often used to compute uptime.
45 function uptime($uptimeS)
47 $uptimeD=intval($uptimeS/86400);
48 $uptimeS=$uptimeD ? $uptimeS % ($uptimeD*86400) : $uptimeS;
49 $uptimeH=intval($uptimeS/3600);
50 $uptimeS=$uptimeH ? $uptimeS % ($uptimeH*3600) : $uptimeS;
51 $uptimeM=intval($uptimeS/60);
52 $uptimeS=$uptimeM ? $uptimeS % ($uptimeM*60) : $uptimeS;
54 $s = ($uptimeD!=1) ? "s" : "";
55 return sprintf("$uptimeD day$s, %d:%02d:%02d",$uptimeH,$uptimeM,$uptimeS);
58 #-------------------------------------------------------------------------------
59 # Try to determine a nodes location in the cluster. Attempts to find the
60 # LOCATION attribute first. Requires the host attribute array from
61 # $hosts[$cluster][$name], where $name is the hostname.
62 # Returns [-1,-1,-1] if we could not determine location.
64 function findlocation($attrs)
66 $rack=$rank=$plane=-1;
68 $loc=$attrs['LOCATION'];
69 if ($loc) {
70 sscanf($loc, "%d,%d,%d", $rack, $rank, $plane);
71 #echo "Found LOCATION: $rack, $rank, $plane.<br>";
73 if ($rack<0 or $rank<0) {
74 # Try to parse the host name. Assumes a compute-<rack>-<rank>
75 # naming scheme.
76 $n=sscanf($attrs['NAME'], "compute-%d-%d", $rack, $rank);
77 $plane=0;
79 return array($rack,$rank,$plane);
83 #-------------------------------------------------------------------------------
84 function cluster_sum($name, $metrics)
86 $sum = 0;
88 foreach ($metrics as $host => $val)
90 if(isset($val[$name]['VAL'])) $sum += $val[$name]['VAL'];
93 return $sum;
96 #-------------------------------------------------------------------------------
97 function cluster_min($name, $metrics)
99 $min = "";
101 foreach ($metrics as $host => $val)
103 $v = $val[$name]['VAL'];
104 if (!is_numeric($min) or $min < $v)
106 $min = $v;
107 $minhost = $host;
110 return array($min, $minhost);
113 #-------------------------------------------------------------------------------
115 # A useful function for giving the correct picture for a given
116 # load. Scope is "node | cluster | grid". Value is 0 <= v <= 1.
117 function load_image ($scope, $value)
119 global $load_scale;
121 $scaled_load = $value / $load_scale;
122 if ($scaled_load>1.00) {
123 $image = template("images/${scope}_overloaded.jpg");
125 else if ($scaled_load>=0.75) {
126 $image = template("images/${scope}_75-100.jpg");
128 else if ($scaled_load >= 0.50) {
129 $image = template("images/${scope}_50-74.jpg");
131 else if ($scaled_load>=0.25) {
132 $image = template("images/${scope}_25-49.jpg");
134 else {
135 $image = template("images/${scope}_0-24.jpg");
138 return $image;
141 #-------------------------------------------------------------------------------
142 # A similar function that specifies the background color for a graph
143 # based on load. Quantizes the load figure into 6 sets.
144 function load_color ($value)
146 global $load_colors;
147 global $load_scale;
149 $scaled_load = $value / $load_scale;
150 if ($scaled_load>1.00) {
151 $color = $load_colors["100+"];
153 else if ($scaled_load>=0.75) {
154 $color = $load_colors["75-100"];
156 else if ($scaled_load >= 0.50) {
157 $color = $load_colors["50-75"];
159 else if ($scaled_load>=0.25) {
160 $color = $load_colors["25-50"];
162 else if ($scaled_load < 0.0)
163 $color = $load_colors["down"];
164 else {
165 $color = $load_colors["0-25"];
168 return $color;
171 #-------------------------------------------------------------------------------
173 # Just a useful function to print the HTML for
174 # the load/death of a cluster node
175 function node_image ($metrics)
177 $cpu_num = $metrics["cpu_num"]['VAL'];
178 if(!$cpu_num || $cpu_num == 0)
180 $cpu_num = 1;
182 $load_one = $metrics["load_one"]['VAL'];
183 $value = $load_one / $cpu_num;
185 # Check if the host is down
186 # RFM - Added isset() check to eliminate error messages in ssl_error_log
187 if (isset($hosts_down) and $hosts_down)
188 $image = template("images/node_dead.jpg");
189 else
190 $image = load_image("node", $value);
192 return $image;
195 #-------------------------------------------------------------------------------
197 # Finds the min/max over a set of metric graphs. Nodes is
198 # an array keyed by host names.
200 function find_limits($nodes, $metricname)
202 global $metrics, $clustername, $rrds, $rrd_dir, $start, $end;
204 if (!count($metrics))
205 return array(0, 0);
207 $firsthost = key($metrics);
209 if (array_key_exists($metricname,$metrics[$firsthost])) {
210 if ($metrics[$firsthost][$metricname]['TYPE'] == "string"
211 or $metrics[$firsthost][$metricname]['SLOPE'] == "zero")
212 return array(0,0);
214 else {
215 return array(0,0);
218 $max=0;
219 $min=0;
220 foreach ( $nodes as $host => $value )
222 $out = array();
224 $rrd_dir = "$rrds/$clustername/$host";
225 if (file_exists("$rrd_dir/$metricname.rrd")) {
226 $command = RRDTOOL . " graph - --start $start --end $end ".
227 "DEF:limits='$rrd_dir/$metricname.rrd':'sum':AVERAGE ".
228 "PRINT:limits:MAX:%.2lf ".
229 "PRINT:limits:MIN:%.2lf";
230 exec($command, $out);
231 if(isset($out[1])) {
232 $thismax = $out[1];
233 } else {
234 $thismax = NULL;
236 if (!is_numeric($thismax)) continue;
237 if ($max < $thismax) $max = $thismax;
239 $thismin=$out[2];
240 if (!is_numeric($thismin)) continue;
241 if ($min > $thismin) $min = $thismin;
242 #echo "$host: $thismin - $thismax (now $value)<br>\n";
246 return array($min, $max);
249 #-------------------------------------------------------------------------------
251 # Generates the colored Node cell HTML. Used in Physical
252 # view and others. Intended to be used to build a table, output
253 # begins with "<tr><td>" and ends the same.
254 function nodebox($hostname, $verbose, $title="", $extrarow="")
256 global $cluster, $clustername, $metrics, $hosts_up, $GHOME;
258 if (!$title) $title = $hostname;
260 # Scalar helps choose a load color. The lower it is, the easier to get red.
261 # The highest level occurs at a load of (loadscalar*10).
262 $loadscalar=0.2;
264 # An array of [NAME|VAL|TYPE|UNITS|SOURCE].
265 $m=$metrics[$hostname];
266 $up = $hosts_up[$hostname] ? 1 : 0;
268 # The metrics we need for this node.
270 # Give memory in Gigabytes. 1GB = 2^20 bytes.
271 $mem_total_gb = $m['mem_total']['VAL']/1048576;
272 $load_one=$m['load_one']['VAL'];
273 $cpu_speed=$m['cpu_speed']['VAL']/1024;
274 $cpu_num= $m['cpu_num']['VAL'];
276 # The nested tables are to get the formatting. Insane.
277 # We have three levels of verbosity. At L3 we show
278 # everything; at L1 we only show name and load.
280 $rowclass = $up ? rowStyle() : "down";
281 $host_url=rawurlencode($hostname);
282 $cluster_url=rawurlencode($clustername);
284 $row1 = "<tr><td class=$rowclass>\n".
285 "<table width=\"100%\" cellpadding=1 cellspacing=0 border=0><tr>".
286 "<td><a href=\"$GHOME/?p=$verbose&amp;c=$cluster_url&amp;h=$host_url\">".
287 "$title</a>&nbsp;<br>\n";
289 $cpus = $cpu_num > 1 ? "($cpu_num)" : "";
290 if ($up)
291 $hardware =
292 sprintf("<em>cpu: </em>%.2f<small>G</small> %s ", $cpu_speed, $cpus) .
293 sprintf("<em>mem: </em>%.2f<small>G</small>",$mem_total_gb);
294 else $hardware = "&nbsp;";
296 $row2 = "<tr><td colspan=2>";
297 if ($verbose==2)
298 $row2 .= $hardware;
299 else if ($verbose > 2) {
300 $hostattrs = $up ? $hosts_up : $hosts_down;
301 $last_heartbeat = $hostattrs[$hostname]['TN'];
302 $age = $last_heartbeat > 3600 ? uptime($last_heartbeat) :
303 "${last_heartbeat}s";
304 $row2 .= "<font size=-2>Last heartbeat $age</font>";
305 $row3 = $hardware;
309 # Load box.
311 if (!$cpu_num) $cpu_num=1;
312 $loadindex = intval($load_one / ($loadscalar*$cpu_num)) + 1;
313 # 10 is currently the highest allowed load index.
314 $load_class = $loadindex > 10 ? "L10" : "L$loadindex";
315 $row1 .= "</td><td align=right valign=top>".
316 "<table cellspacing=1 cellpadding=3 border=0><tr>".
317 "<td class=$load_class align=right><small>$load_one</small>".
318 "</td></tr></table>".
319 "</td></tr>\n";
321 # Construct cell.
322 $cell = $row1;
324 if ($extrarow)
325 $cell .= $extrarow;
327 if ($verbose>1)
328 $cell .= $row2;
330 $cell .= "</td></tr></table>\n";
331 # Tricky.
332 if ($verbose>2)
333 $cell .= $row3;
335 $cell .= "</td></tr>\n";
337 return $cell;
340 #-------------------------------------------------------------------------------
341 # Alternate between even and odd row styles.
342 function rowstyle()
344 static $style;
346 if ($style == "even") { $style = "odd"; }
347 else { $style = "even"; }
349 return $style;
352 #-------------------------------------------------------------------------------
353 # Organize hosts by rack locations.
354 # Works with or without "location" host attributes.
355 function physical_racks()
357 global $hosts_up, $hosts_down;
359 # 2Key = "Rack ID / Rank (order in rack)" = [hostname, UP|DOWN]
360 $rack = NULL;
362 # If we don't know a node's location, it goes in a negative ID rack.
363 $i=1;
364 $unknownID= -1;
365 if (is_array($hosts_up)) {
366 foreach ($hosts_up as $host=>$v) {
367 # Try to find the node's location in the cluster.
368 list($rack, $rank) = findlocation($v);
370 if ($rack>=0 and $rank>=0) {
371 $racks[$rack][$rank]=$v['NAME'];
372 continue;
374 else {
375 $i++;
376 if (! ($i % 25)) {
377 $unknownID--;
379 $racks[$unknownID][] = $v['NAME'];
383 if (is_array($hosts_down)) {
384 foreach ($hosts_down as $host=>$v) {
385 list($rack, $rank) = findlocation($v);
386 if ($rack>=0 and $rank>=0) {
387 $racks[$rack][$rank]=$v['NAME'];
388 continue;
390 else {
391 $i++;
392 if (! ($i % 25)) {
393 $unknownID--;
395 $racks[$unknownID][] = $v['NAME'];
400 # Sort the racks array.
401 if ($unknownID<-1) { krsort($racks); }
402 else {
403 ksort($racks);
404 reset($racks);
405 while (list($rack,) = each($racks)) {
406 # In our convention, y=0 is close to the floor. (Easier to wire up)
407 krsort($racks[$rack]);
411 return $racks;
414 #-------------------------------------------------------------------------------
415 # Return a version of the string which is safe for display on a web page.
416 # Potentially dangerous characters are converted to HTML entities.
417 # Resulting string is not URL-encoded.
418 function clean_string( $string )
420 return htmlentities( $string );
423 #-------------------------------------------------------------------------------
424 # If arg is a valid number, return it. Otherwise, return null.
425 function clean_number( $value )
427 return is_numeric( $value ) ? $value : null;
430 #-------------------------------------------------------------------------------
431 # Return true if string is a 3 or 6 character hex color. Return false otherwise.
432 function is_valid_hex_color( $string )
434 $return_value = false;
435 if( strlen( $string ) == 6 || strlen( $string ) == 3 ) {
436 if( preg_match( '/^[0-9a-fA-F]+$/', $string ) ) {
437 $return_value = true;
440 return $return_value;