summaryrefslogtreecommitdiffstats
path: root/application/forms/AddNodeForm.php
diff options
context:
space:
mode:
Diffstat (limited to 'application/forms/AddNodeForm.php')
-rw-r--r--application/forms/AddNodeForm.php579
1 files changed, 579 insertions, 0 deletions
diff --git a/application/forms/AddNodeForm.php b/application/forms/AddNodeForm.php
new file mode 100644
index 0000000..43afa4c
--- /dev/null
+++ b/application/forms/AddNodeForm.php
@@ -0,0 +1,579 @@
+<?php
+
+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\ImportedNode;
+use Icinga\Module\Businessprocess\Modification\ProcessChanges;
+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 EnumList;
+
+ /** @var MonitoringBackend|IcingaDbConnection*/
+ protected $backend;
+
+ /** @var Storage */
+ protected $storage;
+
+ /** @var BpConfig */
+ 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>'
+ );
+ }
+
+ $type = $this->selectNodeType();
+ switch ($type) {
+ case 'host':
+ $this->selectHost();
+ break;
+ case 'service':
+ $this->selectService();
+ break;
+ case 'process':
+ $this->selectProcess();
+ break;
+ case 'new-process':
+ $this->addNewProcess();
+ break;
+ case 'hosts_from_filter':
+ $this->selectHostsFromFilter();
+ break;
+ case 'services_from_filter':
+ $this->selectServicesFromFilter();
+ break;
+ case null:
+ $this->setSubmitLabel($this->translate('Next'));
+ return;
+ }
+ }
+
+ protected function addNewProcess()
+ {
+ $this->addElement('text', 'name', array(
+ 'label' => $this->translate('ID'),
+ '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')
+ ]
+ ]]
+ ]
+ ));
+
+ $this->addElement('text', 'alias', array(
+ 'label' => $this->translate('Display Name'),
+ 'description' => $this->translate(
+ 'Usually this name will be shown for this node. Equals ID'
+ . ' 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'),
+ '%' => $this->translate('DEGRADED'),
+ '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'),
+ )
+ ));
+
+ $display = 1;
+ if ($this->bp->getMetadata()->isManuallyOrdered() && !$this->bp->isEmpty()) {
+ $rootNodes = $this->bp->getRootNodes();
+ $display = end($rootNodes)->getDisplay() + 1;
+ }
+ $this->addElement('select', 'display', array(
+ 'label' => $this->translate('Visualization'),
+ 'required' => true,
+ 'description' => $this->translate(
+ 'Where to show this process'
+ ),
+ 'value' => $this->hasParentNode() ? '0' : "$display",
+ 'multiOptions' => array(
+ "$display" => $this->translate('Toplevel Process'),
+ '0' => $this->translate('Subprocess only'),
+ )
+ ));
+
+ $this->addElement('text', 'infoUrl', array(
+ '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');
+ $types['hosts_from_filter'] = $this->translate('Hosts from filter');
+ $types['services_from_filter'] = $this->translate('Services from filter');
+ } elseif (! $this->hasProcesses()) {
+ $this->addElement('hidden', 'node_type', array(
+ 'ignore' => true,
+ 'decorators' => array('ViewHelper'),
+ 'value' => 'new-process'
+ ));
+
+ return 'new-process';
+ }
+
+ if ($this->hasProcesses() || ($this->hasParentNode() && $this->hasMoreConfigs())) {
+ $types['process'] = $this->translate('Existing Process');
+ }
+
+ $types['new-process'] = $this->translate('New Process Node');
+
+ $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,
+ 'class' => 'autosubmit',
+ 'multiOptions' => $this->optionalEnum($types)
+ ));
+
+ return $this->getSentValue('node_type');
+ }
+
+ protected function selectHost()
+ {
+ $this->addElement('multiselect', 'children', [
+ 'label' => $this->translate('Hosts'),
+ 'required' => true,
+ 'size' => 8,
+ '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]]
+ ]);
+
+ $this->addHostOverrideCheckbox();
+ if ($this->getSentValue('host_override') === '1') {
+ $this->addHostOverrideElement();
+ }
+ }
+
+ protected function selectService()
+ {
+ $this->addHostElement();
+ if ($host = $this->getSentValue('host')) {
+ $this->addServicesElement($host);
+ $this->addServiceOverrideCheckbox();
+
+ if ($this->getSentValue('service_override') === '1') {
+ $this->addServiceOverrideElement();
+ }
+ } else {
+ $this->setSubmitLabel($this->translate('Next'));
+ }
+ }
+
+ protected function addHostElement()
+ {
+ $this->addElement('select', 'host', array(
+ 'label' => $this->translate('Host'),
+ 'required' => true,
+ 'ignore' => true,
+ 'class' => 'autosubmit',
+ 'multiOptions' => $this->optionalEnum($this->enumHostForServiceList()),
+ ));
+ }
+
+ protected function addServicesElement($host)
+ {
+ $this->addElement('multiselect', 'children', [
+ 'label' => $this->translate('Services'),
+ 'required' => true,
+ 'size' => 8,
+ '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]]
+ ]);
+ }
+
+ protected function addFilteredHostsElement($filter)
+ {
+ $this->addElement('submit', 'refresh', [
+ 'label' => $this->translate('Refresh'),
+ 'class' => 'refresh-filter'
+ ]);
+ $this->addElement('multiselect', 'children', [
+ 'label' => $this->translate('Hosts'),
+ 'required' => true,
+ 'size' => 8,
+ 'style' => 'width: 25em',
+ 'multiOptions' => $this->enumHostListByFilter($filter),
+ 'description' => $this->translate(
+ 'Hosts that should be part of this business process node'
+ ),
+ 'validators' => [[new NoDuplicateChildrenValidator($this, $this->bp, $this->parent), true]]
+ ]);
+ }
+
+ protected function addFilteredServicesElement($filter)
+ {
+ $this->addElement('submit', 'refresh', [
+ 'label' => $this->translate('Refresh'),
+ 'class' => 'refresh-filter'
+ ]);
+ $this->addElement('multiselect', 'children', [
+ 'label' => $this->translate('Services'),
+ 'required' => true,
+ 'size' => 8,
+ 'style' => 'width: 25em',
+ 'multiOptions' => $this->enumServiceListByFilter($filter),
+ 'description' => $this->translate(
+ 'Services that should be part of this business process node'
+ ),
+ 'validators' => [[new NoDuplicateChildrenValidator($this, $this->bp, $this->parent), true]]
+ ]);
+ }
+
+ protected function addFilterElement()
+ {
+ $this->addElement('text', 'filter', array(
+ 'label' => $this->translate('Filter'),
+ 'required' => true,
+ 'ignore' => true
+ ));
+ }
+
+ 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'
+ )
+ ]);
+ }
+
+ protected function addHostOverrideCheckbox()
+ {
+ $this->addElement('checkbox', 'host_override', [
+ 'ignore' => true,
+ 'class' => 'autosubmit',
+ 'label' => $this->translate('Override Host State'),
+ 'description' => $this->translate('Enable host state overrides')
+ ]);
+ }
+
+ protected function addHostOverrideElement()
+ {
+ $this->addElement('stateOverrides', 'stateOverrides', [
+ 'required' => true,
+ 'label' => $this->translate('State Overrides'),
+ 'states' => $this->enumHostStateList()
+ ]);
+ }
+
+ protected function addServiceOverrideCheckbox()
+ {
+ $this->addElement('checkbox', 'service_override', [
+ 'ignore' => true,
+ 'class' => 'autosubmit',
+ 'label' => $this->translate('Override Service State'),
+ 'description' => $this->translate('Enable service state overrides')
+ ]);
+ }
+
+ protected function addServiceOverrideElement()
+ {
+ $this->addElement('stateOverrides', 'stateOverrides', [
+ 'required' => true,
+ 'label' => $this->translate('State Overrides'),
+ 'states' => $this->enumServiceStateList()
+ ]);
+ }
+
+ protected function selectHostsFromFilter()
+ {
+ $this->addFilterElement();
+ if ($filter = $this->getSentValue('filter')) {
+ $this->addFilteredHostsElement($filter);
+ } else {
+ $this->setSubmitLabel($this->translate('Next'));
+ }
+ }
+
+ protected function selectServicesFromFilter()
+ {
+ $this->addFilterElement();
+ if ($filter = $this->getSentValue('filter')) {
+ $this->addFilteredServicesElement($filter);
+ } else {
+ $this->setSubmitLabel($this->translate('Next'));
+ }
+ }
+
+ 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'));
+ }
+ }
+
+ /**
+ * @param MonitoringBackend|IcingaDbConnection $backend
+ * @return $this
+ */
+ public function setBackend($backend)
+ {
+ $this->backend = $backend;
+ return $this;
+ }
+
+ /**
+ * @param Storage $storage
+ * @return $this
+ */
+ public function setStorage(Storage $storage)
+ {
+ $this->storage = $storage;
+ return $this;
+ }
+
+ /**
+ * @param BpConfig $process
+ * @return $this
+ */
+ public function setProcess(BpConfig $process)
+ {
+ $this->bp = $process;
+ $this->setBackend($process->getBackend());
+ return $this;
+ }
+
+ /**
+ * @param BpNode|null $node
+ * @return $this
+ */
+ public function setParentNode(BpNode $node = null)
+ {
+ $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 hasProcesses()
+ {
+ return count($this->enumProcesses()) > 0;
+ }
+
+ /**
+ * @param string $file
+ * @return array
+ */
+ protected function enumProcesses($file = null)
+ {
+ $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 ImportedNode && $node instanceof BpNode && ! isset($parents[$node->getName()])) {
+ $name = $node->getName();
+ if ($differentFile) {
+ $name = '@' . $file . ':' . $name;
+ }
+
+ $list[$name] = $node->getName(); // display name?
+ }
+ }
+
+ if (! $this->bp->getMetadata()->isManuallyOrdered()) {
+ natcasesort($list);
+ }
+ 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);
+ }
+ }
+
+ public function onSuccess()
+ {
+ $changes = ProcessChanges::construct($this->bp, $this->session);
+ switch ($this->getValue('node_type')) {
+ case 'host':
+ case 'service':
+ $stateOverrides = $this->getValue('stateOverrides');
+ if (! empty($stateOverrides)) {
+ $childOverrides = [];
+ foreach ($this->getValue('children') as $service) {
+ $childOverrides[$service] = $stateOverrides;
+ }
+
+ $changes->modifyNode($this->parent, [
+ 'stateOverrides' => array_merge($this->parent->getStateOverrides(), $childOverrides)
+ ]);
+ }
+
+ // Fallthrough
+ case 'process':
+ case 'hosts_from_filter':
+ case 'services_from_filter':
+ 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);
+
+ parent::onSuccess();
+ }
+}