* * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation; only version 2 of the License is applicable. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied wadsnty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ require 'includes/collectd/config.php'; require 'includes/collectd/functions.php'; require 'includes/collectd/definitions.php'; function makeTextBlock($text, $fontfile, $fontsize, $width) { // TODO: handle explicit line-break! $words = explode(' ', $text); $lines = array($words[0]); $currentLine = 0; foreach ($words as $word) { $lineSize = imagettfbbox($fontsize, 0, $fontfile, $lines[$currentLine].' '.$word); if (($lineSize[2] - $lineSize[0]) < $width) { $lines[$currentLine] .= ' '.$word; } else { $currentLine++; $lines[$currentLine] = $word; } } error_log(sprintf('Handles message "%s", %d words => %d/%d lines', $text, count($words), $currentLine, count($lines))); return implode("\n", $lines); }//end makeTextBlock() /** * No RRD files found that could match request * @code HTTP error code * @code_msg Short text description of HTTP error code * @title Title for fake RRD graph * @msg Complete error message to display in place of graph content */ function error($code, $code_msg, $title, $msg) { global $config; header(sprintf('HTTP/1.0 %d %s', $code, $code_msg)); header('Pragma: no-cache'); header('Expires: Mon, 01 Jan 2008 00:00:00 CET'); header('Content-Type: image/png'); $w = ($config['rrd_width'] + 81); $h = ($config['rrd_height'] + 79); $png = imagecreate($w, $h); $c_bkgnd = imagecolorallocate($png, 240, 240, 240); $c_fgnd = imagecolorallocate($png, 255, 255, 255); $c_blt = imagecolorallocate($png, 208, 208, 208); $c_brb = imagecolorallocate($png, 160, 160, 160); $c_grln = imagecolorallocate($png, 114, 114, 114); $c_grarr = imagecolorallocate($png, 128, 32, 32); $c_txt = imagecolorallocate($png, 0, 0, 0); $c_etxt = imagecolorallocate($png, 64, 0, 0); if (function_exists('imageantialias')) { imageantialias($png, true); } imagefilledrectangle($png, 0, 0, $w, $h, $c_bkgnd); imagefilledrectangle($png, 51, 33, ($w - 31), ($h - 47), $c_fgnd); imageline($png, 51, 30, 51, ($h - 43), $c_grln); imageline($png, 48, ($h - 46), ($w - 28), ($h - 46), $c_grln); imagefilledpolygon($png, array(49, 30, 51, 26, 53, 30), 3, $c_grarr); imagefilledpolygon($png, array($w - 28, $h - 48, $w - 24, $h - 46, $w - 28, $h - 44), 3, $c_grarr); imageline($png, 0, 0, $w, 0, $c_blt); imageline($png, 0, 1, $w, 1, $c_blt); imageline($png, 0, 0, 0, $h, $c_blt); imageline($png, 1, 0, 1, $h, $c_blt); imageline($png, ($w - 1), 0, ($w - 1), $h, $c_brb); imageline($png, ($w - 2), 1, ($w - 2), $h, $c_brb); imageline($png, 1, ($h - 2), $w, ($h - 2), $c_brb); imageline($png, 0, ($h - 1), $w, ($h - 1), $c_brb); imagestring($png, 4, ceil(($w - strlen($title) * imagefontwidth(4)) / 2), 10, $title, $c_txt); imagestring($png, 5, 60, 35, sprintf('%s [%d]', $code_msg, $code), $c_etxt); if (function_exists('imagettfbbox') && is_file($config['error_font'])) { // Detailled error message $errorfont = $config['error_font']; $fmt_msg = makeTextBlock($msg, $errorfont, 10, ($w - 86)); $fmtbox = imagettfbbox(12, 0, $errorfont, $fmt_msg); imagettftext($png, 10, 0, 55, (35 + 3 + imagefontwidth(5) - $fmtbox[7] + $fmtbox[1]), $c_txt, $errorfont, $fmt_msg); } else { imagestring($png, 4, 53, (35 + 6 + imagefontwidth(5)), $msg, $c_txt); } imagepng($png); imagedestroy($png); }//end error() /** * No RRD files found that could match request */ function error404($title, $msg) { return error(404, 'Not found', $title, $msg); }//end error404() function error500($title, $msg) { return error(500, 'Not found', $title, $msg); }//end error500() /** * Incomplete / invalid request */ function error400($title, $msg) { return error(400, 'Bad request', $title, $msg); }//end error400() // Process input arguments // $host = read_var('host', $_GET, null); $host = $device['hostname']; if (is_null($host)) { return error400('?/?-?/?', 'Missing host name'); } elseif (!is_string($host)) { return error400('?/?-?/?', 'Expecting exactly 1 host name'); } elseif (strlen($host) == 0) { return error400('?/?-?/?', 'Host name may not be blank'); } $plugin = read_var('c_plugin', $_GET, null); if (is_null($plugin)) { return error400($host.'/?-?/?', 'Missing plugin name'); } elseif (!is_string($plugin)) { return error400($host.'/?-?/?', 'Plugin name must be a string'); } elseif (strlen($plugin) == 0) { return error400($host.'/?-?/?', 'Plugin name may not be blank'); } $pinst = read_var('c_plugin_instance', $_GET, ''); if (!is_string($pinst)) { return error400($host.'/'.$plugin.'-?/?', 'Plugin instance name must be a string'); } $type = read_var('c_type', $_GET, ''); if (is_null($type)) { return error400($host.'/'.$plugin.(strlen($pinst) ? '-'.$pinst : '').'/?', 'Missing type name'); } elseif (!is_string($type)) { return error400($host.'/'.$plugin.(strlen($pinst) ? '-'.$pinst : '').'/?', 'Type name must be a string'); } elseif (strlen($type) == 0) { return error400($host.'/'.$plugin.(strlen($pinst) ? '-'.$pinst : '').'/?', 'Type name may not be blank'); } $tinst = read_var('c_type_instance', $_GET, ''); $graph_identifier = $host.'/'.$plugin.(strlen($pinst) ? '-'.$pinst : '').'/'.$type.(strlen($tinst) ? '-'.$tinst : '-*'); $timespan = read_var('timespan', $_GET, $config['timespan'][0]['name']); $timespan_ok = false; foreach ($config['timespan'] as &$ts) { if ($ts['name'] == $timespan) { $timespan_ok = true; } } if (!$timespan_ok) { return error400($graph_identifier, 'Unknown timespan requested'); } $logscale = (boolean) read_var('logarithmic', $_GET, false); $tinylegend = (boolean) read_var('tinylegend', $_GET, false); // Check that at least 1 RRD exists for the specified request $all_tinst = collectd_list_tinsts($host, $plugin, $pinst, $type); if (count($all_tinst) == 0) { return error404($graph_identifier, 'No rrd file found for graphing'); } // Now that we are read, do the bulk work load_graph_definitions($logscale, $tinylegend); $pinst = strlen($pinst) == 0 ? null : $pinst; $tinst = strlen($tinst) == 0 ? null : $tinst; $opts = array(); $opts['timespan'] = $timespan; if ($logscale) { $opts['logarithmic'] = 1; } if ($tinylegend) { $opts['tinylegend'] = 1; } $rrd_cmd = false; if (isset($MetaGraphDefs[$type])) { $identifiers = array(); foreach ($all_tinst as &$atinst) { $identifiers[] = collectd_identifier($host, $plugin, $type, is_null($pinst) ? '' : $pinst, $atinst); } collectd_flush($identifiers); $rrd_cmd = $MetaGraphDefs[$type]($host, $plugin, $pinst, $type, $all_tinst, $opts); } else { if (!in_array(is_null($tinst) ? '' : $tinst, $all_tinst)) { return error404($host.'/'.$plugin.(!is_null($pinst) ? '-'.$pinst : '').'/'.$type.(!is_null($tinst) ? '-'.$tinst : ''), 'No rrd file found for graphing'); } collectd_flush(collectd_identifier($host, $plugin, $type, is_null($pinst) ? '' : $pinst, is_null($tinst) ? '' : $tinst)); if (isset($GraphDefs[$type])) { $rrd_cmd = collectd_draw_generic($timespan, $host, $plugin, $type, $pinst, $tinst); } else { $rrd_cmd = collectd_draw_rrd($host, $plugin, $type, $pinst, $tinst); } } if (isset($rrd_cmd)) { if ($_GET['from']) { $from = mres($_GET['from']); } if ($_GET['to']) { $to = mres($_GET['to']); } $rrd_cmd .= ' -s '.$from.' -e '.$to; } if ($_GET['legend'] == 'no') { $rrd_cmd .= ' -g '; } if ($height < '99') { $rrd_cmd .= ' --only-graph '; } if ($width <= '300') { $rrd_cmd .= ' --font LEGEND:7:'.$config['mono_font'].' --font AXIS:6:'.$config['mono_font'].' '; } else { $rrd_cmd .= ' --font LEGEND:8:'.$config['mono_font'].' --font AXIS:7:'.$config['mono_font'].' '; } if (isset($_GET['debug'])) { header('Content-Type: text/plain; charset=utf-8'); printf("Would have executed:\n%s\n", $rrd_cmd); return 0; } elseif ($rrd_cmd) { header('Content-Type: image/png'); header('Cache-Control: max-age=60'); $rt = 0; passthru($rrd_cmd, $rt); if ($rt !== 0) { return error500($graph_identifier, 'RRD failed to generate the graph: '.$rt); } return $rt; } else { return error500($graph_identifier, 'Failed to tell RRD how to generate the graph'); }