mirror of
https://github.com/Icinga/icingaweb2-module-businessprocess.git
synced 2026-02-14 08:23:20 -05:00
parent
3fe1c9d1a7
commit
b78983f539
11 changed files with 194 additions and 13 deletions
|
|
@ -117,6 +117,7 @@ class AddNodeForm extends QuickForm
|
|||
'&' => $this->translate('AND'),
|
||||
'|' => $this->translate('OR'),
|
||||
'!' => $this->translate('NOT'),
|
||||
'%' => $this->translate('DEGRADED'),
|
||||
'1' => $this->translate('MIN 1'),
|
||||
'2' => $this->translate('MIN 2'),
|
||||
'3' => $this->translate('MIN 3'),
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ class EditNodeForm extends QuickForm
|
|||
'&' => $this->translate('AND'),
|
||||
'|' => $this->translate('OR'),
|
||||
'!' => $this->translate('NOT'),
|
||||
'%' => $this->translate('DEGRADED'),
|
||||
'1' => $this->translate('MIN 1'),
|
||||
'2' => $this->translate('MIN 2'),
|
||||
'3' => $this->translate('MIN 3'),
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ class ProcessForm extends QuickForm
|
|||
'&' => $this->translate('AND'),
|
||||
'|' => $this->translate('OR'),
|
||||
'!' => $this->translate('NOT'),
|
||||
'%' => $this->translate('DEGRADED'),
|
||||
'1' => $this->translate('MIN 1'),
|
||||
'2' => $this->translate('MIN 2'),
|
||||
'3' => $this->translate('MIN 3'),
|
||||
|
|
|
|||
|
|
@ -17,6 +17,15 @@ The `OR` operator selects the **BEST** state of its child nodes:
|
|||
|
||||

|
||||
|
||||
## DEGRADED <a id="deg-operator">
|
||||
|
||||
The `DEGRADED` operator behaves like an `AND`, but if the resulting
|
||||
state is **CRITICAL** it transforms it into a **WARNING**.
|
||||
Refer to the table below for the case-by-case
|
||||
analysis of the statuses.
|
||||
|
||||

