mirror of
https://github.com/Icinga/icingaweb2-module-director.git
synced 2025-07-28 08:14:04 +02:00
parent
8fb2c26d7f
commit
fda7acc855
@ -2,7 +2,10 @@
|
|||||||
|
|
||||||
namespace Icinga\Module\Director\Controllers;
|
namespace Icinga\Module\Director\Controllers;
|
||||||
|
|
||||||
|
use dipl\Html\Html;
|
||||||
|
use Icinga\Module\Director\Web\Widget\HealthCheckPluginOutput;
|
||||||
use Icinga\Module\Director\Dashboard\Dashboard;
|
use Icinga\Module\Director\Dashboard\Dashboard;
|
||||||
|
use Icinga\Module\Director\Health;
|
||||||
use Icinga\Module\Director\Web\Controller\ActionController;
|
use Icinga\Module\Director\Web\Controller\ActionController;
|
||||||
use Icinga\Module\Director\Web\Form\DbSelectorForm;
|
use Icinga\Module\Director\Web\Form\DbSelectorForm;
|
||||||
|
|
||||||
@ -43,7 +46,19 @@ class DashboardController extends ActionController
|
|||||||
$dashboard = Dashboard::loadByName($name, $this->db());
|
$dashboard = Dashboard::loadByName($name, $this->db());
|
||||||
$this->tabs($dashboard->getTabs())->activate($name);
|
$this->tabs($dashboard->getTabs())->activate($name);
|
||||||
} else {
|
} else {
|
||||||
$this->addSingleTab($this->translate('Overview'));
|
$this->tabs()->add('main', [
|
||||||
|
'label' => $this->translate('Overview'),
|
||||||
|
'url' => 'director'
|
||||||
|
])->add('health', [
|
||||||
|
'label' => $this->translate('Health'),
|
||||||
|
'url' => 'director/health'
|
||||||
|
])->activate('main');
|
||||||
|
$state = $this->getHealthState();
|
||||||
|
if ($state->isProblem()) {
|
||||||
|
$this->tabs()->get('health')->setTagParams([
|
||||||
|
'class' => 'state-' . strtolower($state->getName())
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$cntDashboards = 0;
|
$cntDashboards = 0;
|
||||||
@ -66,4 +81,16 @@ class DashboardController extends ActionController
|
|||||||
$this->content()->add($msg);
|
$this->content()->add($msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \Icinga\Module\Director\CheckPlugin\PluginState
|
||||||
|
*/
|
||||||
|
protected function getHealthState()
|
||||||
|
{
|
||||||
|
$health = new Health();
|
||||||
|
$health->setDbResourceName($this->getDbResourceName());
|
||||||
|
$output = new HealthCheckPluginOutput($health);
|
||||||
|
|
||||||
|
return $output->getState();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
37
application/controllers/HealthController.php
Normal file
37
application/controllers/HealthController.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Icinga\Module\Director\Controllers;
|
||||||
|
|
||||||
|
use dipl\Html\Html;
|
||||||
|
use dipl\Html\Icon;
|
||||||
|
use Icinga\Module\Director\Web\Widget\HealthCheckPluginOutput;
|
||||||
|
use Icinga\Module\Director\Health;
|
||||||
|
use Icinga\Module\Director\Web\Controller\ActionController;
|
||||||
|
|
||||||
|
class HealthController extends ActionController
|
||||||
|
{
|
||||||
|
public function indexAction()
|
||||||
|
{
|
||||||
|
$this->tabs()->add('main', [
|
||||||
|
'label' => $this->translate('Overview'),
|
||||||
|
'url' => 'director'
|
||||||
|
])->add('health', [
|
||||||
|
'label' => $this->translate('Health'),
|
||||||
|
'url' => 'director/health'
|
||||||
|
])->activate('health');
|
||||||
|
|
||||||
|
$this->addTitle($this->translate('Director Health'));
|
||||||
|
$health = new Health();
|
||||||
|
$health->setDbResourceName($this->getDbResourceName());
|
||||||
|
$output = new HealthCheckPluginOutput($health);
|
||||||
|
$this->content()->add($output);
|
||||||
|
$this->content()->add([
|
||||||
|
Html::tag('h1', ['class' => 'icon-pin'], $this->translate('Hint: Check Plugin')),
|
||||||
|
Html::tag('p', $this->translate(
|
||||||
|
'Did you know that you can run this entire Health Check'
|
||||||
|
. ' (or just some sections) as an Icinga Check on a regular'
|
||||||
|
. ' base?'
|
||||||
|
))
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
@ -28,6 +28,11 @@ class CheckResults
|
|||||||
$this->state = new PluginState(0);
|
$this->state = new PluginState(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
public function add(CheckResult $result)
|
public function add(CheckResult $result)
|
||||||
{
|
{
|
||||||
$this->results[] = $result;
|
$this->results[] = $result;
|
||||||
@ -37,7 +42,26 @@ class CheckResults
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getStateSummaryString()
|
public function getStateCounters()
|
||||||
|
{
|
||||||
|
return $this->stateCounters;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getProblemSummary()
|
||||||
|
{
|
||||||
|
$summary = [];
|
||||||
|
for ($i = 1; $i <= 3; $i++) {
|
||||||
|
$count = $this->stateCounters[$i];
|
||||||
|
if ($count === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$summary[PluginState::create($i)->getName()] = $count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $summary;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStateSummaryString()
|
||||||
{
|
{
|
||||||
$summary = [sprintf(
|
$summary = [sprintf(
|
||||||
'%d tests OK',
|
'%d tests OK',
|
||||||
|
@ -30,6 +30,11 @@ class PluginState
|
|||||||
$this->set($state);
|
$this->set($state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isProblem()
|
||||||
|
{
|
||||||
|
return $this->state > 0;
|
||||||
|
}
|
||||||
|
|
||||||
public function set($state)
|
public function set($state)
|
||||||
{
|
{
|
||||||
$this->state = $this->getNumericStateFor($state);
|
$this->state = $this->getNumericStateFor($state);
|
||||||
|
98
library/Director/Web/Widget/HealthCheckPluginOutput.php
Normal file
98
library/Director/Web/Widget/HealthCheckPluginOutput.php
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Icinga\Module\Director\Web\Widget;
|
||||||
|
|
||||||
|
use dipl\Html\Html;
|
||||||
|
use dipl\Html\HtmlDocument;
|
||||||
|
use dipl\Html\HtmlString;
|
||||||
|
use dipl\Translation\TranslationHelper;
|
||||||
|
use Icinga\Module\Director\CheckPlugin\PluginState;
|
||||||
|
use Icinga\Module\Director\Health;
|
||||||
|
|
||||||
|
class HealthCheckPluginOutput extends HtmlDocument
|
||||||
|
{
|
||||||
|
use TranslationHelper;
|
||||||
|
|
||||||
|
/** @var Health */
|
||||||
|
protected $health;
|
||||||
|
|
||||||
|
/** @var PluginState */
|
||||||
|
protected $state;
|
||||||
|
|
||||||
|
public function __construct(Health $health)
|
||||||
|
{
|
||||||
|
$this->state = new PluginState('OK');
|
||||||
|
$this->health = $health;
|
||||||
|
$this->process();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function process()
|
||||||
|
{
|
||||||
|
$checks = $this->health->getAllChecks();
|
||||||
|
|
||||||
|
foreach ($checks as $check) {
|
||||||
|
$this->add([
|
||||||
|
$title = Html::tag('h2', $check->getName()),
|
||||||
|
$ul = Html::tag('ul', ['class' => 'health-check-result'])
|
||||||
|
]);
|
||||||
|
|
||||||
|
$problems = $check->getProblemSummary();
|
||||||
|
if (! empty($problems)) {
|
||||||
|
$badges = Html::tag('span', ['class' => 'title-badges']);
|
||||||
|
foreach ($problems as $state => $count) {
|
||||||
|
$badges->add(Html::tag('span', [
|
||||||
|
'class' => ['badge', 'state-' . strtolower($state)],
|
||||||
|
'title' => $this->translate('Critical Checks'),
|
||||||
|
], $count));
|
||||||
|
}
|
||||||
|
$title->add($badges);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($check->getResults() as $result) {
|
||||||
|
$ul->add(Html::tag('li', [
|
||||||
|
$this->colorizeState($result->getState()->getName()),
|
||||||
|
$this->colorizeStates($result->getOutput())
|
||||||
|
])->setSeparator(' '));
|
||||||
|
}
|
||||||
|
$this->state->raise($check->getState());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getState()
|
||||||
|
{
|
||||||
|
return $this->state;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function colorizeStates($string)
|
||||||
|
{
|
||||||
|
$string = Html::escape($string);
|
||||||
|
$string = preg_replace_callback(
|
||||||
|
"/'([^']+)'/",
|
||||||
|
[$this, 'highlightNames'],
|
||||||
|
$string
|
||||||
|
);
|
||||||
|
|
||||||
|
$string = preg_replace_callback(
|
||||||
|
'/(OK|WARNING|CRITICAL|UNKNOWN)/',
|
||||||
|
[$this, 'getColorized'],
|
||||||
|
$string
|
||||||
|
);
|
||||||
|
|
||||||
|
return new HtmlString($string);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function colorizeState($state)
|
||||||
|
{
|
||||||
|
return Html::tag('span', ['class' => 'badge state-' . strtolower($state)], $state);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function highlightNames($match)
|
||||||
|
{
|
||||||
|
return '"' . Html::tag('strong', $match[1]) . '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getColorized($match)
|
||||||
|
{
|
||||||
|
return $this->colorizeState($match[1]);
|
||||||
|
}
|
||||||
|
}
|
@ -599,6 +599,26 @@ a {
|
|||||||
color: @color-pending;
|
color: @color-pending;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ul.tabs a.state-critical {
|
||||||
|
background-color: @colorCritical;
|
||||||
|
font-weight: bold;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
ul.tabs a.state-warning {
|
||||||
|
background-color: @colorWarning;
|
||||||
|
font-weight: bold;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
ul.tabs a.state-ok {
|
||||||
|
background-color: @colorOk;
|
||||||
|
font-weight: bold;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
ul.tabs a.state-unknown {
|
||||||
|
background-color: @colorUnknown;
|
||||||
|
font-weight: bold;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
a:hover::before {
|
a:hover::before {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
@ -1033,6 +1053,25 @@ form div.hint {
|
|||||||
|
|
||||||
/* END of Forms */
|
/* END of Forms */
|
||||||
|
|
||||||
|
ul.health-check-result {
|
||||||
|
list-style-type: none;
|
||||||
|
padding-left: 2em;
|
||||||
|
margin-bottom: 2em;
|
||||||
|
li {
|
||||||
|
line-height: 2em;
|
||||||
|
}
|
||||||
|
.badge {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-badges {
|
||||||
|
.badge {
|
||||||
|
font-size: 0.75em;
|
||||||
|
margin-left: 0.5em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
span.error {
|
span.error {
|
||||||
color: @colorCritical;
|
color: @colorCritical;
|
||||||
|
|
||||||
@ -1040,6 +1079,7 @@ span.error {
|
|||||||
color: inherit;
|
color: inherit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p.error {
|
p.error {
|
||||||
color: white;
|
color: white;
|
||||||
padding: 1em 2em;
|
padding: 1em 2em;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user