summaryrefslogtreecommitdiffstats
path: root/library/Pnp
diff options
context:
space:
mode:
Diffstat (limited to 'library/Pnp')
-rw-r--r--library/Pnp/ProvidedHook/Grapher.php274
-rw-r--r--library/Pnp/Web/Controller.php27
2 files changed, 301 insertions, 0 deletions
diff --git a/library/Pnp/ProvidedHook/Grapher.php b/library/Pnp/ProvidedHook/Grapher.php
new file mode 100644
index 0000000..2dcfbda
--- /dev/null
+++ b/library/Pnp/ProvidedHook/Grapher.php
@@ -0,0 +1,274 @@
+<?php
+
+namespace Icinga\Module\Pnp\ProvidedHook;
+
+use Icinga\Application\Config;
+use Icinga\Exception\ConfigurationError;
+use Icinga\Application\Hook\GrapherHook;
+use Icinga\Module\Monitoring\Object\MonitoredObject;
+use Icinga\Module\Monitoring\Object\Host;
+use Icinga\Module\Monitoring\Object\Service;
+use Icinga\Web\Url;
+
+class Grapher extends GrapherHook
+{
+ protected $hasPreviews = true;
+
+ protected $pnpConfig;
+
+ protected $pnpViews;
+
+ protected $configDir = '/etc/pnp4nagios';
+
+ protected $baseUrl = '/pnp4nagios';
+
+ protected function init()
+ {
+ $cfg = Config::module('pnp')->getSection('pnp4nagios');
+ $this->configDir = rtrim($cfg->get('config_dir', $this->configDir), '/');
+ $this->baseUrl = rtrim($cfg->get('base_url', $this->baseUrl), '/');
+ $this->readPnpConfig();
+ }
+
+ public function has(MonitoredObject $object)
+ {
+ if ($object instanceof Host) {
+ $service = '_HOST_';
+ } elseif ($object instanceof Service) {
+ $service = $object->service_description;
+ } else {
+ return false;
+ }
+
+ $host = $object->host_name;
+ return is_file($this->getXmlFilename($host, $service));
+ }
+
+ public function getPreviewHtml(MonitoredObject $object)
+ {
+ if (! $object->process_perfdata) {
+ return '';
+ }
+
+ // Skip preview images when missing, for local installations only
+ if (false === strpos($this->baseUrl, '://') && ! $this->has($object)) {
+ return '';
+ }
+
+ if ($object instanceof Host) {
+ $service = '_HOST_';
+ } elseif ($object instanceof Service) {
+ $service = $object->service_description;
+ } else {
+ return '';
+ }
+
+ $host = $object->host_name;
+
+ $html = '<table style="width: 100%; max-width: 40em; text-align: center;'
+ . ' font-size: 0.8em; line-height: 0.8em; table-layout: fixed">'
+ . "\n <tr>\n";
+ $viewKeys = array_reverse(array_keys($this->pnpViews));
+ foreach ($viewKeys as $view) {
+ $html .= '<th>' . htmlspecialchars($this->getViewName($view)) . "</th>\n";
+ }
+ $html .= " </tr>\n <tr>\n";
+ foreach ($viewKeys as $view) {
+ $html .= ' <td style="border-left: 1px solid #555; padding-right: 3px">'
+ . $this->getPreviewImg($host, $service, $view)
+ . "</td>\n";
+ }
+ $html .= "</tr></table>\n";
+ return $html;
+ }
+
+ // Currently unused, but would work fine. This is for tiny preview images
+ // in list views
+ public function getSmallPreviewImage($host, $service = null)
+ {
+ if ($service === null) {
+ $service = '_HOST_';
+ }
+
+ return sprintf(
+ '<img src="%s/image?host=%s&srv=%s&view=0&source=0&h=20&w=50" alt="" style="float: right" />',
+ $this->baseUrl,
+ urlencode($this->pnpClean($host)),
+ urlencode($this->pnpClean($service))
+ );
+ }
+
+ private function listAdditionalConfigFiles()
+ {
+ $files = array();
+ $base = $this->configDir . '/config';
+
+ $file = $base . '_local.php';
+ if (file_exists($file) && is_readable($file)) {
+ $files[] = $file;
+ }
+
+ $confd = $base . '.d';
+ if (is_dir($confd) && is_readable($confd)) {
+ $dh = opendir($confd);
+ while ($file === readdir($dh)) {
+ if ($file[0] === '.') continue;
+ if (substr($file, -4) !== '.php') continue;
+
+ $filename = $confd . '/' . $file;
+ if (is_file($filename) && is_readable($filename)) {
+ $files[] = $filename;
+ }
+ }
+
+ closedir($dh);
+ }
+
+ return $files;
+ }
+
+ // This reads the PNP4Nagios config and makes it's $conf available
+ private function readPnpConfig()
+ {
+ $file = $this->configDir . '/config.php';
+
+ if (! is_readable($file)) {
+ throw new ConfigurationError(
+ sprintf(
+ 'Cannot read PNP4Nagios-Web config file "%s"',
+ $file
+ )
+ );
+ }
+ if (! include($file)) {
+ throw new ConfigurationError(
+ sprintf(
+ 'Including PNP4Nagios-Web config "%s" failed',
+ $file
+ )
+ );
+ }
+
+ if (! isset($views)) {
+ $views = array();
+ }
+
+ foreach ($this->listAdditionalConfigFiles() as $file) {
+ $oldViews = $views;
+ include $file;
+ if (empty($views)) {
+ $views = $oldViews;
+ }
+ }
+
+ if (! isset($conf) || ! is_array($conf)) {
+ throw new ConfigurationError(
+ sprintf(
+ 'There is no $conf in your PNP4Nagios config file "%s"',
+ $file
+ )
+ );
+ }
+
+ if (! isset($views) || ! is_array($views)) {
+ throw new ConfigurationError(
+ sprintf(
+ 'There is no $views array in your PNP4Nagios config file "%s"',
+ $file
+ )
+ );
+ }
+
+ if (! array_key_exists('rrdbase', $conf)) {
+ throw new ConfigurationError(
+ sprintf(
+ 'There is no rrdbase in your PNP4Nagios config file "%s"',
+ $file
+ )
+ );
+ }
+ $this->pnpConfig = $conf;
+ $this->pnpViews = $views;
+ return $this;
+ }
+
+ // pnp_Core::clean
+ private function pnpClean($string)
+ {
+ if ($string === false) {
+ return null;
+ }
+ return preg_replace('~[ :/\\\]~', '_', $string);
+ }
+
+ private function getBasePath($host, $service)
+ {
+ if ($service === null) {
+ $service = '_HOST_';
+ }
+ return rtrim($this->pnpConfig['rrdbase'], '/')
+ . '/' . $this->pnpClean($host) . '/'
+ . $this->pnpClean($service);
+ }
+
+ private function getRrdFilename($host, $service)
+ {
+ return $this->getBasePath($host, $service) . '.rrd';
+ }
+
+ private function getXmlFilename($host, $service)
+ {
+ return $this->getBasePath($host, $service) . '.xml';
+ }
+
+ private function getPreviewImg($host, $service, $view)
+ {
+ $viewName = $this->getViewName($view);
+
+ $host = $this->pnpClean($host);
+ $service = $this->pnpClean($service);
+
+ $title = $service === '_HOST_' ? sprintf(
+ '%s, %s', $host, $viewName
+ ) : sprintf(
+ '%s on %s, %s', $service, $host, $viewName
+ );
+
+ $url = Url::fromPath('pnp/graph', array(
+ 'host' => $this->pnpClean($host),
+ 'srv' => $this->pnpClean($service),
+ 'view' => $view
+ ));
+ $imgUrl = sprintf(
+ '%s/image?host=%s&srv=%s&view=%d&source=0&w=120&h=30',
+ $this->baseUrl,
+ urlencode($this->pnpClean($host)),
+ urlencode($this->pnpClean($service)),
+ $view
+ );
+
+ $html = '<a href="%s" title="%s"><img src="%s" alt="%s" width="100%%" height="30" /></a>';
+
+ return sprintf(
+ $html,
+ $url,
+ htmlspecialchars($title),
+ $imgUrl,
+ htmlspecialchars(mt('pnp', 'Loading') . '...')
+ );
+ }
+
+ protected function getViewName($view)
+ {
+ return mt('pnp4nagios', $this->pnpViews[$view]['title']);
+ }
+
+ private function unusedFunctionAllowingToTranslateForeignStrings()
+ {
+ mt('pnp4nagios', '4 Hours');
+ mt('pnp4nagios', '25 Hours');
+ mt('pnp4nagios', 'One Week');
+ mt('pnp4nagios', 'One Month');
+ mt('pnp4nagios', 'One Year');
+ }
+}
diff --git a/library/Pnp/Web/Controller.php b/library/Pnp/Web/Controller.php
new file mode 100644
index 0000000..4af5c06
--- /dev/null
+++ b/library/Pnp/Web/Controller.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace Icinga\Module\Pnp\Web;
+
+use Icinga\Web\Controller as IcingaController;
+
+class Controller extends IcingaController
+{
+ public function init()
+ {
+ $this->getTabs()->add('pnp', array(
+ 'label' => $this->translate('PNP'),
+ 'url' => 'pnp',
+ ));
+ }
+
+ protected function setViewScript($name)
+ {
+ $this->_helper->viewRenderer->setNoController(true);
+ $this->_helper->viewRenderer->setScriptAction($name);
+ }
+
+ protected function getBaseUrl()
+ {
+ return rtrim($this->Config()->get('pnp4nagios', 'base_url', '/pnp4nagios'), '/');
+ }
+}