Commit 05d7e38e authored by David Kunz's avatar David Kunz

Adding upstream version 1.1.0.

Signed-off-by: David Kunz's avatarDavid Kunz <david.kunz@dknet.ch>
parent 9beee952
<!--- Provide a general summary of the issue in the Title above -->
<!-- Formatting tips:
GitHub supports Markdown: https://guides.github.com/features/mastering-markdown/
Multi-line code blocks either with three back ticks, or four space indent.
```
Stacktrace ...
<line>
<line>
```
-->
## Expected Behavior
<!--- If you're describing a bug, tell us what should happen -->
<!--- If you're suggesting a change/improvement, tell us how it should work -->
## Current Behavior
<!--- If describing a bug, tell us what happens instead of the expected behavior -->
<!--- If suggesting a change/improvement, explain the difference from current behavior -->
## Possible Solution
<!--- Not obligatory, but suggest a fix/reason for the bug, -->
<!--- or ideas how to implement: the addition or change -->
## Steps to Reproduce (for bugs)
<!--- Provide a link to a live example, or an unambiguous set of steps to -->
<!--- reproduce this bug. Include configuration, logs, etc. to reproduce, if relevant -->
1.
2.
3.
4.
## Context
<!--- How has this issue affected you? What are you trying to accomplish? -->
<!--- Providing context helps us come up with a solution that is most useful in the real world -->
## Your Environment
<!--- Include as many relevant details about the environment you experienced the problem in -->
* Module version (System - About):
* Icinga Web 2 version and modules (System - About):
* Icinga 2 version (`icinga2 --version`):
* Operating System and version:
* Webserver, PHP versions:
<markus.frosch@icinga.com> <markus.frosch@netways.de>
<markus.frosch@icinga.com> <markus@lazyfrosch.de>
<michael.friedrich@icinga.com> <michael.friedrich@netways.de>
<eric.lippmann@icinga.com> <eric.lippmann@netways.de>
<johannes.meyer@icinga.com> <johannes.meyer@netways.de>
<thomas.gelf@icinga.com> <thomas@gelf.net>
<marius.hein@icinga.com> <marius.hein@netways.de>
Eric Lippmann <eric.lippmann@icinga.com>
Johannes Meyer <johannes.meyer@icinga.com>
Lee Clemens <java@leeclemens.net>
Marius Hein <marius.hein@icinga.com>
Markus Frosch <markus.frosch@icinga.com>
Matthew Thode <mthode@mthode.org>
Michael Friedrich <michael.friedrich@icinga.com>
Mirko Nardin <mirko.nardin@gmx.net>
Thomas Gelf <thomas.gelf@icinga.com>
# Change Log
## [v1.1.0](https://github.com/Icinga/icingaweb2-module-pnp/tree/v1.1.0) (2017-08-15)
[Full Changelog](https://github.com/Icinga/icingaweb2-module-pnp/compare/v1.0.0...v1.1.0)
**Implemented enhancements:**
- \[dev.icinga.com \#9894\] missing "close-Button" in pnp4nagios Module \(Icinga Web 2 Frame\) [\#14](https://github.com/Icinga/icingaweb2-module-pnp/issues/14)
- \[dev.icinga.com \#9797\] Close button to PNP iframe [\#12](https://github.com/Icinga/icingaweb2-module-pnp/issues/12)
- Improve UI and user interaction [\#28](https://github.com/Icinga/icingaweb2-module-pnp/pull/28) ([lazyfrosch](https://github.com/lazyfrosch))
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
\ No newline at end of file
This diff is collapsed.
PNP module for Icinga Web 2
===========================
General Information
-------------------
PNP is an addon to Icinga which analyzes performance data provided by plugins
and stores them automatically into RRD-databases.
This module integrates PNP4Nagios into your
[Icinga Web 2](https://www.icinga.org/icinga/screenshots/icinga-web-2/)
frontend. It requires [PNP4Nagios](https://docs.pnp4nagios.org/)
to installed and configured.
Installation
------------
Just drop this module to a folder named `pnp` in one of your Icinga Web 2 module
directories. Then enable it in your frontend (Configuration -> Modules -> pnp
-> enable) and it should work out of the box. Check the modules config tab right
there in case you are using a customized installation instead of standard
PNP4Nagios packages.
TODO
----
We should also provide an easy way to integrate our authentication and
permission system into PNP4Nagios. This would require a small wrapper doing an
embedded Icinga Web 2 bootstrap in order to provide our user object and a list
of allowed hosts/services to PNP4Nagios.
# Release Workflow
Specify the release version.
```
VERSION=1.1.0
```
## Issues
Check issues at https://github.com/Icinga/icingaweb2-module-pnp
## Authors
Update the [.mailmap](.mailmap) and [AUTHORS](AUTHORS) files:
```
git checkout master
git log --use-mailmap | grep ^Author: | cut -f2- -d' ' | sort | uniq > AUTHORS
```
## Changelog
Update the [CHANGELOG.md](CHANGELOG.md) file.
Uses [github_changelog_generator](https://github.com/skywinder/github-changelog-generator)
```
export CHANGELOG_GITHUB_TOKEN=xxx
github_changelog_generator --future-release v$VERSION
```
Check if the file has been updated correctly.
## Git Tag
Commit these changes to the "master" branch:
```
git commit -v -a -m "Release version $VERSION"
git push origin master
```
And tag it with a signed tag:
```
git tag -s -m "Version $VERSION" v$VERSION
```
Push the tag.
```
git push --tags
```
## GitHub Release
Create a new release for the newly created Git tag.
https://github.com/Icinga/icingaweb2-module-pnp/releases
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Pnp\Controllers;
use Icinga\Web\Controller;
use Icinga\Module\Pnp\Forms\Config\GeneralConfigForm;
class ConfigController extends Controller
{
/**
* General configuration
*/
public function indexAction()
{
$this->assertPermission('config/modules');
$form = new GeneralConfigForm();
$form->setIniConfig($this->Config());
$form->handleRequest();
$this->view->form = $form;
$this->view->tabs = $this->Module()->getConfigTabs()->activate('config');
}
}
<?php
/* Icinga Web 2 | (c) 2013-2017 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Pnp\Controllers;
use Icinga\Module\Pnp\Web\Controller;
class GraphController extends Controller
{
public function indexAction()
{
$url = $this->getRequest()->getUrl();
$queryString = $url->getQueryString();
$this->view->url = sprintf(
'%s/graph?%s',
$this->getBaseUrl(),
$queryString
);
$host = $this->getParam('host');
$service = $this->getParam('srv');
$serviceTitle = '';
if ($service && $service !== '_HOST_') {
$serviceTitle = sprintf(' | %s: %s', $this->translate('Service'), $service);
}
$this->view->title = $title = sprintf('%s: %s%s',
$this->translate('Host'),
$host,
$serviceTitle
);
$this->getTabs()->add('graph', array(
'label' => $title,
'url' => $url,
))->activate('graph');
$this->setViewScript('index/iframe');
}
}
<?php
/* Icinga Web 2 | (c) 2013-2017 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Pnp\Controllers;
use Icinga\Module\Pnp\Web\Controller;
class IndexController extends Controller
{
public function indexAction()
{
$this->getTabs()->activate('pnp');
$defaultQuery = $this->Config()->get('pnp4nagios', 'default_query', 'host=.pnp-internal&srv=runtime');
$this->view->title = 'PNP';
$this->view->url = sprintf(
'%s/graph?%s',
$this->getBaseUrl(),
$defaultQuery
);
$this->setViewScript('index/iframe');
}
}
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Pnp\Forms\Config;
use Icinga\Forms\ConfigForm;
class GeneralConfigForm extends ConfigForm
{
/**
* Initialize this form
*/
public function init()
{
$this->setName('form_config_pnp4nagios_general');
$this->setSubmitLabel($this->translate('Save Changes'));
}
/**
* {@inheritdoc}
*/
public function createElements(array $formData)
{
$this->addElement(
'text',
'pnp4nagios_config_dir',
array(
'value' => '/etc/pnp4nagios',
'label' => $this->translate('PNP4Nagios configuration'),
'description' => $this->translate('PNP4Nagios configuration path name (e.g. /etc/pnp4nagios)')
)
);
$this->addElement(
'text',
'pnp4nagios_base_url',
array(
'value' => '/pnp4nagios',
'label' => $this->translate('PNP4Nagios url'),
'description' => $this->translate('The base URL of your PNP4Nagios installation (e.g. /pnp4nagios)')
)
);
$this->addElement(
'checkbox',
'pnp4nagios_menu_disabled',
array(
'label' => $this->translate('Disable menu entry'),
'description' => $this->translate('Hide PNP from main menu')
)
);
$this->addElement(
'text',
'pnp4nagios_default_query',
array(
'value' => 'host=.pnp-internal&srv=runtime',
'label' => $this->translate('Index query'),
'description' => $this->translate('Default URL query for the index view: /pnp4nagios/graph?{query}')
)
);
}
}
# Icinga Web 2 - Head for multiple monitoring backends.
# Copyright (C) 2015 Icinga Development Team
# This file is distributed under the same license as Pnp Module.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: Pnp Module (1.0.0)\n"
"Report-Msgid-Bugs-To: dev@icinga.org\n"
"POT-Creation-Date: 2015-11-17 11:56+0100\n"
"PO-Revision-Date: 2015-11-17 12:01+0100\n"
"Last-Translator: Thomas Gelf <thomas@gelf.net>\n"
"Language: de_DE\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 1.5.4\n"
#: /usr/local/icingaweb-modules/pnp/library/Pnp/ProvidedHook/Grapher.php:224
msgid "25 Hours"
msgstr "25 Stunden"
#: /usr/local/icingaweb-modules/pnp/library/Pnp/ProvidedHook/Grapher.php:223
msgid "4 Hours"
msgstr "4 Stunden"
#: /usr/local/icingaweb-modules/pnp/configuration.php:8
msgid "Config"
msgstr "Konfiguration"
#: /usr/local/icingaweb-modules/pnp/configuration.php:7
msgid "Configure this module"
msgstr "Dieses Modul konfigurieren"
#: /usr/local/icingaweb-modules/pnp/library/Pnp/ProvidedHook/Grapher.php:226
msgid "One Month"
msgstr "Ein Monat"
#: /usr/local/icingaweb-modules/pnp/library/Pnp/ProvidedHook/Grapher.php:225
msgid "One Week"
msgstr "Eine Woche"
#: /usr/local/icingaweb-modules/pnp/library/Pnp/ProvidedHook/Grapher.php:227
msgid "One Year"
msgstr "Ein Jahr"
#: /usr/local/icingaweb-modules/pnp/application/forms/Config/GeneralConfigForm.php:29
msgid "PNP4Nagios configuration"
msgstr "PNP4Nagios Konfiguration"
#: /usr/local/icingaweb-modules/pnp/application/forms/Config/GeneralConfigForm.php:30
msgid "PNP4Nagios configuration path name (e.g. /etc/pnp4nagios)"
msgstr "PNP4Nagios Konfigurationspfad (z.b. /etc/pnp4nagios)"
#: /usr/local/icingaweb-modules/pnp/application/forms/Config/GeneralConfigForm.php:38
msgid "PNP4Nagios url"
msgstr "PNP4Nagios URL"
#: /usr/local/icingaweb-modules/pnp/application/forms/Config/GeneralConfigForm.php:16
msgid "Save Changes"
msgstr "Änderungen speichern"
#: /usr/local/icingaweb-modules/pnp/application/forms/Config/GeneralConfigForm.php:39
msgid "The base URL of your PNP4Nagios installation (e.g. /pnp4nagios)"
msgstr "Basis-URL deiner PNP4Nagios installation (z.B. /pnp4nagios)"
#~ msgid ""
#~ "Configuration form is still missing in this prototype. In case your "
#~ "PNP4Nagios config path is not %s or your base PNP4Nagios web url differs "
#~ "from %s please create a config file in %s following this example:"
#~ msgstr ""
#~ "Dieser Prototyp stellt noch kein Konfigurationsformular bereit. Sollte "
#~ "dein PNP4Nagios Konfigurationspfad nicht %s sein oder deine PNP4Nagios "
#~ "URL sich von %s unterscheiden erstelle bitte unter %s eine dem folgenden "
#~ "Beispiel entprechende Konfigurationsdatei:"
# Icinga Web 2 - Head for multiple monitoring backends.
# Copyright (C) 2015 Icinga Development Team
# This file is distributed under the same license as Pnp Module.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: Pnp Module (1.0.0)\n"
"Report-Msgid-Bugs-To: dev@icinga.org\n"
"POT-Creation-Date: 2015-11-17 11:57+0100\n"
"PO-Revision-Date: 2015-11-17 11:59+0100\n"
"Last-Translator: Thomas Gelf <thomas@gelf.net>\n"
"Language: it_IT\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 1.5.4\n"
#: /usr/local/icingaweb-modules/pnp/library/Pnp/ProvidedHook/Grapher.php:224
msgid "25 Hours"
msgstr "25 ore"
#: /usr/local/icingaweb-modules/pnp/library/Pnp/ProvidedHook/Grapher.php:223
msgid "4 Hours"
msgstr "4 ore"
#: /usr/local/icingaweb-modules/pnp/configuration.php:8
msgid "Config"
msgstr "Configurazione"
#: /usr/local/icingaweb-modules/pnp/configuration.php:7
msgid "Configure this module"
msgstr "Configura questo modulo"
#: /usr/local/icingaweb-modules/pnp/library/Pnp/ProvidedHook/Grapher.php:226
msgid "One Month"
msgstr "Un mese"
#: /usr/local/icingaweb-modules/pnp/library/Pnp/ProvidedHook/Grapher.php:225
msgid "One Week"
msgstr "Una settimana"
#: /usr/local/icingaweb-modules/pnp/library/Pnp/ProvidedHook/Grapher.php:227
msgid "One Year"
msgstr "Un anno"
#: /usr/local/icingaweb-modules/pnp/application/forms/Config/GeneralConfigForm.php:29
msgid "PNP4Nagios configuration"
msgstr "Configurazione PNP4Nagios"
#: /usr/local/icingaweb-modules/pnp/application/forms/Config/GeneralConfigForm.php:30
msgid "PNP4Nagios configuration path name (e.g. /etc/pnp4nagios)"
msgstr "Directory della configurazione PNP4Nagios (es. /etc/pnp4nagios)"
#: /usr/local/icingaweb-modules/pnp/application/forms/Config/GeneralConfigForm.php:38
msgid "PNP4Nagios url"
msgstr "URL PNP4Nagios"
#: /usr/local/icingaweb-modules/pnp/application/forms/Config/GeneralConfigForm.php:16
msgid "Save Changes"
msgstr "Salva modifiche"
#: /usr/local/icingaweb-modules/pnp/application/forms/Config/GeneralConfigForm.php:39
msgid "The base URL of your PNP4Nagios installation (e.g. /pnp4nagios)"
msgstr "URL di base della tua installazione PNP4Nagios (es. /pnp4nagios)"
<div class="controls">
<?= $tabs; ?>
</div>
<div class="content">
<?= $form; ?>
</div>
\ No newline at end of file
<div class="controls">
<?= $tabs ?>
</div>
<iframe src="<?= $this->url ?>" style="height: 99%; width:100%" frameborder="no"></iframe>
<?php
/** @var $this Icinga\Application\Modules\Module */
$this->provideConfigTab('config', array(
'title' => $this->translate('Configure this module'),
'label' => $this->translate('Config'),
'url' => 'config'
));
$menuDisabled = $this->getConfig()->get('pnp4nagios', 'menu_disabled');
if (! $menuDisabled) {
/** @var \Icinga\Web\Navigation\NavigationItem $section */
$section = $this->menuSection('pnp');
$section->setLabel('PNP')
->setUrl('pnp')
->setIcon('chart-line')
->setPriority(50);
}
<?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';