diff options
Diffstat (limited to 'application/controllers/NodeController.php')
-rw-r--r-- | application/controllers/NodeController.php | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/application/controllers/NodeController.php b/application/controllers/NodeController.php new file mode 100644 index 0000000..e5c657f --- /dev/null +++ b/application/controllers/NodeController.php @@ -0,0 +1,148 @@ +<?php + +namespace Icinga\Module\Businessprocess\Controllers; + +use Exception; +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; +use ipl\Html\Html; +use ipl\Web\Widget\Link; + +class NodeController extends Controller +{ + public function impactAction() + { + $this->setAutorefreshInterval(10); + $content = $this->content(); + $this->controls()->add( + $this->singleTab($this->translate('Node Impact')) + ); + $name = $this->params->get('name'); + $this->addTitle($this->translate('Business Impact (%s)'), $name); + + $brokenFiles = []; + $simulation = Simulation::fromSession($this->session()); + foreach ($this->storage()->listProcessNames() as $configName) { + try { + $config = $this->storage()->loadProcess($configName); + } catch (Exception $e) { + $meta = $this->storage()->loadMetadata($configName); + $brokenFiles[$meta->get('Title')] = $configName; + continue; + } + + $parents = []; + if ($config->hasNode($name)) { + foreach ($config->getNode($name)->getPaths() as $path) { + array_pop($path); // Remove the monitored node + $immediateParentName = array_pop($path); // The directly affected process + $parents[] = [$config->getNode($immediateParentName), $path]; + } + } + + $askedConfigs = []; + foreach ($config->getImportedNodes() as $importedNode) { + $importedConfig = $importedNode->getBpConfig(); + + if (isset($askedConfigs[$importedConfig->getName()])) { + continue; + } else { + $askedConfigs[$importedConfig->getName()] = true; + } + + if ($importedConfig->hasNode($name)) { + $node = $importedConfig->getNode($name); + $nativePaths = $node->getPaths($config); + + do { + $path = array_pop($nativePaths); + $importedNodePos = array_search($importedNode->getIdentifier(), $path, true); + if ($importedNodePos !== false) { + array_pop($path); // Remove the monitored node + $immediateParentName = array_pop($path); // The directly affected process + $importedPath = array_slice($path, $importedNodePos + 1); + + // We may get multiple native paths. Though, only the right hand of the path + // is what we're interested in. The left part is not what is getting imported. + $antiDuplicator = join('|', $importedPath) . '|' . $immediateParentName; + if (isset($parents[$antiDuplicator])) { + continue; + } + + foreach ($importedNode->getPaths($config) as $targetPath) { + if ($targetPath[count($targetPath) - 1] === $immediateParentName) { + array_pop($targetPath); + $parent = $importedNode; + } else { + $parent = $importedConfig->getNode($immediateParentName); + } + + $parents[$antiDuplicator] = [$parent, array_merge($targetPath, $importedPath)]; + } + } + } while (! empty($nativePaths)); + } + } + + if (empty($parents)) { + continue; + } + + if (Module::exists('icingadb') && + (! $config->getBackendName() && IcingadbSupport::useIcingaDbAsBackend()) + ) { + IcingaDbState::apply($config); + } else { + MonitoringState::apply($config); + } + $config->applySimulation($simulation); + + foreach ($parents as $parentAndPath) { + $renderer = (new TileRenderer($config, array_shift($parentAndPath))) + ->setUrl(Url::fromPath('businessprocess/process/show', ['config' => $configName])) + ->setPath(array_shift($parentAndPath)); + + $bc = Breadcrumb::create($renderer); + $bc->getAttributes()->set('data-base-target', '_next'); + $content->add($bc); + } + } + + if ($content->isEmpty()) { + $content->add($this->translate('No impact detected. Is this node part of a business process?')); + } + + if (! empty($brokenFiles)) { + $elem = Html::tag( + 'ul', + ['class' => 'broken-files'], + tp( + 'The following business process has an invalid config file and therefore cannot be read:', + 'The following business processes have invalid config files and therefore cannot be read:', + count($brokenFiles) + ) + ); + + foreach ($brokenFiles as $bpName => $fileName) { + $elem->addHtml( + Html::tag( + 'li', + new Link( + sprintf('%s (%s.conf)', $bpName, $fileName), + \ipl\Web\Url::fromPath('businessprocess/process/show', ['config' => $fileName]) + ) + ) + ); + } + + $content->addHtml($elem); + } + } +} |