# Part of the Ganglia Project, All Rights Reserved. # # Called from index.php, so cluster and xml tree vars # ($metrics, $clusters, $hosts) are set, and header.php # already called. $tpl = new TemplatePower( template("physical_view.tpl") ); $tpl->prepare(); $tpl->assign("cluster",$cluster); $clusterURL=rawurlencode($cluster); $tpl->assign("clusterURL",$clusterURL); # Assign the verbosity level. Can take the value of the 'p' CGI variable. $verbose = $physical ? $physical : 2; # The name of the variable changes based on the level. Nice. $tpl->assign("checked$verbose","checked"); # # Give the capacities of this cluster: total #CPUs, Memory, Disk, etc. # $CPUs = __reduce("cpu_num", __sum, $cluster); # Divide by 1024^2 to get Memory in GB. $Memory = sprintf("%.1f GB",__reduce("mem_total", __sum, $cluster)/(float)1048576); $Disk = __reduce("disk_total", __sum, $cluster); $Disk = $Disk ? sprintf("%.1f GB", $Disk) : "Unknown"; list($MostFull,$name) = __reduce("part_max_used", __max, $cluster); $tpl->assign("CPUs", $CPUs); $tpl->assign("Memory", $Memory); $tpl->assign("Disk", $Disk); # Show which node has the most full disk. $nameurl=rawurlencode($name); $state = $hosts[$cluster][$name] ? "UP" : "DOWN"; $MostFull = $MostFull ? "$MostFull% Used" : "Unknown"; $tpl->assign("MostFull", $MostFull); #------------------------------------------------------------------------------- # Alternate between even and odd row styles. function rowStyle() { static $style; if ($style == "even") { $style = "odd"; } else { $style = "even"; } return $style; } #------------------------------------------------------------------------------- # Displays a rack and all its nodes. function showrack($ID) { global $verbose, $racks, $metrics, $cluster, $clusterURL, $tpl, $clusters; # An array of [Metrics][Hostname][NAME|VAL|TYPE|UNITS|SOURCE]. $M=$metrics[$cluster]; if ($ID>=0) { $tpl->assign("RackID","Rack $ID"); } # # Scalar helps choose a load color. The lower it is, the easier to get red. # The highest level occurs at a load of (loadscalar*10). $loadscalar=0.2; # A string of node HTML for the template. $nodes=""; foreach ($racks[$ID] as $node) { $name=$node[0]; $state=$node[1]; # The metrics we need for this node. # A megabyte of memory is 1024 KB. This differs from hard drives, where # one MB = 1000 bytes. Everyone agree this is a bad double-standard? $mem_totalMB = intval(intval($M[mem_total][$name][VAL])/1024); $load_one=$M[load_one][$name][VAL]; $cpu_speed=$M[cpu_speed][$name][VAL]; # Choose load color. $cpu_num=$M[cpu_num][$name][VAL]; if (!$cpu_num) { $cpu_num=1; } $loadindex=intval($load_one/($loadscalar*$cpu_num))+1; # 10 is currently the highest allowed load index. $load= $loadindex > 10 ? "L10" : "L$loadindex"; # # The nested tables are to get the formatting. Insane. # We have three levels of verbosity. At L3 we show # everything; at L1 we only show name and load. # # The levels are like HTML tags, we don't tie oursevles # down to what they exactly mean. The levels are flexible, # and may mean different things depending on how you are # viewing them. # $rowclass = ($state=="UP") ? rowStyle() : "down"; $nameurl=rawurlencode($name); $nodes .= "". "". "
$name 
\n"; $hardware = "$cpu_num x $cpu_speedMhz, $mem_totalMBMB"; # # What to show in verbosity level 2. # if ($verbose==2) { $info = $hardware; } else if ($verbose > 2) { $clustertime=$clusters[$cluster][LOCALTIME]; $heartbeat=$M[reported][$name][VAL]; $age = $clustertime - $heartbeat; $age .= "s"; $info = "Last heartbeat $age ago"; } # # Load box. # $nodes .= "
". "". "
$load_one". "
"; if ($verbose>1) { $nodes .= "
$info"; } $nodes .= "
\n"; # # The node hardware. # if ($verbose>2) { $nodes .= $hardware; } $nodes .= "\n"; $tpl->assign("nodes",$nodes); } } #------------------------------------------------------------------------------- # # My Main # # 2Key = "Rack ID / Rank (order in rack)" = [hostname, UP|DOWN] $racks; # # Make racks data structure. We try to order the nodes by their physical # location in the cluster. # # If we don't know a node's location, it goes in a negative ID rack. # $i=1; $unknownID=-1; if (is_array($hosts[$cluster])) { foreach ($hosts[$cluster] as $host=>$v) { # # Try to find the node's location in the cluster. list($rack, $rank) = findlocation($v); if ($rack>=0 and $rank>=0) { $racks[$rack][$rank]=array($v[NAME],"UP"); continue; } else { $i++; if (! ($i % 25)) { $unknownID--; } $racks[$unknownID][] = array($v[NAME],"UP"); } } } if (is_array($hosts_down[$cluster])) { foreach ($hosts_down[$cluster] as $host=>$v) { list($rack, $rank) = findlocation($v); if ($rack>=0 and $rank>=0) { $racks[$rack][$rank]=array($v[NAME],"DOWN"); continue; } else { $i++; if (! ($i % 25)) { $unknownID--; } $racks[$unknownID][] = array($v[NAME],"DOWN"); } } } # Sort the racks array. if ($unknownID<-1) { krsort($racks); } else { ksort($racks); reset($racks); while (list($rack,) = each($racks)) { # In our convention, y=0 is close to the floor. krsort($racks[$rack]); } } # # Talk about the location tag if we see alot of unlocated nodes. # $Explanation="
". "Set the LOCATION attribute (in gmond.conf) to get an ordered ". "view of this page."; if ($unknownID<-1) { $tpl->assign("Explanation",$Explanation); } # Make a $cols-wide table of Racks. $cols=5; $i=1; foreach ($racks as $rack=>$v) { $tpl->newBlock("racks"); showrack($rack); if (! ($i++ % $cols)) { $tpl->assign("tr",""); } } $tpl->printToScreen(); ?>