icingaweb2-module-businessp.../application/forms/AddNodeForm.php

508 lines
16 KiB
PHP
Raw Normal View History

2016-11-29 09:06:24 -05:00
<?php
namespace Icinga\Module\Businessprocess\Forms;
use Icinga\Module\Businessprocess\BpNode;
2017-01-11 08:04:45 -05:00
use Icinga\Module\Businessprocess\BpConfig;
2016-11-29 09:06:24 -05:00
use Icinga\Module\Businessprocess\Modification\ProcessChanges;
use Icinga\Module\Businessprocess\Storage\Storage;
2016-11-29 09:06:24 -05:00
use Icinga\Module\Businessprocess\Web\Form\QuickForm;
use Icinga\Module\Businessprocess\Web\Form\Validator\NoDuplicateChildrenValidator;
2016-11-29 09:06:24 -05:00
use Icinga\Module\Monitoring\Backend\MonitoringBackend;
use Icinga\Web\Session\SessionNamespace;
class AddNodeForm extends QuickForm
{
/** @var MonitoringBackend */
protected $backend;
/** @var Storage */
protected $storage;
2017-01-11 08:04:45 -05:00
/** @var BpConfig */
2016-11-29 09:06:24 -05:00
protected $bp;
/** @var BpNode */
protected $parent;
protected $objectList = array();
protected $processList = array();
/** @var SessionNamespace */
protected $session;
public function setup()
{
$view = $this->getView();
if ($this->hasParentNode()) {
$this->addHtml(
'<h2>' . $view->escape(
sprintf($this->translate('Add a node to %s'), $this->parent->getAlias())
) . '</h2>'
);
} else {
$this->addHtml(
'<h2>' . $this->translate('Add a new root node') . '</h2>'
);
}
2016-11-29 09:32:56 -05:00
$type = $this->selectNodeType();
2016-11-29 09:06:24 -05:00
switch ($type) {
case 'host':
$this->selectHost();
break;
case 'service':
$this->selectService();
break;
case 'process':
$this->selectProcess();
break;
case 'new-process':
$this->addNewProcess();
break;
2016-11-29 09:06:24 -05:00
case null:
$this->setSubmitLabel($this->translate('Next'));
return;
}
}
protected function addNewProcess()
{
$this->addElement('text', 'name', array(
'label' => $this->translate('ID'),
2016-11-29 09:06:24 -05:00
'required' => true,
'description' => $this->translate(
'This is the unique identifier of this process'
),
'validators' => [
['Callback', true, [
'callback' => function ($value) {
if ($this->hasParentNode()) {
return ! $this->parent->hasChild($value);
}
return ! $this->bp->hasRootNode($value);
},
'messages' => [
'callbackValue' => $this->translate('%value% is already defined in this process')
]
]]
]
2016-11-29 09:06:24 -05:00
));
$this->addElement('text', 'alias', array(
'label' => $this->translate('Display Name'),
2016-11-29 09:06:24 -05:00
'description' => $this->translate(
'Usually this name will be shown for this node. Equals ID'
2016-11-29 09:06:24 -05:00
. ' if not given'
),
));
$this->addElement('select', 'operator', array(
'label' => $this->translate('Operator'),
'required' => true,
'multiOptions' => array(
'&' => $this->translate('AND'),
'|' => $this->translate('OR'),
'!' => $this->translate('NOT'),
'1' => $this->translate('MIN 1'),
'2' => $this->translate('MIN 2'),
'3' => $this->translate('MIN 3'),
'4' => $this->translate('MIN 4'),
'5' => $this->translate('MIN 5'),
'6' => $this->translate('MIN 6'),
'7' => $this->translate('MIN 7'),
'8' => $this->translate('MIN 8'),
'9' => $this->translate('MIN 9'),
)
));
$this->addElement('select', 'display', array(
'label' => $this->translate('Visualization'),
'required' => true,
'description' => $this->translate(
'Where to show this process'
),
'value' => $this->hasParentNode() ? '0' : '1',
'multiOptions' => array(
'1' => $this->translate('Toplevel Process'),
'0' => $this->translate('Subprocess only'),
)
));
$this->addElement('text', 'infoUrl', array(
2016-11-29 09:06:24 -05:00
'label' => $this->translate('Info URL'),
'description' => $this->translate(
'URL pointing to more information about this node'
)
));
}
/**
* @return string|null
*/
protected function selectNodeType()
{
$types = array();
if ($this->hasParentNode()) {
$types['host'] = $this->translate('Host');
$types['service'] = $this->translate('Service');
} elseif (! $this->hasProcesses()) {
$this->addElement('hidden', 'node_type', array(
'ignore' => true,
'decorators' => array('ViewHelper'),
'value' => 'new-process'
));
return 'new-process';
2016-11-29 09:06:24 -05:00
}
if ($this->hasProcesses() || ($this->hasParentNode() && $this->hasMoreConfigs())) {
$types['process'] = $this->translate('Existing Process');
}
$types['new-process'] = $this->translate('New Process Node');
2016-11-29 09:06:24 -05:00
$this->addElement('select', 'node_type', array(
'label' => $this->translate('Node type'),
'required' => true,
'description' => $this->translate(
'The node type you want to add'
),
'ignore' => true,
2016-11-29 09:06:24 -05:00
'class' => 'autosubmit',
'multiOptions' => $this->optionalEnum($types)
));
return $this->getSentValue('node_type');
}
protected function selectHost()
{
$this->addElement('multiselect','children', [
2016-11-29 09:06:24 -05:00
'label' => $this->translate('Hosts'),
'required' => true,
'size' => 8,
2016-11-29 09:06:24 -05:00
'style' => 'width: 25em',
'multiOptions' => $this->enumHostList(),
'description' => $this->translate(
'Hosts that should be part of this business process node'
),
'validators' => [[new NoDuplicateChildrenValidator($this, $this->bp, $this->parent), true]]
]);
2016-11-29 09:06:24 -05:00
}
protected function selectService()
{
$this->addHostElement();
if ($host = $this->getSentValue('host')) {
$this->addServicesElement($host);
} else {
$this->setSubmitLabel($this->translate('Next'));
2016-11-29 09:06:24 -05:00
}
}
protected function addHostElement()
{
$this->addElement('select', 'host', array(
'label' => $this->translate('Host'),
'required' => true,
'ignore' => true,
'class' => 'autosubmit',
'multiOptions' => $this->optionalEnum($this->enumHostForServiceList()),
2016-11-29 09:06:24 -05:00
));
}
protected function addServicesElement($host)
{
$this->addElement('multiselect','children', [
2016-11-29 09:06:24 -05:00
'label' => $this->translate('Services'),
'required' => true,
'size' => 8,
2016-11-29 09:06:24 -05:00
'style' => 'width: 25em',
'multiOptions' => $this->enumServiceList($host),
'description' => $this->translate(
'Services that should be part of this business process node'
),
'validators' => [[new NoDuplicateChildrenValidator($this, $this->bp, $this->parent), true]]
]);
2016-11-29 09:06:24 -05:00
}
protected function addFileElement()
{
$this->addElement('select', 'file', [
'label' => $this->translate('File'),
'required' => true,
'ignore' => true,
'value' => $this->bp->getName(),
'class' => 'autosubmit',
'multiOptions' => $this->optionalEnum($this->enumConfigs()),
'description' => $this->translate(
'Choose a different configuration file to import its processes'
)
]);
}
2016-11-29 09:06:24 -05:00
protected function selectProcess()
{
if ($this->hasParentNode()) {
$this->addFileElement();
}
if (($file = $this->getSentValue('file')) || !$this->hasParentNode()) {
$this->addElement('multiselect','children', [
'label' => $this->translate('Process nodes'),
'required' => true,
'size' => 8,
'style' => 'width: 25em',
'multiOptions' => $this->enumProcesses($file),
'description' => $this->translate(
'Other processes that should be part of this business process node'
),
'validators' => [[new NoDuplicateChildrenValidator($this, $this->bp, $this->parent), true]]
]);
} else {
$this->setSubmitLabel($this->translate('Next'));
}
2016-11-29 09:06:24 -05:00
}
/**
* @param MonitoringBackend $backend
* @return $this
*/
public function setBackend(MonitoringBackend $backend)
{
$this->backend = $backend;
return $this;
}
/**
* @param Storage $storage
* @return $this
*/
public function setStorage(Storage $storage)
{
$this->storage = $storage;
return $this;
}
2016-11-29 09:06:24 -05:00
/**
2017-01-11 08:04:45 -05:00
* @param BpConfig $process
2016-11-29 09:06:24 -05:00
* @return $this
*/
2017-01-11 08:04:45 -05:00
public function setProcess(BpConfig $process)
2016-11-29 09:06:24 -05:00
{
$this->bp = $process;
$this->setBackend($process->getBackend());
return $this;
}
/**
* @param BpNode|null $node
2016-11-29 09:06:24 -05:00
* @return $this
*/
public function setParentNode(BpNode $node = null)
2016-11-29 09:06:24 -05:00
{
$this->parent = $node;
return $this;
}
/**
* @return bool
*/
public function hasParentNode()
{
return $this->parent !== null;
}
/**
* @param SessionNamespace $session
* @return $this
*/
public function setSession(SessionNamespace $session)
{
$this->session = $session;
return $this;
}
protected function enumHostForServiceList()
2016-11-29 09:06:24 -05:00
{
$names = $this->backend->select()->from('hostStatus', array(
'hostname' => 'host_name',
))->order('host_name')->getQuery()->fetchColumn();
// fetchPairs doesn't seem to work when using the same column with
// different aliases twice
2016-11-29 09:06:24 -05:00
return array_combine((array) $names, (array) $names);
}
protected function enumHostList()
{
$names = $this->backend->select()->from('hostStatus', array(
'hostname' => 'host_name',
))->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;
}
2016-11-29 09:06:24 -05:00
protected function enumServiceList($host)
{
$query = $this->backend->select()->from(
'serviceStatus',
array('service' => 'service_description')
)->where('host_name', $host);
$query->order('service_description');
$names = $query->getQuery()->fetchColumn();
$services = array();
foreach ($names as $name) {
$services[$host . ';' . $name] = $name;
}
return $services;
}
protected function hasProcesses()
{
return count($this->enumProcesses()) > 0;
}
/**
* @param string $file
* @return array
*/
protected function enumProcesses($file = null)
2016-11-29 09:06:24 -05:00
{
$list = array();
$parents = array();
$differentFile = $file !== null && $file !== $this->bp->getName();
if (! $differentFile && $this->hasParentNode()) {
$this->collectAllParents($this->parent, $parents);
$parents[$this->parent->getName()] = $this->parent;
}
$bp = $this->bp;
if ($differentFile) {
$bp = $this->storage->loadProcess($file);
}
foreach ($bp->getNodes() as $node) {
if ($node instanceof BpNode && ! isset($parents[$node->getName()])) {
$name = $node->getName();
if ($differentFile) {
$name = '@' . $file . ':' . $name;
}
$list[$name] = (string) $node; // display name?
2016-11-29 09:06:24 -05:00
}
}
2018-08-13 07:30:33 -04:00
natcasesort($list);
2016-11-29 09:06:24 -05:00
return $list;
}
protected function hasMoreConfigs()
{
$configs = $this->enumConfigs();
return !empty($configs);
}
protected function enumConfigs()
{
return $this->storage->listProcesses();
}
/**
* Collect the given node's parents recursively into the given array by their names
*
* @param BpNode $node
* @param BpNode[] $parents
*/
protected function collectAllParents(BpNode $node, array & $parents)
{
foreach ($node->getParents() as $parent) {
$parents[$parent->getName()] = $parent;
$this->collectAllParents($parent, $parents);
}
}
2016-11-29 09:06:24 -05:00
protected function fetchObjectList()
{
$this->objectList = array();
$hosts = $this->backend->select()->from('hostStatus', array(
'hostname' => 'host_name',
'in_downtime' => 'host_in_downtime',
'ack' => 'host_acknowledged',
'state' => 'host_state'
))->order('host_name')->getQuery()->fetchAll();
$services = $this->backend->select()->from('serviceStatus', array(
'hostname' => 'host_name',
'service' => 'service_description',
'in_downtime' => 'service_in_downtime',
'ack' => 'service_acknowledged',
'state' => 'service_state'
))->order('host_name')->order('service_description')->getQuery()->fetchAll();
foreach ($hosts as $host) {
$this->objectList[$host->hostname] = array(
$host->hostname . ';Hoststatus' => 'Host Status'
);
}
foreach ($services as $service) {
$this->objectList[$service->hostname][
$service->hostname . ';' . $service->service
] = $service->service;
}
return $this;
}
public function onSuccess()
{
$changes = ProcessChanges::construct($this->bp, $this->session);
switch ($this->getValue('node_type')) {
case 'host':
case 'service':
case 'process':
if ($this->hasParentNode()) {
$changes->addChildrenToNode($this->getValue('children'), $this->parent);
} else {
foreach ($this->getValue('children') as $nodeName) {
$changes->copyNode($nodeName);
}
}
break;
case 'new-process':
$properties = $this->getValues();
unset($properties['name']);
if ($this->hasParentNode()) {
$properties['parentName'] = $this->parent->getName();
}
$changes->createNode($this->getValue('name'), $properties);
break;
}
// Trigger session destruction to make sure it get's stored.
// TODO: figure out why this is necessary, might be an unclean shutdown on redirect
unset($changes);
2016-11-29 09:06:24 -05:00
parent::onSuccess();
}
}