|
||||
|
||||
## MIN n <a id="min-operator">
|
||||
|
||||
The `MIN` operator selects the **WORST** state out of the **BEST n** child node states:
|
||||
|
|
|
|||
BIN
doc/screenshot/09_operators/0905_deg-operator.jpg
Normal file
BIN
doc/screenshot/09_operators/0905_deg-operator.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 67 KiB |
|
|
@ -11,6 +11,7 @@ class BpNode extends Node
|
|||
const OP_AND = '&';
|
||||
const OP_OR = '|';
|
||||
const OP_NOT = '!';
|
||||
const OP_DEGRADED = '%';
|
||||
|
||||
protected $operator = '&';
|
||||
protected $url;
|
||||
|
|
@ -289,6 +290,7 @@ class BpNode extends Node
|
|||
case self::OP_AND:
|
||||
case self::OP_OR:
|
||||
case self::OP_NOT:
|
||||
case self::OP_DEGRADED:
|
||||
return;
|
||||
default:
|
||||
if (is_numeric($operator)) {
|
||||
|
|
@ -460,6 +462,15 @@ class BpNode extends Node
|
|||
case self::OP_OR:
|
||||
$sort_state = min($sort_states);
|
||||
break;
|
||||
case self::OP_DEGRADED:
|
||||
$maxState = max($sort_states);
|
||||
$flags = $maxState & 0xf;
|
||||
|
||||
$maxIcingaState = $this->sortStateTostate($maxState);
|
||||
$warningState = ($this->stateToSortState(self::ICINGA_WARNING) << self::SHIFT_FLAGS) + $flags;
|
||||
|
||||
$sort_state = ($maxIcingaState === self::ICINGA_CRITICAL) ? $warningState : $maxState;
|
||||
break;
|
||||
default:
|
||||
// MIN:
|
||||
$sort_state = 3 << self::SHIFT_FLAGS;
|
||||
|
|
@ -624,6 +635,9 @@ class BpNode extends Node
|
|||
case self::OP_NOT:
|
||||
return 'NOT';
|
||||
break;
|
||||
case self::OP_DEGRADED:
|
||||
return 'DEG';
|
||||
break;
|
||||
default:
|
||||
// MIN
|
||||
$this->assertNumericOperator();
|
||||
|
|
|
|||
|
|
@ -322,7 +322,7 @@ class LegacyConfigParser
|
|||
}
|
||||
|
||||
$op = '&';
|
||||
if (preg_match_all('~(?<!\\\\)([\|\+&\!])~', $value, $m)) {
|
||||
if (preg_match_all('~(?<!\\\\)([\|\+&\!\%])~', $value, $m)) {
|
||||
$op = implode('', $m[1]);
|
||||
for ($i = 1; $i < strlen($op); $i++) {
|
||||
if ($op[$i] !== $op[$i - 1]) {
|
||||
|
|
@ -351,7 +351,7 @@ class LegacyConfigParser
|
|||
|
||||
$cmps = preg_split('~\s*(?<!\\\\)\\' . $op . '\s*~', $value, -1, PREG_SPLIT_NO_EMPTY);
|
||||
foreach ($cmps as $val) {
|
||||
$val = preg_replace('~(\\\\([\|\+&\!]))~', '$2', $val);
|
||||
$val = preg_replace('~(\\\\([\|\+&\!\%]))~', '$2', $val);
|
||||
if (strpos($val, ';') !== false) {
|
||||
if ($bp->hasNode($val)) {
|
||||
$node->addChild($bp->getNode($val));
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ class LegacyConfigRenderer
|
|||
$op = static::renderOperator($node);
|
||||
$children = $node->getChildNames();
|
||||
$str = implode(' ' . $op . ' ', array_map(function ($val) {
|
||||
return preg_replace('~([\|\+&\!])~', '\\\\$1', $val);
|
||||
return preg_replace('~([\|\+&\!\%])~', '\\\\$1', $val);
|
||||
}, $children));
|
||||
|
||||
if ((count($children) < 2) && $op !== '&') {
|
||||
|
|
|
|||
|
|
@ -7,22 +7,20 @@ use Icinga\Module\Businessprocess\Test\BaseTestCase;
|
|||
|
||||
class BpNodeTest extends BaseTestCase
|
||||
{
|
||||
/**
|
||||
* @expectedException \Icinga\Module\Businessprocess\Exception\NestingError
|
||||
*/
|
||||
public function testThrowsNestingErrorWhenCheckedForLoops()
|
||||
{
|
||||
$this->expectException(\Icinga\Module\Businessprocess\Exception\NestingError::class);
|
||||
|
||||
/** @var BpNode $bpNode */
|
||||
$bpNode = $this->makeLoop()->getNode('d');
|
||||
$bpNode->checkForLoops();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedExceptionMessage d -> a -> b -> c -> a
|
||||
* @expectedException \Icinga\Module\Businessprocess\Exception\NestingError
|
||||
*/
|
||||
public function testNestingErrorReportsFullLoop()
|
||||
{
|
||||
$this->expectException(\Icinga\Module\Businessprocess\Exception\NestingError::class);
|
||||
$this->expectExceptionMessage('d -> a -> b -> c -> a');
|
||||
|
||||
/** @var BpNode $bpNode */
|
||||
$bpNode = $this->makeLoop()->getNode('d');
|
||||
$bpNode->checkForLoops();
|
||||
|
|
|
|||
|
|
@ -41,11 +41,9 @@ class HostNodeTest extends BaseTestCase
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Icinga\Exception\ProgrammingError
|
||||
*/
|
||||
public function testSettingAnInvalidStateFails()
|
||||
{
|
||||
$this->expectException(\Icinga\Exception\ProgrammingError::class);
|
||||
$bp = new BpConfig();
|
||||
$host = $bp->createHost('localhost')->setState(98);
|
||||
$bp->createBp('p')->addChild($host)->getState();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,159 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\Icinga\Module\Businessprocess\Operator;
|
||||
|
||||
use Icinga\Module\Businessprocess\BpConfig;
|
||||
use Icinga\Module\Businessprocess\Test\BaseTestCase;
|
||||
use Icinga\Module\Businessprocess\Storage\LegacyStorage;
|
||||
|
||||
class DegradedOperatorTest extends BaseTestCase
|
||||
{
|
||||
public function testDegradedOperatorCanBeParsed()
|
||||
{
|
||||
$storage = new LegacyStorage($this->emptyConfigSection());
|
||||
$expressions = [
|
||||
'a = b;c',
|
||||
'a = b;c % c;d % d;e',
|
||||
];
|
||||
|
||||
foreach ($expressions as $expression) {
|
||||
$this->assertInstanceOf(
|
||||
'Icinga\\Module\\Businessprocess\\BpConfig',
|
||||
$storage->loadFromString('dummy', $expression)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function testThreeTimesCriticalIsWarning()
|
||||
{
|
||||
$bp = $this->getBp();
|
||||
$bp->setNodeState('b;c', 2);
|
||||
$bp->setNodeState('c;d', 2);
|
||||
$bp->setNodeState('d;e', 2);
|
||||
|
||||
$this->assertEquals(
|
||||
'WARNING',
|
||||
$bp->getNode('a')->getStateName()
|
||||
);
|
||||
}
|
||||
|
||||
public function testTwoTimesCriticalAndOkIsWarning()
|
||||
{
|
||||
$bp = $this->getBp();
|
||||
$bp->setNodeState('b;c', 2);
|
||||
$bp->setNodeState('c;d', 0);
|
||||
$bp->setNodeState('d;e', 2);
|
||||
|
||||
$this->assertEquals(
|
||||
'WARNING',
|
||||
$bp->getNode('a')->getStateName()
|
||||
);
|
||||
}
|
||||
|
||||
public function testCriticalAndWarningAndOkIsWarning()
|
||||
{
|
||||
$bp = $this->getBp();
|
||||
$bp->setNodeState('b;c', 2);
|
||||
$bp->setNodeState('c;d', 1);
|
||||
$bp->setNodeState('d;e', 0);
|
||||
|
||||
$this->assertEquals(
|
||||
'WARNING',
|
||||
$bp->getNode('a')->getStateName()
|
||||
);
|
||||
}
|
||||
|
||||
public function testUnknownAndWarningAndOkIsUnknown()
|
||||
{
|
||||
$bp = $this->getBp();
|
||||
$bp->setNodeState('b;c', 0);
|
||||
$bp->setNodeState('c;d', 1);
|
||||
$bp->setNodeState('d;e', 3);
|
||||
|
||||
$this->assertEquals(
|
||||
'UNKNOWN',
|
||||
$bp->getNode('a')->getStateName()
|
||||
);
|
||||
}
|
||||
|
||||
public function testTwoTimesWarningAndOkIsWarning()
|
||||
{
|
||||
$bp = $this->getBp();
|
||||
$bp->setNodeState('b;c', 0);
|
||||
$bp->setNodeState('c;d', 1);
|
||||
$bp->setNodeState('d;e', 1);
|
||||
|
||||
$this->assertEquals(
|
||||
'WARNING',
|
||||
$bp->getNode('a')->getStateName()
|
||||
);
|
||||
}
|
||||
|
||||
public function testUnknownAndWarningAndCriticalIsWarning()
|
||||
{
|
||||
$bp = $this->getBp();
|
||||
$bp->setNodeState('b;c', 2);
|
||||
$bp->setNodeState('c;d', 1);
|
||||
$bp->setNodeState('d;e', 3);
|
||||
|
||||
$this->assertEquals(
|
||||
'WARNING',
|
||||
$bp->getNode('a')->getStateName()
|
||||
);
|
||||
}
|
||||
|
||||
public function testThreeTimesOkIsOk()
|
||||
{
|
||||
$bp = $this->getBp();
|
||||
$bp->setNodeState('b;c', 0);
|
||||
$bp->setNodeState('c;d', 0);
|
||||
$bp->setNodeState('d;e', 0);
|
||||
|
||||
$this->assertEquals(
|
||||
'OK',
|
||||
$bp->getNode('a')->getStateName()
|
||||
);
|
||||
}
|
||||
|
||||
public function testSimpleDegOperationWorksCorrectly()
|
||||
{
|
||||
$bp = new BpConfig();
|
||||
$bp->throwErrors();
|
||||
$host = $bp->createHost('localhost')->setState(0);
|
||||
$service = $bp->createService('localhost', 'ping')->setState(2);
|
||||
$p = $bp->createBp('p');
|
||||
$p->setOperator('%');
|
||||
$p->addChild($host);
|
||||
$p->addChild($service);
|
||||
|
||||
$this->assertEquals(
|
||||
'UP',
|
||||
$host->getStateName()
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
'CRITICAL',
|
||||
$service->getStateName()
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
'WARNING',
|
||||
$p->getStateName()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BpConfig
|
||||
*/
|
||||
protected function getBp()
|
||||
{
|
||||
$storage = new LegacyStorage($this->emptyConfigSection());
|
||||
$expression = 'a = b;c % c;d % d;e';
|
||||
$bp = $storage->loadFromString('dummy', $expression);
|
||||
$bp->createBp('b');
|
||||
$bp->createBp('c');
|
||||
$bp->createBp('d');
|
||||
|
||||
return $bp;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue