Merge pull request #277 from Icinga/feature/icingaDb-MySQL-backend-#276

Support Icinga DB
This commit is contained in:
Johannes Meyer 2022-02-18 12:11:56 +01:00 committed by GitHub
commit 711677f903
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 678 additions and 267 deletions

View file

@ -4,11 +4,14 @@ namespace Icinga\Module\Businessprocess\Clicommands;
use Exception;
use Icinga\Application\Logger;
use Icinga\Application\Modules\Module;
use Icinga\Cli\Command;
use Icinga\Module\Businessprocess\BpConfig;
use Icinga\Module\Businessprocess\BpNode;
use Icinga\Module\Businessprocess\HostNode;
use Icinga\Module\Businessprocess\Node;
use Icinga\Module\Businessprocess\ProvidedHook\Icingadb\IcingadbSupport;
use Icinga\Module\Businessprocess\State\IcingaDbState;
use Icinga\Module\Businessprocess\State\MonitoringState;
use Icinga\Module\Businessprocess\Storage\LegacyStorage;
@ -132,7 +135,14 @@ class ProcessCommand extends Command
/** @var BpNode $node */
try {
$node = $bp->getNode($nodeName);
MonitoringState::apply($bp);
if (Module::exists('icingadb')
&& (! $bp->hasBackendName() && IcingadbSupport::useIcingaDbAsBackend())
) {
IcingaDbState::apply($bp);
} else {
MonitoringState::apply($bp);
}
if ($bp->hasErrors()) {
Logger::error("Checking Business Process '%s' failed: %s\n", $name, $bp->getErrors());

View file

@ -2,23 +2,63 @@
namespace Icinga\Module\Businessprocess\Controllers;
use Icinga\Application\Modules\Module;
use Icinga\Module\Businessprocess\IcingaDbObject;
use Icinga\Module\Businessprocess\ProvidedHook\Icingadb\IcingadbSupport;
use Icinga\Module\Icingadb\Model\Host;
use Icinga\Module\Monitoring\Controller;
use Icinga\Web\Url;
use ipl\Stdlib\Filter;
class HostController extends Controller
{
/**
* True if business process prefers to use icingadb as backend for it's nodes
*
* @var bool
*/
protected $isIcingadbPreferred;
protected function moduleInit()
{
$this->isIcingadbPreferred = Module::exists('icingadb')
&& ! $this->params->has('backend')
&& IcingadbSupport::useIcingaDbAsBackend();
if (! $this->isIcingadbPreferred) {
parent::moduleInit();
}
}
public function showAction()
{
$host = $this->params->getRequired('host');
if ($this->isIcingadbPreferred) {
$hostName = $this->params->shift('host');
$query = $this->backend->select()
->from('hoststatus', array('host_name'))
->where('host_name', $host);
$query = Host::on(IcingaDbObject::fetchDb());
IcingaDbObject::applyIcingaDbRestrictions($query);
if ($this->applyRestriction('monitoring/filter/objects', $query)->fetchRow() !== false) {
$this->redirectNow(Url::fromPath('monitoring/host/show')->setParams($this->params));
$query->filter(Filter::equal('host.name', $hostName));
$host = $query->first();
$this->params->add('name', $hostName);
if ($host !== false) {
$this->redirectNow(Url::fromPath('icingadb/host')->setParams($this->params));
}
} else {
$hostName = $this->params->get('host');
$query = $this->backend->select()
->from('hoststatus', array('host_name'))
->where('host_name', $hostName);
if ($this->applyRestriction('monitoring/filter/objects', $query)->fetchRow() !== false) {
$this->redirectNow(Url::fromPath('monitoring/host/show')->setParams($this->params));
}
}
$this->view->host = $host;
$this->view->host = $hostName;
}
}

View file

@ -2,9 +2,12 @@
namespace Icinga\Module\Businessprocess\Controllers;
use Icinga\Application\Modules\Module;
use Icinga\Module\Businessprocess\ProvidedHook\Icingadb\IcingadbSupport;
use Icinga\Module\Businessprocess\Renderer\Breadcrumb;
use Icinga\Module\Businessprocess\Renderer\TileRenderer;
use Icinga\Module\Businessprocess\Simulation;
use Icinga\Module\Businessprocess\State\IcingaDbState;
use Icinga\Module\Businessprocess\State\MonitoringState;
use Icinga\Module\Businessprocess\Web\Controller;
use Icinga\Module\Businessprocess\Web\Url;
@ -82,7 +85,13 @@ class NodeController extends Controller
continue;
}
MonitoringState::apply($config);
if (Module::exists('icingadb') &&
(! $config->getBackendName() && IcingadbSupport::useIcingaDbAsBackend())
) {
IcingaDbState::apply($config);
} else {
MonitoringState::apply($config);
}
$config->applySimulation($simulation);
foreach ($parents as $parentAndPath) {

View file

@ -2,15 +2,18 @@
namespace Icinga\Module\Businessprocess\Controllers;
use Icinga\Application\Modules\Module;
use Icinga\Date\DateFormatter;
use Icinga\Module\Businessprocess\BpConfig;
use Icinga\Module\Businessprocess\BpNode;
use Icinga\Module\Businessprocess\Node;
use Icinga\Module\Businessprocess\ProvidedHook\Icingadb\IcingadbSupport;
use Icinga\Module\Businessprocess\Renderer\Breadcrumb;
use Icinga\Module\Businessprocess\Renderer\Renderer;
use Icinga\Module\Businessprocess\Renderer\TileRenderer;
use Icinga\Module\Businessprocess\Renderer\TreeRenderer;
use Icinga\Module\Businessprocess\Simulation;
use Icinga\Module\Businessprocess\State\IcingaDbState;
use Icinga\Module\Businessprocess\State\MonitoringState;
use Icinga\Module\Businessprocess\Storage\ConfigDiff;
use Icinga\Module\Businessprocess\Storage\LegacyConfigRenderer;
@ -81,7 +84,14 @@ class ProcessController extends Controller
$bp = $this->loadModifiedBpConfig();
$node = $this->getNode($bp);
MonitoringState::apply($bp);
if (Module::exists('icingadb') &&
(! $bp->hasBackendName() && IcingadbSupport::useIcingaDbAsBackend())
) {
IcingaDbState::apply($bp);
} else {
MonitoringState::apply($bp);
}
$this->handleSimulations($bp);
$this->setTitle($this->translate('Business Process "%s"'), $bp->getTitle());

View file

@ -2,26 +2,71 @@
namespace Icinga\Module\Businessprocess\Controllers;
use Icinga\Application\Modules\Module;
use Icinga\Module\Businessprocess\IcingaDbObject;
use Icinga\Module\Businessprocess\ProvidedHook\Icingadb\IcingadbSupport;
use Icinga\Module\Icingadb\Model\Service;
use Icinga\Module\Monitoring\Controller;
use Icinga\Web\Url;
use ipl\Stdlib\Filter;
class ServiceController extends Controller
{
/**
* True if business process prefers to use icingadb as backend for it's nodes
*
* @var bool
*/
protected $isIcingadbPreferred;
protected function moduleInit()
{
$this->isIcingadbPreferred = Module::exists('icingadb')
&& ! $this->params->has('backend')
&& IcingadbSupport::useIcingaDbAsBackend();
if (! $this->isIcingadbPreferred) {
parent::moduleInit();
}
}
public function showAction()
{
$host = $this->params->getRequired('host');
$service = $this->params->getRequired('service');
if ($this->isIcingadbPreferred) {
$hostName = $this->params->shift('host');
$serviceName = $this->params->shift('service');
$query = $this->backend->select()
->from('servicestatus', array('service_description'))
->where('host_name', $host)
->where('service_description', $service);
$query = Service::on(IcingaDbObject::fetchDb());
IcingaDbObject::applyIcingaDbRestrictions($query);
if ($this->applyRestriction('monitoring/filter/objects', $query)->fetchRow() !== false) {
$this->redirectNow(Url::fromPath('monitoring/service/show')->setParams($this->params));
$query->filter(Filter::all(
Filter::equal('service.name', $serviceName),
Filter::equal('host.name', $hostName)
));
$service = $query->first();
$this->params->add('name', $serviceName);
$this->params->add('host.name', $hostName);
if ($service !== false) {
$this->redirectNow(Url::fromPath('icingadb/service')->setParams($this->params));
}
} else {
$hostName = $this->params->get('host');
$serviceName = $this->params->get('service');
$query = $this->backend->select()
->from('servicestatus', array('service_description'))
->where('host_name', $hostName)
->where('service_description', $serviceName);
if ($this->applyRestriction('monitoring/filter/objects', $query)->fetchRow() !== false) {
$this->redirectNow(Url::fromPath('monitoring/service/show')->setParams($this->params));
}
}
$this->view->host = $host;
$this->view->service = $service;
$this->view->host = $hostName;
$this->view->service = $serviceName;
}
}

View file

@ -2,23 +2,23 @@
namespace Icinga\Module\Businessprocess\Forms;
use Icinga\Data\Filter\Filter;
use Icinga\Module\Businessprocess\BpNode;
use Icinga\Module\Businessprocess\BpConfig;
use Icinga\Module\Businessprocess\Common\EnumList;
use Icinga\Module\Businessprocess\ImportedNode;
use Icinga\Module\Businessprocess\Modification\ProcessChanges;
use Icinga\Module\Businessprocess\MonitoringRestrictions;
use Icinga\Module\Businessprocess\Storage\Storage;
use Icinga\Module\Businessprocess\Web\Form\QuickForm;
use Icinga\Module\Businessprocess\Web\Form\Validator\NoDuplicateChildrenValidator;
use Icinga\Module\Monitoring\Backend\MonitoringBackend;
use Icinga\Web\Session\SessionNamespace;
use ipl\Sql\Connection as IcingaDbConnection;
class AddNodeForm extends QuickForm
{
use MonitoringRestrictions;
use EnumList;
/** @var MonitoringBackend */
/** @var MonitoringBackend|IcingaDbConnection*/
protected $backend;
/** @var Storage */
@ -402,10 +402,10 @@ class AddNodeForm extends QuickForm
}
/**
* @param MonitoringBackend $backend
* @param MonitoringBackend|IcingaDbConnection $backend
* @return $this
*/
public function setBackend(MonitoringBackend $backend)
public function setBackend($backend)
{
$this->backend = $backend;
return $this;
@ -460,127 +460,6 @@ class AddNodeForm extends QuickForm
return $this;
}
protected function enumHostForServiceList()
{
$names = $this->backend
->select()
->from('hostStatus', ['hostname' => 'host_name'])
->applyFilter($this->getRestriction('monitoring/filter/objects'))
->order('host_name')
->getQuery()
->fetchColumn();
// fetchPairs doesn't seem to work when using the same column with
// different aliases twice
return array_combine((array) $names, (array) $names);
}
protected function enumHostList()
{
$names = $this->backend
->select()
->from('hostStatus', ['hostname' => 'host_name'])
->applyFilter($this->getRestriction('monitoring/filter/objects'))
->order('host_name')
->getQuery()
->fetchColumn();
// fetchPairs doesn't seem to work when using the same column with
// different aliases twice
$res = array();
$suffix = ';Hoststatus';
foreach ($names as $name) {
$res[$name . $suffix] = $name;
}
return $res;
}
protected function enumHostStateList()
{
$hostStateList = [
0 => $this->translate('UP'),
1 => $this->translate('DOWN'),
99 => $this->translate('PENDING')
];
return $hostStateList;
}
protected function enumServiceList($host)
{
$names = $this->backend
->select()
->from('serviceStatus', ['service' => 'service_description'])
->where('host_name', $host)
->applyFilter($this->getRestriction('monitoring/filter/objects'))
->order('service_description')
->getQuery()
->fetchColumn();
$services = array();
foreach ($names as $name) {
$services[$host . ';' . $name] = $name;
}
return $services;
}
protected function enumServiceStateList()
{
$serviceStateList = [
0 => $this->translate('OK'),
1 => $this->translate('WARNING'),
2 => $this->translate('CRITICAL'),
3 => $this->translate('UNKNOWN'),
99 => $this->translate('PENDING'),
];
return $serviceStateList;
}
protected function enumHostListByFilter($filter)
{
$names = $this->backend
->select()
->from('hostStatus', ['hostname' => 'host_name'])
->applyFilter(Filter::fromQueryString($filter))
->applyFilter($this->getRestriction('monitoring/filter/objects'))
->order('host_name')
->getQuery()
->fetchColumn();
// fetchPairs doesn't seem to work when using the same column with
// different aliases twice
$res = array();
$suffix = ';Hoststatus';
foreach ($names as $name) {
$res[$name . $suffix] = $name;
}
return $res;
}
protected function enumServiceListByFilter($filter)
{
$objects = $this->backend
->select()
->from('serviceStatus', ['host' => 'host_name', 'service' => 'service_description'])
->applyFilter(Filter::fromQueryString($filter))
->applyFilter($this->getRestriction('monitoring/filter/objects'))
->order('service_description')
->getQuery()
->fetchAll();
$services = array();
foreach ($objects as $object) {
$services[$object->host . ';' . $object->service] = $object->host . ':' . $object->service;
}
return $services;
}
protected function hasProcesses()
{
return count($this->enumProcesses()) > 0;

View file

@ -51,16 +51,18 @@ class BpConfigForm extends BpConfigBaseForm
'rows' => 4,
));
$this->addElement('select', 'Backend', array(
'label' => $this->translate('Backend'),
'description' => $this->translate(
'Icinga Web Monitoring Backend where current object states for'
. ' this process should be retrieved from'
),
'multiOptions' => array(
null => $this->translate('Use the configured default backend'),
) + $this->listAvailableBackends()
));
if (! empty($this->listAvailableBackends())) {
$this->addElement('select', 'Backend', array(
'label' => $this->translate('Backend'),
'description' => $this->translate(
'Icinga Web Monitoring Backend where current object states for'
. ' this process should be retrieved from'
),
'multiOptions' => array(
null => $this->translate('Use the configured default backend'),
) + $this->listAvailableBackends()
));
}
$this->addElement('select', 'Statetype', array(
'label' => $this->translate('State Type'),
@ -167,9 +169,11 @@ class BpConfigForm extends BpConfigBaseForm
}
$meta = $config->getMetadata();
foreach ($this->getValues() as $key => $value) {
if ($value === null || $value === '') {
if (! in_array($key, ['Title', 'Description', 'Backend'], true)
&& ($value === null || $value === '')) {
continue;
}
if ($meta->hasKey($key)) {
$meta->set($key, $value);
}

View file

@ -9,10 +9,11 @@ use Icinga\Module\Businessprocess\Node;
use Icinga\Module\Businessprocess\Web\Form\QuickForm;
use Icinga\Module\Monitoring\Backend\MonitoringBackend;
use Icinga\Web\Session\SessionNamespace;
use ipl\Sql\Connection as IcingaDbConnection;
class DeleteNodeForm extends QuickForm
{
/** @var MonitoringBackend */
/** @var MonitoringBackend|IcingaDbConnection */
protected $backend;
/** @var BpConfig */
@ -79,10 +80,10 @@ class DeleteNodeForm extends QuickForm
}
/**
* @param MonitoringBackend $backend
* @param MonitoringBackend|IcingaDbConnection $backend
* @return $this
*/
public function setBackend(MonitoringBackend $backend)
public function setBackend($backend)
{
$this->backend = $backend;
return $this;

View file

@ -4,19 +4,20 @@ namespace Icinga\Module\Businessprocess\Forms;
use Icinga\Module\Businessprocess\BpNode;
use Icinga\Module\Businessprocess\BpConfig;
use Icinga\Module\Businessprocess\Common\EnumList;
use Icinga\Module\Businessprocess\Modification\ProcessChanges;
use Icinga\Module\Businessprocess\MonitoringRestrictions;
use Icinga\Module\Businessprocess\Node;
use Icinga\Module\Businessprocess\Web\Form\QuickForm;
use Icinga\Module\Businessprocess\Web\Form\Validator\NoDuplicateChildrenValidator;
use Icinga\Module\Monitoring\Backend\MonitoringBackend;
use Icinga\Web\Session\SessionNamespace;
use ipl\Sql\Connection as IcingaDbConnection;
class EditNodeForm extends QuickForm
{
use MonitoringRestrictions;
use EnumList;
/** @var MonitoringBackend */
/** @var MonitoringBackend|IcingaDbConnection */
protected $backend;
/** @var BpConfig */
@ -296,10 +297,10 @@ class EditNodeForm extends QuickForm
}
/**
* @param MonitoringBackend $backend
* @param MonitoringBackend|IcingaDbConnection $backend
* @return $this
*/
public function setBackend(MonitoringBackend $backend)
public function setBackend($backend)
{
$this->backend = $backend;
return $this;
@ -344,86 +345,6 @@ class EditNodeForm extends QuickForm
return $this;
}
protected function enumHostForServiceList()
{
$names = $this->backend
->select()
->from('hostStatus', ['hostname' => 'host_name'])
->applyFilter($this->getRestriction('monitoring/filter/objects'))
->order('host_name')
->getQuery()
->fetchColumn();
// fetchPairs doesn't seem to work when using the same column with
// different aliases twice
return array_combine((array) $names, (array) $names);
}
protected function enumHostList()
{
$names = $this->backend
->select()
->from('hostStatus', ['hostname' => 'host_name'])
->applyFilter($this->getRestriction('monitoring/filter/objects'))
->order('host_name')
->getQuery()
->fetchColumn();
// fetchPairs doesn't seem to work when using the same column with
// different aliases twice
$res = array();
$suffix = ';Hoststatus';
foreach ($names as $name) {
$res[$name . $suffix] = $name;
}
return $res;
}
protected function enumHostStateList()
{
$hostStateList = [
0 => $this->translate('UP'),
1 => $this->translate('DOWN'),
99 => $this->translate('PENDING')
];
return $hostStateList;
}
protected function enumServiceList($host)
{
$names = $this->backend
->select()
->from('serviceStatus', ['service' => 'service_description'])
->where('host_name', $host)
->applyFilter($this->getRestriction('monitoring/filter/objects'))
->order('service_description')
->getQuery()
->fetchColumn();
$services = array();
foreach ($names as $name) {
$services[$host . ';' . $name] = $name;
}
return $services;
}
protected function enumServiceStateList()
{
$serviceStateList = [
0 => $this->translate('OK'),
1 => $this->translate('WARNING'),
2 => $this->translate('CRITICAL'),
3 => $this->translate('UNKNOWN'),
99 => $this->translate('PENDING'),
];
return $serviceStateList;
}
protected function hasProcesses()
{
return count($this->enumProcesses()) > 0;

View file

@ -9,10 +9,11 @@ use Icinga\Module\Businessprocess\Web\Form\QuickForm;
use Icinga\Module\Monitoring\Backend\MonitoringBackend;
use Icinga\Web\Notification;
use Icinga\Web\Session\SessionNamespace;
use ipl\Sql\Connection as IcingaDbConnection;
class ProcessForm extends QuickForm
{
/** @var MonitoringBackend */
/** @var MonitoringBackend|IcingaDbConnection */
protected $backend;
/** @var BpConfig */
@ -111,10 +112,10 @@ class ProcessForm extends QuickForm
}
/**
* @param MonitoringBackend $backend
* @param MonitoringBackend|IcingaDbConnection $backend
* @return $this
*/
public function setBackend(MonitoringBackend $backend)
public function setBackend($backend)
{
$this->backend = $backend;
return $this;

View file

@ -7,7 +7,7 @@ Requirements
* Icinga Web 2 (>= 2.9)
* PHP (>= 7.2)
* Icinga Web 2 modules:
* The `monitoring` module needs to be configured and enabled.
* The `monitoring` or `icingadb` module needs to be configured and enabled.
Installation from .tar.gz
-------------------------

View file

@ -3,13 +3,15 @@
namespace Icinga\Module\Businessprocess;
use Exception;
use Icinga\Application\Config;
use Icinga\Application\Modules\Module;
use Icinga\Exception\IcingaException;
use Icinga\Exception\NotFoundError;
use Icinga\Module\Businessprocess\Exception\NestingError;
use Icinga\Module\Businessprocess\Modification\ProcessChanges;
use Icinga\Module\Businessprocess\ProvidedHook\Icingadb\IcingadbSupport;
use Icinga\Module\Businessprocess\Storage\LegacyStorage;
use Icinga\Module\Monitoring\Backend\MonitoringBackend;
use ipl\Sql\Connection as IcingaDbConnection;
class BpConfig
{
@ -25,9 +27,9 @@ class BpConfig
protected $backendName;
/**
* Monitoring backend to retrieve states from
* Backend to retrieve states from
*
* @var MonitoringBackend
* @var MonitoringBackend|IcingaDbConnection
*/
protected $backend;
@ -281,7 +283,7 @@ class BpConfig
return $this->getMetadata()->has('Backend');
}
public function setBackend(MonitoringBackend $backend)
public function setBackend($backend)
{
$this->backend = $backend;
return $this;
@ -290,9 +292,14 @@ class BpConfig
public function getBackend()
{
if ($this->backend === null) {
$this->backend = MonitoringBackend::instance(
$this->getBackendName()
);
if (Module::exists('icingadb')
&& (! $this->hasBackendName() && IcingadbSupport::useIcingaDbAsBackend())) {
$this->backend = IcingaDbObject::fetchDb();
} else {
$this->backend = MonitoringBackend::instance(
$this->getBackendName()
);
}
}
return $this->backend;

View file

@ -0,0 +1,168 @@
<?php
namespace Icinga\Module\Businessprocess\Common;
use Icinga\Application\Modules\Module;
use Icinga\Data\Filter\Filter;
use Icinga\Module\Businessprocess\IcingaDbObject;
use Icinga\Module\Businessprocess\MonitoringRestrictions;
use Icinga\Module\Businessprocess\ProvidedHook\Icingadb\IcingadbSupport;
trait EnumList
{
protected function enumHostForServiceList()
{
if ($this->useIcingaDbBackend()) {
$names = (new IcingaDbObject())->yieldHostnames();
} else {
$names = $this->backend
->select()
->from('hostStatus', ['hostname' => 'host_name'])
->applyFilter(MonitoringRestrictions::getRestriction('monitoring/filter/objects'))
->order('host_name')
->getQuery()
->fetchColumn();
}
// fetchPairs doesn't seem to work when using the same column with
// different aliases twice
$res = array();
foreach ($names as $name) {
$res[$name] = $name;
}
return $res;
}
protected function enumHostList()
{
if ($this->useIcingaDbBackend()) {
$names = (new IcingaDbObject())->yieldHostnames();
} else {
$names = $this->backend
->select()
->from('hostStatus', ['hostname' => 'host_name'])
->applyFilter(MonitoringRestrictions::getRestriction('monitoring/filter/objects'))
->order('host_name')
->getQuery()
->fetchColumn();
}
// fetchPairs doesn't seem to work when using the same column with
// different aliases twice
$res = array();
$suffix = ';Hoststatus';
foreach ($names as $name) {
$res[$name . $suffix] = $name;
}
return $res;
}
protected function enumServiceList($host)
{
if ($this->useIcingaDbBackend()) {
$names = (new IcingaDbObject())->yieldServicenames($host);
} else {
$names = $this->backend
->select()
->from('serviceStatus', ['service' => 'service_description'])
->where('host_name', $host)
->applyFilter(MonitoringRestrictions::getRestriction('monitoring/filter/objects'))
->order('service_description')
->getQuery()
->fetchColumn();
}
$services = array();
foreach ($names as $name) {
$services[$host . ';' . $name] = $name;
}
return $services;
}
protected function enumHostListByFilter($filter)
{
if ($this->useIcingaDbBackend()) {
$names = (new IcingaDbObject())->yieldHostnames($filter);
} else {
$names = $this->backend
->select()
->from('hostStatus', ['hostname' => 'host_name'])
->applyFilter(MonitoringRestrictions::getRestriction('monitoring/filter/objects'))
->order('host_name')
->getQuery()
->fetchColumn();
}
// fetchPairs doesn't seem to work when using the same column with
// different aliases twice
$res = array();
$suffix = ';Hoststatus';
foreach ($names as $name) {
$res[$name . $suffix] = $name;
}
return $res;
}
protected function enumServiceListByFilter($filter)
{
$services = array();
if ($this->useIcingaDbBackend()) {
$objects = (new IcingaDbObject())->fetchServices($filter);
foreach ($objects as $object) {
$services[$object->host->name . ';' . $object->name] = $object->host->name . ':' . $object->name;
}
} else {
$objects = $this->backend
->select()
->from('serviceStatus', ['host' => 'host_name', 'service' => 'service_description'])
->applyFilter(Filter::fromQueryString($filter))
->applyFilter(MonitoringRestrictions::getRestriction('monitoring/filter/objects'))
->order('service_description')
->getQuery()
->fetchAll();
foreach ($objects as $object) {
$services[$object->host . ';' . $object->service] = $object->host . ':' . $object->service;
}
}
return $services;
}
protected function enumHostStateList()
{
$hostStateList = [
0 => $this->translate('UP'),
1 => $this->translate('DOWN'),
99 => $this->translate('PENDING')
];
return $hostStateList;
}
protected function enumServiceStateList()
{
$serviceStateList = [
0 => $this->translate('OK'),
1 => $this->translate('WARNING'),
2 => $this->translate('CRITICAL'),
3 => $this->translate('UNKNOWN'),
99 => $this->translate('PENDING'),
];
return $serviceStateList;
}
protected function useIcingaDbBackend()
{
if (Module::exists('icingadb')) {
return ! $this->bp->hasBackendName() && IcingadbSupport::useIcingaDbAsBackend();
}
return false;
}
}

View file

@ -3,7 +3,6 @@
namespace Icinga\Module\Businessprocess;
use Icinga\Module\Businessprocess\Web\Url;
use ipl\Html\Html;
class HostNode extends MonitoredNode
{

View file

@ -0,0 +1,94 @@
<?php
namespace Icinga\Module\Businessprocess;
use Icinga\Module\Icingadb\Common\Auth;
use Icinga\Module\Icingadb\Common\Database as IcingadbDatabase;
use Icinga\Module\Icingadb\Model\Host;
use Icinga\Module\Icingadb\Model\Service;
use ipl\Sql\Connection as IcingaDbConnection;
use ipl\Web\Filter\QueryString;
class IcingaDbObject
{
use IcingadbDatabase;
use Auth;
/** @var BpConfig */
protected $config;
/** @var IcingaDbConnection */
protected $conn;
public function __construct()
{
$this->conn = $this->getDb();
}
public function fetchHosts($filter = null)
{
$hosts = Host::on($this->conn);
if ($filter !== null) {
$filterQuery = QueryString::parse($filter);
$hosts->filter($filterQuery);
}
$hosts->orderBy('host.name');
$this->applyIcingaDbRestrictions($hosts);
return $hosts;
}
public function fetchServices($filter)
{
$services = Service::on($this->conn)
->with('host');
if ($filter !== null) {
$filterQuery = QueryString::parse($filter);
$services->filter($filterQuery);
}
$services->orderBy('service.name');
$this->applyIcingaDbRestrictions($services);
return $services;
}
public function yieldHostnames($filter = null)
{
foreach ($this->fetchHosts($filter) as $host) {
yield $host->name;
}
}
public function yieldServicenames($host)
{
$filter = "host.name=$host";
foreach ($this->fetchServices($filter) as $service) {
yield $service->name;
}
}
public static function applyIcingaDbRestrictions($query)
{
$object = new self;
$object->applyRestrictions($query);
return $object;
}
public static function fetchDb()
{
$object = new self;
return $object->getDb();
}
}

View file

@ -7,7 +7,7 @@ use Icinga\Data\Filter\Filter;
use Icinga\Exception\ConfigurationError;
use Icinga\Exception\QueryException;
trait MonitoringRestrictions
class MonitoringRestrictions
{
/**
* Return a filter for the given restriction
@ -17,7 +17,7 @@ trait MonitoringRestrictions
* @return Filter|null Filter object or null if the authenticated user is not restricted
* @throws ConfigurationError If the restriction contains invalid filter columns
*/
protected function getRestriction($name)
public static function getRestriction($name)
{
// Borrowed from Icinga\Module\Monitoring\Controller
$restriction = Filter::matchAny();

View file

@ -0,0 +1,22 @@
<?php
namespace Icinga\Module\Businessprocess\ProvidedHook\Icingadb;
use Icinga\Module\Icingadb\Hook\HostActionsHook;
use Icinga\Module\Icingadb\Model\Host;
use ipl\Web\Widget\Link;
class HostActions extends HostActionsHook
{
public function getActionsForObject(Host $host): array
{
$label = mt('businessprocess', 'Business Impact');
return array(
new Link(
$label,
'businessprocess/node/impact?name='
. rawurlencode($host->name . ';Hoststatus')
)
);
}
}

View file

@ -0,0 +1,10 @@
<?php
namespace Icinga\Module\Businessprocess\ProvidedHook\Icingadb;
use Icinga\Module\Icingadb\Hook\IcingadbSupportHook;
class IcingadbSupport extends IcingadbSupportHook
{
}

View file

@ -0,0 +1,26 @@
<?php
namespace Icinga\Module\Businessprocess\ProvidedHook\Icingadb;
use Icinga\Module\Icingadb\Hook\ServiceActionsHook;
use Icinga\Module\Icingadb\Model\Service;
use ipl\Web\Widget\Link;
class ServiceActions extends ServiceActionsHook
{
public function getActionsForObject(Service $service): array
{
$label = mt('businessprocess', 'Business Impact');
return array(
new Link(
$label,
sprintf(
'businessprocess/node/impact?name=%s',
rawurlencode(
sprintf('%s;%s', $service->host->name, $service->name)
)
)
)
);
}
}

View file

@ -0,0 +1,145 @@
<?php
namespace Icinga\Module\Businessprocess\State;
use Exception;
use Icinga\Application\Benchmark;
use Icinga\Module\Businessprocess\BpConfig;
use Icinga\Module\Businessprocess\IcingaDbObject;
use Icinga\Module\Businessprocess\ServiceNode;
use Icinga\Module\Icingadb\Model\Host;
use Icinga\Module\Icingadb\Model\Service;
use ipl\Sql\Connection as IcingaDbConnection;
use ipl\Stdlib\Filter;
class IcingaDbState
{
/** @var BpConfig */
protected $config;
/** @var IcingaDbConnection */
protected $backend;
public function __construct(BpConfig $config)
{
$this->config = $config;
$this->backend = IcingaDbObject::fetchDb();
}
public static function apply(BpConfig $config)
{
$self = new static($config);
$self->retrieveStatesFromBackend();
return $config;
}
public function retrieveStatesFromBackend()
{
$config = $this->config;
try {
$this->reallyRetrieveStatesFromBackend();
} catch (Exception $e) {
$config->addError(
$config->translate('Could not retrieve process state: %s'),
$e->getMessage()
);
}
}
public function reallyRetrieveStatesFromBackend()
{
$config = $this->config;
Benchmark::measure(sprintf(
'Retrieving states for business process %s using Icinga DB backend',
$config->getName()
));
$hosts = $config->listInvolvedHostNames();
if (empty($hosts)) {
return $this;
}
$queryHost = Host::on($this->backend)->with('state');
IcingaDbObject::applyIcingaDbRestrictions($queryHost);
$queryHost->filter(Filter::equal('host.name', $hosts));
$hostObject = $queryHost->getModel()->getTableName();
Benchmark::measure('Retrieved states for ' . $queryHost->count() . ' hosts in ' . $config->getName());
$queryService = Service::on($this->backend)->with([
'state',
'host',
'host.state'
]);
$queryService->filter(Filter::equal('host.name', $hosts));
IcingaDbObject::applyIcingaDbRestrictions($queryService);
Benchmark::measure('Retrieved states for ' . $queryService->count() . ' services in ' . $config->getName());
$configs = $config->listInvolvedConfigs();
$serviceObject = $queryService->getModel()->getTableName();
foreach ($configs as $cfg) {
foreach ($queryService as $row) {
$this->handleDbRow($row, $cfg, $serviceObject);
}
foreach ($queryHost as $row) {
$this->handleDbRow($row, $cfg, $hostObject);
}
}
Benchmark::measure('Got states for business process ' . $config->getName());
return $this;
}
protected function handleDbRow($row, BpConfig $config, $objectName)
{
if ($objectName === 'service') {
$key = $row->host->name . ';' . $row->name;
} else {
$key = $row->name . ';Hoststatus';
}
// We fetch more states than we need, so skip unknown ones
if (! $config->hasNode($key)) {
return;
}
$node = $config->getNode($key);
if ($this->config->usesHardStates()) {
if ($row->state->hard_state !== null) {
$node->setState($row->state->hard_state)->setMissing(false);
}
} else {
if ($row->state->soft_state !== null) {
$node->setState($row->state->soft_state)->setMissing(false);
}
}
if ($row->state->last_state_change !== null) {
$node->setLastStateChange($row->state->last_state_change/1000);
}
if ($row->state->in_downtime) {
$node->setDowntime(true);
}
if ($row->state->is_acknowledged) {
$node->setAck(true);
}
$node->setAlias($row->display_name);
if ($node instanceof ServiceNode) {
$node->setHostAlias($row->host->display_name);
}
}
}

View file

@ -2,7 +2,10 @@
namespace Icinga\Module\Businessprocess\Web\Component;
use Icinga\Application\Modules\Module;
use Icinga\Authentication\Auth;
use Icinga\Module\Businessprocess\ProvidedHook\Icingadb\IcingadbSupport;
use Icinga\Module\Businessprocess\State\IcingaDbState;
use Icinga\Module\Businessprocess\State\MonitoringState;
use Icinga\Module\Businessprocess\Storage\Storage;
use ipl\Html\BaseHtmlElement;
@ -91,7 +94,14 @@ class Dashboard extends BaseHtmlElement
}
$bp = $storage->loadProcess($name);
MonitoringState::apply($bp);
if (Module::exists('icingadb') &&
(! $bp->hasBackendName() && IcingadbSupport::useIcingaDbAsBackend())
) {
IcingaDbState::apply($bp);
} else {
MonitoringState::apply($bp);
}
$this->add(new BpDashboardTile(
$bp,

View file

@ -3,6 +3,7 @@
namespace Icinga\Module\Businessprocess\Web\Form;
use Icinga\Application\Config;
use Icinga\Application\Icinga;
use Icinga\Authentication\Auth;
use Icinga\Module\Businessprocess\Storage\LegacyStorage;
use Icinga\Module\Businessprocess\BpConfig;
@ -17,8 +18,14 @@ abstract class BpConfigBaseForm extends QuickForm
protected function listAvailableBackends()
{
$keys = array_keys(Config::module('monitoring', 'backends')->toArray());
return array_combine($keys, $keys);
$keys = [];
$moduleManager = Icinga::app()->getModuleManager();
if ($moduleManager->hasEnabled('monitoring')) {
$keys = array_keys(Config::module('monitoring', 'backends')->toArray());
$keys = array_combine($keys, $keys);
}
return $keys;
}
public function setStorage(LegacyStorage $storage)

View file

@ -1,14 +1,14 @@
Name: Businessprocess
Version: 2.3.1
Depends: monitoring (>= 2.4.1), ipl (>= 0.1.1)
Depends: monitoring (>= 2.4.1), icingadb (>= 1.0.0), ipl (>= 0.5.0)
Description: A Business Process viewer and modeler
Provides a web-based process modeler for. It integrates as a module into
Icinga Web 2 and provides a plugin check command for Icinga. Tile and tree
views can be shown inline, as dashlets or fullscreen. All of those for whole
processes or just parts of them.
Hooks into the monitoring module to show Business Impact for a specific host
or service and provides a Business Impact Simulation mode to visualize the
influence of a potential outage.
Hooks into the monitoring or icingadb module to show Business Impact for a
specific host or service and provides a Business Impact Simulation mode to
visualize the influence of a potential outage.
Supports legacy BPaddon config files.

View file

@ -2,4 +2,7 @@
$this->provideHook('monitoring/HostActions');
$this->provideHook('monitoring/ServiceActions');
$this->provideHook('icingadb/HostActions');
$this->provideHook('icingadb/ServiceActions');
$this->provideHook('icingadb/icingadbSupport');
//$this->provideHook('director/shipConfigFiles');