diff options
Diffstat (limited to '')
69 files changed, 11372 insertions, 0 deletions
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/IdoBackend.php b/modules/monitoring/library/Monitoring/Backend/Ido/IdoBackend.php new file mode 100644 index 0000000..71fc6a1 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/IdoBackend.php @@ -0,0 +1,10 @@ +<?php +/* Icinga Web 2 | (c) 2014 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido; + +use Icinga\Module\Monitoring\Backend\MonitoringBackend; + +class IdoBackend extends MonitoringBackend +{ +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/AllcontactsQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/AllcontactsQuery.php new file mode 100644 index 0000000..3598726 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/AllcontactsQuery.php @@ -0,0 +1,75 @@ +<?php +/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Zend_Db_Select; + +class AllcontactsQuery extends IdoQuery +{ + protected $columnMap = array( + 'contacts' => array( + 'contact_name' => 'c.contact_name', + 'host_object_id' => 'c.host_object_id', + 'host_name' => 'c.host_name', + 'service_object_id' => 'c.service_object_id', + 'service_host_name' => 'c.service_host_name', + 'service_description' => 'c.service_description', + + 'contact_alias' => 'c.contact_alias', + 'contact_email' => 'c.contact_email', + 'contact_pager' => 'c.contact_pager', + 'contact_has_host_notfications' => 'c.contact_has_host_notfications', + 'contact_has_service_notfications' => 'c.contact_has_service_notfications', + 'contact_can_submit_commands' => 'c.contact_can_submit_commands', + 'contact_notify_service_recovery' => 'c.notify_service_recovery', + 'contact_notify_service_warning' => 'c.notify_service_warning', + 'contact_notify_service_critical' => 'c.notify_service_critical', + 'contact_notify_service_unknown' => 'c.notify_service_unknown', + 'contact_notify_service_flapping' => 'c.notify_service_flapping', + 'contact_notify_service_downtime' => 'c.notify_service_downtime', + 'contact_notify_host_recovery' => 'c.notify_host_recovery', + 'contact_notify_host_down' => 'c.notify_host_down', + 'contact_notify_host_unreachable' => 'c.notify_host_unreachable', + 'contact_notify_host_flapping' => 'c.notify_host_flapping', + 'contact_notify_host_downtime' => 'c.notify_host_downtime', + + + ) + ); + + protected $contacts; + protected $contactgroups; + protected $baseQuery; + protected $useSubqueryCount = true; + + public function requireColumn($alias) + { + $this->contacts->addColumn($alias); + $this->contactgroups->addColumn($alias); + return parent::requireColumn($alias); + } + + protected function joinBaseTables() + { + $this->contacts = $this->createSubQuery( + 'contact', + array('contact_name') + ); + $this->contactgroups = $this->createSubQuery( + 'contactgroup', + array('contact_name') + ); + $sub = $this->db->select()->union( + array($this->contacts, $this->contactgroups), + Zend_Db_Select::SQL_UNION_ALL + ); + + $this->baseQuery = $this->db->select()->distinct()->from( + array('c' => $sub), + array() + ); + + $this->joinedVirtualTables = array('contacts' => true); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommandQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommandQuery.php new file mode 100644 index 0000000..59a4ccb --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommandQuery.php @@ -0,0 +1,61 @@ +<?php +/* Icinga Web 2 | (c) 2014 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +/** + * Query for commands + */ +class CommandQuery extends IdoQuery +{ + /** + * @var array + */ + protected $columnMap = array( + 'commands' => array( + 'command_id' => 'c.command_id', + 'command_instance_id' => 'c.instance_id', + 'command_config_type' => 'c.config_type', + 'command_line' => 'c.command_line', + 'command_name' => 'co.name1' + ), + + 'contacts' => array( + 'contact_id' => 'con.contact_id', + 'contact_alias' => 'con.contact_alias' + ) + ); + + /** + * Fetch basic information about commands + */ + protected function joinBaseTables() + { + $this->select->from( + array('c' => $this->prefix . 'commands'), + array() + )->join( + array('co' => $this->prefix . 'objects'), + 'co.object_id = c.object_id', + array() + ); + + $this->joinedVirtualTables = array('commands' => true); + } + + /** + * Join contacts + */ + protected function joinContacts() + { + $this->select->join( + array('cnc' => $this->prefix . 'contact_notificationcommands'), + 'cnc.command_object_id = co.object_id', + array() + )->join( + array('con' => $this->prefix . 'contacts'), + 'con.contact_id = cnc.contact_id', + array() + ); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommentQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommentQuery.php new file mode 100644 index 0000000..6c01931 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommentQuery.php @@ -0,0 +1,158 @@ +<?php +/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Data\Filter\FilterExpression; +use Zend_Db_Expr; +use Zend_Db_Select; +use Icinga\Data\Filter\Filter; + +/** + * Query for host and service comments + */ +class CommentQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'comments' => array( + 'comment_author' => 'c.comment_author', + 'comment_author_name' => 'c.comment_author_name', + 'comment_data' => 'c.comment_data', + 'comment_expiration' => 'c.comment_expiration', + 'comment_internal_id' => 'c.comment_internal_id', + 'comment_is_persistent' => 'c.comment_is_persistent', + 'comment_name' => 'c.comment_name', + 'comment_timestamp' => 'c.comment_timestamp', + 'comment_type' => 'c.comment_type', + 'instance_name' => 'c.instance_name', + 'object_type' => 'c.object_type' + ), + 'hosts' => array( + 'host_display_name' => 'c.host_display_name', + 'host_name' => 'c.host_name', + 'host_state' => 'c.host_state' + ), + 'services' => array( + 'service_description' => 'c.service_description', + 'service_display_name' => 'c.service_display_name', + 'service_host_name' => 'c.service_host_name', + 'service_state' => 'c.service_state' + ) + ); + + /** + * The union + * + * @var Zend_Db_Select + */ + protected $commentQuery; + + /** + * Subqueries used for the comment query + * + * @var IdoQuery[] + */ + protected $subQueries = array(); + + /** + * {@inheritdoc} + */ + public function allowsCustomVars() + { + foreach ($this->subQueries as $query) { + if (! $query->allowsCustomVars()) { + return false; + } + } + + return true; + } + + /** + * {@inheritdoc} + */ + public function addFilter(Filter $filter) + { + foreach ($this->subQueries as $sub) { + $sub->applyFilter(clone $filter); + } + return $this; + } + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + if (version_compare($this->getIdoVersion(), '1.14.0', '<')) { + $this->columnMap['comments']['comment_name'] = '(NULL)'; + } + $this->commentQuery = $this->db->select(); + $this->select->from( + array('c' => $this->commentQuery), + array() + ); + $this->joinedVirtualTables['comments'] = true; + } + + /** + * Join hosts + */ + protected function joinHosts() + { + $columns = array_keys($this->columnMap['comments'] + $this->columnMap['hosts']); + foreach (array_keys($this->columnMap['services']) as $column) { + $columns[$column] = new Zend_Db_Expr('NULL'); + } + $hosts = $this->createSubQuery('hostcomment', $columns); + $this->subQueries[] = $hosts; + $this->commentQuery->union(array($hosts), Zend_Db_Select::SQL_UNION_ALL); + } + + /** + * Join services + */ + protected function joinServices() + { + $columns = array_keys($this->columnMap['comments'] + $this->columnMap['hosts'] + $this->columnMap['services']); + $services = $this->createSubQuery('servicecomment', $columns); + $this->subQueries[] = $services; + $this->commentQuery->union(array($services), Zend_Db_Select::SQL_UNION_ALL); + } + + /** + * {@inheritdoc} + */ + public function order($columnOrAlias, $dir = null) + { + foreach ($this->subQueries as $sub) { + $sub->requireColumn($columnOrAlias); + } + return parent::order($columnOrAlias, $dir); + } + + /** + * {@inheritdoc} + */ + public function where($condition, $value = null) + { + $this->requireColumn($condition); + foreach ($this->subQueries as $sub) { + $sub->where($condition, $value); + } + return $this; + } + + public function whereEx(FilterExpression $ex) + { + $this->requireColumn($ex->getColumn()); + foreach ($this->subQueries as $sub) { + $sub->whereEx($ex); + } + + return $this; + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommentdeletionhistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommentdeletionhistoryQuery.php new file mode 100644 index 0000000..8cb4ddb --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommentdeletionhistoryQuery.php @@ -0,0 +1,179 @@ +<?php +/* Icinga Web 2 | (c) 2014 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Data\Filter\FilterExpression; +use Zend_Db_Expr; +use Zend_Db_Select; +use Icinga\Data\Filter\Filter; + +/** + * Query for host and service comment removal records + */ +class CommentdeletionhistoryQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'commenthistory' => array( + 'id' => 'cdh.id', + 'object_type' => 'cdh.object_type' + ), + 'history' => array( + 'type' => 'cdh.type', + 'timestamp' => 'cdh.timestamp', + 'object_id' => 'cdh.object_id', + 'state' => 'cdh.state', + 'output' => 'cdh.output' + ), + 'hosts' => array( + 'host_display_name' => 'cdh.host_display_name', + 'host_name' => 'cdh.host_name' + ), + 'services' => array( + 'service_description' => 'cdh.service_description', + 'service_display_name' => 'cdh.service_display_name', + 'service_host_name' => 'cdh.service_host_name' + ) + ); + + /** + * The union + * + * @var Zend_Db_Select + */ + protected $commentDeletionHistoryQuery; + + /** + * Subqueries used for the comment history query + * + * @var IdoQuery[] + */ + protected $subQueries = array(); + + /** + * Whether to additionally select all history columns + * + * @var bool + */ + protected $fetchHistoryColumns = false; + + /** + * {@inheritdoc} + */ + public function allowsCustomVars() + { + foreach ($this->subQueries as $query) { + if (! $query->allowsCustomVars()) { + return false; + } + } + + return true; + } + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + $this->commentDeletionHistoryQuery = $this->db->select(); + $this->select->from( + array('cdh' => $this->commentDeletionHistoryQuery), + array() + ); + $this->joinedVirtualTables['commenthistory'] = true; + } + + /** + * Join history related columns and tables + */ + protected function joinHistory() + { + // TODO: Ensure that one is selecting the history columns first... + $this->fetchHistoryColumns = true; + $this->requireVirtualTable('hosts'); + $this->requireVirtualTable('services'); + } + + /** + * Join hosts + */ + protected function joinHosts() + { + $columns = array_keys( + $this->columnMap['commenthistory'] + $this->columnMap['hosts'] + ); + foreach ($this->columnMap['services'] as $column => $_) { + $columns[$column] = new Zend_Db_Expr('NULL'); + } + if ($this->fetchHistoryColumns) { + $columns = array_merge($columns, array_keys($this->columnMap['history'])); + } + $hosts = $this->createSubQuery('Hostcommentdeletionhistory', $columns); + $this->subQueries[] = $hosts; + $this->commentDeletionHistoryQuery->union(array($hosts), Zend_Db_Select::SQL_UNION_ALL); + } + + /** + * Join services + */ + protected function joinServices() + { + $columns = array_keys( + $this->columnMap['commenthistory'] + $this->columnMap['hosts'] + $this->columnMap['services'] + ); + if ($this->fetchHistoryColumns) { + $columns = array_merge($columns, array_keys($this->columnMap['history'])); + } + $services = $this->createSubQuery('Servicecommentdeletionhistory', $columns); + $this->subQueries[] = $services; + $this->commentDeletionHistoryQuery->union(array($services), Zend_Db_Select::SQL_UNION_ALL); + } + + /** + * {@inheritdoc} + */ + public function order($columnOrAlias, $dir = null) + { + foreach ($this->subQueries as $sub) { + $sub->requireColumn($columnOrAlias); + } + return parent::order($columnOrAlias, $dir); + } + + /** + * {@inheritdoc} + */ + public function where($condition, $value = null) + { + $this->requireColumn($condition); + foreach ($this->subQueries as $sub) { + $sub->where($condition, $value); + } + return $this; + } + + /** + * {@inheritdoc} + */ + public function addFilter(Filter $filter) + { + foreach ($this->subQueries as $sub) { + $sub->applyFilter(clone $filter); + } + return $this; + } + + public function whereEx(FilterExpression $ex) + { + $this->requireColumn($ex->getColumn()); + foreach ($this->subQueries as $sub) { + $sub->whereEx($ex); + } + + return $this; + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommenteventQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommenteventQuery.php new file mode 100644 index 0000000..c85adff --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommenteventQuery.php @@ -0,0 +1,39 @@ +<?php +/* Icinga Web 2 | (c) 2017 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +/** + * Query for host and service comment entry and deletion events + */ +class CommenteventQuery extends IdoQuery +{ + protected $columnMap = array( + 'commentevent' => array( + 'commentevent_id' => 'ch.commenthistory_id', + 'commentevent_entry_type' => "(CASE ch.entry_type WHEN 1 THEN 'comment' WHEN 2 THEN 'downtime' WHEN 3 THEN 'flapping' WHEN 4 THEN 'ack' ELSE NULL END)", + 'commentevent_comment_time' => 'UNIX_TIMESTAMP(ch.comment_time)', + 'commentevent_author_name' => 'ch.author_name', + 'commentevent_comment_data' => 'ch.comment_data', + 'commentevent_is_persistent' => 'ch.is_persistent', + 'commentevent_comment_source' => "(CASE ch.comment_source WHEN 0 THEN 'icinga' WHEN 1 THEN 'user' ELSE NULL END)", + 'commentevent_expires' => 'ch.expires', + 'commentevent_expiration_time' => 'UNIX_TIMESTAMP(ch.expiration_time)', + 'commentevent_deletion_time' => 'UNIX_TIMESTAMP(ch.deletion_time)' + ), + 'object' => array( + 'host_name' => 'o.name1', + 'service_description' => 'o.name2' + ) + ); + + protected function joinBaseTables() + { + $this->select() + ->from(array('ch' => $this->prefix . 'commenthistory'), array()) + ->join(array('o' => $this->prefix . 'objects'), 'ch.object_id = o.object_id', array()); + + $this->joinedVirtualTables['commentevent'] = true; + $this->joinedVirtualTables['object'] = true; + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommenthistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommenthistoryQuery.php new file mode 100644 index 0000000..47dd97c --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommenthistoryQuery.php @@ -0,0 +1,179 @@ +<?php +/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Data\Filter\FilterExpression; +use Zend_Db_Expr; +use Zend_Db_Select; +use Icinga\Data\Filter\Filter; + +/** + * Query for host and service comment history records + */ +class CommenthistoryQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'commenthistory' => array( + 'id' => 'ch.id', + 'object_type' => 'ch.object_type' + ), + 'history' => array( + 'type' => 'ch.type', + 'timestamp' => 'ch.timestamp', + 'object_id' => 'ch.object_id', + 'state' => 'ch.state', + 'output' => 'ch.output' + ), + 'hosts' => array( + 'host_display_name' => 'ch.host_display_name', + 'host_name' => 'ch.host_name' + ), + 'services' => array( + 'service_description' => 'ch.service_description', + 'service_display_name' => 'ch.service_display_name', + 'service_host_name' => 'ch.service_host_name' + ) + ); + + /** + * The union + * + * @var Zend_Db_Select + */ + protected $commentHistoryQuery; + + /** + * Subqueries used for the comment history query + * + * @var IdoQuery[] + */ + protected $subQueries = array(); + + /** + * Whether to additionally select all history columns + * + * @var bool + */ + protected $fetchHistoryColumns = false; + + /** + * {@inheritdoc} + */ + public function allowsCustomVars() + { + foreach ($this->subQueries as $query) { + if (! $query->allowsCustomVars()) { + return false; + } + } + + return true; + } + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + $this->commentHistoryQuery = $this->db->select(); + $this->select->from( + array('ch' => $this->commentHistoryQuery), + array() + ); + $this->joinedVirtualTables['commenthistory'] = true; + } + + /** + * Join history related columns and tables + */ + protected function joinHistory() + { + // TODO: Ensure that one is selecting the history columns first... + $this->fetchHistoryColumns = true; + $this->requireVirtualTable('hosts'); + $this->requireVirtualTable('services'); + } + + /** + * Join hosts + */ + protected function joinHosts() + { + $columns = array_keys( + $this->columnMap['commenthistory'] + $this->columnMap['hosts'] + ); + foreach ($this->columnMap['services'] as $column => $_) { + $columns[$column] = new Zend_Db_Expr('NULL'); + } + if ($this->fetchHistoryColumns) { + $columns = array_merge($columns, array_keys($this->columnMap['history'])); + } + $hosts = $this->createSubQuery('Hostcommenthistory', $columns); + $this->subQueries[] = $hosts; + $this->commentHistoryQuery->union(array($hosts), Zend_Db_Select::SQL_UNION_ALL); + } + + /** + * Join services + */ + protected function joinServices() + { + $columns = array_keys( + $this->columnMap['commenthistory'] + $this->columnMap['hosts'] + $this->columnMap['services'] + ); + if ($this->fetchHistoryColumns) { + $columns = array_merge($columns, array_keys($this->columnMap['history'])); + } + $services = $this->createSubQuery('Servicecommenthistory', $columns); + $this->subQueries[] = $services; + $this->commentHistoryQuery->union(array($services), Zend_Db_Select::SQL_UNION_ALL); + } + + /** + * {@inheritdoc} + */ + public function order($columnOrAlias, $dir = null) + { + foreach ($this->subQueries as $sub) { + $sub->requireColumn($columnOrAlias); + } + return parent::order($columnOrAlias, $dir); + } + + /** + * {@inheritdoc} + */ + public function where($condition, $value = null) + { + $this->requireColumn($condition); + foreach ($this->subQueries as $sub) { + $sub->where($condition, $value); + } + return $this; + } + + /** + * {@inheritdoc} + */ + public function addFilter(Filter $filter) + { + foreach ($this->subQueries as $sub) { + $sub->applyFilter(clone $filter); + } + return $this; + } + + public function whereEx(FilterExpression $ex) + { + $this->requireColumn($ex->getColumn()); + foreach ($this->subQueries as $sub) { + $sub->whereEx($ex); + } + + return $this; + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactQuery.php new file mode 100644 index 0000000..ca10323 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactQuery.php @@ -0,0 +1,139 @@ +<?php +/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Data\Filter\FilterExpression; +use Zend_Db_Select; +use Icinga\Data\Filter\Filter; + +/** + * Query for contacts + */ +class ContactQuery extends IdoQuery +{ + protected $columnMap = [ + 'contacts' => [ + 'contact_id' => 'c.contact_id', + 'contact' => 'c.contact', + 'contact_name' => 'c.contact_name', + 'contact_alias' => 'c.contact_alias', + 'contact_email' => 'c.contact_email', + 'contact_pager' => 'c.contact_pager', + 'contact_object_id' => 'c.contact_object_id', + 'contact_has_host_notfications' => 'c.contact_has_host_notfications', + 'contact_has_service_notfications' => 'c.contact_has_service_notfications', + 'contact_can_submit_commands' => 'c.contact_can_submit_commands', + 'contact_notify_service_recovery' => 'c.contact_notify_service_recovery', + 'contact_notify_service_warning' => 'c.contact_notify_service_warning', + 'contact_notify_service_critical' => 'c.contact_notify_service_critical', + 'contact_notify_service_unknown' => 'c.contact_notify_service_unknown', + 'contact_notify_service_flapping' => 'c.contact_notify_service_flapping', + 'contact_notify_service_downtime' => 'c.contact_notify_service_downtime', + 'contact_notify_host_recovery' => 'c.contact_notify_host_recovery', + 'contact_notify_host_down' => 'c.contact_notify_host_down', + 'contact_notify_host_unreachable' => 'c.contact_notify_host_unreachable', + 'contact_notify_host_flapping' => 'c.contact_notify_host_flapping', + 'contact_notify_host_downtime' => 'c.contact_notify_host_downtime', + 'contact_notify_host_timeperiod' => 'c.contact_notify_host_timeperiod', + 'contact_notify_service_timeperiod' => 'c.contact_notify_service_timeperiod' + ] + ]; + + /** @var Zend_Db_Select The union */ + protected $contactQuery; + + /** @var IdoQuery[] Subqueries used for the contact query */ + protected $subQueries = []; + + public function allowsCustomVars() + { + foreach ($this->subQueries as $query) { + if (! $query->allowsCustomVars()) { + return false; + } + } + + return true; + } + + public function addFilter(Filter $filter) + { + $strangers = array_diff( + $filter->listFilteredColumns(), + array_keys($this->columnMap['contacts']) + ); + if (! empty($strangers)) { + $this->transformToUnion(); + } + + foreach ($this->subQueries as $sub) { + $sub->applyFilter(clone $filter); + } + + return $this; + } + + protected function joinBaseTables() + { + $this->contactQuery = $this->createSubQuery('Hostcontact', array_keys($this->columnMap['contacts'])); + $this->contactQuery->setIsSubQuery(); + $this->subQueries[] = $this->contactQuery; + + $this->select->from( + ['c' => $this->contactQuery], + [] + ); + + $this->joinedVirtualTables['contacts'] = true; + } + + public function order($columnOrAlias, $dir = null) + { + foreach ($this->subQueries as $sub) { + $sub->requireColumn($columnOrAlias); + } + + return parent::order($columnOrAlias, $dir); + } + + public function where($condition, $value = null) + { + $this->requireColumn($condition); + foreach ($this->subQueries as $sub) { + $sub->where($condition, $value); + } + + return $this; + } + + public function whereEx(FilterExpression $ex) + { + $this->requireColumn($ex->getColumn()); + foreach ($this->subQueries as $sub) { + $sub->whereEx($ex); + } + + return $this; + } + + public function transformToUnion() + { + $this->contactQuery = $this->db->select(); + $this->select->reset(); + $this->subQueries = []; + + $this->select->distinct()->from( + ['c' => $this->contactQuery], + [] + ); + + $hosts = $this->createSubQuery('Hostcontact', array_keys($this->columnMap['contacts'])); + $this->subQueries[] = $hosts; + $this->contactQuery->union([$hosts], Zend_Db_Select::SQL_UNION_ALL); + + $services = $this->createSubQuery('Servicecontact', array_keys($this->columnMap['contacts'])); + $this->subQueries[] = $services; + $this->contactQuery->union([$services], Zend_Db_Select::SQL_UNION_ALL); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactgroupQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactgroupQuery.php new file mode 100644 index 0000000..7d4cbc1 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactgroupQuery.php @@ -0,0 +1,214 @@ +<?php +/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +/** + * Query for contact groups + */ +class ContactgroupQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $allowCustomVars = true; + + /** + * {@inheritdoc} + */ + protected $groupBase = array('contactgroups' => array('cg.contactgroup_id', 'cgo.object_id')); + + /** + * {@inheritdoc} + */ + protected $groupOrigin = array('hosts', 'members', 'services'); + + protected $subQueryTargets = array( + 'hostgroups' => 'hostgroup', + 'servicegroups' => 'servicegroup' + ); + + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'contactgroups' => array( + 'contactgroup' => 'cgo.name1 COLLATE latin1_general_ci', + 'contactgroup_name' => 'cgo.name1', + 'contactgroup_alias' => 'cg.alias COLLATE latin1_general_ci' + ), + 'members' => array( + 'contact_count' => 'SUM(CASE WHEN cgmo.object_id IS NOT NULL THEN 1 ELSE 0 END)' + ), + 'hostgroups' => array( + 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci', + 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci', + 'hostgroup_name' => 'hgo.name1' + ), + 'hosts' => array( + 'host' => 'ho.name1 COLLATE latin1_general_ci', + 'host_name' => 'ho.name1', + 'host_alias' => 'h.alias', + 'host_display_name' => 'h.display_name COLLATE latin1_general_ci' + ), + 'instances' => array( + 'instance_name' => 'i.instance_name' + ), + 'servicegroups' => array( + 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci', + 'servicegroup_name' => 'sgo.name1', + 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci' + ), + 'services' => array( + 'service' => 'so.name2 COLLATE latin1_general_ci', + 'service_description' => 'so.name2', + 'service_display_name' => 's.display_name COLLATE latin1_general_ci', + 'service_host_name' => 'so.name1' + ) + ); + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + $this->select->from( + array('cg' => $this->prefix . 'contactgroups'), + array() + )->join( + array('cgo' => $this->prefix . 'objects'), + 'cgo.object_id = cg.contactgroup_object_id AND cgo.is_active = 1 AND cgo.objecttype_id = 11', + array() + ); + $this->joinedVirtualTables['contactgroups'] = true; + } + + /** + * Join contact group members + */ + protected function joinMembers() + { + $this->select->joinLeft( + array('cgm' => $this->prefix . 'contactgroup_members'), + 'cgm.contactgroup_id = cg.contactgroup_id', + array() + )->joinLeft( + array('cgmo' => $this->prefix . 'objects'), + 'cgmo.object_id = cgm.contact_object_id AND cgmo.is_active = 1 AND cgmo.objecttype_id = 10', + array() + ); + } + + /** + * Join host groups + */ + protected function joinHostgroups() + { + $this->requireVirtualTable('hosts'); + $this->select->joinLeft( + array('hgm' => $this->prefix . 'hostgroup_members'), + 'hgm.host_object_id = ho.object_id', + array() + )->joinLeft( + array('hg' => $this->prefix . 'hostgroups'), + 'hg.hostgroup_id = hgm.hostgroup_id', + array() + )->joinLeft( + array('hgo' => $this->prefix . 'objects'), + 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3', + array() + ); + } + + /** + * Join hosts + */ + protected function joinHosts() + { + $this->select->joinLeft( + array('hcg' => $this->prefix . 'host_contactgroups'), + 'hcg.contactgroup_object_id = cg.contactgroup_object_id', + array() + )->joinLeft( + array('h' => $this->prefix . 'hosts'), + 'h.host_id = hcg.host_id', + array() + )->joinLeft( + array('ho' => $this->prefix . 'objects'), + 'ho.object_id = h.host_object_id AND ho.is_active = 1 AND ho.objecttype_id = 1', + array() + ); + } + + /** + * Join instances + */ + protected function joinInstances() + { + $this->select->join( + array('i' => $this->prefix . 'instances'), + 'i.instance_id = cg.instance_id', + array() + ); + } + + /** + * Join service groups + */ + protected function joinServicegroups() + { + $this->requireVirtualTable('services'); + $this->select->joinLeft( + array('sgm' => $this->prefix . 'servicegroup_members'), + 'sgm.service_object_id = s.service_object_id', + array() + )->joinLeft( + array('sg' => $this->prefix . 'servicegroups'), + 'sg.servicegroup_id = sgm.servicegroup_id', + array() + )->joinLeft( + array('sgo' => $this->prefix . 'objects'), + 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4', + array() + ); + } + + /** + * Join services + */ + protected function joinServices() + { + $this->select->joinLeft( + array('scg' => $this->prefix . 'service_contactgroups'), + 'scg.contactgroup_object_id = cg.contactgroup_object_id', + array() + )->joinLeft( + array('s' => $this->prefix . 'services'), + 's.service_id = scg.service_id', + array() + )->joinLeft( + array('so' => $this->prefix . 'objects'), + 'so.object_id = s.service_object_id AND so.is_active = 1 AND so.objecttype_id = 2', + array() + ); + } + + protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter) + { + if ($name === 'hostgroup') { + $this->requireVirtualTable('hosts'); + + $query->joinVirtualTable('members'); + + return ['hgm.host_object_id', 'ho.object_id']; + } elseif ($name === 'servicegroup') { + $this->requireVirtualTable('services'); + + $query->joinVirtualTable('members'); + + return ['sgm.service_object_id', 'so.object_id']; + } + + return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/CustomvarQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CustomvarQuery.php new file mode 100644 index 0000000..1492894 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CustomvarQuery.php @@ -0,0 +1,116 @@ +<?php +/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Application\Config; +use Icinga\Data\Filter\FilterExpression; + +class CustomvarQuery extends IdoQuery +{ + protected $columnMap = array( + 'instances' => array( + 'instance_name' => 'i.instance_name' + ), + 'customvariablestatus' => array( + 'varname' => 'cvs.varname', + 'varvalue' => 'cvs.varvalue', + 'is_json' => 'cvs.is_json', + ), + 'objects' => array( + 'host' => 'cvo.name1 COLLATE latin1_general_ci', + 'host_name' => 'cvo.name1', + 'service' => 'cvo.name2 COLLATE latin1_general_ci', + 'service_description' => 'cvo.name2', + 'contact' => 'cvo.name1 COLLATE latin1_general_ci', + 'contact_name' => 'cvo.name1', + 'object_type' => "CASE cvo.objecttype_id WHEN 1 THEN 'host' WHEN 2 THEN 'service' WHEN 10 THEN 'contact' ELSE 'invalid' END", + 'object_type_id' => 'cvo.objecttype_id' +// 'object_type' => "CASE cvo.objecttype_id WHEN 1 THEN 'host' WHEN 2 THEN 'service' WHEN 3 THEN 'hostgroup' WHEN 4 THEN 'servicegroup' WHEN 5 THEN 'hostescalation' WHEN 6 THEN 'serviceescalation' WHEN 7 THEN 'hostdependency' WHEN 8 THEN 'servicedependency' WHEN 9 THEN 'timeperiod' WHEN 10 THEN 'contact' WHEN 11 THEN 'contactgroup' WHEN 12 THEN 'command' ELSE 'other' END" + ), + ); + + public function where($expression, $parameters = null) + { + $types = array('host' => 1, 'service' => 2, 'contact' => 10); + if ($expression === 'object_type') { + parent::where('object_type_id', $types[$parameters]); + } else { + parent::where($expression, $parameters); + } + return $this; + } + + public function whereEx(FilterExpression $ex) + { + $types = ['host' => 1, 'service' => 2, 'contact' => 10]; + if ($ex->getColumn() === 'object_type') { + $ex = clone $ex; + $ex->setColumn('object_type_id'); + $ex->setExpression($types[$ex->getExpression()]); + } + + parent::whereEx($ex); + + return $this; + } + + protected function joinBaseTables() + { + if (version_compare($this->getIdoVersion(), '1.12.0', '<')) { + $this->columnMap['customvariablestatus']['is_json'] = '(0)'; + } + + if (! (bool) Config::module('monitoring')->get('ido', 'use_customvar_status_table', true)) { + $table = 'customvariables'; + } else { + $table = 'customvariablestatus'; + } + + $this->select->from( + array('cvs' => $this->prefix . $table), + array() + )->join( + array('cvo' => $this->prefix . 'objects'), + 'cvs.object_id = cvo.object_id AND cvo.is_active = 1', + array() + ); + $this->joinedVirtualTables = array( + 'customvariablestatus' => true, + 'objects' => true + ); + } + + /** + * Join instances + */ + protected function joinInstances() + { + $this->select->join( + array('i' => $this->prefix . 'instances'), + 'i.instance_id = cvs.instance_id', + array() + ); + } + + /** + * {@inheritdoc} + */ + public function getGroup() + { + $group = parent::getGroup(); + if (! empty($group) && $this->ds->getDbType() === 'pgsql') { + foreach ($this->columnMap as $table => $columns) { + $pk = ($table === 'objects' ? 'cvo.' : 'cvs.') . $this->getPrimaryKeyColumn($table); + foreach ($columns as $alias => $_) { + if (! in_array($pk, $group, true) && in_array($alias, $group, true)) { + $group[] = $pk; + break; + } + } + } + } + + return $group; + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimeQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimeQuery.php new file mode 100644 index 0000000..9bc1d88 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimeQuery.php @@ -0,0 +1,163 @@ +<?php +/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Data\Filter\FilterExpression; +use Zend_Db_Expr; +use Zend_Db_Select; +use Icinga\Data\Filter\Filter; + +/** + * Query for host and service downtimes + */ +class DowntimeQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'downtimes' => array( + 'downtime_author' => 'd.downtime_author', + 'downtime_author_name' => 'd.downtime_author_name', + 'downtime_comment' => 'd.downtime_comment', + 'downtime_duration' => 'd.downtime_duration', + 'downtime_end' => 'd.downtime_end', + 'downtime_entry_time' => 'd.downtime_entry_time', + 'downtime_internal_id' => 'd.downtime_internal_id', + 'downtime_is_fixed' => 'd.downtime_is_fixed', + 'downtime_is_flexible' => 'd.downtime_is_flexible', + 'downtime_is_in_effect' => 'd.downtime_is_in_effect', + 'downtime_name' => 'd.downtime_name', + 'downtime_scheduled_end' => 'd.downtime_scheduled_end', + 'downtime_scheduled_start' => 'd.downtime_scheduled_start', + 'downtime_start' => 'd.downtime_start', + 'object_type' => 'd.object_type', + 'instance_name' => 'd.instance_name' + ), + 'hosts' => array( + 'host_display_name' => 'd.host_display_name', + 'host_name' => 'd.host_name', + 'host_state' => 'd.host_state' + ), + 'services' => array( + 'service_description' => 'd.service_description', + 'service_display_name' => 'd.service_display_name', + 'service_host_name' => 'd.service_host_name', + 'service_state' => 'd.service_state' + ) + ); + + /** + * The union + * + * @var Zend_Db_Select + */ + protected $downtimeQuery; + + /** + * Subqueries used for the downtime query + * + * @var IdoQuery[] + */ + protected $subQueries = array(); + + /** + * {@inheritdoc} + */ + public function allowsCustomVars() + { + foreach ($this->subQueries as $query) { + if (! $query->allowsCustomVars()) { + return false; + } + } + + return true; + } + + /** + * {@inheritdoc} + */ + public function addFilter(Filter $filter) + { + foreach ($this->subQueries as $sub) { + $sub->applyFilter(clone $filter); + } + return $this; + } + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + if (version_compare($this->getIdoVersion(), '1.14.0', '<')) { + $this->columnMap['downtimes']['downtime_name'] = '(NULL)'; + } + $this->downtimeQuery = $this->db->select(); + $this->select->from( + array('d' => $this->downtimeQuery), + array() + ); + $this->joinedVirtualTables['downtimes'] = true; + } + + /** + * Join hosts + */ + protected function joinHosts() + { + $columns = array_keys($this->columnMap['downtimes'] + $this->columnMap['hosts']); + foreach (array_keys($this->columnMap['services']) as $column) { + $columns[$column] = new Zend_Db_Expr('NULL'); + } + $hosts = $this->createSubQuery('hostdowntime', $columns); + $this->subQueries[] = $hosts; + $this->downtimeQuery->union(array($hosts), Zend_Db_Select::SQL_UNION_ALL); + } + + /** + * Join services + */ + protected function joinServices() + { + $columns = array_keys($this->columnMap['downtimes'] + $this->columnMap['hosts'] + $this->columnMap['services']); + $services = $this->createSubQuery('servicedowntime', $columns); + $this->subQueries[] = $services; + $this->downtimeQuery->union(array($services), Zend_Db_Select::SQL_UNION_ALL); + } + + /** + * {@inheritdoc} + */ + public function order($columnOrAlias, $dir = null) + { + foreach ($this->subQueries as $sub) { + $sub->requireColumn($columnOrAlias); + } + return parent::order($columnOrAlias, $dir); + } + + /** + * {@inheritdoc} + */ + public function where($condition, $value = null) + { + $this->requireColumn($condition); + foreach ($this->subQueries as $sub) { + $sub->where($condition, $value); + } + return $this; + } + + public function whereEx(FilterExpression $ex) + { + $this->requireColumn($ex->getColumn()); + foreach ($this->subQueries as $sub) { + $sub->whereEx($ex); + } + + return $this; + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimeendhistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimeendhistoryQuery.php new file mode 100644 index 0000000..de47418 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimeendhistoryQuery.php @@ -0,0 +1,179 @@ +<?php +/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Data\Filter\FilterExpression; +use Zend_Db_Expr; +use Zend_Db_Select; +use Icinga\Data\Filter\Filter; + +/** + * Query for host and service downtime end history records + */ +class DowntimeendhistoryQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'downtimehistory' => array( + 'id' => 'deh.id', + 'object_type' => 'deh.object_type' + ), + 'history' => array( + 'type' => 'deh.type', + 'timestamp' => 'deh.timestamp', + 'object_id' => 'deh.object_id', + 'state' => 'deh.state', + 'output' => 'deh.output' + ), + 'hosts' => array( + 'host_display_name' => 'deh.host_display_name', + 'host_name' => 'deh.host_name' + ), + 'services' => array( + 'service_description' => 'deh.service_description', + 'service_display_name' => 'deh.service_display_name', + 'service_host_name' => 'deh.service_host_name' + ) + ); + + /** + * The union + * + * @var Zend_Db_Select + */ + protected $downtimeEndHistoryQuery; + + /** + * Subqueries used for the downtime end history query + * + * @var IdoQuery[] + */ + protected $subQueries = array(); + + /** + * Whether to additionally select all history columns + * + * @var bool + */ + protected $fetchHistoryColumns = false; + + /** + * {@inheritdoc} + */ + public function allowsCustomVars() + { + foreach ($this->subQueries as $query) { + if (! $query->allowsCustomVars()) { + return false; + } + } + + return true; + } + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + $this->downtimeEndHistoryQuery = $this->db->select(); + $this->select->from( + array('deh' => $this->downtimeEndHistoryQuery), + array() + ); + $this->joinedVirtualTables['downtimehistory'] = true; + } + + /** + * Join history related columns and tables + */ + protected function joinHistory() + { + // TODO: Ensure that one is selecting the history columns first... + $this->fetchHistoryColumns = true; + $this->requireVirtualTable('hosts'); + $this->requireVirtualTable('services'); + } + + /** + * Join hosts + */ + protected function joinHosts() + { + $columns = array_keys( + $this->columnMap['downtimehistory'] + $this->columnMap['hosts'] + ); + foreach ($this->columnMap['services'] as $column => $_) { + $columns[$column] = new Zend_Db_Expr('NULL'); + } + if ($this->fetchHistoryColumns) { + $columns = array_merge($columns, array_keys($this->columnMap['history'])); + } + $hosts = $this->createSubQuery('Hostdowntimeendhistory', $columns); + $this->subQueries[] = $hosts; + $this->downtimeEndHistoryQuery->union(array($hosts), Zend_Db_Select::SQL_UNION_ALL); + } + + /** + * Join services + */ + protected function joinServices() + { + $columns = array_keys( + $this->columnMap['downtimehistory'] + $this->columnMap['hosts'] + $this->columnMap['services'] + ); + if ($this->fetchHistoryColumns) { + $columns = array_merge($columns, array_keys($this->columnMap['history'])); + } + $services = $this->createSubQuery('Servicedowntimeendhistory', $columns); + $this->subQueries[] = $services; + $this->downtimeEndHistoryQuery->union(array($services), Zend_Db_Select::SQL_UNION_ALL); + } + + /** + * {@inheritdoc} + */ + public function order($columnOrAlias, $dir = null) + { + foreach ($this->subQueries as $sub) { + $sub->requireColumn($columnOrAlias); + } + return parent::order($columnOrAlias, $dir); + } + + /** + * {@inheritdoc} + */ + public function where($condition, $value = null) + { + $this->requireColumn($condition); + foreach ($this->subQueries as $sub) { + $sub->where($condition, $value); + } + return $this; + } + + /** + * {@inheritdoc} + */ + public function addFilter(Filter $filter) + { + foreach ($this->subQueries as $sub) { + $sub->applyFilter(clone $filter); + } + return $this; + } + + public function whereEx(FilterExpression $ex) + { + $this->requireColumn($ex->getColumn()); + foreach ($this->subQueries as $sub) { + $sub->whereEx($ex); + } + + return $this; + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimeeventQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimeeventQuery.php new file mode 100644 index 0000000..04e6aa5 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimeeventQuery.php @@ -0,0 +1,42 @@ +<?php +/* Icinga Web 2 | (c) 2017 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +/** + * Query for host and service downtime events + */ +class DowntimeeventQuery extends IdoQuery +{ + protected $columnMap = array( + 'downtimeevent' => array( + 'downtimeevent_id' => 'dth.downtimehistory_id', + 'downtimeevent_entry_time' => 'UNIX_TIMESTAMP(dth.entry_time)', + 'downtimeevent_author_name' => 'dth.author_name', + 'downtimeevent_comment_data' => 'dth.comment_data', + 'downtimeevent_is_fixed' => 'dth.is_fixed', + 'downtimeevent_scheduled_start_time' => 'UNIX_TIMESTAMP(dth.scheduled_start_time)', + 'downtimeevent_scheduled_end_time' => 'UNIX_TIMESTAMP(dth.scheduled_end_time)', + 'downtimeevent_was_started' => 'dth.was_started', + 'downtimeevent_actual_start_time' => 'UNIX_TIMESTAMP(dth.actual_start_time)', + 'downtimeevent_actual_end_time' => 'UNIX_TIMESTAMP(dth.actual_end_time)', + 'downtimeevent_was_cancelled' => 'dth.was_cancelled', + 'downtimeevent_is_in_effect' => 'dth.is_in_effect', + 'downtimeevent_trigger_time' => 'UNIX_TIMESTAMP(dth.trigger_time)' + ), + 'object' => array( + 'host_name' => 'o.name1', + 'service_description' => 'o.name2' + ) + ); + + protected function joinBaseTables() + { + $this->select() + ->from(array('dth' => $this->prefix . 'downtimehistory'), array()) + ->join(array('o' => $this->prefix . 'objects'), 'dth.object_id = o.object_id', array()); + + $this->joinedVirtualTables['downtimeevent'] = true; + $this->joinedVirtualTables['object'] = true; + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimestarthistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimestarthistoryQuery.php new file mode 100644 index 0000000..3ba600d --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimestarthistoryQuery.php @@ -0,0 +1,179 @@ +<?php +/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Data\Filter\FilterExpression; +use Zend_Db_Expr; +use Zend_Db_Select; +use Icinga\Data\Filter\Filter; + +/** + * Query for host and service downtime start history records + */ +class DowntimestarthistoryQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'downtimehistory' => array( + 'id' => 'dsh.id', + 'object_type' => 'dsh.object_type' + ), + 'history' => array( + 'type' => 'dsh.type', + 'timestamp' => 'dsh.timestamp', + 'object_id' => 'dsh.object_id', + 'state' => 'dsh.state', + 'output' => 'dsh.output' + ), + 'hosts' => array( + 'host_display_name' => 'dsh.host_display_name', + 'host_name' => 'dsh.host_name' + ), + 'services' => array( + 'service_description' => 'dsh.service_description', + 'service_display_name' => 'dsh.service_display_name', + 'service_host_name' => 'dsh.service_host_name' + ) + ); + + /** + * The union + * + * @var Zend_Db_Select + */ + protected $downtimeStartHistoryQuery; + + /** + * Subqueries used for the downtime start history query + * + * @var IdoQuery[] + */ + protected $subQueries = array(); + + /** + * Whether to additionally select all history columns + * + * @var bool + */ + protected $fetchHistoryColumns = false; + + /** + * {@inheritdoc} + */ + public function allowsCustomVars() + { + foreach ($this->subQueries as $query) { + if (! $query->allowsCustomVars()) { + return false; + } + } + + return true; + } + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + $this->downtimeStartHistoryQuery = $this->db->select(); + $this->select->from( + array('dsh' => $this->downtimeStartHistoryQuery), + array() + ); + $this->joinedVirtualTables['downtimehistory'] = true; + } + + /** + * Join history related columns and tables + */ + protected function joinHistory() + { + // TODO: Ensure that one is selecting the history columns first... + $this->fetchHistoryColumns = true; + $this->requireVirtualTable('hosts'); + $this->requireVirtualTable('services'); + } + + /** + * Join hosts + */ + protected function joinHosts() + { + $columns = array_keys( + $this->columnMap['downtimehistory'] + $this->columnMap['hosts'] + ); + foreach ($this->columnMap['services'] as $column => $_) { + $columns[$column] = new Zend_Db_Expr('NULL'); + } + if ($this->fetchHistoryColumns) { + $columns = array_merge($columns, array_keys($this->columnMap['history'])); + } + $hosts = $this->createSubQuery('Hostdowntimestarthistory', $columns); + $this->subQueries[] = $hosts; + $this->downtimeStartHistoryQuery->union(array($hosts), Zend_Db_Select::SQL_UNION_ALL); + } + + /** + * Join services + */ + protected function joinServices() + { + $columns = array_keys( + $this->columnMap['downtimehistory'] + $this->columnMap['hosts'] + $this->columnMap['services'] + ); + if ($this->fetchHistoryColumns) { + $columns = array_merge($columns, array_keys($this->columnMap['history'])); + } + $services = $this->createSubQuery('Servicedowntimestarthistory', $columns); + $this->subQueries[] = $services; + $this->downtimeStartHistoryQuery->union(array($services), Zend_Db_Select::SQL_UNION_ALL); + } + + /** + * {@inheritdoc} + */ + public function order($columnOrAlias, $dir = null) + { + foreach ($this->subQueries as $sub) { + $sub->requireColumn($columnOrAlias); + } + return parent::order($columnOrAlias, $dir); + } + + /** + * {@inheritdoc} + */ + public function where($condition, $value = null) + { + $this->requireColumn($condition); + foreach ($this->subQueries as $sub) { + $sub->where($condition, $value); + } + return $this; + } + + /** + * {@inheritdoc} + */ + public function addFilter(Filter $filter) + { + foreach ($this->subQueries as $sub) { + $sub->applyFilter(clone $filter); + } + return $this; + } + + public function whereEx(FilterExpression $ex) + { + $this->requireColumn($ex->getColumn()); + foreach ($this->subQueries as $sub) { + $sub->whereEx($ex); + } + + return $this; + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/EmptyhostgroupQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/EmptyhostgroupQuery.php new file mode 100644 index 0000000..a99d6b7 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/EmptyhostgroupQuery.php @@ -0,0 +1,38 @@ +<?php +/* Icinga Web 2 | (c) 2019 Icinga GmbH | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +class EmptyhostgroupQuery extends HostgroupQuery +{ + protected $subQueryTargets = []; + + protected $columnMap = [ + 'hostgroups' => [ + 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci', + 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci', + 'hostgroup_name' => 'hgo.name1', + 'host_name' => '(NULL)', + 'service_description' => '(NULL)', + 'servicegroup_name' => '(NULL)', + 'host_contact' => '(NULL)', + 'host_contactgroup' => '(NULL)' + ], + 'instances' => [ + 'instance_name' => 'i.instance_name' + ] + ]; + + protected function joinBaseTables() + { + parent::joinBaseTables(); + + $this->select->joinLeft( + ['ehgm' => $this->prefix . 'hostgroup_members'], + 'ehgm.hostgroup_id = hg.hostgroup_id', + [] + ); + $this->select->group(['hgo.object_id', 'hg.hostgroup_id']); + $this->select->having('COUNT(ehgm.hostgroup_member_id) = ?', 0); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/EmptyservicegroupQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/EmptyservicegroupQuery.php new file mode 100644 index 0000000..88ee4c3 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/EmptyservicegroupQuery.php @@ -0,0 +1,51 @@ +<?php +/* Icinga Web 2 | (c) 2019 Icinga GmbH | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +class EmptyservicegroupQuery extends ServicegroupQuery +{ + protected $subQueryTargets = []; + + protected $columnMap = [ + 'servicegroups' => [ + 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci', + 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci', + 'servicegroup_name' => 'sgo.name1', + 'host_name' => '(NULL)', + 'hostgroup_name' => '(NULL)', + 'service_description' => '(NULL)', + 'host_contact' => '(NULL)', + 'host_contactgroup' => '(NULL)', + 'service_contact' => '(NULL)', + 'service_contactgroup' => '(NULL)' + ], + 'instances' => [ + 'instance_name' => 'i.instance_name' + ] + ]; + + protected function joinBaseTables() + { + parent::joinBaseTables(); + + $this->select->joinLeft( + ['esgm' => $this->prefix . 'servicegroup_members'], + 'esgm.servicegroup_id = sg.servicegroup_id', + [] + ); + $this->select->group(['sgo.object_id', 'sg.servicegroup_id']); + $this->select->having('COUNT(esgm.servicegroup_member_id) = ?', 0); + } + + protected function joinHosts() + { + parent::joinHosts(); + + $this->select->joinLeft( + ['h' => 'icinga_hosts'], + 'h.host_object_id = s.host_object_id', + [] + ); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventgridQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventgridQuery.php new file mode 100644 index 0000000..4a75bf2 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventgridQuery.php @@ -0,0 +1,56 @@ +<?php +/* Icinga Web 2 | (c) 2014 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +abstract class EventgridQuery extends StatehistoryQuery +{ + /** + * The columns additionally provided by this query + * + * @var array + */ + protected $additionalColumns = array( + 'day' => 'DATE(FROM_UNIXTIME(sth.timestamp))', + 'cnt_up' => "SUM(CASE WHEN sth.state = 0 THEN 1 ELSE 0 END)", + 'cnt_down_hard' => "SUM(CASE WHEN sth.state = 1 AND sth.type = 'hard_state' THEN 1 ELSE 0 END)", + 'cnt_down' => "SUM(CASE WHEN sth.state = 1 THEN 1 ELSE 0 END)", + 'cnt_unreachable_hard' => "SUM(CASE WHEN sth.state = 2 AND sth.type = 'hard_state' THEN 1 ELSE 0 END)", + 'cnt_unreachable' => "SUM(CASE WHEN sth.state = 2 THEN 1 ELSE 0 END)", + 'cnt_unknown' => "SUM(CASE WHEN sth.state = 3 THEN 1 ELSE 0 END)", + 'cnt_unknown_hard' => "SUM(CASE WHEN sth.state = 3 AND sth.type = 'hard_state' THEN 1 ELSE 0 END)", + 'cnt_critical' => "SUM(CASE WHEN sth.state = 2 THEN 1 ELSE 0 END)", + 'cnt_critical_hard' => "SUM(CASE WHEN sth.state = 2 AND sth.type = 'hard_state' THEN 1 ELSE 0 END)", + 'cnt_warning' => "SUM(CASE WHEN sth.state = 1 THEN 1 ELSE 0 END)", + 'cnt_warning_hard' => "SUM(CASE WHEN sth.state = 1 AND sth.type = 'hard_state' THEN 1 ELSE 0 END)", + 'cnt_ok' => "SUM(CASE WHEN sth.state = 0 THEN 1 ELSE 0 END)" + ); + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + parent::joinBaseTables(); + $this->requireVirtualTable('history'); + $this->columnMap['statehistory'] += $this->additionalColumns; + $this->select->group(array('DATE(FROM_UNIXTIME(sth.timestamp))')); + } + + /** + * {@inheritdoc} + */ + public function order($columnOrAlias, $dir = null) + { + if (array_key_exists($columnOrAlias, $this->additionalColumns)) { + $subQueries = $this->subQueries; + $this->subQueries = array(); + parent::order($columnOrAlias, $dir); + $this->subQueries = $subQueries; + } else { + parent::order($columnOrAlias, $dir); + } + + return $this; + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventgridhostsQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventgridhostsQuery.php new file mode 100644 index 0000000..62d92e4 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventgridhostsQuery.php @@ -0,0 +1,16 @@ +<?php + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +class EventgridhostsQuery extends EventgridQuery +{ + + /** + * Join history related columns and tables, hosts only + */ + protected function joinHistory() + { + $this->fetchHistoryColumns = true; + $this->requireVirtualTable('hosts'); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventgridservicesQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventgridservicesQuery.php new file mode 100644 index 0000000..424de45 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventgridservicesQuery.php @@ -0,0 +1,15 @@ +<?php + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +class EventgridservicesQuery extends EventgridQuery +{ + /** + * Join history related columns and tables, services only + */ + protected function joinHistory() + { + $this->fetchHistoryColumns = true; + $this->requireVirtualTable('services'); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventhistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventhistoryQuery.php new file mode 100644 index 0000000..680e2ca --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventhistoryQuery.php @@ -0,0 +1,134 @@ +<?php +/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Data\Filter\FilterExpression; +use Zend_Db_Select; +use Icinga\Data\Filter\Filter; + +/** + * Query for event history records + */ +class EventhistoryQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $useSubqueryCount = true; + + /** + * Subqueries used for the event history query + * + * @type IdoQuery[] + */ + protected $subQueries = array(); + + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'eventhistory' => array( + 'id' => 'eh.id', + 'host_name' => 'eh.host_name', + 'service_description' => 'eh.service_description', + 'object_type' => 'eh.object_type', + 'timestamp' => 'eh.timestamp', + 'state' => 'eh.state', + 'output' => 'eh.output', + 'type' => 'eh.type', + 'host_display_name' => 'eh.host_display_name', + 'service_display_name' => 'eh.service_display_name' + ) + ); + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + $columns = array( + 'id', + 'timestamp', + 'output', + 'type', + 'state', + 'object_type', + 'host_name', + 'service_description', + 'host_display_name', + 'service_display_name' + ); + $this->subQueries = array( + $this->createSubQuery('Notificationhistory', $columns), + $this->createSubQuery('Statehistory', $columns), + $this->createSubQuery('Downtimestarthistory', $columns), + $this->createSubQuery('Downtimeendhistory', $columns), + $this->createSubQuery('Commenthistory', $columns), + $this->createSubQuery('Commentdeletionhistory', $columns), + $this->createSubQuery('Flappingstarthistory', $columns), + $this->createSubQuery('Flappingendhistory', $columns) + ); + $sub = $this->db->select()->union($this->subQueries, Zend_Db_Select::SQL_UNION_ALL); + $this->select->from(array('eh' => $sub), array()); + $this->joinedVirtualTables['eventhistory'] = true; + } + + /** + * {@inheritdoc} + */ + public function allowsCustomVars() + { + foreach ($this->subQueries as $query) { + if (! $query->allowsCustomVars()) { + return false; + } + } + + return true; + } + + /** + * {@inheritdoc} + */ + public function order($columnOrAlias, $dir = null) + { + foreach ($this->subQueries as $sub) { + $sub->requireColumn($columnOrAlias); + } + return parent::order($columnOrAlias, $dir); + } + + /** + * {@inheritdoc} + */ + public function where($condition, $value = null) + { + $this->requireColumn($condition); + foreach ($this->subQueries as $sub) { + $sub->where($condition, $value); + } + return $this; + } + + /** + * {@inheritdoc} + */ + public function addFilter(Filter $filter) + { + foreach ($this->subQueries as $sub) { + $sub->applyFilter(clone $filter); + } + return $this; + } + + public function whereEx(FilterExpression $ex) + { + $this->requireColumn($ex->getColumn()); + foreach ($this->subQueries as $sub) { + $sub->whereEx($ex); + } + + return $this; + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/FlappingendhistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/FlappingendhistoryQuery.php new file mode 100644 index 0000000..7bdf332 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/FlappingendhistoryQuery.php @@ -0,0 +1,49 @@ +<?php +/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Zend_Db_Expr; +use Zend_Db_Select; +use Icinga\Data\Filter\Filter; + +/** + * Query for host and service flapping end history records + */ +class FlappingendhistoryQuery extends FlappingstarthistoryQuery +{ + /** + * Join hosts + */ + protected function joinHosts() + { + $columns = array_keys( + $this->columnMap['flappinghistory'] + $this->columnMap['hosts'] + ); + foreach ($this->columnMap['services'] as $column => $_) { + $columns[$column] = new Zend_Db_Expr('NULL'); + } + if ($this->fetchHistoryColumns) { + $columns = array_merge($columns, array_keys($this->columnMap['history'])); + } + $hosts = $this->createSubQuery('Hostflappingendhistory', $columns); + $this->subQueries[] = $hosts; + $this->flappingStartHistoryQuery->union(array($hosts), Zend_Db_Select::SQL_UNION_ALL); + } + + /** + * Join services + */ + protected function joinServices() + { + $columns = array_keys( + $this->columnMap['flappinghistory'] + $this->columnMap['hosts'] + $this->columnMap['services'] + ); + if ($this->fetchHistoryColumns) { + $columns = array_merge($columns, array_keys($this->columnMap['history'])); + } + $services = $this->createSubQuery('Serviceflappingendhistory', $columns); + $this->subQueries[] = $services; + $this->flappingStartHistoryQuery->union(array($services), Zend_Db_Select::SQL_UNION_ALL); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/FlappingeventQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/FlappingeventQuery.php new file mode 100644 index 0000000..d993467 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/FlappingeventQuery.php @@ -0,0 +1,36 @@ +<?php +/* Icinga Web 2 | (c) 2017 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +/** + * Query for host and service flapping events + */ +class FlappingeventQuery extends IdoQuery +{ + protected $columnMap = array( + 'flappingevent' => array( + 'flappingevent_id' => 'fh.flappinghistory_id', + 'flappingevent_event_time' => 'UNIX_TIMESTAMP(fh.event_time)', + 'flappingevent_event_type' => "(CASE fh.event_type WHEN 1000 THEN 'flapping' WHEN 1001 THEN 'flapping_deleted' ELSE NULL END)", + 'flappingevent_reason_type' => "(CASE fh.reason_type WHEN 1 THEN 'stopped' WHEN 2 THEN 'disabled' ELSE NULL END)", + 'flappingevent_percent_state_change' => 'fh.percent_state_change', + 'flappingevent_low_threshold' => 'fh.low_threshold', + 'flappingevent_high_threshold' => 'fh.high_threshold' + ), + 'object' => array( + 'host_name' => 'o.name1', + 'service_description' => 'o.name2' + ) + ); + + protected function joinBaseTables() + { + $this->select() + ->from(array('fh' => $this->prefix . 'flappinghistory'), array()) + ->join(array('o' => $this->prefix . 'objects'), 'fh.object_id = o.object_id', array()); + + $this->joinedVirtualTables['flappingevent'] = true; + $this->joinedVirtualTables['object'] = true; + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/FlappingstarthistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/FlappingstarthistoryQuery.php new file mode 100644 index 0000000..5c8bec5 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/FlappingstarthistoryQuery.php @@ -0,0 +1,179 @@ +<?php +/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Data\Filter\FilterExpression; +use Zend_Db_Expr; +use Zend_Db_Select; +use Icinga\Data\Filter\Filter; + +/** + * Query for host and service flapping start history records + */ +class FlappingstarthistoryQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'flappinghistory' => array( + 'id' => 'fsh.id', + 'object_type' => 'fsh.object_type' + ), + 'history' => array( + 'type' => 'fsh.type', + 'timestamp' => 'fsh.timestamp', + 'object_id' => 'fsh.object_id', + 'state' => 'fsh.state', + 'output' => 'fsh.output' + ), + 'hosts' => array( + 'host_display_name' => 'fsh.host_display_name', + 'host_name' => 'fsh.host_name' + ), + 'services' => array( + 'service_description' => 'fsh.service_description', + 'service_display_name' => 'fsh.service_display_name', + 'service_host_name' => 'fsh.service_host_name' + ) + ); + + /** + * The union + * + * @var Zend_Db_Select + */ + protected $flappingStartHistoryQuery; + + /** + * Subqueries used for the flapping start history query + * + * @var IdoQuery[] + */ + protected $subQueries = array(); + + /** + * Whether to additionally select all history columns + * + * @var bool + */ + protected $fetchHistoryColumns = false; + + /** + * {@inheritdoc} + */ + public function allowsCustomVars() + { + foreach ($this->subQueries as $query) { + if (! $query->allowsCustomVars()) { + return false; + } + } + + return true; + } + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + $this->flappingStartHistoryQuery = $this->db->select(); + $this->select->from( + array('fsh' => $this->flappingStartHistoryQuery), + array() + ); + $this->joinedVirtualTables['flappinghistory'] = true; + } + + /** + * Join history related columns and tables + */ + protected function joinHistory() + { + // TODO: Ensure that one is selecting the history columns first... + $this->fetchHistoryColumns = true; + $this->requireVirtualTable('hosts'); + $this->requireVirtualTable('services'); + } + + /** + * Join hosts + */ + protected function joinHosts() + { + $columns = array_keys( + $this->columnMap['flappinghistory'] + $this->columnMap['hosts'] + ); + foreach ($this->columnMap['services'] as $column => $_) { + $columns[$column] = new Zend_Db_Expr('NULL'); + } + if ($this->fetchHistoryColumns) { + $columns = array_merge($columns, array_keys($this->columnMap['history'])); + } + $hosts = $this->createSubQuery('Hostflappingstarthistory', $columns); + $this->subQueries[] = $hosts; + $this->flappingStartHistoryQuery->union(array($hosts), Zend_Db_Select::SQL_UNION_ALL); + } + + /** + * Join services + */ + protected function joinServices() + { + $columns = array_keys( + $this->columnMap['flappinghistory'] + $this->columnMap['hosts'] + $this->columnMap['services'] + ); + if ($this->fetchHistoryColumns) { + $columns = array_merge($columns, array_keys($this->columnMap['history'])); + } + $services = $this->createSubQuery('Serviceflappingstarthistory', $columns); + $this->subQueries[] = $services; + $this->flappingStartHistoryQuery->union(array($services), Zend_Db_Select::SQL_UNION_ALL); + } + + /** + * {@inheritdoc} + */ + public function order($columnOrAlias, $dir = null) + { + foreach ($this->subQueries as $sub) { + $sub->requireColumn($columnOrAlias); + } + return parent::order($columnOrAlias, $dir); + } + + /** + * {@inheritdoc} + */ + public function where($condition, $value = null) + { + $this->requireColumn($condition); + foreach ($this->subQueries as $sub) { + $sub->where($condition, $value); + } + return $this; + } + + /** + * {@inheritdoc} + */ + public function addFilter(Filter $filter) + { + foreach ($this->subQueries as $sub) { + $sub->applyFilter(clone $filter); + } + return $this; + } + + public function whereEx(FilterExpression $ex) + { + $this->requireColumn($ex->getColumn()); + foreach ($this->subQueries as $sub) { + $sub->whereEx($ex); + } + + return $this; + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/GroupsummaryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/GroupsummaryQuery.php new file mode 100644 index 0000000..60ea5ef --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/GroupsummaryQuery.php @@ -0,0 +1,131 @@ +<?php +/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Zend_Db_Select; + +/** + * Query for host and service group summaries + */ +class GroupsummaryQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'hoststatussummary' => array( + 'hostgroup' => 'hostgroup COLLATE latin1_general_ci', + 'hostgroup_alias' => 'hostgroup_alias COLLATE latin1_general_ci', + 'hostgroup_name' => 'hostgroup_name', + 'hosts_up' => 'SUM(CASE WHEN object_type = \'host\' AND state = 0 THEN 1 ELSE 0 END)', + 'hosts_unreachable' => 'SUM(CASE WHEN object_type = \'host\' AND state = 2 THEN 1 ELSE 0 END)', + 'hosts_unreachable_handled' => 'SUM(CASE WHEN object_type = \'host\' AND state = 2 AND acknowledged + in_downtime != 0 THEN 1 ELSE 0 END)', + 'hosts_unreachable_unhandled' => 'SUM(CASE WHEN object_type = \'host\' AND state = 2 AND acknowledged + in_downtime = 0 THEN 1 ELSE 0 END)', + 'hosts_down' => 'SUM(CASE WHEN object_type = \'host\' AND state = 1 THEN 1 ELSE 0 END)', + 'hosts_down_handled' => 'SUM(CASE WHEN object_type = \'host\' AND state = 1 AND acknowledged + in_downtime != 0 THEN 1 ELSE 0 END)', + 'hosts_down_last_state_change_handled' => 'MAX(CASE WHEN object_type = \'host\' AND state = 1 AND acknowledged + in_downtime != 0 THEN state_change ELSE 0 END)', + 'hosts_down_last_state_change_unhandled' => 'MAX(CASE WHEN object_type = \'host\' AND state = 1 AND acknowledged + in_downtime = 0 THEN state_change ELSE 0 END)', + 'hosts_down_unhandled' => 'SUM(CASE WHEN object_type = \'host\' AND state = 1 AND acknowledged + in_downtime = 0 THEN 1 ELSE 0 END)', + 'hosts_pending' => 'SUM(CASE WHEN object_type = \'host\' AND state = 99 THEN 1 ELSE 0 END)', + 'hosts_pending_last_state_change' => 'MAX(CASE WHEN object_type = \'host\' AND state = 99 THEN state_change ELSE 0 END)', + 'hosts_severity' => 'MAX(CASE WHEN object_type = \'host\' THEN severity ELSE 0 END)', + 'hosts_total' => 'SUM(CASE WHEN object_type = \'host\' THEN 1 ELSE 0 END)', + 'hosts_unreachable_last_state_change_handled' => 'MAX(CASE WHEN object_type = \'host\' AND state = 2 AND acknowledged + in_downtime != 0 THEN state_change ELSE 0 END)', + 'hosts_unreachable_last_state_change_unhandled' => 'MAX(CASE WHEN object_type = \'host\' AND state = 2 AND acknowledged + in_downtime = 0 THEN state_change ELSE 0 END)', + 'hosts_up_last_state_change' => 'MAX(CASE WHEN object_type = \'host\' AND state = 0 THEN state_change ELSE 0 END)' + ), + 'servicestatussummary' => array( + 'servicegroup' => 'servicegroup COLLATE latin1_general_ci', + 'servicegroup_alias' => 'servicegroup_alias COLLATE latin1_general_ci', + 'servicegroup_name' => 'servicegroup_name', + 'services_critical' => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 THEN 1 ELSE 0 END)', + 'services_critical_handled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 AND acknowledged + in_downtime + host_state > 0 THEN 1 ELSE 0 END)', + 'services_critical_last_state_change_handled' => 'MAX(CASE WHEN object_type = \'service\' AND state = 2 AND acknowledged + in_downtime + host_state > 0 THEN state_change ELSE 0 END)', + 'services_critical_last_state_change_unhandled' => 'MAX(CASE WHEN object_type = \'service\' AND state = 2 AND acknowledged + in_downtime + host_state = 0 THEN state_change ELSE 0 END)', + 'services_critical_unhandled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 AND acknowledged + in_downtime + host_state = 0 THEN 1 ELSE 0 END)', + 'services_ok' => 'SUM(CASE WHEN object_type = \'service\' AND state = 0 THEN 1 ELSE 0 END)', + 'services_ok_last_state_change' => 'MAX(CASE WHEN object_type = \'service\' AND state = 0 THEN state_change ELSE 0 END)', + 'services_pending' => 'SUM(CASE WHEN object_type = \'service\' AND state = 99 THEN 1 ELSE 0 END)', + 'services_pending_last_state_change' => 'MAX(CASE WHEN object_type = \'service\' AND state = 99 THEN state_change ELSE 0 END)', + 'services_severity' => 'MAX(CASE WHEN object_type = \'service\' THEN severity ELSE 0 END)', + 'services_total' => 'SUM(CASE WHEN object_type = \'service\' THEN 1 ELSE 0 END)', + 'services_unknown' => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 THEN 1 ELSE 0 END)', + 'services_unknown_handled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 AND acknowledged + in_downtime + host_state > 0 THEN 1 ELSE 0 END)', + 'services_unknown_last_state_change_handled' => 'MAX(CASE WHEN object_type = \'service\' AND state = 3 AND acknowledged + in_downtime + host_state > 0 THEN state_change ELSE 0 END)', + 'services_unknown_last_state_change_unhandled' => 'MAX(CASE WHEN object_type = \'service\' AND state = 3 AND acknowledged + in_downtime + host_state = 0 THEN state_change ELSE 0 END)', + 'services_unknown_unhandled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 AND acknowledged + in_downtime + host_state = 0 THEN 1 ELSE 0 END)', + 'services_warning' => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 THEN 1 ELSE 0 END)', + 'services_warning_handled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 AND acknowledged + in_downtime + host_state > 0 THEN 1 ELSE 0 END)', + 'services_warning_last_state_change_handled' => 'MAX(CASE WHEN object_type = \'service\' AND state = 1 AND acknowledged + in_downtime + host_state > 0 THEN state_change ELSE 0 END)', + 'services_warning_last_state_change_unhandled' => 'MAX(CASE WHEN object_type = \'service\' AND state = 1 AND acknowledged + in_downtime + host_state = 0 THEN state_change ELSE 0 END)', + 'services_warning_unhandled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 AND acknowledged + in_downtime + host_state = 0 THEN 1 ELSE 0 END)' + ) + ); + + /** + * {@inheritdoc} + */ + protected $useSubqueryCount = true; + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + $columns = array( + 'object_type', + 'host_state' + ); + + if (in_array('servicegroup', $this->desiredColumns) || in_array('servicegroup_name', $this->desiredColumns)) { + $columns[] = 'servicegroup'; + $columns[] = 'servicegroup_name'; + $columns[] = 'servicegroup_alias'; + $groupColumns = array('servicegroup_name', 'servicegroup_alias'); + } else { + $columns[] = 'hostgroup'; + $columns[] = 'hostgroup_name'; + $columns[] = 'hostgroup_alias'; + $groupColumns = array('hostgroup_name', 'hostgroup_alias'); + } + $hosts = $this->createSubQuery( + 'Hoststatus', + $columns + array( + 'state' => 'host_state', + 'acknowledged' => 'host_acknowledged', + 'in_downtime' => 'host_in_downtime', + 'state_change' => 'host_last_state_change', + 'severity' => 'host_severity' + ) + ); + if (in_array('servicegroup_name', $this->desiredColumns)) { + $hosts->group(array( + 'sgo.name1', + 'ho.object_id', + 'sg.alias', + 'state', + 'acknowledged', + 'in_downtime', + 'state_change', + 'severity' + )); + } + $services = $this->createSubQuery( + 'Status', + $columns + array( + 'state' => 'service_state', + 'acknowledged' => 'service_acknowledged', + 'in_downtime' => 'service_in_downtime', + 'state_change' => 'service_last_state_change', + 'severity' => 'service_severity' + ) + ); + $union = $this->db->select()->union(array($hosts, $services), Zend_Db_Select::SQL_UNION_ALL); + $this->select->from(array('statussummary' => $union), array())->group($groupColumns); + $this->joinedVirtualTables = array( + 'servicestatussummary' => true, + 'hoststatussummary' => true + ); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostcommentQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostcommentQuery.php new file mode 100644 index 0000000..b388204 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostcommentQuery.php @@ -0,0 +1,202 @@ +<?php +/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +/** + * Query for host comments + */ +class HostcommentQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $allowCustomVars = true; + + /** + * {@inheritdoc} + */ + protected $groupBase = array('comments' => array('c.comment_id', 'ho.object_id')); + + /** + * {@inheritdoc} + */ + protected $groupOrigin = array('hostgroups', 'services'); + + protected $subQueryTargets = array( + 'hostgroups' => 'hostgroup', + 'servicegroups' => 'servicegroup' + ); + + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'comments' => array( + 'comment_author' => 'c.author_name COLLATE latin1_general_ci', + 'comment_author_name' => 'c.author_name', + 'comment_data' => 'c.comment_data', + 'comment_expiration' => 'CASE c.expires WHEN 1 THEN UNIX_TIMESTAMP(c.expiration_time) ELSE NULL END', + 'comment_internal_id' => 'c.internal_comment_id', + 'comment_is_persistent' => 'c.is_persistent', + 'comment_name' => 'c.name', + 'comment_timestamp' => 'UNIX_TIMESTAMP(c.comment_time)', + 'comment_type' => "CASE c.entry_type WHEN 1 THEN 'comment' WHEN 2 THEN 'downtime' WHEN 3 THEN 'flapping' WHEN 4 THEN 'ack' END", + 'host' => 'ho.name1 COLLATE latin1_general_ci', + 'host_name' => 'ho.name1', + 'object_type' => '(\'host\')' + ), + 'hostgroups' => array( + 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci', + 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci', + 'hostgroup_name' => 'hgo.name1' + ), + 'hosts' => array( + 'host_alias' => 'h.alias', + 'host_display_name' => 'h.display_name COLLATE latin1_general_ci' + ), + 'hoststatus' => array( + 'host_state' => 'CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 99 ELSE hs.current_state END' + ), + 'instances' => array( + 'instance_name' => 'i.instance_name' + ), + 'servicegroups' => array( + 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci', + 'servicegroup_name' => 'sgo.name1', + 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci' + ), + 'services' => array( + 'service' => 'so.name2 COLLATE latin1_general_ci', + 'service_description' => 'so.name2', + 'service_display_name' => 's.display_name COLLATE latin1_general_ci', + ) + ); + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + if (version_compare($this->getIdoVersion(), '1.14.0', '<')) { + $this->columnMap['comments']['comment_name'] = '(NULL)'; + } + $this->select->from( + array('c' => $this->prefix . 'comments'), + array() + )->join( + array('ho' => $this->prefix . 'objects'), + 'ho.object_id = c.object_id AND ho.is_active = 1 AND ho.objecttype_id = 1', + array() + ); + $this->joinedVirtualTables['comments'] = true; + } + + /** + * Join host groups + */ + protected function joinHostgroups() + { + $this->select->joinLeft( + array('hgm' => $this->prefix . 'hostgroup_members'), + 'hgm.host_object_id = ho.object_id', + array() + )->joinLeft( + array('hg' => $this->prefix . 'hostgroups'), + 'hg.hostgroup_id = hgm.hostgroup_id', + array() + )->joinLeft( + array('hgo' => $this->prefix . 'objects'), + 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3', + array() + ); + } + + /** + * Join hosts + */ + protected function joinHosts() + { + $this->select->join( + array('h' => $this->prefix . 'hosts'), + 'h.host_object_id = ho.object_id', + array() + ); + } + + /** + * Join host status + */ + protected function joinHoststatus() + { + $this->select->join( + array('hs' => $this->prefix . 'hoststatus'), + 'hs.host_object_id = ho.object_id', + array() + ); + } + + /** + * Join instances + */ + protected function joinInstances() + { + $this->select->join( + array('i' => $this->prefix . 'instances'), + 'i.instance_id = c.instance_id', + array() + ); + } + + /** + * Join service groups + */ + protected function joinServicegroups() + { + $this->requireVirtualTable('services'); + $this->select->joinLeft( + array('sgm' => $this->prefix . 'servicegroup_members'), + 'sgm.service_object_id = s.service_object_id', + array() + )->joinLeft( + array('sg' => $this->prefix . 'servicegroups'), + 'sgm.servicegroup_id = sg.' . $this->servicegroup_id, + array() + )->joinLeft( + array('sgo' => $this->prefix . 'objects'), + 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4', + array() + ); + } + + /** + * Join services + */ + protected function joinServices() + { + $this->select->joinLeft( + array('s' => $this->prefix . 'services'), + 's.host_object_id = ho.object_id', + array() + )->joinLeft( + array('so' => $this->prefix . 'objects'), + 'so.object_id = s.service_object_id AND so.is_active = 1 AND so.objecttype_id = 2', + array() + ); + } + + protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter) + { + if ($name === 'hostgroup') { + $query->joinVirtualTable('members'); + + return ['hgm.host_object_id', 'ho.object_id']; + } elseif ($name === 'servicegroup') { + $query->joinVirtualTable('services'); + + return ['s.host_object_id', 'ho.object_id']; + } + + return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostcommentdeletionhistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostcommentdeletionhistoryQuery.php new file mode 100644 index 0000000..d798d56 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostcommentdeletionhistoryQuery.php @@ -0,0 +1,44 @@ +<?php +/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Data\Filter\Filter; +use Icinga\Data\Filter\FilterExpression; + +/** + * Query for host comment removal records + */ +class HostcommentdeletionhistoryQuery extends HostcommenthistoryQuery +{ + protected function requireFilterColumns(Filter $filter) + { + if ($filter instanceof FilterExpression && $filter->getColumn() === 'timestamp') { + $this->requireColumn('timestamp'); + $filter->setColumn('hch.deletion_time'); + $filter->setExpression($this->timestampForSql($this->valueToTimestamp($filter->getExpression()))); + return null; + } + + return parent::requireFilterColumns($filter); + } + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + parent::joinBaseTables(); + $this->select->where("hch.deletion_time > '1970-01-02 00:00:00'"); + $this->columnMap['commenthistory']['timestamp'] = str_replace( + 'comment_time', + 'deletion_time', + $this->columnMap['commenthistory']['timestamp'] + ); + $this->columnMap['commenthistory']['type'] = str_replace( + 'END)', + "END || '_deleted')", + $this->columnMap['commenthistory']['type'] + ); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostcommenthistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostcommenthistoryQuery.php new file mode 100644 index 0000000..b8f166a --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostcommenthistoryQuery.php @@ -0,0 +1,197 @@ +<?php +/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Data\Filter\Filter; +use Icinga\Data\Filter\FilterExpression; + +/** + * Query for host comment history records + */ +class HostcommenthistoryQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $allowCustomVars = true; + + /** + * {@inheritdoc} + */ + protected $groupBase = array('commenthistory' => array('hch.commenthistory_id', 'ho.object_id')); + + /** + * {@inheritdoc} + */ + protected $groupOrigin = array('hostgroups', 'services'); + + protected $subQueryTargets = array( + 'hostgroups' => 'hostgroup', + 'servicegroups' => 'servicegroup' + ); + + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'commenthistory' => array( + 'id' => 'hch.commenthistory_id', + 'host' => 'ho.name1 COLLATE latin1_general_ci', + 'host_name' => 'ho.name1', + 'object_id' => 'hch.object_id', + 'object_type' => '(\'host\')', + 'output' => "('[' || hch.author_name || '] ' || hch.comment_data)", + 'state' => '(-1)', + 'timestamp' => 'UNIX_TIMESTAMP(hch.comment_time)', + 'type' => "(CASE hch.entry_type WHEN 1 THEN 'comment' WHEN 2 THEN 'dt_comment' WHEN 3 THEN 'flapping' WHEN 4 THEN 'ack' END)" + ), + 'hostgroups' => array( + 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci', + 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci', + 'hostgroup_name' => 'hgo.name1' + ), + 'hosts' => array( + 'host_alias' => 'h.alias', + 'host_display_name' => 'h.display_name COLLATE latin1_general_ci' + ), + 'instances' => array( + 'instance_name' => 'i.instance_name' + ), + 'servicegroups' => array( + 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci', + 'servicegroup_name' => 'sgo.name1', + 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci' + ), + 'services' => array( + 'service' => 'so.name2 COLLATE latin1_general_ci', + 'service_description' => 'so.name2', + 'service_display_name' => 's.display_name COLLATE latin1_general_ci', + 'service_host_name' => 'so.name1' + ) + ); + + protected function requireFilterColumns(Filter $filter) + { + if ($filter instanceof FilterExpression && $filter->getColumn() === 'timestamp') { + $this->requireColumn('timestamp'); + $filter->setColumn('hch.comment_time'); + $filter->setExpression($this->timestampForSql($this->valueToTimestamp($filter->getExpression()))); + return null; + } + + return parent::requireFilterColumns($filter); + } + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + $this->select->from( + array('hch' => $this->prefix . 'commenthistory'), + array() + )->join( + array('ho' => $this->prefix . 'objects'), + 'ho.object_id = hch.object_id AND ho.is_active = 1 AND ho.objecttype_id = 1', + array() + ); + $this->joinedVirtualTables['commenthistory'] = true; + } + + /** + * Join host groups + */ + protected function joinHostgroups() + { + $this->select->joinLeft( + array('hgm' => $this->prefix . 'hostgroup_members'), + 'hgm.host_object_id = ho.object_id', + array() + )->joinLeft( + array('hg' => $this->prefix . 'hostgroups'), + 'hg.hostgroup_id = hgm.hostgroup_id', + array() + )->joinLeft( + array('hgo' => $this->prefix . 'objects'), + 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3', + array() + ); + } + + /** + * Join hosts + */ + protected function joinHosts() + { + $this->select->join( + array('h' => $this->prefix . 'hosts'), + 'h.host_object_id = ho.object_id', + array() + ); + } + + /** + * Join instances + */ + protected function joinInstances() + { + $this->select->join( + array('i' => $this->prefix . 'instances'), + 'i.instance_id = hch.instance_id', + array() + ); + } + + /** + * Join service groups + */ + protected function joinServicegroups() + { + $this->requireVirtualTable('services'); + $this->select->joinLeft( + array('sgm' => $this->prefix . 'servicegroup_members'), + 'sgm.service_object_id = s.service_object_id', + array() + )->joinLeft( + array('sg' => $this->prefix . 'servicegroups'), + 'sg.' . $this->servicegroup_id . ' = sgm.servicegroup_id', + array() + )->joinLeft( + array('sgo' => $this->prefix . 'objects'), + 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4', + array() + ); + } + + /** + * Join services + */ + protected function joinServices() + { + $this->select->joinLeft( + array('s' => $this->prefix . 'services'), + 's.host_object_id = ho.object_id', + array() + )->joinLeft( + array('so' => $this->prefix . 'objects'), + 'so.object_id = s.service_object_id AND so.is_active = 1 AND so.objecttype_id = 2', + array() + ); + } + + protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter) + { + if ($name === 'hostgroup') { + $query->joinVirtualTable('members'); + + return ['hgm.host_object_id', 'ho.object_id']; + } elseif ($name === 'servicegroup') { + $query->joinVirtualTable('services'); + + return ['s.host_object_id', 'ho.object_id']; + } + + return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostcontactQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostcontactQuery.php new file mode 100644 index 0000000..23b0e90 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostcontactQuery.php @@ -0,0 +1,247 @@ +<?php +/* Icinga Web 2 | (c) 2018 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +/** + * Query for host contacts + */ +class HostcontactQuery extends IdoQuery +{ + protected $allowCustomVars = true; + + protected $groupBase = [ + 'contacts' => ['co.object_id', 'c.contact_id'], + 'timeperiods' => ['ht.timeperiod_id', 'st.timeperiod_id'] + ]; + + protected $groupOrigin = ['contactgroups', 'hosts', 'services']; + + protected $subQueryTargets = [ + 'hostgroups' => 'hostgroup', + 'servicegroups' => 'servicegroup' + ]; + + protected $columnMap = [ + 'contactgroups' => [ + 'contactgroup' => 'cgo.name1 COLLATE latin1_general_ci', + 'contactgroup_name' => 'cgo.name1', + 'contactgroup_alias' => 'cg.alias COLLATE latin1_general_ci' + ], + 'contacts' => [ + 'contact_id' => 'c.contact_id', + 'contact' => 'co.name1 COLLATE latin1_general_ci', + 'contact_name' => 'co.name1', + 'contact_alias' => 'c.alias COLLATE latin1_general_ci', + 'contact_email' => 'c.email_address COLLATE latin1_general_ci', + 'contact_pager' => 'c.pager_address', + 'contact_object_id' => 'c.contact_object_id', + 'contact_has_host_notfications' => 'c.host_notifications_enabled', + 'contact_has_service_notfications' => 'c.service_notifications_enabled', + 'contact_can_submit_commands' => 'c.can_submit_commands', + 'contact_notify_service_recovery' => 'c.notify_service_recovery', + 'contact_notify_service_warning' => 'c.notify_service_warning', + 'contact_notify_service_critical' => 'c.notify_service_critical', + 'contact_notify_service_unknown' => 'c.notify_service_unknown', + 'contact_notify_service_flapping' => 'c.notify_service_flapping', + 'contact_notify_service_downtime' => 'c.notify_service_downtime', + 'contact_notify_host_recovery' => 'c.notify_host_recovery', + 'contact_notify_host_down' => 'c.notify_host_down', + 'contact_notify_host_unreachable' => 'c.notify_host_unreachable', + 'contact_notify_host_flapping' => 'c.notify_host_flapping', + 'contact_notify_host_downtime' => 'c.notify_host_downtime' + ], + 'hostgroups' => [ + 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci', + 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci', + 'hostgroup_name' => 'hgo.name1' + ], + 'hosts' => [ + 'host' => 'ho.name1 COLLATE latin1_general_ci', + 'host_name' => 'ho.name1', + 'host_alias' => 'h.alias', + 'host_display_name' => 'h.display_name COLLATE latin1_general_ci' + ], + 'instances' => [ + 'instance_name' => 'i.instance_name' + ], + 'servicegroups' => [ + 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci', + 'servicegroup_name' => 'sgo.name1', + 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci' + ], + 'services' => [ + 'service' => 'so.name2 COLLATE latin1_general_ci', + 'service_description' => 'so.name2', + 'service_display_name' => 's.display_name COLLATE latin1_general_ci', + 'service_host_name' => 'so.name1' + ], + 'timeperiods' => [ + 'contact_notify_host_timeperiod' => 'ht.alias COLLATE latin1_general_ci', + 'contact_notify_service_timeperiod' => 'st.alias COLLATE latin1_general_ci' + ] + ]; + + protected function joinBaseTables() + { + $this->select->from( + ['c' => $this->prefix . 'contacts'], + [] + )->join( + ['co' => $this->prefix . 'objects'], + 'co.object_id = c.contact_object_id AND co.is_active = 1 AND co.objecttype_id = 10', + [] + ); + + $this->joinedVirtualTables = array('contacts' => true); + } + + /** + * Join contact groups + */ + protected function joinContactgroups() + { + $this->select->joinLeft( + ['cgm' => $this->prefix . 'contactgroup_members'], + 'co.object_id = cgm.contact_object_id', + [] + )->joinLeft( + ['cg' => $this->prefix . 'contactgroups'], + 'cgm.contactgroup_id = cg.contactgroup_id', + [] + )->joinLeft( + ['cgo' => $this->prefix . 'objects'], + 'cg.contactgroup_object_id = cgo.object_id AND cgo.is_active = 1 AND cgo.objecttype_id = 11', + [] + ); + } + + /** + * Join host groups + */ + protected function joinHostgroups() + { + $this->requireVirtualTable('hosts'); + + $this->select->joinLeft( + ['hgm' => $this->prefix . 'hostgroup_members'], + 'hgm.host_object_id = ho.object_id', + [] + )->joinLeft( + ['hg' => $this->prefix . 'hostgroups'], + 'hg.hostgroup_id = hgm.hostgroup_id', + [] + )->joinLeft( + ['hgo' => $this->prefix . 'objects'], + 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3', + [] + ); + } + + /** + * Join hosts + */ + protected function joinHosts() + { + $this->select->joinLeft( + ['hc' => $this->prefix . 'host_contacts'], + 'hc.contact_object_id = c.contact_object_id', + [] + )->joinLeft( + ['h' => $this->prefix . 'hosts'], + 'h.host_id = hc.host_id', + [] + )->joinLeft( + ['ho' => $this->prefix . 'objects'], + 'ho.object_id = h.host_object_id AND ho.is_active = 1 AND ho.objecttype_id = 1', + [] + ); + } + + /** + * Join instances + */ + protected function joinInstances() + { + $this->select->join( + ['i' => $this->prefix . 'instances'], + 'i.instance_id = c.instance_id', + [] + ); + } + + /** + * Join service groups + */ + protected function joinServicegroups() + { + $this->requireVirtualTable('services'); + $this->select->joinLeft( + ['sgm' => $this->prefix . 'servicegroup_members'], + 'sgm.service_object_id = s.service_object_id', + [] + )->joinLeft( + ['sg' => $this->prefix . 'servicegroups'], + 'sg.servicegroup_id = sgm.servicegroup_id', + [] + )->joinLeft( + ['sgo' => $this->prefix . 'objects'], + 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4', + [] + ); + } + + /** + * Join services + */ + protected function joinServices() + { + $this->requireVirtualTable('hosts'); + + $this->select->joinLeft( + ['s' => $this->prefix . 'services'], + 's.host_object_id = ho.object_id', + [] + )->joinLeft( + ['so' => $this->prefix . 'objects'], + 'so.object_id = s.service_object_id AND so.is_active = 1 AND so.objecttype_id = 2', + [] + ); + } + + /** + * Join time periods + */ + protected function joinTimeperiods() + { + $this->select->joinLeft( + ['ht' => $this->prefix . 'timeperiods'], + 'ht.timeperiod_object_id = c.host_timeperiod_object_id', + [] + ); + $this->select->joinLeft( + ['st' => $this->prefix . 'timeperiods'], + 'st.timeperiod_object_id = c.service_timeperiod_object_id', + [] + ); + } + + protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter) + { + if ($name === 'hostgroup') { + $this->requireVirtualTable('hosts'); + + $query->joinVirtualTable('members'); + + return ['hgm.host_object_id', 'ho.object_id']; + } elseif ($name === 'servicegroup') { + $this->requireVirtualTable('services'); + + $query->joinVirtualTable('members'); + + return ['sgm.service_object_id', 'so.object_id']; + } + + return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostdowntimeQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostdowntimeQuery.php new file mode 100644 index 0000000..62f5ceb --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostdowntimeQuery.php @@ -0,0 +1,208 @@ +<?php +/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +/** + * Query for host downtimes + */ +class HostdowntimeQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $allowCustomVars = true; + + /** + * {@inheritdoc} + */ + protected $groupBase = array('downtimes' => array('sd.scheduleddowntime_id', 'ho.object_id')); + + /** + * {@inheritdoc} + */ + protected $groupOrigin = array('hostgroups', 'servicegroups', 'services'); + + protected $subQueryTargets = array( + 'hostgroups' => 'hostgroup', + 'servicegroups' => 'servicegroup' + ); + + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'downtimes' => array( + 'downtime_author' => 'sd.author_name COLLATE latin1_general_ci', + 'downtime_author_name' => 'sd.author_name', + 'downtime_comment' => 'sd.comment_data', + 'downtime_duration' => 'sd.duration', + 'downtime_end' => 'CASE WHEN sd.is_fixed > 0 THEN UNIX_TIMESTAMP(sd.scheduled_end_time) ELSE UNIX_TIMESTAMP(sd.trigger_time) + sd.duration END', + 'downtime_entry_time' => 'UNIX_TIMESTAMP(sd.entry_time)', + 'downtime_internal_id' => 'sd.internal_downtime_id', + 'downtime_is_fixed' => 'sd.is_fixed', + 'downtime_is_flexible' => 'CASE WHEN sd.is_fixed = 0 THEN 1 ELSE 0 END', + 'downtime_is_in_effect' => 'sd.is_in_effect', + 'downtime_name' => 'sd.name', + 'downtime_scheduled_end' => 'UNIX_TIMESTAMP(sd.scheduled_end_time)', + 'downtime_scheduled_start' => 'UNIX_TIMESTAMP(sd.scheduled_start_time)', + 'downtime_start' => 'UNIX_TIMESTAMP(CASE WHEN UNIX_TIMESTAMP(sd.trigger_time) > 0 then sd.trigger_time ELSE sd.scheduled_start_time END)', + 'downtime_triggered_by_id' => 'sd.triggered_by_id', + 'host' => 'ho.name1 COLLATE latin1_general_ci', + 'host_name' => 'ho.name1', + 'object_type' => '(\'host\')' + ), + 'hostgroups' => array( + 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci', + 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci', + 'hostgroup_name' => 'hgo.name1' + ), + 'hosts' => array( + 'host_alias' => 'h.alias', + 'host_display_name' => 'h.display_name COLLATE latin1_general_ci' + ), + 'hoststatus' => array( + 'host_state' => 'CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 99 ELSE hs.current_state END' + ), + 'instances' => array( + 'instance_name' => 'i.instance_name' + ), + 'servicegroups' => array( + 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci', + 'servicegroup_name' => 'sgo.name1', + 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci' + ), + 'services' => array( + 'service' => 'so.name2 COLLATE latin1_general_ci', + 'service_description' => 'so.name2', + 'service_display_name' => 's.display_name COLLATE latin1_general_ci', + ) + ); + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + if (version_compare($this->getIdoVersion(), '1.14.0', '<')) { + $this->columnMap['downtimes']['downtime_name'] = '(NULL)'; + } + $this->select->from( + array('sd' => $this->prefix . 'scheduleddowntime'), + array() + )->join( + array('ho' => $this->prefix . 'objects'), + 'sd.object_id = ho.object_id AND ho.is_active = 1 AND ho.objecttype_id = 1', + array() + ); + $this->joinedVirtualTables['downtimes'] = true; + } + + /** + * Join host groups + */ + protected function joinHostgroups() + { + $this->select->joinLeft( + array('hgm' => $this->prefix . 'hostgroup_members'), + 'hgm.host_object_id = ho.object_id', + array() + )->joinLeft( + array('hg' => $this->prefix . 'hostgroups'), + 'hg.hostgroup_id = hgm.hostgroup_id', + array() + )->joinLeft( + array('hgo' => $this->prefix . 'objects'), + 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3', + array() + ); + } + + /** + * Join hosts + */ + protected function joinHosts() + { + $this->select->join( + array('h' => $this->prefix . 'hosts'), + 'h.host_object_id = ho.object_id', + array() + ); + } + + /** + * Join host status + */ + protected function joinHoststatus() + { + $this->select->join( + array('hs' => $this->prefix . 'hoststatus'), + 'hs.host_object_id = ho.object_id', + array() + ); + } + + /** + * Join instances + */ + protected function joinInstances() + { + $this->select->join( + array('i' => $this->prefix . 'instances'), + 'i.instance_id = sd.instance_id', + array() + ); + } + + /** + * Join service groups + */ + protected function joinServicegroups() + { + $this->requireVirtualTable('services'); + $this->select->joinLeft( + array('sgm' => $this->prefix . 'servicegroup_members'), + 'sgm.service_object_id = s.service_object_id', + array() + )->joinLeft( + array('sg' => $this->prefix . 'servicegroups'), + 'sgm.servicegroup_id = sg.' . $this->servicegroup_id, + array() + )->joinLeft( + array('sgo' => $this->prefix . 'objects'), + 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4', + array() + ); + } + + /** + * Join services + */ + protected function joinServices() + { + $this->select->joinLeft( + array('s' => $this->prefix . 'services'), + 's.host_object_id = ho.object_id', + array() + )->joinLeft( + array('so' => $this->prefix . 'objects'), + 'so.object_id = s.service_object_id AND so.is_active = 1 AND so.objecttype_id = 2', + array() + ); + } + + protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter) + { + if ($name === 'hostgroup') { + $query->joinVirtualTable('members'); + + return ['hgm.host_object_id', 'ho.object_id']; + } elseif ($name === 'servicegroup') { + $query->joinVirtualTable('services'); + + return ['s.host_object_id', 'ho.object_id']; + } + + return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostdowntimeendhistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostdowntimeendhistoryQuery.php new file mode 100644 index 0000000..808b3f2 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostdowntimeendhistoryQuery.php @@ -0,0 +1,42 @@ +<?php +/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Data\Filter\Filter; +use Icinga\Data\Filter\FilterExpression; + +/** + * Query for host downtime end history records + */ +class HostdowntimeendhistoryQuery extends HostdowntimestarthistoryQuery +{ + protected function requireFilterColumns(Filter $filter) + { + if ($filter instanceof FilterExpression && $filter->getColumn() === 'timestamp') { + $this->requireColumn('timestamp'); + $filter->setColumn('hdh.actual_end_time'); + $filter->setExpression($this->timestampForSql($this->valueToTimestamp($filter->getExpression()))); + return null; + } + + return parent::requireFilterColumns($filter); + } + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + parent::joinBaseTables(true); + $this->select->where( + "hdh.actual_end_time > '1970-01-02 00:00:00' AND hdh.was_started = 1 AND hdh.was_cancelled = 0" + ); + $this->columnMap['downtimehistory']['type'] = "('dt_end')"; + $this->columnMap['downtimehistory']['timestamp'] = str_replace( + 'actual_start_time', + 'actual_end_time', + $this->columnMap['downtimehistory']['timestamp'] + ); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostdowntimestarthistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostdowntimestarthistoryQuery.php new file mode 100644 index 0000000..a6f97e7 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostdowntimestarthistoryQuery.php @@ -0,0 +1,206 @@ +<?php +/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Data\Filter\Filter; +use Icinga\Data\Filter\FilterExpression; + +/** + * Query for host downtime start history records + */ +class HostdowntimestarthistoryQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $allowCustomVars = true; + + /** + * {@inheritdoc} + */ + protected $groupBase = array('downtimehistory' => array('hdh.downtimehistory_id', 'ho.object_id')); + + /** + * {@inheritdoc} + */ + protected $groupOrigin = array('hostgroups', 'services'); + + protected $subQueryTargets = array( + 'hostgroups' => 'hostgroup', + 'servicegroups' => 'servicegroup' + ); + + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'downtimehistory' => array( + 'id' => 'hdh.downtimehistory_id', + 'host' => 'ho.name1 COLLATE latin1_general_ci', + 'host_name' => 'ho.name1', + 'object_id' => 'hdh.object_id', + 'object_type' => '(\'host\')', + 'output' => "('[' || hdh.author_name || '] ' || hdh.comment_data)", + 'state' => '(-1)', + 'timestamp' => 'UNIX_TIMESTAMP(hdh.actual_start_time)', + 'type' => "('dt_start')" + ), + 'hostgroups' => array( + 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci', + 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci', + 'hostgroup_name' => 'hgo.name1' + ), + 'hosts' => array( + 'host_alias' => 'h.alias', + 'host_display_name' => 'h.display_name COLLATE latin1_general_ci' + ), + 'instances' => array( + 'instance_name' => 'i.instance_name' + ), + 'servicegroups' => array( + 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci', + 'servicegroup_name' => 'sgo.name1', + 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci' + ), + 'services' => array( + 'service' => 'so.name2 COLLATE latin1_general_ci', + 'service_description' => 'so.name2', + 'service_display_name' => 's.display_name COLLATE latin1_general_ci', + 'service_host_name' => 'so.name1' + ) + ); + + protected function requireFilterColumns(Filter $filter) + { + if ($filter instanceof FilterExpression && $filter->getColumn() === 'timestamp') { + $this->requireColumn('timestamp'); + $filter->setColumn('hdh.actual_start_time'); + $filter->setExpression($this->timestampForSql($this->valueToTimestamp($filter->getExpression()))); + return null; + } + + return parent::requireFilterColumns($filter); + } + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + $this->select->from( + array('hdh' => $this->prefix . 'downtimehistory'), + array() + )->join( + array('ho' => $this->prefix . 'objects'), + 'ho.object_id = hdh.object_id AND ho.is_active = 1 AND ho.objecttype_id = 1', + array() + ); + + if (func_num_args() === 0 || func_get_arg(0) === false) { + $this->select->where( + "hdh.actual_start_time > '1970-01-02 00:00:00'" + ); + } + $this->select->where( + "hdh.was_started = 1 AND hdh.was_cancelled = 0" + ); + $this->joinedVirtualTables['downtimehistory'] = true; + } + + /** + * Join host groups + */ + protected function joinHostgroups() + { + $this->select->joinLeft( + array('hgm' => $this->prefix . 'hostgroup_members'), + 'hgm.host_object_id = ho.object_id', + array() + )->joinLeft( + array('hg' => $this->prefix . 'hostgroups'), + 'hg.hostgroup_id = hgm.hostgroup_id', + array() + )->joinLeft( + array('hgo' => $this->prefix . 'objects'), + 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3', + array() + ); + } + + /** + * Join hosts + */ + protected function joinHosts() + { + $this->select->join( + array('h' => $this->prefix . 'hosts'), + 'h.host_object_id = ho.object_id', + array() + ); + } + + /** + * Join instances + */ + protected function joinInstances() + { + $this->select->join( + array('i' => $this->prefix . 'instances'), + 'i.instance_id = hdh.instance_id', + array() + ); + } + + /** + * Join service groups + */ + protected function joinServicegroups() + { + $this->requireVirtualTable('services'); + $this->select->joinLeft( + array('sgm' => $this->prefix . 'servicegroup_members'), + 'sgm.service_object_id = s.service_object_id', + array() + )->joinLeft( + array('sg' => $this->prefix . 'servicegroups'), + 'sg.' . $this->servicegroup_id . ' = sgm.servicegroup_id', + array() + )->joinLeft( + array('sgo' => $this->prefix . 'objects'), + 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4', + array() + ); + } + + /** + * Join services + */ + protected function joinServices() + { + $this->select->joinLeft( + array('s' => $this->prefix . 'services'), + 's.host_object_id = ho.object_id', + array() + )->joinLeft( + array('so' => $this->prefix . 'objects'), + 'so.object_id = s.service_object_id AND so.is_active = 1 AND so.objecttype_id = 2', + array() + ); + } + + protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter) + { + if ($name === 'hostgroup') { + $query->joinVirtualTable('members'); + + return ['hgm.host_object_id', 'ho.object_id']; + } elseif ($name === 'servicegroup') { + $query->joinVirtualTable('services'); + + return ['s.host_object_id', 'ho.object_id']; + } + + return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostflappingendhistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostflappingendhistoryQuery.php new file mode 100644 index 0000000..ebc346b --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostflappingendhistoryQuery.php @@ -0,0 +1,31 @@ +<?php +/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +/** + * Query for host flapping end history records + */ +class HostflappingendhistoryQuery extends HostflappingstarthistoryQuery +{ + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + $this->select->from( + array('hfh' => $this->prefix . 'flappinghistory'), + array() + )->join( + array('ho' => $this->prefix . 'objects'), + 'ho.object_id = hfh.object_id AND ho.is_active = 1 AND ho.objecttype_id = 1', + array() + ); + + $this->select->where('hfh.event_type = 1001'); + + $this->joinedVirtualTables['flappinghistory'] = true; + + $this->columnMap['flappinghistory']['type'] = '(\'flapping_deleted\')'; + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostflappingstarthistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostflappingstarthistoryQuery.php new file mode 100644 index 0000000..497a493 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostflappingstarthistoryQuery.php @@ -0,0 +1,200 @@ +<?php +/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Data\Filter\Filter; +use Icinga\Data\Filter\FilterExpression; + +/** + * Query for host flapping start history records + */ +class HostflappingstarthistoryQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $allowCustomVars = true; + + /** + * {@inheritdoc} + */ + protected $groupBase = array('flappinghistory' => array('hfh.flappinghistory_id', 'ho.object_id')); + + /** + * {@inheritdoc} + */ + protected $groupOrigin = array('hostgroups', 'services'); + + protected $subQueryTargets = array( + 'hostgroups' => 'hostgroup', + 'servicegroups' => 'servicegroup' + ); + + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'flappinghistory' => array( + 'id' => 'hfh.flappinghistory_id', + 'host' => 'ho.name1 COLLATE latin1_general_ci', + 'host_name' => 'ho.name1', + 'object_id' => 'hfh.object_id', + 'object_type' => '(\'host\')', + 'output' => '(hfh.percent_state_change || \'\')', + 'state' => '(-1)', + 'timestamp' => 'UNIX_TIMESTAMP(hfh.event_time)', + 'type' => '(\'flapping\')' + ), + 'hostgroups' => array( + 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci', + 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci', + 'hostgroup_name' => 'hgo.name1' + ), + 'hosts' => array( + 'host_alias' => 'h.alias', + 'host_display_name' => 'h.display_name COLLATE latin1_general_ci' + ), + 'instances' => array( + 'instance_name' => 'i.instance_name' + ), + 'servicegroups' => array( + 'servicegroup_name' => 'sgo.name1', + 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci', + 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci' + ), + 'services' => array( + 'service' => 'so.name2 COLLATE latin1_general_ci', + 'service_description' => 'so.name2', + 'service_display_name' => 's.display_name COLLATE latin1_general_ci', + 'service_host_name' => 'so.name1' + ) + ); + + protected function requireFilterColumns(Filter $filter) + { + if ($filter instanceof FilterExpression && $filter->getColumn() === 'timestamp') { + $this->requireColumn('timestamp'); + $filter->setColumn('hfh.event_time'); + $filter->setExpression($this->timestampForSql($this->valueToTimestamp($filter->getExpression()))); + return null; + } + + return parent::requireFilterColumns($filter); + } + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + $this->select->from( + array('hfh' => $this->prefix . 'flappinghistory'), + array() + )->join( + array('ho' => $this->prefix . 'objects'), + 'ho.object_id = hfh.object_id AND ho.is_active = 1 AND ho.objecttype_id = 1', + array() + ); + + $this->select->where('hfh.event_type = 1000'); + + $this->joinedVirtualTables['flappinghistory'] = true; + } + + /** + * Join host groups + */ + protected function joinHostgroups() + { + $this->select->joinLeft( + array('hgm' => $this->prefix . 'hostgroup_members'), + 'hgm.host_object_id = ho.object_id', + array() + )->joinLeft( + array('hg' => $this->prefix . 'hostgroups'), + 'hg.hostgroup_id = hgm.hostgroup_id', + array() + )->joinLeft( + array('hgo' => $this->prefix . 'objects'), + 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3', + array() + ); + } + + /** + * Join hosts + */ + protected function joinHosts() + { + $this->select->join( + array('h' => $this->prefix . 'hosts'), + 'h.host_object_id = ho.object_id', + array() + ); + } + + /** + * Join instances + */ + protected function joinInstances() + { + $this->select->join( + array('i' => $this->prefix . 'instances'), + 'i.instance_id = hfh.instance_id', + array() + ); + } + + /** + * Join service groups + */ + protected function joinServicegroups() + { + $this->requireVirtualTable('services'); + $this->select->joinLeft( + array('sgm' => $this->prefix . 'servicegroup_members'), + 'sgm.service_object_id = s.service_object_id', + array() + )->joinLeft( + array('sg' => $this->prefix . 'servicegroups'), + 'sg.' . $this->servicegroup_id . ' = sgm.servicegroup_id', + array() + )->joinLeft( + array('sgo' => $this->prefix . 'objects'), + 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4', + array() + ); + } + + /** + * Join services + */ + protected function joinServices() + { + $this->select->joinLeft( + array('s' => $this->prefix . 'services'), + 's.host_object_id = ho.object_id', + array() + )->joinLeft( + array('so' => $this->prefix . 'objects'), + 'so.object_id = s.service_object_id AND so.is_active = 1 AND so.objecttype_id = 2', + array() + ); + } + + protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter) + { + if ($name === 'hostgroup') { + $query->joinVirtualTable('members'); + + return ['hgm.host_object_id', 'ho.object_id']; + } elseif ($name === 'servicegroup') { + $query->joinVirtualTable('services'); + + return ['s.host_object_id', 'ho.object_id']; + } + + return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostgroupQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostgroupQuery.php new file mode 100644 index 0000000..463fba9 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostgroupQuery.php @@ -0,0 +1,295 @@ +<?php +/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +/** + * Query for host groups + */ +class HostgroupQuery extends IdoQuery +{ + protected $allowCustomVars = true; + + protected $groupBase = array( + 'hostgroups' => array('hgo.object_id', 'hg.hostgroup_id'), + 'hoststatus' => array('hs.hoststatus_id'), + 'servicestatus' => array('ss.servicestatus_id') + ); + + protected $groupOrigin = array('members'); + + protected $subQueryTargets = array( + 'hostgroups' => 'hostgroup', + 'servicegroups' => 'servicegroup' + ); + + protected $columnMap = array( + 'contacts' => [ + 'host_contact' => 'hco.name1' + ], + 'contactgroups' => [ + 'host_contactgroup' => 'hcgo.name1' + ], + 'hostgroups' => array( + 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci', + 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci', + 'hostgroup_name' => 'hgo.name1' + ), + 'hoststatus' => array( + 'host_handled' => 'CASE WHEN (hs.problem_has_been_acknowledged + hs.scheduled_downtime_depth) > 0 THEN 1 ELSE 0 END', + 'host_severity' => ' + CASE + WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL + THEN 16 + ELSE + CASE + WHEN hs.current_state = 0 + THEN 1 + ELSE + CASE + WHEN hs.current_state = 1 THEN 64 + WHEN hs.current_state = 2 THEN 32 + ELSE 256 + END + + + CASE + WHEN hs.problem_has_been_acknowledged = 1 THEN 2 + WHEN hs.scheduled_downtime_depth > 0 THEN 1 + ELSE 256 + END + END + END', + 'host_state' => 'CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 99 ELSE hs.current_state END' + ), + 'instances' => array( + 'instance_name' => 'i.instance_name' + ), + 'members' => array( + 'host_name' => 'ho.name1' + ), + 'servicegroups' => array( + 'servicegroup_name' => 'sgo.name1' + ), + 'services' => array( + 'service_description' => 'so.name2' + ), + 'servicestatus' => array( + 'service_handled' => 'CASE WHEN (ss.problem_has_been_acknowledged + ss.scheduled_downtime_depth + COALESCE(hs.current_state, 0)) > 0 THEN 1 ELSE 0 END', + 'service_severity' => ' + CASE WHEN ss.current_state = 0 + THEN + CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL + THEN 16 + ELSE 0 + END + + + CASE WHEN ss.problem_has_been_acknowledged = 1 + THEN 2 + ELSE + CASE WHEN ss.scheduled_downtime_depth > 0 + THEN 1 + ELSE 4 + END + END + ELSE + CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 16 + WHEN ss.current_state = 1 THEN 32 + WHEN ss.current_state = 2 THEN 128 + WHEN ss.current_state = 3 THEN 64 + ELSE 256 + END + + + CASE WHEN hs.current_state > 0 + THEN 1024 + ELSE + CASE WHEN ss.problem_has_been_acknowledged = 1 + THEN 512 + ELSE + CASE WHEN ss.scheduled_downtime_depth > 0 + THEN 256 + ELSE 2048 + END + END + END + END', + 'service_state' => 'CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 99 ELSE ss.current_state END' + ) + ); + + protected function joinBaseTables() + { + $this->select->from( + array('hgo' => $this->prefix . 'objects'), + array() + )->join( + array('hg' => $this->prefix . 'hostgroups'), + 'hg.hostgroup_object_id = hgo.object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3', + array() + ); + $this->joinedVirtualTables['hostgroups'] = true; + } + + /** + * Join contacts + */ + protected function joinContacts() + { + $this->requireVirtualTable('hosts'); + + $this->select->joinLeft( + ['hc' => 'icinga_host_contacts'], + 'hc.host_id = h.host_id', + [] + )->joinLeft( + ['hco' => 'icinga_objects'], + 'hco.object_id = hc.contact_object_id AND hco.is_active = 1 AND hco.objecttype_id = 10', + [] + ); + } + + /** + * Join contact groups + */ + protected function joinContactgroups() + { + $this->requireVirtualTable('hosts'); + + $this->select->joinLeft( + ['hcg' => 'icinga_host_contactgroups'], + 'hcg.host_id = h.host_id', + [] + )->joinLeft( + ['hcgo' => 'icinga_objects'], + 'hcgo.object_id = hcg.contactgroup_object_id AND hcgo.is_active = 1 AND hcgo.objecttype_id = 11', + [] + ); + } + + /** + * Join hosts + */ + protected function joinHosts() + { + $this->requireVirtualTable('members'); + $this->select->join( + array('h' => $this->prefix . 'hosts'), + 'h.host_object_id = ho.object_id', + array() + ); + } + + /** + * Join host status + */ + protected function joinHoststatus() + { + $this->requireVirtualTable('members'); + $this->select->join( + array('hs' => $this->prefix . 'hoststatus'), + 'hs.host_object_id = ho.object_id', + array() + ); + } + + /** + * Join instances + */ + protected function joinInstances() + { + $this->select->join( + array('i' => $this->prefix . 'instances'), + 'i.instance_id = hg.instance_id', + array() + ); + } + + /** + * Join members + */ + protected function joinMembers() + { + $this->select->join( + array('hgm' => $this->prefix . 'hostgroup_members'), + 'hgm.hostgroup_id = hg.hostgroup_id', + array() + )->join( + array('ho' => $this->prefix . 'objects'), + 'hgm.host_object_id = ho.object_id AND ho.is_active = 1 AND ho.objecttype_id = 1', + array() + ); + } + + /** + * Join service groups + */ + protected function joinServicegroups() + { + $this->requireVirtualTable('services'); + $this->select->joinLeft( + array('sgm' => $this->prefix . 'servicegroup_members'), + 'sgm.service_object_id = s.service_object_id', + array() + )->joinLeft( + array('sg' => $this->prefix . 'servicegroups'), + 'sgm.servicegroup_id = sg.servicegroup_id', + array() + )->joinLeft( + array('sgo' => $this->prefix . 'objects'), + 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4', + array() + ); + } + + /** + * Join services + */ + protected function joinServices() + { + $this->requireVirtualTable('hosts'); + $this->select->joinLeft( + array('s' => $this->prefix . 'services'), + 's.host_object_id = h.host_object_id', + array() + )->joinLeft( + array('so' => $this->prefix . 'objects'), + 'so.object_id = s.service_object_id AND so.is_active = 1 AND so.objecttype_id = 2', + array() + ); + } + + /** + * Join service status + */ + protected function joinServicestatus() + { + $this->requireVirtualTable('services'); + $this->requireVirtualTable('hoststatus'); + $this->select->join( + array('ss' => $this->prefix . 'servicestatus'), + 'ss.service_object_id = so.object_id', + array() + ); + } + + protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter) + { + if ($name === 'hostgroup') { + // Propagate that the "parent" query has to be filtered as well + $additionalFilter = clone $filter; + + $this->requireVirtualTable('members'); + + $query->joinVirtualTable('members'); + + return ['hgm.host_object_id', 'ho.object_id']; + } elseif ($name === 'servicegroup') { + $this->requireVirtualTable('members'); + + $query->joinVirtualTable('services'); + + return ['s.host_object_id', 'ho.object_id']; + } + + return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostgroupsummaryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostgroupsummaryQuery.php new file mode 100644 index 0000000..a1b7182 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostgroupsummaryQuery.php @@ -0,0 +1,142 @@ +<?php +/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Zend_Db_Expr; +use Zend_Db_Select; + +use Icinga\Data\Filter\Filter; + +/** + * Query for host group summary + */ +class HostgroupsummaryQuery extends IdoQuery +{ + protected $allowCustomVars = true; + + protected $columnMap = array( + 'hostgroupsummary' => array( + 'hostgroup_alias' => 'hostgroup_alias', + 'hostgroup_name' => 'hostgroup_name', + 'hosts_down' => 'SUM(CASE WHEN host_state = 1 THEN 1 ELSE 0 END)', + 'hosts_down_handled' => 'SUM(CASE WHEN host_state = 1 AND host_handled = 1 THEN 1 ELSE 0 END)', + 'hosts_down_unhandled' => 'SUM(CASE WHEN host_state = 1 AND host_handled = 0 THEN 1 ELSE 0 END)', + 'hosts_pending' => 'SUM(CASE WHEN host_state = 99 THEN 1 ELSE 0 END)', + 'hosts_severity' => 'MAX(host_severity)', + 'hosts_total' => 'SUM(CASE WHEN host_state IS NOT NULL THEN 1 ELSE 0 END)', + 'hosts_unreachable' => 'SUM(CASE WHEN host_state = 2 THEN 1 ELSE 0 END)', + 'hosts_unreachable_handled' => 'SUM(CASE WHEN host_state = 2 AND host_handled = 1 THEN 1 ELSE 0 END)', + 'hosts_unreachable_unhandled' => 'SUM(CASE WHEN host_state = 2 AND host_handled = 0 THEN 1 ELSE 0 END)', + 'hosts_up' => 'SUM(CASE WHEN host_state = 0 THEN 1 ELSE 0 END)', + 'services_critical' => 'SUM(CASE WHEN service_state = 2 THEN 1 ELSE 0 END)', + 'services_critical_handled' => 'SUM(CASE WHEN service_state = 2 AND service_handled = 1 THEN 1 ELSE 0 END)', + 'services_critical_unhandled' => 'SUM(CASE WHEN service_state = 2 AND service_handled = 0 THEN 1 ELSE 0 END)', + 'services_ok' => 'SUM(CASE WHEN service_state = 0 THEN 1 ELSE 0 END)', + 'services_pending' => 'SUM(CASE WHEN service_state = 99 THEN 1 ELSE 0 END)', + 'services_total' => 'SUM(CASE WHEN service_state IS NOT NULL THEN 1 ELSE 0 END)', + 'services_unknown' => 'SUM(CASE WHEN service_state = 3 THEN 1 ELSE 0 END)', + 'services_unknown_handled' => 'SUM(CASE WHEN service_state = 3 AND service_handled = 1 THEN 1 ELSE 0 END)', + 'services_unknown_unhandled' => 'SUM(CASE WHEN service_state = 3 AND service_handled = 0 THEN 1 ELSE 0 END)', + 'services_warning' => 'SUM(CASE WHEN service_state = 1 THEN 1 ELSE 0 END)', + 'services_warning_handled' => 'SUM(CASE WHEN service_state = 1 AND service_handled = 1 THEN 1 ELSE 0 END)', + 'services_warning_unhandled' => 'SUM(CASE WHEN service_state = 1 AND service_handled = 0 THEN 1 ELSE 0 END)', + ) + ); + + /** + * The union + * + * @var Zend_Db_Select + */ + protected $summaryQuery; + + /** + * Subqueries used for the summary query + * + * @var IdoQuery[] + */ + protected $subQueries = array(); + + /** + * Count query + * + * @var IdoQuery + */ + protected $countQuery; + + public function addFilter(Filter $filter) + { + foreach ($this->subQueries as $sub) { + $sub->applyFilter(clone $filter); + } + $this->countQuery->applyFilter(clone $filter); + return $this; + } + + protected function joinBaseTables() + { + $this->countQuery = $this->createSubQuery( + 'Hostgroup', + array() + ); + $hosts = $this->createSubQuery( + 'Hostgroup', + array( + 'hostgroup_alias', + 'hostgroup_name', + 'host_handled', + 'host_severity', + 'host_state', + 'service_handled' => new Zend_Db_Expr('NULL'), + 'service_severity' => new Zend_Db_Expr('0'), + 'service_state' => new Zend_Db_Expr('NULL'), + ) + ); + $this->subQueries[] = $hosts; + $services = $this->createSubQuery( + 'Hostgroup', + array( + 'hostgroup_alias', + 'hostgroup_name', + 'host_handled' => new Zend_Db_Expr('NULL'), + 'host_severity' => new Zend_Db_Expr('0'), + 'host_state' => new Zend_Db_Expr('NULL'), + 'service_handled', + 'service_severity', + 'service_state' + ) + ); + $this->subQueries[] = $services; + $emptyGroups = $this->createSubQuery( + 'Emptyhostgroup', + [ + 'hostgroup_alias', + 'hostgroup_name', + 'host_handled' => new Zend_Db_Expr('NULL'), + 'host_severity' => new Zend_Db_Expr('0'), + 'host_state' => new Zend_Db_Expr('NULL'), + 'service_handled' => new Zend_Db_Expr('NULL'), + 'service_severity' => new Zend_Db_Expr('0'), + 'service_state' => new Zend_Db_Expr('NULL'), + ] + ); + $this->subQueries[] = $emptyGroups; + $this->summaryQuery = $this->db->select()->union( + [$hosts, $services, $emptyGroups], + Zend_Db_Select::SQL_UNION_ALL + ); + $this->select->from(array('hostgroupsummary' => $this->summaryQuery), array()); + $this->group(array('hostgroup_name', 'hostgroup_alias')); + $this->joinedVirtualTables['hostgroupsummary'] = true; + } + + public function getCountQuery() + { + $count = $this->countQuery->select(); + $this->countQuery->applyFilterSql($count); + $count->columns(array('hgo.object_id')); + $count->group(array('hgo.object_id')); + return $this->db->select()->from($count, array('cnt' => 'COUNT(*)')); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostnotificationQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostnotificationQuery.php new file mode 100644 index 0000000..f252a7e --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostnotificationQuery.php @@ -0,0 +1,284 @@ +<?php +/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Data\Filter\Filter; +use Icinga\Data\Filter\FilterExpression; + +/** + * Query for host notifications + */ +class HostnotificationQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $allowCustomVars = true; + + protected $subQueryTargets = array( + 'hostgroups' => 'hostgroup', + 'servicegroups' => 'servicegroup' + ); + + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'contactnotifications' => array( + 'notification_contact_name' => 'co.name1' + ), + 'hostgroups' => array( + 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci', + 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci', + 'hostgroup_name' => 'hgo.name1' + ), + 'hosts' => array( + 'host_display_name' => 'h.display_name COLLATE latin1_general_ci', + 'host_alias' => 'h.alias COLLATE latin1_general_ci', + ), + 'history' => array( + 'output' => null, + 'state' => 'hn.state', + 'timestamp' => 'UNIX_TIMESTAMP(hn.start_time)', + 'type' => ' + CASE hn.notification_reason + WHEN 1 THEN \'notification_ack\' + WHEN 2 THEN \'notification_flapping\' + WHEN 3 THEN \'notification_flapping_end\' + WHEN 5 THEN \'notification_dt_start\' + WHEN 6 THEN \'notification_dt_end\' + WHEN 7 THEN \'notification_dt_end\' + WHEN 8 THEN \'notification_custom\' + ELSE \'notification_state\' + END', + ), + 'instances' => array( + 'instance_name' => 'i.instance_name' + ), + 'notifications' => array( + 'id' => 'hn.notification_id', + 'host' => 'ho.name1 COLLATE latin1_general_ci', + 'host_name' => 'ho.name1', + 'notification_output' => 'hn.output', + 'notification_reason' => 'hn.notification_reason', + 'notification_state' => 'hn.state', + 'notification_timestamp' => 'UNIX_TIMESTAMP(hn.start_time)', + 'object_type' => '(\'host\')' + ), + 'servicegroups' => array( + 'servicegroup_name' => 'sgo.name1', + 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci', + 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci' + ), + 'services' => array( + 'service' => 'so.name2 COLLATE latin1_general_ci', + 'service_description' => 'so.name2', + 'service_display_name' => 's.display_name COLLATE latin1_general_ci', + 'service_host_name' => 'so.name1' + ) + ); + + protected function requireFilterColumns(Filter $filter) + { + if ($filter instanceof FilterExpression) { + switch ($filter->getColumn()) { + case 'output': + $this->requireColumn('output'); + $filter->setColumn('hn.output'); + return null; + case 'timestamp': + case 'notification_timestamp': + $this->requireColumn($filter->getColumn()); + $filter->setColumn('hn.start_time'); + $filter->setExpression($this->timestampForSql($this->valueToTimestamp($filter->getExpression()))); + return null; + } + } + + return parent::requireFilterColumns($filter); + } + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + $concattedContacts = null; + switch ($this->ds->getDbType()) { + case 'mysql': + $concattedContacts = "GROUP_CONCAT(" + . "DISTINCT co.name1 ORDER BY co.name1 SEPARATOR ', '" + . ") COLLATE latin1_general_ci"; + break; + case 'pgsql': + // TODO: Find a way to order the contact alias list: + $concattedContacts = "ARRAY_TO_STRING(ARRAY_AGG(DISTINCT co.name1), ', ')"; + break; + } + $this->columnMap['history']['output'] = "('[' || $concattedContacts || '] ' || hn.output)"; + + $this->select->from( + array('hn' => $this->prefix . 'notifications'), + array() + )->join( + array('ho' => $this->prefix . 'objects'), + 'ho.object_id = hn.object_id AND ho.is_active = 1 AND ho.objecttype_id = 1', + array() + ); + $this->joinedVirtualTables['notifications'] = true; + } + + /** + * Join virtual table history + */ + protected function joinHistory() + { + $this->requireVirtualTable('contactnotifications'); + } + + /** + * Join contact notifications + */ + protected function joinContactnotifications() + { + $this->select->joinLeft( + array('cn' => $this->prefix . 'contactnotifications'), + 'cn.notification_id = hn.notification_id', + array() + ); + $this->select->joinLeft( + array('co' => $this->prefix . 'objects'), + 'co.object_id = cn.contact_object_id AND co.is_active = 1 AND co.objecttype_id = 10', + array() + ); + } + + /** + * Join host groups + */ + protected function joinHostgroups() + { + $this->select->joinLeft( + array('hgm' => $this->prefix . 'hostgroup_members'), + 'hgm.host_object_id = ho.object_id', + array() + )->joinLeft( + array('hg' => $this->prefix . 'hostgroups'), + 'hg.hostgroup_id = hgm.hostgroup_id', + array() + )->joinLeft( + array('hgo' => $this->prefix . 'objects'), + 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3', + array() + ); + } + + /** + * Join hosts + */ + protected function joinHosts() + { + $this->select->join( + array('h' => $this->prefix . 'hosts'), + 'h.host_object_id = ho.object_id', + array() + ); + } + + /** + * Join service groups + */ + protected function joinServicegroups() + { + $this->requireVirtualTable('services'); + $this->select->joinLeft( + array('sgm' => $this->prefix . 'servicegroup_members'), + 'sgm.service_object_id = s.service_object_id', + array() + )->joinLeft( + array('sg' => $this->prefix . 'servicegroups'), + 'sg.' . $this->servicegroup_id . ' = sgm.servicegroup_id', + array() + )->joinLeft( + array('sgo' => $this->prefix . 'objects'), + 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4', + array() + ); + } + + /** + * Join services + */ + protected function joinServices() + { + $this->select->joinLeft( + array('s' => $this->prefix . 'services'), + 's.host_object_id = ho.object_id', + array() + )->joinLeft( + array('so' => $this->prefix . 'objects'), + 'so.object_id = s.service_object_id AND so.is_active = 1 AND so.objecttype_id = 2', + array() + ); + } + + /** + * Join instances + */ + protected function joinInstances() + { + $this->select->join( + array('i' => $this->prefix . 'instances'), + 'i.instance_id = hn.instance_id', + array() + ); + } + + /** + * {@inheritdoc} + */ + public function getGroup() + { + $group = array(); + + if ($this->hasJoinedVirtualTable('history') + || $this->hasJoinedVirtualTable('services') + || $this->hasJoinedVirtualTable('hostgroups') + ) { + $group = array('hn.notification_id', 'ho.object_id'); + if ($this->hasJoinedVirtualTable('contactnotifications') && !$this->hasJoinedVirtualTable('history')) { + $group[] = 'co.object_id'; + } + } elseif ($this->hasJoinedVirtualTable('contactnotifications')) { + $group = array('hn.notification_id', 'co.object_id', 'ho.object_id'); + } + + if (! empty($group)) { + if ($this->hasJoinedVirtualTable('hosts')) { + $group[] = 'h.host_id'; + } + + if ($this->hasJoinedVirtualTable('instances')) { + $group[] = 'i.instance_id'; + } + } + + return $group; + } + + protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter) + { + if ($name === 'hostgroup') { + $query->joinVirtualTable('members'); + + return ['hgm.host_object_id', 'ho.object_id']; + } elseif ($name === 'servicegroup') { + $query->joinVirtualTable('services'); + + return ['s.host_object_id', 'ho.object_id']; + } + + return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatehistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatehistoryQuery.php new file mode 100644 index 0000000..ac85c1f --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatehistoryQuery.php @@ -0,0 +1,222 @@ +<?php +/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Data\Filter\Filter; +use Icinga\Data\Filter\FilterExpression; + +/** + * Query for host state history records + */ +class HoststatehistoryQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $allowCustomVars = true; + + /** + * {@inheritdoc} + */ + protected $groupBase = array('statehistory' => array('hh.statehistory_id', 'ho.object_id')); + + /** + * {@inheritdoc} + */ + protected $groupOrigin = array('hostgroups', 'services'); + + /** + * Array to map type names to type ids for query optimization + * + * @var array + */ + protected $types = array( + 'soft_state' => 0, + 'hard_state' => 1 + ); + + protected $subQueryTargets = array( + 'hostgroups' => 'hostgroup', + 'servicegroups' => 'servicegroup' + ); + + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'hostgroups' => array( + 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci', + 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci', + 'hostgroup_name' => 'hgo.name1' + ), + 'hosts' => array( + 'host_alias' => 'h.alias', + 'host_display_name' => 'h.display_name COLLATE latin1_general_ci' + ), + 'instances' => array( + 'instance_name' => 'i.instance_name' + ), + 'servicegroups' => array( + 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci', + 'servicegroup_name' => 'sgo.name1', + 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci' + ), + 'services' => array( + 'service' => 'so.name2 COLLATE latin1_general_ci', + 'service_description' => 'so.name2', + 'service_display_name' => 's.display_name COLLATE latin1_general_ci', + 'service_host_name' => 'so.name1' + ), + 'statehistory' => array( + 'id' => 'hh.statehistory_id', + 'host' => 'ho.name1 COLLATE latin1_general_ci', + 'host_name' => 'ho.name1', + 'object_id' => 'hh.object_id', + 'object_type' => '(\'host\')', + 'output' => '(CASE WHEN hh.state_type = 1 THEN hh.output ELSE \'[ \' || hh.current_check_attempt || \'/\' || hh.max_check_attempts || \' ] \' || hh.output END)', + 'state' => 'hh.state', + 'timestamp' => 'UNIX_TIMESTAMP(hh.state_time)', + 'type' => "(CASE WHEN hh.state_type = 1 THEN 'hard_state' ELSE 'soft_state' END)" + ), + ); + + protected function requireFilterColumns(Filter $filter) + { + if ($filter instanceof FilterExpression) { + switch ($filter->getColumn()) { + case 'timestamp': + $this->requireColumn('timestamp'); + $filter->setColumn('hh.state_time'); + $filter->setExpression($this->timestampForSql($this->valueToTimestamp($filter->getExpression()))); + return null; + case 'type': + if (! is_array($filter->getExpression())) { + $this->requireColumn('type'); + $filter->setColumn('hh.state_type'); + if (isset($this->types[$filter->getExpression()])) { + $filter->setExpression($this->types[$filter->getExpression()]); + } else { + $filter->setExpression(-1); + } + + return null; + } + } + } + + return parent::requireFilterColumns($filter); + } + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + $this->select->from( + array('hh' => $this->prefix . 'statehistory'), + array() + )->join( + array('ho' => $this->prefix . 'objects'), + 'ho.object_id = hh.object_id AND ho.is_active = 1 AND ho.objecttype_id = 1', + array() + ); + $this->joinedVirtualTables['statehistory'] = true; + } + + /** + * Join host groups + */ + protected function joinHostgroups() + { + $this->select->joinLeft( + array('hgm' => $this->prefix . 'hostgroup_members'), + 'hgm.host_object_id = ho.object_id', + array() + )->joinLeft( + array('hg' => $this->prefix . 'hostgroups'), + 'hg.hostgroup_id = hgm.hostgroup_id', + array() + )->joinLeft( + array('hgo' => $this->prefix . 'objects'), + 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3', + array() + ); + } + + /** + * Join hosts + */ + protected function joinHosts() + { + $this->select->join( + array('h' => $this->prefix . 'hosts'), + 'h.host_object_id = ho.object_id', + array() + ); + } + + /** + * Join instances + */ + protected function joinInstances() + { + $this->select->join( + array('i' => $this->prefix . 'instances'), + 'i.instance_id = hh.instance_id', + array() + ); + } + + /** + * Join service groups + */ + protected function joinServicegroups() + { + $this->requireVirtualTable('services'); + $this->select->joinLeft( + array('sgm' => $this->prefix . 'servicegroup_members'), + 'sgm.service_object_id = s.service_object_id', + array() + )->joinLeft( + array('sg' => $this->prefix . 'servicegroups'), + 'sg.' . $this->servicegroup_id . ' = sgm.servicegroup_id', + array() + )->joinLeft( + array('sgo' => $this->prefix . 'objects'), + 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4', + array() + ); + } + + /** + * Join services + */ + protected function joinServices() + { + $this->select->joinLeft( + array('s' => $this->prefix . 'services'), + 's.host_object_id = ho.object_id', + array() + )->joinLeft( + array('so' => $this->prefix . 'objects'), + 'so.object_id = s.service_object_id AND so.is_active = 1 AND so.objecttype_id = 2', + array() + ); + } + + protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter) + { + if ($name === 'hostgroup') { + $query->joinVirtualTable('members'); + + return ['hgm.host_object_id', 'ho.object_id']; + } elseif ($name === 'servicegroup') { + $query->joinVirtualTable('services'); + + return ['s.host_object_id', 'ho.object_id']; + } + + return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatusQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatusQuery.php new file mode 100644 index 0000000..e1b5480 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatusQuery.php @@ -0,0 +1,338 @@ +<?php +/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +class HoststatusQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $allowCustomVars = true; + + /** + * {@inheritdoc} + */ + protected $groupBase = array('hosts' => array('ho.object_id', 'h.host_id')); + + /** + * {@inheritdoc} + */ + protected $groupOrigin = array('hostgroups', 'servicegroups', 'services'); + + protected $subQueryTargets = array( + 'hostgroups' => 'hostgroup', + 'servicegroups' => 'servicegroup' + ); + + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'checktimeperiods' => array( + 'host_check_timeperiod' => 'ctp.alias COLLATE latin1_general_ci' + ), + 'contacts' => [ + 'host_contact' => 'hco.name1' + ], + 'contactgroups' => [ + 'host_contactgroup' => 'hcgo.name1' + ], + 'hostgroups' => array( + 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci', + 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci', + 'hostgroup_name' => 'hgo.name1' + ), + 'hosts' => array( + 'host' => 'ho.name1 COLLATE latin1_general_ci', + 'host_action_url' => 'h.action_url', + 'host_address' => 'h.address', + 'host_address6' => 'h.address6', + 'host_alias' => 'h.alias', + 'host_check_interval' => '(h.check_interval * 60)', + 'host_display_name' => 'h.display_name COLLATE latin1_general_ci', + 'host_icon_image' => 'h.icon_image', + 'host_icon_image_alt' => 'h.icon_image_alt', + 'host_ipv4' => 'INET_ATON(h.address)', + 'host_name' => 'ho.name1', + 'host_notes' => 'h.notes', + 'host_notes_url' => 'h.notes_url', + 'object_type' => '(\'host\')', + 'object_id' => 'ho.object_id' + ), + 'hoststatus' => array( + 'host_acknowledged' => 'hs.problem_has_been_acknowledged', + 'host_acknowledgement_type' => 'hs.acknowledgement_type', + 'host_active_checks_enabled' => 'hs.active_checks_enabled', + 'host_active_checks_enabled_changed' => 'CASE WHEN hs.active_checks_enabled = h.active_checks_enabled THEN 0 ELSE 1 END', + 'host_attempt' => 'hs.current_check_attempt || \'/\' || hs.max_check_attempts', + 'host_check_command' => 'hs.check_command', + 'host_check_execution_time' => 'hs.execution_time', + 'host_check_latency' => 'hs.latency', + 'host_check_source' => 'hs.check_source', + 'host_check_type' => 'hs.check_type', + 'host_current_check_attempt' => 'hs.current_check_attempt', + 'host_current_notification_number' => 'hs.current_notification_number', + 'host_event_handler' => 'hs.event_handler', + 'host_event_handler_enabled' => 'hs.event_handler_enabled', + 'host_event_handler_enabled_changed' => 'CASE WHEN hs.event_handler_enabled = h.event_handler_enabled THEN 0 ELSE 1 END', + 'host_failure_prediction_enabled' => 'hs.failure_prediction_enabled', + 'host_flap_detection_enabled' => 'hs.flap_detection_enabled', + 'host_flap_detection_enabled_changed' => 'CASE WHEN hs.flap_detection_enabled = h.flap_detection_enabled THEN 0 ELSE 1 END', + 'host_handled' => 'CASE WHEN (hs.problem_has_been_acknowledged + hs.scheduled_downtime_depth) > 0 THEN 1 ELSE 0 END', + 'host_hard_state' => 'CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 99 ELSE CASE WHEN hs.state_type = 1 THEN hs.current_state ELSE hs.last_hard_state END END', + 'host_in_downtime' => 'CASE WHEN (hs.scheduled_downtime_depth = 0) THEN 0 ELSE 1 END', + 'host_is_flapping' => 'hs.is_flapping', + 'host_is_passive_checked' => 'CASE WHEN hs.active_checks_enabled = 0 AND hs.passive_checks_enabled = 1 THEN 1 ELSE 0 END', + 'host_is_reachable' => 'hs.is_reachable', + 'host_last_check' => 'UNIX_TIMESTAMP(hs.last_check)', + 'host_last_hard_state' => 'hs.last_hard_state', + 'host_last_hard_state_change' => 'UNIX_TIMESTAMP(hs.last_hard_state_change)', + 'host_last_notification' => 'UNIX_TIMESTAMP(hs.last_notification)', + 'host_last_state_change' => 'UNIX_TIMESTAMP(hs.last_state_change)', + 'host_last_state_change_ts' => 'hs.last_state_change', + 'host_last_time_down' => 'UNIX_TIMESTAMP(hs.last_time_down)', + 'host_last_time_unreachable' => 'UNIX_TIMESTAMP(hs.last_time_unreachable)', + 'host_last_time_up' => 'UNIX_TIMESTAMP(hs.last_time_up)', + 'host_long_output' => 'hs.long_output', + 'host_max_check_attempts' => 'hs.max_check_attempts', + 'host_modified_host_attributes' => 'hs.modified_host_attributes', + 'host_next_check' => 'CASE hs.should_be_scheduled WHEN 1 THEN UNIX_TIMESTAMP(hs.next_check) ELSE NULL END', + 'host_next_notification' => 'UNIX_TIMESTAMP(hs.next_notification)', + 'host_next_update' => 'CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL + THEN + CASE hs.should_be_scheduled WHEN 1 THEN UNIX_TIMESTAMP(hs.next_check) + (hs.normal_check_interval * 60) ELSE NULL END + ELSE + UNIX_TIMESTAMP(hs.next_check) + + (CASE WHEN + COALESCE(hs.current_state, 0) > 0 AND hs.state_type = 0 + THEN + hs.retry_check_interval + ELSE + hs.normal_check_interval + END * 60) + + (CEIL(hs.execution_time + hs.latency) * 2) + END', + 'host_no_more_notifications' => 'hs.no_more_notifications', + 'host_normal_check_interval' => 'hs.normal_check_interval', + 'host_notifications_enabled' => 'hs.notifications_enabled', + 'host_notifications_enabled_changed' => 'CASE WHEN hs.notifications_enabled = h.notifications_enabled THEN 0 ELSE 1 END', + 'host_obsessing' => 'hs.obsess_over_host', + 'host_obsessing_changed' => 'CASE WHEN hs.obsess_over_host = h.obsess_over_host THEN 0 ELSE 1 END', + 'host_output' => 'hs.output', + 'host_passive_checks_enabled' => 'hs.passive_checks_enabled', + 'host_passive_checks_enabled_changed' => 'CASE WHEN hs.passive_checks_enabled = h.passive_checks_enabled THEN 0 ELSE 1 END', + 'host_percent_state_change' => 'hs.percent_state_change', + 'host_perfdata' => 'hs.perfdata', + 'host_problem' => 'CASE WHEN COALESCE(hs.current_state, 0) = 0 THEN 0 ELSE 1 END', + 'host_problem_has_been_acknowledged' => 'hs.problem_has_been_acknowledged', + 'host_process_performance_data' => 'hs.process_performance_data', + 'host_retry_check_interval' => 'hs.retry_check_interval', + 'host_scheduled_downtime_depth' => 'hs.scheduled_downtime_depth', + 'host_severity' => ' + CASE + WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL + THEN 16 + ELSE + CASE + WHEN hs.current_state = 0 + THEN 1 + ELSE + CASE + WHEN hs.current_state = 1 THEN 64 + WHEN hs.current_state = 2 THEN 32 + ELSE 256 + END + + + CASE + WHEN hs.problem_has_been_acknowledged = 1 THEN 2 + WHEN hs.scheduled_downtime_depth > 0 THEN 1 + ELSE 256 + END + END + END', + 'host_state' => 'CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 99 ELSE hs.current_state END', + 'host_state_type' => 'hs.state_type', + 'host_status_update_time' => 'hs.status_update_time', + 'host_unhandled' => 'CASE WHEN (hs.problem_has_been_acknowledged + hs.scheduled_downtime_depth) = 0 THEN 1 ELSE 0 END', + 'problems' => 'CASE WHEN COALESCE(hs.current_state, 0) = 0 THEN 0 ELSE 1 END' + ), + 'instances' => array( + 'instance_name' => 'i.instance_name' + ), + 'servicegroups' => array( + 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci', + 'servicegroup_name' => 'sgo.name1', + 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci' + ), + 'services' => array( + 'service' => 'so.name2 COLLATE latin1_general_ci', + 'service_description' => 'so.name2', + 'service_display_name' => 's.display_name COLLATE latin1_general_ci', + ) + ); + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + if (version_compare($this->getIdoVersion(), '1.10.0', '<')) { + $this->columnMap['hoststatus']['host_check_source'] = '(NULL)'; + } + if (version_compare($this->getIdoVersion(), '1.13.0', '<')) { + $this->columnMap['hoststatus']['host_is_reachable'] = '(NULL)'; + } + + $this->select->from( + array('ho' => $this->prefix . 'objects'), + array() + )->join( + array('h' => $this->prefix . 'hosts'), + 'h.host_object_id = ho.object_id AND ho.is_active = 1 AND ho.objecttype_id = 1', + array() + ); + $this->joinedVirtualTables['hosts'] = true; + } + + /** + * Join check time periods + */ + protected function joinChecktimeperiods() + { + $this->select->joinLeft( + array('ctp' => $this->prefix . 'timeperiods'), + 'ctp.timeperiod_object_id = h.check_timeperiod_object_id', + array() + ); + } + + /** + * Join contacts + */ + protected function joinContacts() + { + $this->select->joinLeft( + ['hc' => 'icinga_host_contacts'], + 'hc.host_id = h.host_id', + [] + )->joinLeft( + ['hco' => 'icinga_objects'], + 'hco.object_id = hc.contact_object_id AND hco.is_active = 1 AND hco.objecttype_id = 10', + [] + ); + } + + /** + * Join contact groups + */ + protected function joinContactgroups() + { + $this->select->joinLeft( + ['hcg' => 'icinga_host_contactgroups'], + 'hcg.host_id = h.host_id', + [] + )->joinLeft( + ['hcgo' => 'icinga_objects'], + 'hcgo.object_id = hcg.contactgroup_object_id AND hcgo.is_active = 1 AND hcgo.objecttype_id = 11', + [] + ); + } + + /** + * Join host groups + */ + protected function joinHostgroups() + { + $this->select->joinLeft( + array('hgm' => $this->prefix . 'hostgroup_members'), + 'hgm.host_object_id = ho.object_id', + array() + )->joinLeft( + array('hg' => $this->prefix . 'hostgroups'), + 'hg.hostgroup_id = hgm.hostgroup_id', + array() + )->joinLeft( + array('hgo' => $this->prefix . 'objects'), + 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3', + array() + ); + } + + /** + * Join host status + */ + protected function joinHoststatus() + { + $this->select->join( + array('hs' => $this->prefix . 'hoststatus'), + 'hs.host_object_id = ho.object_id', + array() + ); + } + + /** + * Join instances + */ + protected function joinInstances() + { + $this->select->join( + array('i' => $this->prefix . 'instances'), + 'i.instance_id = ho.instance_id', + array() + ); + } + + /** + * Join service groups + */ + protected function joinServicegroups() + { + $this->requireVirtualTable('services'); + $this->select->joinLeft( + array('sgm' => $this->prefix . 'servicegroup_members'), + 'sgm.service_object_id = s.service_object_id', + array() + )->joinLeft( + array('sg' => $this->prefix . 'servicegroups'), + 'sgm.servicegroup_id = sg.' . $this->servicegroup_id, + array() + )->joinLeft( + array('sgo' => $this->prefix . 'objects'), + 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4', + array() + ); + } + + /** + * Join services + */ + protected function joinServices() + { + $this->requireVirtualTable('hosts'); + $this->select->joinLeft( + array('s' => $this->prefix . 'services'), + 's.host_object_id = h.host_object_id', + array() + )->joinLeft( + array('so' => $this->prefix . 'objects'), + 'so.object_id = s.service_object_id AND so.is_active = 1 AND so.objecttype_id = 2', + array() + ); + } + + protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter) + { + if ($name === 'hostgroup') { + $query->joinVirtualTable('members'); + + return ['hgm.host_object_id', 'ho.object_id']; + } elseif ($name === 'servicegroup') { + $query->joinVirtualTable('services'); + + return ['s.host_object_id', 'ho.object_id']; + } + + return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatussummaryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatussummaryQuery.php new file mode 100644 index 0000000..b4a91f3 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatussummaryQuery.php @@ -0,0 +1,91 @@ +<?php +/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Data\Filter\Filter; +use Icinga\Data\Filter\FilterExpression; + +/** + * Query for host group summaries + */ +class HoststatussummaryQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'hoststatussummary' => array( + 'hosts_down' => 'SUM(CASE WHEN state = 1 THEN 1 ELSE 0 END)', + 'hosts_down_handled' => 'SUM(CASE WHEN state = 1 AND handled = 1 THEN 1 ELSE 0 END)', + 'hosts_down_unhandled' => 'SUM(CASE WHEN state = 1 AND handled = 0 THEN 1 ELSE 0 END)', + 'hosts_pending' => 'SUM(CASE WHEN state = 99 THEN 1 ELSE 0 END)', + 'hosts_total' => 'SUM(1)', + 'hosts_unreachable' => 'SUM(CASE WHEN state = 2 THEN 1 ELSE 0 END)', + 'hosts_unreachable_handled' => 'SUM(CASE WHEN state = 2 AND handled = 1 THEN 1 ELSE 0 END)', + 'hosts_unreachable_unhandled' => 'SUM(CASE WHEN state = 2 AND handled = 0 THEN 1 ELSE 0 END)', + 'hosts_up' => 'SUM(CASE WHEN state = 0 THEN 1 ELSE 0 END)' + ) + ); + + /** + * The host status sub select + * + * @var HoststatusQuery + */ + protected $subSelect; + + /** + * {@inheritdoc} + */ + public function allowsCustomVars() + { + return $this->subSelect->allowsCustomVars(); + } + + /** + * {@inheritdoc} + */ + public function addFilter(Filter $filter) + { + $this->subSelect->applyFilter(clone $filter); + return $this; + } + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + // TODO(el): Allow to switch between hard and soft states + $this->subSelect = $this->createSubQuery( + 'Hoststatus', + array( + 'handled' => 'host_handled', + 'state' => 'host_state', + 'state_change' => 'host_last_state_change' + ) + ); + $this->select->from( + array('hoststatussummary' => $this->subSelect->setIsSubQuery(true)), + array() + ); + $this->joinedVirtualTables['hoststatussummary'] = true; + } + + /** + * {@inheritdoc} + */ + public function where($condition, $value = null) + { + $this->subSelect->where($condition, $value); + return $this; + } + + public function whereEx(FilterExpression $ex) + { + $this->subSelect->whereEx($ex); + + return $this; + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php new file mode 100644 index 0000000..5785092 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php @@ -0,0 +1,1599 @@ +<?php +/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Data\Filter\FilterNot; +use Zend_Db_Expr; +use Icinga\Application\Icinga; +use Icinga\Application\Hook; +use Icinga\Application\Logger; +use Icinga\Data\Db\DbQuery; +use Icinga\Data\Filter\Filter; +use Icinga\Data\Filter\FilterExpression; +use Icinga\Exception\IcingaException; +use Icinga\Exception\NotImplementedError; +use Icinga\Exception\ProgrammingError; +use Icinga\Exception\QueryException; +use Icinga\Web\Session; +use Icinga\Module\Monitoring\Data\ColumnFilterIterator; +use Zend_Db_Select; + +/** + * Base class for Ido Queries + * + * This is the base class for all Ido queries and should be extended for new queries + * The starting point for implementations is the columnMap attribute. This is an asscociative array in the + * following form: + * + * <pre> + * <code> + * array( + * 'virtualTable' => array( + * 'fieldalias1' => 'queryColumn1', + * 'fieldalias2' => 'queryColumn2', + * .... + * ), + * 'virtualTable2' => array( + * 'host' => 'host_name1' + * ) + * ) + * </code> + * </pre> + * + * This allows you to select e.g. fieldalias1, which automatically calls the query code for joining 'virtualTable'. If + * you afterwards select 'host', 'virtualTable2' will be joined. The joining logic is up to you, in order to make the + * above example work you need to implement the joinVirtualTable() method which contain your + * custom (Zend_Db) logic for joining, filtering and querying the data you want. + * + */ +abstract class IdoQuery extends DbQuery +{ + /** + * The prefix to use + * + * @var string + */ + protected $prefix; + + /** + * An array to map aliases to column names + * + * @var array + */ + protected $idxAliasColumn; + + /** + * An array to map aliases to table names + * + * @var array + */ + protected $idxAliasTable; + + /** + * An array to map custom aliases to aliases + * + * @var array + */ + protected $idxCustomAliases; + + /** + * The column map containing all filterable columns + * + * This must be overwritten by child classes, in the format + * array( + * 'virtualTable' => array( + * 'fieldalias1' => 'queryColumn1', + * 'fieldalias2' => 'queryColumn2', + * .... + * ) + * ) + * + * @var array + */ + protected $columnMap = array(); + + /** + * Custom vars available for this query + * + * @var array + */ + protected $customVars = array(); + + /** + * Printf compatible string to joins custom vars + * + * - %1$s Source field, contain the object_id + * - %2$s Alias used for the relation + * - %3$s Name of the CustomVariable + * + * @var string + */ + private $customVarsJoinTemplate = '%1$s = %2$s.object_id AND %2$s.varname = %3$s'; + + /** + * An array with all 'virtual' tables that are already joined + * + * Virtual tables are the keys of the columnMap array and require a + * join%VirtualTableName%() method to be defined in the concrete + * query + * + * @var array + */ + protected $joinedVirtualTables = array(); + + /** + * A map of virtual table names and corresponding hook instances + * + * Joins for those tables will be delegated to them + * + * @var array + */ + protected $hookedVirtualTables = array(); + + /** + * List of column aliases used for sorting the result + * + * @var array + */ + protected $orderColumns = array(); + + /** + * Table to columns map which have to be added to the GROUP BY list if the query is grouped + * + * @var array + */ + protected $groupBase = array(); + + /** + * List of table names which initiate grouping if one of them is joined + * + * @var array + */ + protected $groupOrigin = array(); + + /** + * Map of table names to query names for which to create subquery filters + * + * @var array + */ + protected $subQueryTargets = array(); + + /** + * The primary key column for the instances table + * + * @var string + */ + protected $instance_id = 'instance_id'; + + /** + * The primary key column for the objects table + * + * @var string + */ + protected $object_id = 'object_id'; + + /** + * The primary key column for the acknowledgements table + * + * @var string + */ + protected $acknowledgement_id = 'acknowledgement_id'; + + /** + * The primary key column for the commenthistory table + * + * @var string + */ + protected $commenthistory_id = 'commenthistory_id'; + + /** + * The primary key column for the contactnotifications table + * + * @var string + */ + protected $contactnotification_id = 'contactnotification_id'; + + /** + * The primary key column for the downtimehistory table + * + * @var string + */ + protected $downtimehistory_id = 'downtimehistory_id'; + + /** + * The primary key column for the flappinghistory table + * + * @var string + */ + protected $flappinghistory_id = 'flappinghistory_id'; + + /** + * The primary key column for the notifications table + * + * @var string + */ + protected $notification_id = 'notification_id'; + + /** + * The primary key column for the statehistory table + * + * @var string + */ + protected $statehistory_id = 'statehistory_id'; + + /** + * The primary key column for the comments table + * + * @var string + */ + protected $comment_id = 'comment_id'; + + /** + * The primary key column for the customvariablestatus table + * + * @var string + */ + protected $customvariablestatus_id = 'customvariablestatus_id'; + + /** + * The primary key column for the hoststatus table + * + * @var string + */ + protected $hoststatus_id = 'hoststatus_id'; + + /** + * The primary key column for the programstatus table + * + * @var string + */ + protected $programstatus_id = 'programstatus_id'; + + /** + * The primary key column for the runtimevariables table + * + * @var string + */ + protected $runtimevariable_id = 'runtimevariable_id'; + + /** + * The primary key column for the scheduleddowntime table + * + * @var string + */ + protected $scheduleddowntime_id = 'scheduleddowntime_id'; + + /** + * The primary key column for the servicestatus table + * + * @var string + */ + protected $servicestatus_id = 'servicestatus_id'; + + /** + * The primary key column for the contactstatus table + * + * @var string + */ + protected $contactstatus_id = 'contactstatus_id'; + + /** + * The primary key column for the commands table + * + * @var string + */ + protected $command_id = 'command_id'; + + /** + * The primary key column for the contactgroup_members table + * + * @var string + */ + protected $contactgroup_member_id = 'contactgroup_member_id'; + + /** + * The primary key column for the contactgroups table + * + * @var string + */ + protected $contactgroup_id = 'contactgroup_id'; + + /** + * The primary key column for the contacts table + * + * @var string + */ + protected $contact_id = 'contact_id'; + + /** + * The primary key column for the customvariables table + * + * @var string + */ + protected $customvariable_id = 'customvariable_id'; + + /** + * The primary key column for the host_contactgroups table + * + * @var string + */ + protected $host_contactgroup_id = 'host_contactgroup_id'; + + /** + * The primary key column for the host_contacts table + * + * @var string + */ + protected $host_contact_id = 'host_contact_id'; + + /** + * The primary key column for the hostgroup_members table + * + * @var string + */ + protected $hostgroup_member_id = 'hostgroup_member_id'; + + /** + * The primary key column for the hostgroups table + * + * @var string + */ + protected $hostgroup_id = 'hostgroup_id'; + + /** + * The primary key column for the hosts table + * + * @var string + */ + protected $host_id = 'host_id'; + + /** + * The primary key column for the service_contactgroup table + * + * @var string + */ + protected $service_contactgroup_id = 'service_contactgroup_id'; + + /** + * The primary key column for the service_contact table + * + * @var string + */ + protected $service_contact_id = 'service_contact_id'; + + /** + * The primary key column for the servicegroup_members table + * + * @var string + */ + protected $servicegroup_member_id = 'servicegroup_member_id'; + + /** + * The primary key column for the servicegroups table + * + * @var string + */ + protected $servicegroup_id = 'servicegroup_id'; + + /** + * The primary key column for the services table + * + * @var string + */ + protected $service_id = 'service_id'; + + /** + * The primary key column for the timeperiods table + * + * @var string + */ + protected $timeperiod_id = 'timeperiod_id'; + + /** + * An array containing Column names that cause an aggregation of the query + * + * @var array + */ + protected $aggregateColumnIdx = array(); + + /** + * True to allow customvar filters and queries + * + * @var bool + */ + protected $allowCustomVars = false; + + /** + * Current IDO version. This is bullshit and needs to be moved somewhere + * else. As someone decided that we need no Backend-specific connection + * class unfortunately there is no better place right now. And as of the + * 'check_source' patch we need a quick fix immediately. So here you go. + * + * TODO: Fix this. + * + * @var string + */ + protected static $idoVersion; + + /** + * List of column aliases mapped to their table where the COLLATE SQL-instruction has been removed + * + * This list is being populated in case of a PostgreSQL backend only, + * to ensure case-insensitive string comparison in WHERE clauses. + * + * @var array + */ + protected $caseInsensitiveColumns; + + /** + * Return true when the column is an aggregate column + * + * @param String $column The column to test + * @return bool True when the column is an aggregate column + */ + public function isAggregateColumn($column) + { + return array_key_exists($column, $this->aggregateColumnIdx); + } + + /** + * Order the result by the given alias + * + * @param string $alias The column alias to order by + * @param int $dir The sort direction or null to use the default direction + * + * @return $this + */ + public function order($alias, $dir = null) + { + $this->requireColumn($alias); + + if ($this->isCustomVar($alias)) { + $column = $this->getCustomvarColumnName($alias); + } elseif ($this->hasAliasName($alias)) { + $column = $this->aliasToColumnName($alias); + $table = $this->aliasToTableName($alias); + if (isset($this->caseInsensitiveColumns[$table][$alias])) { + $column = 'LOWER(' . $column . ')'; + } + } else { + Logger::info('Can\'t order by column ' . $alias); + return $this; + } + + $this->orderColumns[] = $alias; + return parent::order($column, $dir); + } + + /** + * Return true when the given field can be used for filtering + * + * @param String $field The field to test + * @return bool True when the field can be used for querying, otherwise false + */ + public function isValidFilterTarget($field) + { + return $this->getMappedField($field) !== null; + } + + /** + * Return the resolved field for an alias + * + * @param String $field The alias to resolve + * @return String The resolved alias or null if unknown + */ + public function getMappedField($field) + { + foreach ($this->columnMap as $columnSource => $columnSet) { + if (isset($columnSet[$field])) { + return $columnSet[$field]; + } + } + if ($this->isCustomVar($field)) { + return $this->getCustomvarColumnName($field); + } + return null; + } + + public function distinct() + { + $this->select->distinct(); + return $this; + } + + /** + * Prepare the given query so that it can be linked to the parent + * + * @param IdoQuery $query + * @param string $name + * @param FilterExpression $filter The filter which initiated the sub query + * @param bool $and Whether it's an AND filter + * @param bool $negate Whether it's an != filter + * @param FilterExpression $additionalFilter Filters which should be applied to the "parent" query + * + * @return array The first value is their, the second our key column + * + * @throws NotImplementedError In case the given query is unknown + */ + protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter) + { + throw new NotImplementedError('Query "%s" is unknown', $name); + } + + /** + * Create and return a sub-query filter for the given filter expression + * + * @param FilterExpression $filter + * @param string $queryName + * + * @return Filter + * + * @throws QueryException + */ + protected function createSubQueryFilter(FilterExpression $filter, $queryName) + { + $expr = $filter->getExpression(); + $op = $filter->getSign(); + + if ($op === '=' && ! is_array($expr) && $op !== '!=') { + // We're joining a subquery only if the filter is enclosed in parentheses or if it's a != filter, + // e.g. hostgroup_name=(linux...), hostgroup_name!=linux, hostgroup_name!=(linux...) + throw new NotImplementedError(''); + } + + $subQuery = $this->createSubQuery($queryName); + $subQuery->setIsSubQuery(); + + $subQueryFilter = clone $filter; + + if ($op === '!=') { + $negate = true; + if (! is_array($expr)) { + // We assume that expression is an array later on but we'll support subquery joins for != filters + // which are not enclosed in parentheses + $expr = [$expr]; + } + } else { + $negate = false; + } + + if (count($expr) === 1 && strpos($expr[0], '&') !== false) { + // Our current filter implementation does not specify & as a control character so the count of the + // expression array is always one in this case + $expr = array_unique(explode('&', $expr[0])); + $subQueryFilter->setExpression($expr); + $and = true; + } else { + // Or filters are respected by our filter implementation. No special handling needed here + $and = false; + } + + $alias = $filter->getColumn(); + $column = $subQuery->aliasToColumnName($alias); + if (isset($this->caseInsensitiveColumns[$subQuery->aliasToTableName($alias)][$alias])) { + $column = 'LOWER( ' . $column . ' )'; + $subQueryFilter->setColumn($column); + $subQueryFilter->setExpression(array_map('strtolower', (array) $subQueryFilter->getExpression())); + } else { + $subQueryFilter->setColumn($column); + } + + $additional = null; + + list($theirs, $ours) = $this->joinSubQuery($subQuery, $queryName, $subQueryFilter, $and, $negate, $additional); + + $zendSelect = $subQuery->select(); + $fromPart = $zendSelect->getPart($zendSelect::FROM); + $zendSelect->reset($zendSelect::FROM); + + foreach ($fromPart as $correlationName => $joinOptions) { + if (isset($joinOptions['joinCondition'])) { + $joinOptions['joinCondition'] = preg_replace( + '/(?<=^|\s)\w+(?=\.)/', + 'sub_$0', + $joinOptions['joinCondition'] + ); + } + + $name = ['sub_' . $correlationName => $joinOptions['tableName']]; + switch ($joinOptions['joinType']) { + case $zendSelect::FROM: + $zendSelect->from($name); + break; + case $zendSelect::INNER_JOIN: + $zendSelect->joinInner($name, $joinOptions['joinCondition'], null); + break; + case $zendSelect::LEFT_JOIN: + $zendSelect->joinLeft($name, $joinOptions['joinCondition'], null); + break; + default: + // TODO: Add support for other join types if required? + throw new QueryException( + 'Unsupported join type %s. Cannot create subquery filter.', + $joinOptions['joinType'] + ); + } + } + + if ($and || $negate) { + // Having is only required for AND and != filters, + // e.g. hostgroup_name=(ping&linux), hostgroup_name!=ping, hostgroup_name!=(ping|linux) + $groups = $subQuery->getGroup(); + if (! empty($groups)) { + $group = $groups[0]; + $group = preg_replace('/(?<=^|\s)\w+(?=\.)/', 'sub_$0', $group); + + $cnt = count($expr); + + $subQuery->select()->having("COUNT(DISTINCT $group) >= $cnt"); + } + } + + $subQueryFilter->setColumn(preg_replace( + '/(?<=^|\s)\w+(?=\.)/', + 'sub_$0', + $column + )); + + if ($negate) { + // != will be NOT EXISTS later + $subQueryFilter = $subQueryFilter->setSign('='); + } + + $subQueryFilter = $subQueryFilter->andFilter(Filter::where( + preg_replace('/(?<=^|\s)\w+(?=\.)/', 'sub_$0', $theirs), + new Zend_Db_Expr($ours) + )); + + $subQuery + ->setFilter($subQueryFilter) + ->clearGroupingRules() + ->select() + ->reset('columns') + ->columns([new Zend_Db_Expr('1')]); + + // EXISTS is the column name because without any column $this->isCustomVar() fails badly otherwise. + // Additionally it bypasses the non-required optimizations made by our filter rendering implementation. + $exists = new FilterExpression($negate ? 'NOT EXISTS' : 'EXISTS', '', new Zend_Db_Expr($subQuery)); + + if ($additional !== null) { + return Filter::matchAll($exists, $additional); + } + + return $exists; + } + + protected function requireFilterColumns(Filter $filter) + { + if ($filter instanceof FilterExpression) { + $alias = $filter->getColumn(); + + $virtualTable = $this->aliasToTableName($alias); + if (isset($this->subQueryTargets[$virtualTable])) { + try { + return $this->createSubQueryFilter($filter, $this->subQueryTargets[$virtualTable]); + } catch (NotImplementedError $e) { + // We don't want to create subquery filters in all cases + } + } + + $this->requireColumn($alias); + + if ($this->isCustomVar($alias)) { + $column = $this->getCustomvarColumnName($alias); + } else { + $column = $this->aliasToColumnName($alias); + if (isset($this->caseInsensitiveColumns[$this->aliasToTableName($alias)][$alias])) { + $column = 'LOWER(' . $column . ')'; + $expression = $filter->getExpression(); + if (is_array($expression)) { + $filter->setExpression(array_map('strtolower', $expression)); + } else { + $filter->setExpression(strtolower($expression)); + } + } + } + + $filter->setColumn($column); + } else { + if (! $filter instanceof FilterNot) { + // Allow subquery filters in a filter chain + $columns = $filter->listFilteredColumns(); + if (count($columns) === 1) { + $column = $columns[0]; + $virtualTable = $this->aliasToTableName($column); + if (isset($this->subQueryTargets[$virtualTable])) { + $lastSign = null; + $filters = []; + $expressions = []; + foreach ($filter->filters() as $child) { + switch (true) { + case $child instanceof FilterExpression: + $expression = $child->getExpression(); + if (! is_array($expression)) { + break; + } + // Move to default + default: + $filters[] = $child; + continue 2; + } + if ($lastSign === null) { + $lastSign = $child->getSign(); + } else { + $sign = $child->getSign(); + if ($sign !== $lastSign) { + $filters[] = new FilterExpression( + $column, + $lastSign, + $filter->getOperatorSymbol() === '&' + ? [implode('&', $expressions)] + : $expressions + ); + $expressions = []; + $lastSign = $sign; + } + } + $expressions[] = $expression; + } + if (! empty($expressions)) { + $filters[] = new FilterExpression( + $column, + $lastSign, + $filter->getOperatorSymbol() === '&' + ? [implode('&', $expressions)] + : $expressions + ); + } + $filter->setFilters($filters); + } + } + } + + foreach ($filter->filters() as $child) { + $replacement = $this->requireFilterColumns($child); + if ($replacement !== null) { + // setId($child->getId()) is performed because replaceById() doesn't already do it + $filter->replaceById($child->getId(), $replacement->setId($child->getId())); + } + } + } + } + + /** + * {@inheritdoc} + */ + public function addFilter(Filter $filter) + { + $filter = clone $filter; + return parent::addFilter($this->requireFilterColumns($filter) ?: $filter); + } + + public function where($condition, $value = null) + { + $this->requireColumn($condition); + $col = $this->getMappedField($condition); + if ($col === null) { + throw new IcingaException( + 'No such field: %s', + $condition + ); + } + return parent::where($col, $value); + } + + /** + * Add a filter expression, with as less validation as possible + * + * @param FilterExpression $ex + * + * @internal If you use this outside the monitoring module, it's your fault if something breaks + * @return $this + */ + public function whereEx(FilterExpression $ex) + { + $this->requireColumn($ex->getColumn()); + $col = $this->getMappedField($ex->getColumn()); + if ($col === null) { + throw new IcingaException( + 'No such field: %s', + $ex->getColumn() + ); + } + + parent::addFilter((clone $ex)->setColumn($col)); + + return $this; + } + + /** + * Return true if an field contains an explicit timestamp + * + * @param string $field The field to test for containing an timestamp + * + * @return bool True when the field represents an timestamp + */ + public function isTimestamp($field) + { + if ($this->isCustomVar($field)) { + return false; + } + + return stripos($this->getMappedField($field) ?: $field, 'UNIX_TIMESTAMP') !== false; + } + + /** + * Return whether the given alias provides case insensitive value comparison + * + * @param string $alias + * + * @return bool + */ + public function isCaseInsensitive($alias) + { + if ($this->isCustomVar($alias)) { + return false; + } + + $column = $this->getMappedField($alias); + if (! $column) { + return false; + } + + if (empty($this->caseInsensitiveColumns)) { + return preg_match('/ COLLATE .+$/', $column) === 1; + } + + if (strpos($column, 'LOWER') === 0) { + return true; + } + + $table = $this->aliasToTableName($alias); + if (! $table) { + return false; + } + + return isset($this->caseInsensitiveColumns[$table][$alias]); + } + + /** + * Return our column map + * + * Might be useful for hooks + * + * @return array + */ + public function getColumnMap() + { + return $this->columnMap; + } + + /** + * Apply oracle specific query initialization + */ + private function initializeForOracle() + { + // Oracle uses the reserved field 'id' for primary keys, so + // these must be used instead of the normally defined ids + $this->object_id = $this->host_id = $this->service_id + = $this->hostgroup_id = $this->servicegroup_id + = $this->contact_id = $this->contactgroup_id = 'id'; + $this->customVarsJoinTemplate = + '%1$s = %2$s.object_id AND LOWER(%2$s.varname) = %3$s'; + foreach ($this->columnMap as &$columns) { + foreach ($columns as &$value) { + $value = preg_replace('/UNIX_TIMESTAMP/', 'localts2unixts', $value); + $value = preg_replace('/ COLLATE .+$/', '', $value); + } + } + } + + /** + * Apply PostgreSQL specific query initialization + */ + private function initializeForPostgres() + { + $this->customVarsJoinTemplate = + '%1$s = %2$s.object_id AND LOWER(%2$s.varname) = %3$s'; + foreach ($this->columnMap as $table => & $columns) { + foreach ($columns as $alias => & $column) { + if ($column === null) { + continue; + } + + // Using a regex here because COLLATE may occur anywhere in the string + $column = preg_replace('/ COLLATE .+$/', '', $column, -1, $count); + if ($count > 0) { + $this->caseInsensitiveColumns[$table][$alias] = true; + } + + $column = preg_replace( + '/inet_aton\(([[:word:].]+)\)/i', + '(CASE WHEN $1 ~ \'(?:[0-9]{1,3}\\\\.){3}[0-9]{1,3}\' THEN $1::inet - \'0.0.0.0\' ELSE NULL END)', + $column + ); + if (version_compare($this->getIdoVersion(), '1.14.2', '>=')) { + $column = str_replace('NOW()', 'NOW() AT TIME ZONE \'UTC\'', $column); + } else { + $column = preg_replace( + '/UNIX_TIMESTAMP(\((?>[^()]|(?-1))*\))/i', + 'CASE WHEN ($1 < \'1970-01-03 00:00:00+00\'::timestamp with time zone) THEN 0 ELSE UNIX_TIMESTAMP($1) END', + $column + ); + } + } + } + } + + /** + * Set up this query and join the initial tables + * + * @see IdoQuery::initializeForPostgres For postgresql specific setup + */ + protected function init() + { + parent::init(); + $this->prefix = $this->ds->getTablePrefix(); + + foreach (Hook::all('monitoring/idoQueryExtension') as $hook) { + $extensions = $hook->extendColumnMap($this); + if (! is_array($extensions)) { + continue; + } + + foreach ($extensions as $vTable => $cols) { + if (! array_key_exists($vTable, $this->columnMap)) { + $this->hookedVirtualTables[$vTable] = $hook; + $this->columnMap[$vTable] = array(); + } + + foreach ($cols as $k => $v) { + $this->columnMap[$vTable][$k] = $v; + } + } + } + + $dbType = $this->ds->getDbType(); + if ($dbType === 'oracle') { + $this->initializeForOracle(); + } elseif ($dbType === 'pgsql') { + $this->initializeForPostgres(); + } else { + $charset = $this->ds->getConfig()->get('charset') ?: 'latin1'; + $this->customVarsJoinTemplate .= " COLLATE {$charset}_general_ci"; + } + $this->joinBaseTables(); + $this->select->columns($this->columns); + $this->prepareAliasIndexes(); + } + + /** + * Join the base tables for this query + */ + protected function joinBaseTables() + { + reset($this->columnMap); + $table = key($this->columnMap); + + $this->select->from( + array($table => $this->prefix . $table), + array() + ); + + $this->joinedVirtualTables = array($table => true); + } + + /** + * Populates the idxAliasTAble and idxAliasColumn properties + */ + protected function prepareAliasIndexes() + { + foreach ($this->columnMap as $tbl => & $cols) { + foreach ($cols as $alias => $col) { + $this->idxAliasTable[$alias] = $tbl; + $this->idxAliasColumn[$alias] = preg_replace('~\n\s*~', ' ', $col); + } + } + } + + /** + * Resolve columns aliases to their database field using the columnMap + * + * @param array $columns + * + * @return array + */ + public function resolveColumns($columns) + { + $resolvedColumns = array(); + + foreach ($columns as $alias => $col) { + if ($col instanceof Zend_Db_Expr) { + // Support selecting NULL as column for example + $resolvedColumns[$alias] = $col; + continue; + } + $this->requireColumn($col); + if ($this->isCustomVar($col)) { + $name = $this->getCustomvarColumnName($col); + } else { + $name = $this->aliasToColumnName($col); + } + if (is_int($alias)) { + $alias = $col; + } else { + $this->idxCustomAliases[$alias] = $col; + } + + $resolvedColumns[$alias] = preg_replace('|\n|', ' ', $name); + } + + return $resolvedColumns; + } + + /** + * Return all columns that will be selected when no columns are given in the constructor or from + * + * @return array An array of column aliases + */ + public function getDefaultColumns() + { + reset($this->columnMap); + $table = key($this->columnMap); + return array_keys($this->columnMap[$table]); + } + + /** + * Modify the query to the given alias can be used in the result set or queries + * + * This calls requireVirtualTable if needed + * + * @param string $alias The alias of the column to require + * + * @return $this Fluent interface + * @see IdoQuery::requireVirtualTable The method initializing required joins + * @throws \Icinga\Exception\ProgrammingError When an unknown column is requested + */ + public function requireColumn($alias) + { + if ($this->hasAliasName($alias)) { + $this->requireVirtualTable($this->aliasToTableName($alias)); + } elseif ($this->isCustomVar($alias)) { + $this->requireCustomvar($alias); + } else { + throw new ProgrammingError( + '%s : Got invalid column: %s', + get_called_class(), + $alias + ); + } + return $this; + } + + /** + * Return true if the given alias exists + * + * @param String $alias The alias to test for + * @return bool True when the alias exists, otherwise false + */ + protected function hasAliasName($alias) + { + return array_key_exists($alias, $this->idxAliasColumn); + } + + /** + * Require a virtual table for the given table name if not already required + * + * @param String $name The table name to require + * @return $this Fluent interface + */ + protected function requireVirtualTable($name) + { + if ($this->hasJoinedVirtualTable($name)) { + return $this; + } + + if ($this->virtualTableIsHooked($name)) { + return $this->joinHookedVirtualTable($name); + } else { + return $this->joinVirtualTable($name); + } + } + + /** + * Whether a given virtual table name has been provided by a hook + * + * @param string $name Virtual table name + * + * @return boolean + */ + protected function virtualTableIsHooked($name) + { + return array_key_exists($name, $this->hookedVirtualTables); + } + + protected function conflictsWithVirtualTable($name) + { + if ($this->hasJoinedVirtualTable($name)) { + throw new ProgrammingError( + 'IDO query virtual table conflict with "%s"', + $name + ); + } + return $this; + } + + /** + * Call the method for joining a virtual table + * + * This requires a join$Table() method to exist + * + * @param String $table The table to join by calling join$Table() in the concrete implementation + * @return $this Fluent interface + * + * @throws \Icinga\Exception\ProgrammingError If the join method for this table does not exist + */ + protected function joinVirtualTable($table) + { + $func = 'join' . ucfirst($table); + if (method_exists($this, $func)) { + $this->$func(); + } else { + throw new ProgrammingError( + 'Cannot join "%s", no such table found', + $table + ); + } + $this->joinedVirtualTables[$table] = true; + return $this; + } + + /** + * Tell a hook to join a virtual table + * + * @param String $table + * @return $this + */ + protected function joinHookedVirtualTable($table) + { + $this->hookedVirtualTables[$table]->joinVirtualTable($this, $table); + $this->joinedVirtualTables[$table] = true; + return $this; + } + + /** + * Get the table for a specific alias + * + * @param String $alias The alias to request the table for + * @return String The table for the alias or null if it doesn't exist + */ + protected function aliasToTableName($alias) + { + return isset($this->idxAliasTable[$alias]) ? $this->idxAliasTable[$alias] : null; + } + + /** + * Return whether this query allows to join custom variables + * + * @return bool + */ + public function allowsCustomVars() + { + return $this->allowCustomVars; + } + + /** + * Return true if the given alias denotes a custom variable + * + * @param String $alias The alias to test for being a customvariable + * @return bool True if the alias is a customvariable, otherwise false + */ + protected function isCustomVar($alias) + { + return $this->allowCustomVars && $alias[0] === '_'; + } + + protected function requireCustomvar($customvar) + { + if (! $this->hasCustomvar($customvar)) { + $this->joinCustomvar($customvar); + } + return $this; + } + + protected function hasCustomvar($customvar) + { + return array_key_exists(strtolower($customvar), $this->customVars); + } + + protected function joinCustomvar($customvar) + { + // TODO: This is not generic enough yet + list($type, $name) = $this->customvarNameToTypeName($customvar); + $alias = ($type === 'host' ? 'hcv_' : 'scv_') . preg_replace('~[^a-zA-Z0-9_]~', '_', $name); + + // We're replacing any problematic char with an underscore, which will lead to duplicates, this avoids them + $from = $this->select->getPart(Zend_Db_Select::FROM); + for ($i = 2; array_key_exists($alias, $from); $i++) { + $alias = $alias . '_' . $i; + } + + $this->customVars[strtolower($customvar)] = $alias; + + if ($type === 'host') { + if ($this instanceof ServicecommentQuery + || $this instanceof ServicedowntimeQuery + || $this instanceof ServicecommenthistoryQuery + || $this instanceof ServicedowntimestarthistoryQuery + || $this instanceof ServiceflappingstarthistoryQuery + || $this instanceof ServicegroupQuery + || $this instanceof ServicenotificationQuery + || $this instanceof ServicestatehistoryQuery + || $this instanceof ServicestatusQuery + ) { + $this->requireVirtualTable('services'); + $leftcol = 's.host_object_id'; + } else { + $leftcol = 'ho.object_id'; + if (! $this->hasJoinedTable('ho')) { + $this->requireVirtualTable('hosts'); + } + } + } else { // $type === 'service' + $leftcol = 'so.object_id'; + if (! $this->hasJoinedTable('so')) { + $this->requireVirtualTable('services'); + } + } + + $mapped = $this->getMappedField($leftcol); + if ($mapped !== null) { + $this->requireColumn($leftcol); + $leftcol = $mapped; + } + + $joinOn = sprintf( + $this->customVarsJoinTemplate, + $leftcol, + $alias, + $this->db->quote($name) + ); + + $this->select->joinLeft( + array($alias => $this->prefix . 'customvariablestatus'), + $joinOn, + array() + ); + + return $this; + } + + protected function customvarNameToTypeName($customvar) + { + $customvar = strtolower($customvar); + if (! preg_match('~^_(host|service)_(.+)$~', $customvar, $m)) { + throw new ProgrammingError( + 'Got invalid custom var: "%s"', + $customvar + ); + } + return array($m[1], $m[2]); + } + + protected function hasJoinedVirtualTable($name) + { + return array_key_exists($name, $this->joinedVirtualTables); + } + + /** + * Get the query column of a already joined custom variable + * + * @param string $customvar + * + * @return string + * @throws QueryException If the custom variable has not been joined + */ + protected function getCustomvarColumnName($customvar) + { + if (! isset($this->customVars[($customvar = strtolower($customvar))])) { + throw new QueryException('Custom variable %s has not been joined', $customvar); + } + return $this->customVars[$customvar] . '.varvalue'; + } + + public function aliasToColumnName($alias) + { + return $this->idxAliasColumn[$alias]; + } + + /** + * Get the alias of a column expression as defined in the {@link $columnMap} property. + * + * @param string $alias Potential custom alias + * + * @return string + */ + public function customAliasToAlias($alias) + { + if (isset($this->idxCustomAliases[$alias])) { + return $this->idxCustomAliases[$alias]; + } + return $alias; + } + + /** + * Create a sub query + * + * @param string $queryName + * @param array $columns + * + * @return static + */ + protected function createSubQuery($queryName, $columns = array()) + { + $class = '\\' + . substr(__CLASS__, 0, strrpos(__CLASS__, '\\') + 1) + . ucfirst($queryName) . 'Query'; + $query = new $class($this->ds, $columns); + return $query; + } + + /** + * Set columns to select + * + * @param array $columns + * + * @return $this + */ + public function columns(array $columns) + { + $this->idxCustomAliases = array(); + $this->columns = $this->resolveColumns($columns); + // TODO: we need to refresh our select! + // $this->select->columns($columns); + return $this; + } + + public function clearGroupingRules() + { + $this->groupBase = array(); + $this->groupOrigin = array(); + return $this; + } + + /** + * Register the GROUP BY columns required for the given alias + * + * @param string $alias The alias to register columns for + * @param string $table The table the given alias is associated with + * @param array $groupedColumns The grouping columns registered so far + * @param array $groupedTables The tables for which columns were registered so far + */ + protected function registerGroupColumns($alias, $table, array &$groupedColumns, array &$groupedTables) + { + switch ($table) { + case 'checktimeperiods': + $groupedColumns[] = 'ctp.timeperiod_id'; + break; + case 'contacts': + $groupedColumns[] = 'co.object_id'; + $groupedColumns[] = 'c.contact_id'; + break; + case 'hostobjects': + $groupedColumns[] = 'ho.object_id'; + break; + case 'hosts': + $groupedColumns[] = 'h.host_id'; + break; + case 'hostgroups': + $groupedColumns[] = 'hgo.object_id'; + $groupedColumns[] = 'hg.hostgroup_id'; + break; + case 'hoststatus': + $groupedColumns[] = 'hs.hoststatus_id'; + break; + case 'instances': + $groupedColumns[] = 'i.instance_id'; + break; + case 'servicegroups': + $groupedColumns[] = 'sgo.object_id'; + $groupedColumns[] = 'sg.servicegroup_id'; + break; + case 'serviceobjects': + $groupedColumns[] = 'so.object_id'; + break; + case 'serviceproblemsummary': + $groupedColumns[] = 'sps.unhandled_services_count'; + break; + case 'services': + $groupedColumns[] = 'so.object_id'; + $groupedColumns[] = 's.service_id'; + break; + case 'servicestatus': + $groupedColumns[] = 'ss.servicestatus_id'; + break; + default: + return; + } + + $groupedTables[$table] = true; + } + + /** + * {@inheritdoc} + */ + public function getGroup() + { + $group = parent::getGroup() ?: array(); + if (! is_array($group)) { + $group = array($group); + } + + $joinedOrigins = array_filter($this->groupOrigin, array($this, 'hasJoinedVirtualTable')); + if (empty($joinedOrigins)) { + return $group; + } + + $groupedTables = array(); + foreach ($this->groupBase as $baseTable => $aliasedPks) { + if (! $this->hasJoinedVirtualTable($baseTable)) { + continue; + } + $groupedTables[$baseTable] = true; + foreach ($aliasedPks as $aliasedPk) { + $group[] = $aliasedPk; + } + } + + foreach (new ColumnFilterIterator($this->columns) as $desiredAlias => $desiredColumn) { + $alias = is_string($desiredAlias) ? $this->customAliasToAlias($desiredAlias) : $desiredColumn; + if ($this->isCustomVar($alias) && $this->getDatasource()->getDbType() === 'pgsql') { + $table = $this->customVars[$alias]; + if (! isset($groupedTables[$table])) { + $group[] = $this->getCustomvarColumnName($alias); + $groupedTables[$table] = true; + } + continue; + } + $table = $this->aliasToTableName($alias); + if ($table && !isset($groupedTables[$table]) && ( + in_array($table, $joinedOrigins, true) || $this->getDatasource()->getDbType() === 'pgsql') + ) { + $this->registerGroupColumns($alias, $table, $group, $groupedTables); + } + } + + if (! empty($group) && $this->getDatasource()->getDbType() === 'pgsql') { + foreach (new ColumnFilterIterator($this->orderColumns) as $alias) { + if ($this->isCustomVar($alias)) { + $table = $this->customVars[$alias]; + if (! isset($groupedTables[$table])) { + $group[] = $this->getCustomvarColumnName($alias); + $groupedTables[$table] = true; + } + continue; + } + $table = $this->aliasToTableName($alias); + if ($table && !isset($groupedTables[$table]) + && !in_array($this->getMappedField($alias), $this->columns, true) + ) { + $this->registerGroupColumns($alias, $table, $group, $groupedTables); + } + } + } + + return array_unique($group); + } + + // TODO: Move this away, see note related to $idoVersion var + protected function getIdoVersion() + { + if (self::$idoVersion === null) { + $dbconf = $this->db->getConfig(); + $id = $dbconf['host'] . '/' . $dbconf['dbname']; + $session = null; + if (Icinga::app()->isWeb()) { + // TODO: Once we have version per connection we should choose a + // namespace based on resource name + $session = Session::getSession()->getNamespace('monitoring/ido/' . $id); + if (isset($session->version)) { + self::$idoVersion = $session->version; + return self::$idoVersion; + } + } + self::$idoVersion = $this->db->fetchOne( + $this->db->select()->from($this->prefix . 'dbversion', 'version') + ); + if ($session !== null) { + $session->version = self::$idoVersion; + } + } + return self::$idoVersion; + } + + /** + * Return the name of the primary key column for the given table name + * + * @param string $table + * + * @return string + * + * @throws ProgrammingError In case $table is unknown + */ + protected function getPrimaryKeyColumn($table) + { + // TODO: For god's sake, make this being a mapping + // (instead of matching a ton of properties using a ridiculous long switch case) + switch ($table) { + case 'instances': + return $this->instance_id; + case 'objects': + return $this->object_id; + case 'acknowledgements': + return $this->acknowledgement_id; + case 'commenthistory': + return $this->commenthistory_id; + case 'contactnotifiations': + return $this->contactnotification_id; + case 'downtimehistory': + return $this->downtimehistory_id; + case 'flappinghistory': + return $this->flappinghistory_id; + case 'notifications': + return $this->notification_id; + case 'statehistory': + return $this->statehistory_id; + case 'comments': + return $this->comment_id; + case 'customvariablestatus': + return $this->customvariablestatus_id; + case 'hoststatus': + return $this->hoststatus_id; + case 'programstatus': + return $this->programstatus_id; + case 'runtimevariables': + return $this->runtimevariable_id; + case 'scheduleddowntime': + return $this->scheduleddowntime_id; + case 'servicestatus': + return $this->servicestatus_id; + case 'contactstatus': + return $this->contactstatus_id; + case 'commands': + return $this->command_id; + case 'contactgroup_members': + return $this->contactgroup_member_id; + case 'contactgroups': + return $this->contactgroup_id; + case 'contacts': + return $this->contact_id; + case 'customvariables': + return $this->customvariable_id; + case 'host_contactgroups': + return $this->host_contactgroup_id; + case 'host_contacts': + return $this->host_contact_id; + case 'hostgroup_members': + return $this->hostgroup_member_id; + case 'hostgroups': + return $this->hostgroup_id; + case 'hosts': + return $this->host_id; + case 'service_contactgroups': + return $this->service_contactgroup_id; + case 'service_contacts': + return $this->service_contact_id; + case 'servicegroup_members': + return $this->servicegroup_member_id; + case 'servicegroups': + return $this->servicegroup_id; + case 'services': + return $this->service_id; + case 'timeperiods': + return $this->timeperiod_id; + default: + throw new ProgrammingError('Cannot provide a primary key column. Table "%s" is unknown', $table); + } + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/InstanceQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/InstanceQuery.php new file mode 100644 index 0000000..ac538ec --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/InstanceQuery.php @@ -0,0 +1,26 @@ +<?php +/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +class InstanceQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'instances' => array( + 'instance_id' => 'i.instance_id', + 'instance_name' => 'i.instance_name' + ) + ); + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + $this->select()->from(array('i' => $this->prefix . 'instances'), array()); + $this->joinedVirtualTables['instances'] = true; + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationQuery.php new file mode 100644 index 0000000..8bfb725 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationQuery.php @@ -0,0 +1,144 @@ +<?php +/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Data\Filter\FilterExpression; +use Zend_Db_Expr; +use Zend_Db_Select; +use Icinga\Data\Filter\Filter; + +/** + * Query for host and service notifications + */ +class NotificationQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $allowCustomVars = true; + + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'notifications' => array( + 'id' => 'n.id', + 'instance_name' => 'n.instance_name', + 'notification_contact_name' => 'n.notification_contact_name', + 'notification_output' => 'n.notification_output', + 'notification_reason' => 'n.notification_reason', + 'notification_state' => 'n.notification_state', + 'notification_timestamp' => 'n.notification_timestamp' + ), + 'hosts' => array( + 'host_display_name' => 'n.host_display_name', + 'host_name' => 'n.host_name' + ), + 'services' => array( + 'service_description' => 'n.service_description', + 'service_display_name' => 'n.service_display_name', + 'service_host_name' => 'n.service_host_name' + ) + ); + + /** + * The union + * + * @var Zend_Db_Select + */ + protected $notificationQuery; + + /** + * Subqueries used for the notification query + * + * @var IdoQuery[] + */ + protected $subQueries = array(); + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + $this->notificationQuery = $this->db->select(); + $this->select->from( + array('n' => $this->notificationQuery), + array() + ); + $this->joinedVirtualTables['notifications'] = true; + } + + /** + * Join hosts + */ + protected function joinHosts() + { + $columns = $this->desiredColumns; + $columns = array_combine($columns, $columns); + foreach ($this->columnMap['services'] as $column => $_) { + if (isset($columns[$column])) { + $columns[$column] = new Zend_Db_Expr('NULL'); + } + } + $hosts = $this->createSubQuery('hostnotification', $columns); + $hosts->setIsSubQuery(true); + $this->subQueries[] = $hosts; + $this->notificationQuery->union(array($hosts), Zend_Db_Select::SQL_UNION_ALL); + } + + /** + * Join services + */ + protected function joinServices() + { + $services = $this->createSubQuery('servicenotification', $this->desiredColumns); + $services->setIsSubQuery(true); + $this->subQueries[] = $services; + $this->notificationQuery->union(array($services), Zend_Db_Select::SQL_UNION_ALL); + } + + /** + * {@inheritdoc} + */ + public function addFilter(Filter $filter) + { + foreach ($this->subQueries as $sub) { + $sub->applyFilter(clone $filter); + } + return $this; + } + + /** + * {@inheritdoc} + */ + public function order($columnOrAlias, $dir = null) + { + foreach ($this->subQueries as $sub) { + $sub->requireColumn($columnOrAlias); + } + return parent::order($columnOrAlias, $dir); + } + + /** + * {@inheritdoc} + */ + public function where($condition, $value = null) + { + $this->requireColumn($condition); + foreach ($this->subQueries as $sub) { + $sub->where($condition, $value); + } + return $this; + } + + public function whereEx(FilterExpression $ex) + { + $this->requireColumn($ex->getColumn()); + foreach ($this->subQueries as $sub) { + $sub->whereEx($ex); + } + + return $this; + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationeventQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationeventQuery.php new file mode 100644 index 0000000..87a71f6 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationeventQuery.php @@ -0,0 +1,52 @@ +<?php +/* Icinga Web 2 | (c) 2017 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +/** + * Query for host and service notification events + */ +class NotificationeventQuery extends IdoQuery +{ + protected $columnMap = array( + 'notificationevent' => array( + 'notificationevent_id' => 'n.notification_id', + 'notificationevent_reason' => <<<EOF +(CASE n.notification_reason + WHEN 0 THEN 'normal_notification' + WHEN 1 THEN 'ack' + WHEN 2 THEN 'flapping_started' + WHEN 3 THEN 'flapping_stopped' + WHEN 4 THEN 'flapping_disabled' + WHEN 5 THEN 'dt_start' + WHEN 6 THEN 'dt_end' + WHEN 7 THEN 'dt_cancel' + WHEN 99 THEN 'custom_notification' + ELSE NULL +END) +EOF + , + 'notificationevent_start_time' => 'UNIX_TIMESTAMP(n.start_time)', + 'notificationevent_end_time' => 'UNIX_TIMESTAMP(n.end_time)', + 'notificationevent_state' => 'n.state', + 'notificationevent_output' => 'n.output', + 'notificationevent_long_output' => 'n.long_output', + 'notificationevent_escalated' => 'n.escalated', + 'notificationevent_contacts_notified' => 'n.contacts_notified' + ), + 'object' => array( + 'host_name' => 'o.name1', + 'service_description' => 'o.name2' + ) + ); + + protected function joinBaseTables() + { + $this->select() + ->from(array('n' => $this->prefix . 'notifications'), array()) + ->join(array('o' => $this->prefix . 'objects'), 'n.object_id = o.object_id', array()); + + $this->joinedVirtualTables['notificationevent'] = true; + $this->joinedVirtualTables['object'] = true; + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationhistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationhistoryQuery.php new file mode 100644 index 0000000..f629115 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationhistoryQuery.php @@ -0,0 +1,142 @@ +<?php +/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Data\Filter\FilterExpression; +use Zend_Db_Expr; +use Zend_Db_Select; +use Icinga\Data\Filter\Filter; + +/** + * Query for host and service notification history + */ +class NotificationhistoryQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $allowCustomVars = true; + + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'history' => array( + 'id' => 'n.id', + 'object_type' => 'n.object_type', + 'output' => 'n.output', + 'state' => 'n.state', + 'timestamp' => 'n.timestamp', + 'type' => 'n.type' + ), + 'hosts' => array( + 'host_display_name' => 'n.host_display_name', + 'host_name' => 'n.host_name' + ), + 'services' => array( + 'service_description' => 'n.service_description', + 'service_display_name' => 'n.service_display_name', + 'service_host_name' => 'n.service_host_name' + ) + ); + + /** + * The union + * + * @var Zend_Db_Select + */ + protected $notificationQuery; + + /** + * Subqueries used for the notification query + * + * @var IdoQuery[] + */ + protected $subQueries = array(); + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + $this->notificationQuery = $this->db->select(); + $this->select->from( + array('n' => $this->notificationQuery), + array() + ); + $this->joinedVirtualTables['history'] = true; + } + + /** + * Join hosts + */ + protected function joinHosts() + { + $columns = $this->desiredColumns; + $columns = array_combine($columns, $columns); + foreach ($this->columnMap['services'] as $column => $_) { + if (isset($columns[$column])) { + $columns[$column] = new Zend_Db_Expr('NULL'); + } + } + $hosts = $this->createSubQuery('hostnotification', $columns); + $this->subQueries[] = $hosts; + $this->notificationQuery->union(array($hosts), Zend_Db_Select::SQL_UNION_ALL); + } + + /** + * Join services + */ + protected function joinServices() + { + $columns = array_flip($this->desiredColumns); + $services = $this->createSubQuery('servicenotification', array_flip($columns)); + $this->subQueries[] = $services; + $this->notificationQuery->union(array($services), Zend_Db_Select::SQL_UNION_ALL); + } + + /** + * {@inheritdoc} + */ + public function addFilter(Filter $filter) + { + foreach ($this->subQueries as $sub) { + $sub->applyFilter(clone $filter); + } + return $this; + } + + /** + * {@inheritdoc} + */ + public function order($columnOrAlias, $dir = null) + { + foreach ($this->subQueries as $sub) { + $sub->requireColumn($columnOrAlias); + } + return parent::order($columnOrAlias, $dir); + } + + /** + * {@inheritdoc} + */ + public function where($condition, $value = null) + { + $this->requireColumn($condition); + foreach ($this->subQueries as $sub) { + $sub->where($condition, $value); + } + return $this; + } + + public function whereEx(FilterExpression $ex) + { + $this->requireColumn($ex->getColumn()); + foreach ($this->subQueries as $sub) { + $sub->whereEx($ex); + } + + return $this; + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ProgramstatusQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ProgramstatusQuery.php new file mode 100644 index 0000000..9e9f5f6 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ProgramstatusQuery.php @@ -0,0 +1,68 @@ +<?php +/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +/** + * Program status query + */ +class ProgramstatusQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'programstatus' => array( + 'id' => 'programstatus_id', + 'status_update_time' => 'UNIX_TIMESTAMP(programstatus.status_update_time)', + 'program_version' => 'program_version', + 'program_start_time' => 'UNIX_TIMESTAMP(programstatus.program_start_time)', + 'program_end_time' => 'UNIX_TIMESTAMP(programstatus.program_end_time)', + 'is_currently_running' => 'CASE WHEN (UNIX_TIMESTAMP(programstatus.status_update_time) + 60 > UNIX_TIMESTAMP(NOW())) + THEN + 1 + ELSE + 0 + END', + 'process_id' => 'process_id', + 'endpoint_name' => 'endpoint_name', + 'daemon_mode' => 'daemon_mode', + 'last_command_check' => 'UNIX_TIMESTAMP(programstatus.last_command_check)', + 'last_log_rotation' => 'UNIX_TIMESTAMP(programstatus.last_log_rotation)', + 'notifications_enabled' => 'notifications_enabled', + 'disable_notif_expire_time' => 'UNIX_TIMESTAMP(programstatus.disable_notif_expire_time)', + 'active_service_checks_enabled' => 'active_service_checks_enabled', + 'passive_service_checks_enabled' => 'passive_service_checks_enabled', + 'active_host_checks_enabled' => 'active_host_checks_enabled', + 'passive_host_checks_enabled' => 'passive_host_checks_enabled', + 'event_handlers_enabled' => 'event_handlers_enabled', + 'flap_detection_enabled' => 'flap_detection_enabled', + 'failure_prediction_enabled' => 'failure_prediction_enabled', + 'process_performance_data' => 'process_performance_data', + 'obsess_over_hosts' => 'obsess_over_hosts', + 'obsess_over_services' => 'obsess_over_services', + 'modified_host_attributes' => 'modified_host_attributes', + 'modified_service_attributes' => 'modified_service_attributes', + 'global_host_event_handler' => 'global_host_event_handler', + 'global_service_event_handler' => 'global_service_event_handler', + ) + ); + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + parent::joinBaseTables(); + + if (version_compare($this->getIdoVersion(), '1.11.7', '<')) { + $this->columnMap['programstatus']['endpoint_name'] = '(0)'; + } + if (version_compare($this->getIdoVersion(), '1.11.8', '<')) { + $this->columnMap['programstatus']['program_version'] = '(NULL)'; + } + if (version_compare($this->getIdoVersion(), '1.8', '<')) { + $this->columnMap['programstatus']['disable_notif_expire_time'] = '(NULL)'; + } + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/RuntimesummaryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/RuntimesummaryQuery.php new file mode 100644 index 0000000..1aa2257 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/RuntimesummaryQuery.php @@ -0,0 +1,80 @@ +<?php +/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Zend_Db_Select; + +/** + * Query check summaries out of database + */ +class RuntimesummaryQuery extends IdoQuery +{ + protected $columnMap = array( + 'runtimesummary' => array( + 'check_type' => 'check_type', + 'active_checks_enabled' => 'active_checks_enabled', + 'passive_checks_enabled' => 'passive_checks_enabled', + 'execution_time' => 'execution_time', + 'latency' => 'latency', + 'object_count' => 'object_count', + 'object_type' => 'object_type' + ) + ); + + protected function joinBaseTables() + { + $hosts = $this->db->select()->from( + array('ho' => $this->prefix . 'objects'), + array() + )->join( + array('hs' => $this->prefix . 'hoststatus'), + 'ho.object_id = hs.host_object_id AND ho.is_active = 1 AND ho.objecttype_id = 1', + array() + )->columns( + array( + 'check_type' => 'CASE ' + . 'WHEN hs.active_checks_enabled = 0 AND hs.passive_checks_enabled = 1 THEN \'passive\' ' + . 'WHEN hs.active_checks_enabled = 1 THEN \'active\' ' + . 'END', + 'active_checks_enabled' => 'hs.active_checks_enabled', + 'passive_checks_enabled' => 'hs.passive_checks_enabled', + 'execution_time' => 'SUM(hs.execution_time)', + 'latency' => 'SUM(hs.latency)', + 'object_count' => 'COUNT(*)', + 'object_type' => "('host')" + ) + )->group('check_type')->group('active_checks_enabled')->group('passive_checks_enabled'); + + $services = $this->db->select()->from( + array('so' => $this->prefix . 'objects'), + array() + )->join( + array('ss' => $this->prefix . 'servicestatus'), + 'so.object_id = ss.service_object_id AND so.is_active = 1 AND so.objecttype_id = 2', + array() + )->columns( + array( + 'check_type' => 'CASE ' + . 'WHEN ss.active_checks_enabled = 0 AND ss.passive_checks_enabled = 1 THEN \'passive\' ' + . 'WHEN ss.active_checks_enabled = 1 THEN \'active\' ' + . 'END', + 'active_checks_enabled' => 'ss.active_checks_enabled', + 'passive_checks_enabled' => 'ss.passive_checks_enabled', + 'execution_time' => 'SUM(ss.execution_time)', + 'latency' => 'SUM(ss.latency)', + 'object_count' => 'COUNT(*)', + 'object_type' => "('service')" + ) + )->group('check_type')->group('active_checks_enabled')->group('passive_checks_enabled'); + + $union = $this->db->select()->union( + array('s' => $services, 'h' => $hosts), + Zend_Db_Select::SQL_UNION_ALL + ); + + $this->select->from(array('hs' => $union)); + + $this->joinedVirtualTables = array('runtimesummary' => true); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/RuntimevariablesQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/RuntimevariablesQuery.php new file mode 100644 index 0000000..494744a --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/RuntimevariablesQuery.php @@ -0,0 +1,18 @@ +<?php +/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +/** + * Query for runtimevariables table + */ +class RuntimevariablesQuery extends IdoQuery +{ + protected $columnMap = array( + 'runtimevariables' => array( + 'id' => 'runtimevariable_id', + 'varname' => 'varname', + 'varvalue' => 'varvalue' + ) + ); +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicecommentQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicecommentQuery.php new file mode 100644 index 0000000..cae11bc --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicecommentQuery.php @@ -0,0 +1,218 @@ +<?php +/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +/** + * Query for service comments + */ +class ServicecommentQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $allowCustomVars = true; + + /** + * {@inheritdoc} + */ + protected $groupBase = array('comments' => array('c.comment_id', 'so.object_id')); + + /** + * {@inheritdoc} + */ + protected $groupOrigin = array('hostgroups', 'servicegroups'); + + protected $subQueryTargets = array( + 'hostgroups' => 'hostgroup', + 'servicegroups' => 'servicegroup' + ); + + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'comments' => array( + 'comment_author' => 'c.author_name COLLATE latin1_general_ci', + 'comment_author_name' => 'c.author_name', + 'comment_data' => 'c.comment_data', + 'comment_expiration' => 'CASE c.expires WHEN 1 THEN UNIX_TIMESTAMP(c.expiration_time) ELSE NULL END', + 'comment_internal_id' => 'c.internal_comment_id', + 'comment_is_persistent' => 'c.is_persistent', + 'comment_name' => 'c.name', + 'comment_timestamp' => 'UNIX_TIMESTAMP(c.comment_time)', + 'comment_type' => "CASE c.entry_type WHEN 1 THEN 'comment' WHEN 2 THEN 'downtime' WHEN 3 THEN 'flapping' WHEN 4 THEN 'ack' END", + 'host' => 'so.name1 COLLATE latin1_general_ci', + 'host_name' => 'so.name1', + 'object_type' => '(\'service\')', + 'service' => 'so.name2 COLLATE latin1_general_ci', + 'service_description' => 'so.name2', + 'service_host' => 'so.name1 COLLATE latin1_general_ci', + 'service_host_name' => 'so.name1' + ), + 'hostgroups' => array( + 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci', + 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci', + 'hostgroup_name' => 'hgo.name1' + ), + 'hosts' => array( + 'host_alias' => 'h.alias', + 'host_display_name' => 'h.display_name COLLATE latin1_general_ci' + ), + 'instances' => array( + 'instance_name' => 'i.instance_name' + ), + 'hoststatus' => array( + 'host_state' => 'CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 99 ELSE hs.current_state END' + ), + 'servicegroups' => array( + 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci', + 'servicegroup_name' => 'sgo.name1', + 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci' + ), + 'services' => array( + 'service_display_name' => 's.display_name COLLATE latin1_general_ci' + ), + 'servicestatus' => array( + 'service_state' => 'CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 99 ELSE ss.current_state END' + ) + ); + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + if (version_compare($this->getIdoVersion(), '1.14.0', '<')) { + $this->columnMap['comments']['comment_name'] = '(NULL)'; + } + $this->select->from( + array('c' => $this->prefix . 'comments'), + array() + )->join( + array('so' => $this->prefix . 'objects'), + 'so.object_id = c.object_id AND so.is_active = 1 AND so.objecttype_id = 2', + array() + ); + $this->joinedVirtualTables['comments'] = true; + } + /** + * Join host groups + */ + protected function joinHostgroups() + { + $this->requireVirtualTable('services'); + $this->select->joinLeft( + array('hgm' => $this->prefix . 'hostgroup_members'), + 'hgm.host_object_id = s.host_object_id', + array() + )->joinLeft( + array('hg' => $this->prefix . 'hostgroups'), + 'hg.hostgroup_id = hgm.hostgroup_id', + array() + )->joinLeft( + array('hgo' => $this->prefix . 'objects'), + 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3', + array() + ); + } + + /** + * Join hosts + */ + protected function joinHosts() + { + $this->requireVirtualTable('services'); + $this->select->join( + array('h' => $this->prefix . 'hosts'), + 'h.host_object_id = s.host_object_id', + array() + ); + } + + /** + * Join host status + */ + protected function joinHoststatus() + { + $this->requireVirtualTable('services'); + $this->select->join( + array('hs' => $this->prefix . 'hoststatus'), + 'hs.host_object_id = s.host_object_id', + array() + ); + } + + /** + * Join service groups + */ + protected function joinServicegroups() + { + $this->select->joinLeft( + array('sgm' => $this->prefix . 'servicegroup_members'), + 'sgm.service_object_id = so.object_id', + array() + )->joinLeft( + array('sg' => $this->prefix . 'servicegroups'), + 'sgm.servicegroup_id = sg.' . $this->servicegroup_id, + array() + )->joinLeft( + array('sgo' => $this->prefix . 'objects'), + 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4', + array() + ); + } + + /** + * Join instances + */ + protected function joinInstances() + { + $this->select->join( + array('i' => $this->prefix . 'instances'), + 'i.instance_id = c.instance_id', + array() + ); + } + + /** + * Join services + */ + protected function joinServices() + { + $this->select->join( + array('s' => $this->prefix . 'services'), + 's.service_object_id = so.object_id', + array() + ); + } + + /** + * Join service status + */ + protected function joinServicestatus() + { + $this->select->join( + array('ss' => $this->prefix . 'servicestatus'), + 'ss.service_object_id = so.object_id', + array() + ); + } + + protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter) + { + if ($name === 'hostgroup') { + $this->requireVirtualTable('services'); + + $query->joinVirtualTable('members'); + + return ['hgm.host_object_id', 's.host_object_id']; + } elseif ($name === 'servicegroup') { + $query->joinVirtualTable('members'); + + return ['sgm.service_object_id', 'so.object_id']; + } + + return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicecommentdeletionhistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicecommentdeletionhistoryQuery.php new file mode 100644 index 0000000..33aaa25 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicecommentdeletionhistoryQuery.php @@ -0,0 +1,44 @@ +<?php +/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Data\Filter\Filter; +use Icinga\Data\Filter\FilterExpression; + +/** + * Query for service comment removal records + */ +class ServicecommentdeletionhistoryQuery extends ServicecommenthistoryQuery +{ + protected function requireFilterColumns(Filter $filter) + { + if ($filter instanceof FilterExpression && $filter->getColumn() === 'timestamp') { + $this->requireColumn('timestamp'); + $filter->setColumn('sch.deletion_time'); + $filter->setExpression($this->timestampForSql($this->valueToTimestamp($filter->getExpression()))); + return null; + } + + return parent::requireFilterColumns($filter); + } + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + parent::joinBaseTables(); + $this->select->where("sch.deletion_time > '1970-01-02 00:00:00'"); + $this->columnMap['commenthistory']['timestamp'] = str_replace( + 'comment_time', + 'deletion_time', + $this->columnMap['commenthistory']['timestamp'] + ); + $this->columnMap['commenthistory']['type'] = str_replace( + 'END)', + "END || '_deleted')", + $this->columnMap['commenthistory']['type'] + ); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicecommenthistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicecommenthistoryQuery.php new file mode 100644 index 0000000..b3e9c16 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicecommenthistoryQuery.php @@ -0,0 +1,195 @@ +<?php +/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Data\Filter\Filter; +use Icinga\Data\Filter\FilterExpression; + +/** + * Query for service comment history records + */ +class ServicecommenthistoryQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $allowCustomVars = true; + + /** + * {@inheritdoc} + */ + protected $groupBase = array('commenthistory' => array('sch.commenthistory_id', 'so.object_id')); + + /** + * {@inheritdoc} + */ + protected $groupOrigin = array('hostgroups', 'servicegroups', 'services'); + + protected $subQueryTargets = array( + 'hostgroups' => 'hostgroup', + 'servicegroups' => 'servicegroup' + ); + + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'commenthistory' => array( + 'id' => 'sch.commenthistory_id', + 'host' => 'so.name1 COLLATE latin1_general_ci', + 'host_name' => 'so.name1', + 'object_id' => 'sch.object_id', + 'object_type' => '(\'service\')', + 'output' => "('[' || sch.author_name || '] ' || sch.comment_data)", + 'service' => 'so.name2 COLLATE latin1_general_ci', + 'service_description' => 'so.name2', + 'service_host' => 'so.name1 COLLATE latin1_general_ci', + 'service_host_name' => 'so.name1', + 'state' => '(-1)', + 'timestamp' => 'UNIX_TIMESTAMP(sch.comment_time)', + 'type' => "(CASE sch.entry_type WHEN 1 THEN 'comment' WHEN 2 THEN 'dt_comment' WHEN 3 THEN 'flapping' WHEN 4 THEN 'ack' END)" + ), + 'hostgroups' => array( + 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci', + 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci', + 'hostgroup_name' => 'hgo.name1' + ), + 'hosts' => array( + 'host_alias' => 'h.alias', + 'host_display_name' => 'h.display_name COLLATE latin1_general_ci' + ), + 'instances' => array( + 'instance_name' => 'i.instance_name' + ), + 'servicegroups' => array( + 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci', + 'servicegroup_name' => 'sgo.name1', + 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci' + ), + 'services' => array( + 'service_display_name' => 's.display_name COLLATE latin1_general_ci' + ) + ); + + protected function requireFilterColumns(Filter $filter) + { + if ($filter instanceof FilterExpression && $filter->getColumn() === 'timestamp') { + $this->requireColumn('timestamp'); + $filter->setColumn('sch.comment_time'); + $filter->setExpression($this->timestampForSql($this->valueToTimestamp($filter->getExpression()))); + return null; + } + + return parent::requireFilterColumns($filter); + } + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + $this->select->from( + array('sch' => $this->prefix . 'commenthistory'), + array() + )->join( + array('so' => $this->prefix . 'objects'), + 'so.object_id = sch.object_id AND so.is_active = 1 AND so.objecttype_id = 2', + array() + ); + $this->joinedVirtualTables['commenthistory'] = true; + } + + /** + * Join host groups + */ + protected function joinHostgroups() + { + $this->requireVirtualTable('services'); + $this->select->joinLeft( + array('hgm' => $this->prefix . 'hostgroup_members'), + 'hgm.host_object_id = s.host_object_id', + array() + )->joinLeft( + array('hg' => $this->prefix . 'hostgroups'), + 'hg.hostgroup_id = hgm.hostgroup_id', + array() + )->joinLeft( + array('hgo' => $this->prefix . 'objects'), + 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3', + array() + ); + } + + /** + * Join hosts + */ + protected function joinHosts() + { + $this->requireVirtualTable('services'); + $this->select->join( + array('h' => $this->prefix . 'hosts'), + 'h.host_object_id = s.host_object_id', + array() + ); + } + + /** + * Join instances + */ + protected function joinInstances() + { + $this->select->join( + array('i' => $this->prefix . 'instances'), + 'i.instance_id = sch.instance_id', + array() + ); + } + + /** + * Join service groups + */ + protected function joinServicegroups() + { + $this->select->joinLeft( + array('sgm' => $this->prefix . 'servicegroup_members'), + 'sgm.service_object_id = so.object_id', + array() + )->joinLeft( + array('sg' => $this->prefix . 'servicegroups'), + 'sg.' . $this->servicegroup_id . ' = sgm.servicegroup_id', + array() + )->joinLeft( + array('sgo' => $this->prefix . 'objects'), + 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4', + array() + ); + } + + /** + * Join services + */ + protected function joinServices() + { + $this->select->join( + array('s' => $this->prefix . 'services'), + 's.service_object_id = so.object_id', + array() + ); + } + + protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter) + { + if ($name === 'hostgroup') { + $query->joinVirtualTable('services'); + + return ['so.object_id', 'so.object_id']; + } elseif ($name === 'servicegroup') { + $query->joinVirtualTable('members'); + + return ['sgm.service_object_id', 'so.object_id']; + } + + return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicecontactQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicecontactQuery.php new file mode 100644 index 0000000..0a46709 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicecontactQuery.php @@ -0,0 +1,235 @@ +<?php +/* Icinga Web 2 | (c) 2018 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +/** + * Query for service contacts + */ +class ServicecontactQuery extends IdoQuery +{ + protected $allowCustomVars = true; + + protected $groupBase = [ + 'contacts' => ['co.object_id', 'c.contact_id'], + 'timeperiods' => ['ht.timeperiod_id', 'st.timeperiod_id'] + ]; + + protected $groupOrigin = ['contactgroups', 'hosts', 'services']; + + protected $subQueryTargets = [ + 'hostgroups' => 'hostgroup', + 'servicegroups' => 'servicegroup' + ]; + + protected $columnMap = [ + 'contactgroups' => [ + 'contactgroup' => 'cgo.name1 COLLATE latin1_general_ci', + 'contactgroup_name' => 'cgo.name1', + 'contactgroup_alias' => 'cg.alias COLLATE latin1_general_ci' + ], + 'contacts' => [ + 'contact_id' => 'c.contact_id', + 'contact' => 'co.name1 COLLATE latin1_general_ci', + 'contact_name' => 'co.name1', + 'contact_alias' => 'c.alias COLLATE latin1_general_ci', + 'contact_email' => 'c.email_address COLLATE latin1_general_ci', + 'contact_pager' => 'c.pager_address', + 'contact_object_id' => 'c.contact_object_id', + 'contact_has_host_notfications' => 'c.host_notifications_enabled', + 'contact_has_service_notfications' => 'c.service_notifications_enabled', + 'contact_can_submit_commands' => 'c.can_submit_commands', + 'contact_notify_service_recovery' => 'c.notify_service_recovery', + 'contact_notify_service_warning' => 'c.notify_service_warning', + 'contact_notify_service_critical' => 'c.notify_service_critical', + 'contact_notify_service_unknown' => 'c.notify_service_unknown', + 'contact_notify_service_flapping' => 'c.notify_service_flapping', + 'contact_notify_service_downtime' => 'c.notify_service_downtime', + 'contact_notify_host_recovery' => 'c.notify_host_recovery', + 'contact_notify_host_down' => 'c.notify_host_down', + 'contact_notify_host_unreachable' => 'c.notify_host_unreachable', + 'contact_notify_host_flapping' => 'c.notify_host_flapping', + 'contact_notify_host_downtime' => 'c.notify_host_downtime' + ], + 'hostgroups' => [ + 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci', + 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci', + 'hostgroup_name' => 'hgo.name1' + ], + 'hosts' => [ + 'host' => 'ho.name1 COLLATE latin1_general_ci', + 'host_name' => 'ho.name1', + 'host_alias' => 'h.alias', + 'host_display_name' => 'h.display_name COLLATE latin1_general_ci' + ], + 'instances' => [ + 'instance_name' => 'i.instance_name' + ], + 'servicegroups' => [ + 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci', + 'servicegroup_name' => 'sgo.name1', + 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci' + ], + 'services' => [ + 'service' => 'so.name2 COLLATE latin1_general_ci', + 'service_description' => 'so.name2', + 'service_display_name' => 's.display_name COLLATE latin1_general_ci', + 'service_host_name' => 'so.name1' + ], + 'timeperiods' => [ + 'contact_notify_host_timeperiod' => 'ht.alias COLLATE latin1_general_ci', + 'contact_notify_service_timeperiod' => 'st.alias COLLATE latin1_general_ci' + ] + ]; + + protected function joinBaseTables() + { + $this->select->from( + ['c' => $this->prefix . 'contacts'], + [] + )->join( + ['co' => $this->prefix . 'objects'], + 'co.object_id = c.contact_object_id AND co.is_active = 1 AND co.objecttype_id = 10', + [] + ); + + $this->select->joinLeft( + ['sc' => $this->prefix . 'service_contacts'], + 'sc.contact_object_id = c.contact_object_id', + [] + )->joinLeft( + ['s' => $this->prefix . 'services'], + 's.service_id = sc.service_id', + [] + )->joinLeft( + ['so' => $this->prefix . 'objects'], + 'so.object_id = s.service_object_id AND so.is_active = 1 AND so.objecttype_id = 2', + [] + ); + + $this->joinedVirtualTables['contacts'] = true; + $this->joinedVirtualTables['services'] = true; + } + + /** + * Join contact groups + */ + protected function joinContactgroups() + { + $this->select->joinLeft( + ['cgm' => $this->prefix . 'contactgroup_members'], + 'co.object_id = cgm.contact_object_id', + [] + )->joinLeft( + ['cg' => $this->prefix . 'contactgroups'], + 'cgm.contactgroup_id = cg.contactgroup_id', + [] + )->joinLeft( + ['cgo' => $this->prefix . 'objects'], + 'cg.contactgroup_object_id = cgo.object_id AND cgo.is_active = 1 AND cgo.objecttype_id = 11', + [] + ); + } + + /** + * Join host groups + */ + protected function joinHostgroups() + { + $this->requireVirtualTable('hosts'); + $this->select->joinLeft( + ['hgm' => $this->prefix . 'hostgroup_members'], + 'hgm.host_object_id = ho.object_id', + [] + )->joinLeft( + ['hg' => $this->prefix . 'hostgroups'], + 'hg.hostgroup_id = hgm.hostgroup_id', + [] + )->joinLeft( + ['hgo' => $this->prefix . 'objects'], + 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3', + [] + ); + } + + /** + * Join hosts + */ + protected function joinHosts() + { + $this->select->joinLeft( + ['h' => $this->prefix . 'hosts'], + 'h.host_object_id = s.host_object_id', + [] + )->joinLeft( + ['ho' => $this->prefix . 'objects'], + 'ho.object_id = h.host_object_id AND ho.is_active = 1 AND ho.objecttype_id = 1', + [] + ); + } + + /** + * Join instances + */ + protected function joinInstances() + { + $this->select->join( + ['i' => $this->prefix . 'instances'], + 'i.instance_id = c.instance_id', + [] + ); + } + + /** + * Join service groups + */ + protected function joinServicegroups() + { + $this->requireVirtualTable('services'); + $this->select->joinLeft( + ['sgm' => $this->prefix . 'servicegroup_members'], + 'sgm.service_object_id = s.service_object_id', + [] + )->joinLeft( + ['sg' => $this->prefix . 'servicegroups'], + 'sg.servicegroup_id = sgm.servicegroup_id', + [] + )->joinLeft( + ['sgo' => $this->prefix . 'objects'], + 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4', + [] + ); + } + + /** + * Join time periods + */ + protected function joinTimeperiods() + { + $this->select->joinLeft( + ['ht' => $this->prefix . 'timeperiods'], + 'ht.timeperiod_object_id = c.host_timeperiod_object_id', + [] + ); + $this->select->joinLeft( + ['st' => $this->prefix . 'timeperiods'], + 'st.timeperiod_object_id = c.service_timeperiod_object_id', + [] + ); + } + + protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter) + { + if ($name === 'hostgroup') { + $query->joinVirtualTable('members'); + + return ['hgm.host_object_id', 's.host_object_id']; + } elseif ($name === 'servicegroup') { + $query->joinVirtualTable('members'); + + return ['sgm.service_object_id', 'so.object_id']; + } + + return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicedowntimeQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicedowntimeQuery.php new file mode 100644 index 0000000..feea061 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicedowntimeQuery.php @@ -0,0 +1,222 @@ +<?php +/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +/** + * Query for service downtimes + */ +class ServicedowntimeQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $allowCustomVars = true; + + /** + * {@inheritdoc} + */ + protected $groupBase = array('downtimes' => array('sd.scheduleddowntime_id', 'so.object_id')); + + /** + * {@inheritdoc} + */ + protected $groupOrigin = array('hostgroups', 'servicegroups'); + + protected $subQueryTargets = array( + 'hostgroups' => 'hostgroup', + 'servicegroups' => 'servicegroup' + ); + + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'downtimes' => array( + 'downtime_author' => 'sd.author_name COLLATE latin1_general_ci', + 'downtime_author_name' => 'sd.author_name', + 'downtime_comment' => 'sd.comment_data', + 'downtime_duration' => 'sd.duration', + 'downtime_end' => 'CASE WHEN sd.is_fixed > 0 THEN UNIX_TIMESTAMP(sd.scheduled_end_time) ELSE UNIX_TIMESTAMP(sd.trigger_time) + sd.duration END', + 'downtime_entry_time' => 'UNIX_TIMESTAMP(sd.entry_time)', + 'downtime_internal_id' => 'sd.internal_downtime_id', + 'downtime_is_fixed' => 'sd.is_fixed', + 'downtime_is_flexible' => 'CASE WHEN sd.is_fixed = 0 THEN 1 ELSE 0 END', + 'downtime_is_in_effect' => 'sd.is_in_effect', + 'downtime_name' => 'sd.name', + 'downtime_scheduled_end' => 'UNIX_TIMESTAMP(sd.scheduled_end_time)', + 'downtime_scheduled_start' => 'UNIX_TIMESTAMP(sd.scheduled_start_time)', + 'downtime_start' => 'UNIX_TIMESTAMP(CASE WHEN UNIX_TIMESTAMP(sd.trigger_time) > 0 then sd.trigger_time ELSE sd.scheduled_start_time END)', + 'downtime_triggered_by_id' => 'sd.triggered_by_id', + 'host' => 'so.name1 COLLATE latin1_general_ci', + 'host_name' => 'so.name1', + 'object_type' => '(\'service\')', + 'service' => 'so.name2 COLLATE latin1_general_ci', + 'service_description' => 'so.name2', + 'service_host' => 'so.name1 COLLATE latin1_general_ci', + 'service_host_name' => 'so.name1' + ), + 'hostgroups' => array( + 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci', + 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci', + 'hostgroup_name' => 'hgo.name1' + ), + 'hosts' => array( + 'host_alias' => 'h.alias', + 'host_display_name' => 'h.display_name COLLATE latin1_general_ci' + ), + 'hoststatus' => array( + 'host_state' => 'CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 99 ELSE hs.current_state END' + ), + 'instances' => array( + 'instance_name' => 'i.instance_name' + ), + 'servicegroups' => array( + 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci', + 'servicegroup_name' => 'sgo.name1', + 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci' + ), + 'services' => array( + 'service_display_name' => 's.display_name COLLATE latin1_general_ci' + ), + 'servicestatus' => array( + 'service_state' => 'CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 99 ELSE ss.current_state END' + ) + ); + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + if (version_compare($this->getIdoVersion(), '1.14.0', '<')) { + $this->columnMap['downtimes']['downtime_name'] = '(NULL)'; + } + $this->select->from( + array('sd' => $this->prefix . 'scheduleddowntime'), + array() + )->join( + array('so' => $this->prefix . 'objects'), + 'sd.object_id = so.object_id AND so.is_active = 1 AND so.objecttype_id = 2', + array() + ); + $this->joinedVirtualTables['downtimes'] = true; + } + /** + * Join host groups + */ + protected function joinHostgroups() + { + $this->requireVirtualTable('services'); + $this->select->joinLeft( + array('hgm' => $this->prefix . 'hostgroup_members'), + 'hgm.host_object_id = s.host_object_id', + array() + )->joinLeft( + array('hg' => $this->prefix . 'hostgroups'), + 'hg.hostgroup_id = hgm.hostgroup_id', + array() + )->joinLeft( + array('hgo' => $this->prefix . 'objects'), + 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3', + array() + ); + } + + /** + * Join hosts + */ + protected function joinHosts() + { + $this->requireVirtualTable('services'); + $this->select->join( + array('h' => $this->prefix . 'hosts'), + 'h.host_object_id = s.host_object_id', + array() + ); + } + + /** + * Join host status + */ + protected function joinHoststatus() + { + $this->requireVirtualTable('services'); + $this->select->join( + array('hs' => $this->prefix . 'hoststatus'), + 'hs.host_object_id = s.host_object_id', + array() + ); + } + + /** + * Join instances + */ + protected function joinInstances() + { + $this->select->join( + array('i' => $this->prefix . 'instances'), + 'i.instance_id = sd.instance_id', + array() + ); + } + + /** + * Join service groups + */ + protected function joinServicegroups() + { + $this->select->joinLeft( + array('sgm' => $this->prefix . 'servicegroup_members'), + 'sgm.service_object_id = so.object_id', + array() + )->joinLeft( + array('sg' => $this->prefix . 'servicegroups'), + 'sgm.servicegroup_id = sg.' . $this->servicegroup_id, + array() + )->joinLeft( + array('sgo' => $this->prefix . 'objects'), + 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4', + array() + ); + } + + /** + * Join services + */ + protected function joinServices() + { + $this->select->join( + array('s' => $this->prefix . 'services'), + 's.service_object_id = so.object_id', + array() + ); + } + + /** + * Join service status + */ + protected function joinServicestatus() + { + $this->select->join( + array('ss' => $this->prefix . 'servicestatus'), + 'ss.service_object_id = so.object_id', + array() + ); + } + + protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter) + { + if ($name === 'hostgroup') { + $query->joinVirtualTable('services'); + + return ['so.object_id', 'so.object_id']; + } elseif ($name === 'servicegroup') { + $query->joinVirtualTable('members'); + + return ['sgm.service_object_id', 'so.object_id']; + } + + return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicedowntimeendhistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicedowntimeendhistoryQuery.php new file mode 100644 index 0000000..6243829 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicedowntimeendhistoryQuery.php @@ -0,0 +1,42 @@ +<?php +/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Data\Filter\Filter; +use Icinga\Data\Filter\FilterExpression; + +/** + * Query for host downtime end history records + */ +class ServicedowntimeendhistoryQuery extends ServicedowntimestarthistoryQuery +{ + protected function requireFilterColumns(Filter $filter) + { + if ($filter instanceof FilterExpression && $filter->getColumn() === 'timestamp') { + $this->requireColumn('timestamp'); + $filter->setColumn('sdh.actual_end_time'); + $filter->setExpression($this->timestampForSql($this->valueToTimestamp($filter->getExpression()))); + return null; + } + + return parent::requireFilterColumns($filter); + } + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + parent::joinBaseTables(true); + $this->select->where( + "sdh.actual_end_time > '1970-01-02 00:00:00' AND sdh.was_started = 1 AND sdh.was_cancelled = 0" + ); + $this->columnMap['downtimehistory']['type'] = "('dt_end')"; + $this->columnMap['downtimehistory']['timestamp'] = str_replace( + 'actual_start_time', + 'actual_end_time', + $this->columnMap['downtimehistory']['timestamp'] + ); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicedowntimestarthistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicedowntimestarthistoryQuery.php new file mode 100644 index 0000000..b8805fe --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicedowntimestarthistoryQuery.php @@ -0,0 +1,205 @@ +<?php +/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Data\Filter\Filter; +use Icinga\Data\Filter\FilterExpression; + +/** + * Query for service downtime start history records + */ +class ServicedowntimestarthistoryQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $allowCustomVars = true; + + /** + * {@inheritdoc} + */ + protected $groupBase = array('downtimehistory' => array('sdh.downtimehistory_id', 'so.object_id')); + + /** + * {@inheritdoc} + */ + protected $groupOrigin = array('hostgroups', 'servicegroups'); + + protected $subQueryTargets = array( + 'hostgroups' => 'hostgroup', + 'servicegroups' => 'servicegroup' + ); + + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'downtimehistory' => array( + 'id' => 'sdh.downtimehistory_id', + 'host' => 'so.name1 COLLATE latin1_general_ci', + 'host_name' => 'so.name1', + 'object_id' => 'sdh.object_id', + 'object_type' => '(\'service\')', + 'output' => "('[' || sdh.author_name || '] ' || sdh.comment_data)", + 'service' => 'so.name2 COLLATE latin1_general_ci', + 'service_description' => 'so.name2', + 'service_host' => 'so.name1 COLLATE latin1_general_ci', + 'service_host_name' => 'so.name1', + 'state' => '(-1)', + 'timestamp' => 'UNIX_TIMESTAMP(sdh.actual_start_time)', + 'type' => "('dt_start')" + ), + 'hostgroups' => array( + 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci', + 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci', + 'hostgroup_name' => 'hgo.name1' + ), + 'hosts' => array( + 'host_alias' => 'h.alias', + 'host_display_name' => 'h.display_name COLLATE latin1_general_ci' + ), + 'instances' => array( + 'instance_name' => 'i.instance_name' + ), + 'servicegroups' => array( + 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci', + 'servicegroup_name' => 'sgo.name1', + 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci' + ), + 'services' => array( + 'service_display_name' => 's.display_name COLLATE latin1_general_ci' + ) + ); + + protected function requireFilterColumns(Filter $filter) + { + if ($filter instanceof FilterExpression && $filter->getColumn() === 'timestamp') { + $this->requireColumn('timestamp'); + $filter->setColumn('sdh.actual_start_time'); + $filter->setExpression($this->timestampForSql($this->valueToTimestamp($filter->getExpression()))); + return null; + } + + return parent::requireFilterColumns($filter); + } + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + $this->select->from( + array('sdh' => $this->prefix . 'downtimehistory'), + array() + )->join( + array('so' => $this->prefix . 'objects'), + 'so.object_id = sdh.object_id AND so.is_active = 1 AND so.objecttype_id = 2', + array() + ); + + if (func_num_args() === 0 || func_get_arg(0) === false) { + $this->select->where( + "sdh.actual_start_time > '1970-01-02 00:00:00'" + ); + } + $this->select->where( + "sdh.was_started = 1 AND sdh.was_cancelled = 0" + ); + + $this->joinedVirtualTables['downtimehistory'] = true; + } + + /** + * Join host groups + */ + protected function joinHostgroups() + { + $this->requireVirtualTable('services'); + $this->select->joinLeft( + array('hgm' => $this->prefix . 'hostgroup_members'), + 'hgm.host_object_id = s.host_object_id', + array() + )->joinLeft( + array('hg' => $this->prefix . 'hostgroups'), + 'hg.hostgroup_id = hgm.hostgroup_id', + array() + )->joinLeft( + array('hgo' => $this->prefix . 'objects'), + 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3', + array() + ); + } + + /** + * Join hosts + */ + protected function joinHosts() + { + $this->requireVirtualTable('services'); + $this->select->join( + array('h' => $this->prefix . 'hosts'), + 'h.host_object_id = s.host_object_id', + array() + ); + } + + /** + * Join instances + */ + protected function joinInstances() + { + $this->select->join( + array('i' => $this->prefix . 'instances'), + 'i.instance_id = sdh.instance_id', + array() + ); + } + + /** + * Join service groups + */ + protected function joinServicegroups() + { + $this->select->joinLeft( + array('sgm' => $this->prefix . 'servicegroup_members'), + 'sgm.service_object_id = so.object_id', + array() + )->joinLeft( + array('sg' => $this->prefix . 'servicegroups'), + 'sg.' . $this->servicegroup_id . ' = sgm.servicegroup_id', + array() + )->joinLeft( + array('sgo' => $this->prefix . 'objects'), + 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4', + array() + ); + } + + /** + * Join services + */ + protected function joinServices() + { + $this->select->join( + array('s' => $this->prefix . 'services'), + 's.service_object_id = so.object_id', + array() + ); + } + + protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter) + { + if ($name === 'hostgroup') { + $query->joinVirtualTable('services'); + + return ['so.object_id', 'so.object_id']; + } elseif ($name === 'servicegroup') { + $query->joinVirtualTable('members'); + + return ['sgm.service_object_id', 'so.object_id']; + } + + return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServiceflappingendhistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServiceflappingendhistoryQuery.php new file mode 100644 index 0000000..48fb0bc --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServiceflappingendhistoryQuery.php @@ -0,0 +1,31 @@ +<?php +/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +/** + * Query for service flapping end history records + */ +class ServiceflappingendhistoryQuery extends ServiceflappingstarthistoryQuery +{ + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + $this->select->from( + array('sfh' => $this->prefix . 'flappinghistory'), + array() + )->join( + array('so' => $this->prefix . 'objects'), + 'so.object_id = sfh.object_id AND so.is_active = 1 AND so.objecttype_id = 2', + array() + ); + + $this->select->where('sfh.event_type = 1001'); + + $this->joinedVirtualTables['flappinghistory'] = true; + + $this->columnMap['flappinghistory']['type'] = '(\'flapping_deleted\')'; + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServiceflappingstarthistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServiceflappingstarthistoryQuery.php new file mode 100644 index 0000000..f068681 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServiceflappingstarthistoryQuery.php @@ -0,0 +1,197 @@ +<?php +/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Data\Filter\Filter; +use Icinga\Data\Filter\FilterExpression; + +/** + * Query for service flapping start history records + */ +class ServiceflappingstarthistoryQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $allowCustomVars = true; + + /** + * {@inheritdoc} + */ + protected $groupBase = array('flappinghistory' => array('sfh.flappinghistory_id', 'so.object_id')); + + /** + * {@inheritdoc} + */ + protected $groupOrigin = array('hostgroups', 'servicegroups'); + + protected $subQueryTargets = array( + 'hostgroups' => 'hostgroup', + 'servicegroups' => 'servicegroup' + ); + + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'flappinghistory' => array( + 'id' => 'sfh.flappinghistory_id', + 'host' => 'so.name1 COLLATE latin1_general_ci', + 'host_name' => 'so.name1', + 'object_id' => 'sfh.object_id', + 'object_type' => '(\'service\')', + 'output' => '(sfh.percent_state_change || \'\')', + 'service' => 'so.name2 COLLATE latin1_general_ci', + 'service_description' => 'so.name2', + 'service_host_name' => 'so.name1', + 'state' => '(-1)', + 'timestamp' => 'UNIX_TIMESTAMP(sfh.event_time)', + 'type' => "('flapping')" + ), + 'hostgroups' => array( + 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci', + 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci', + 'hostgroup_name' => 'hgo.name1' + ), + 'hosts' => array( + 'host_alias' => 'h.alias', + 'host_display_name' => 'h.display_name COLLATE latin1_general_ci' + ), + 'instances' => array( + 'instance_name' => 'i.instance_name' + ), + 'servicegroups' => array( + 'servicegroup_name' => 'sgo.name1', + 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci', + 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci' + ), + 'services' => array( + 'service_display_name' => 's.display_name COLLATE latin1_general_ci' + ) + ); + + protected function requireFilterColumns(Filter $filter) + { + if ($filter instanceof FilterExpression && $filter->getColumn() === 'timestamp') { + $this->requireColumn('timestamp'); + $filter->setColumn('sfh.event_time'); + $filter->setExpression($this->timestampForSql($this->valueToTimestamp($filter->getExpression()))); + return null; + } + + return parent::requireFilterColumns($filter); + } + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + $this->select->from( + array('sfh' => $this->prefix . 'flappinghistory'), + array() + )->join( + array('so' => $this->prefix . 'objects'), + 'so.object_id = sfh.object_id AND so.is_active = 1 AND so.objecttype_id = 2', + array() + ); + + $this->select->where('sfh.event_type = 1000'); + + $this->joinedVirtualTables['flappinghistory'] = true; + } + + /** + * Join host groups + */ + protected function joinHostgroups() + { + $this->requireVirtualTable('services'); + $this->select->joinLeft( + array('hgm' => $this->prefix . 'hostgroup_members'), + 'hgm.host_object_id = s.host_object_id', + array() + )->joinLeft( + array('hg' => $this->prefix . 'hostgroups'), + 'hg.hostgroup_id = hgm.hostgroup_id', + array() + )->joinLeft( + array('hgo' => $this->prefix . 'objects'), + 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3', + array() + ); + } + + /** + * Join hosts + */ + protected function joinHosts() + { + $this->requireVirtualTable('services'); + $this->select->join( + array('h' => $this->prefix . 'hosts'), + 'h.host_object_id = s.host_object_id', + array() + ); + } + + /** + * Join instances + */ + protected function joinInstances() + { + $this->select->join( + array('i' => $this->prefix . 'instances'), + 'i.instance_id = sfh.instance_id', + array() + ); + } + + /** + * Join service groups + */ + protected function joinServicegroups() + { + $this->select->joinLeft( + array('sgm' => $this->prefix . 'servicegroup_members'), + 'sgm.service_object_id = so.object_id', + array() + )->joinLeft( + array('sg' => $this->prefix . 'servicegroups'), + 'sg.' . $this->servicegroup_id . ' = sgm.servicegroup_id', + array() + )->joinLeft( + array('sgo' => $this->prefix . 'objects'), + 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4', + array() + ); + } + + /** + * Join services + */ + protected function joinServices() + { + $this->select->join( + array('s' => $this->prefix . 'services'), + 's.service_object_id = so.object_id', + array() + ); + } + + protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter) + { + if ($name === 'hostgroup') { + $query->joinVirtualTable('services'); + + return ['so.object_id', 'so.object_id']; + } elseif ($name === 'servicegroup') { + $query->joinVirtualTable('members'); + + return ['sgm.service_object_id', 'so.object_id']; + } + + return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicegroupQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicegroupQuery.php new file mode 100644 index 0000000..7f7be50 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicegroupQuery.php @@ -0,0 +1,303 @@ +<?php +/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +class ServicegroupQuery extends IdoQuery +{ + protected $groupBase = array( + 'servicegroups' => array('sgo.object_id', 'sg.servicegroup_id'), + 'servicestatus' => array('ss.servicestatus_id', 'hs.hoststatus_id') + ); + + protected $groupOrigin = array('members'); + + protected $allowCustomVars = true; + + protected $subQueryTargets = array( + 'hostgroups' => 'hostgroup', + 'servicegroups' => 'servicegroup' + ); + + protected $columnMap = array( + 'contacts' => [ + 'service_contact' => 'sco.name1' + ], + 'contactgroups' => [ + 'service_contactgroup' => 'scgo.name1' + ], + 'hostcontacts' => [ + 'host_contact' => 'hco.name1' + ], + 'hostcontactgroups' => [ + 'host_contactgroup' => 'hcgo.name1' + ], + 'hostgroups' => array( + 'hostgroup_name' => 'hgo.name1' + ), + 'hosts' => array( + 'h.host_object_id' => 's.host_object_id' + ), + 'instances' => array( + 'instance_name' => 'i.instance_name' + ), + 'members' => array( + 'host_name' => 'so.name1', + 'service_description' => 'so.name2' + ), + 'servicegroups' => array( + 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci', + 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci', + 'servicegroup_name' => 'sgo.name1' + ), + 'servicestatus' => array( + 'service_handled' => 'CASE WHEN (ss.problem_has_been_acknowledged + ss.scheduled_downtime_depth + COALESCE(hs.current_state, 0)) > 0 THEN 1 ELSE 0 END', + 'service_severity' => ' + CASE WHEN ss.current_state = 0 + THEN + CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL + THEN 16 + ELSE 0 + END + + + CASE WHEN ss.problem_has_been_acknowledged = 1 + THEN 2 + ELSE + CASE WHEN ss.scheduled_downtime_depth > 0 + THEN 1 + ELSE 4 + END + END + ELSE + CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 16 + WHEN ss.current_state = 1 THEN 32 + WHEN ss.current_state = 2 THEN 128 + WHEN ss.current_state = 3 THEN 64 + ELSE 256 + END + + + CASE WHEN hs.current_state > 0 + THEN 1024 + ELSE + CASE WHEN ss.problem_has_been_acknowledged = 1 + THEN 512 + ELSE + CASE WHEN ss.scheduled_downtime_depth > 0 + THEN 256 + ELSE 2048 + END + END + END + END', + 'service_state' => 'CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 99 ELSE ss.current_state END' + ) + ); + + protected function joinBaseTables() + { + $this->select->from( + array('sgo' => $this->prefix . 'objects'), + array() + )->join( + array('sg' => $this->prefix . 'servicegroups'), + 'sg.servicegroup_object_id = sgo.object_id AND sgo.objecttype_id = 4 AND sgo.is_active = 1', + array() + ); + $this->joinedVirtualTables = array('servicegroups' => true); + } + + /** + * Join contacts + */ + protected function joinContacts() + { + $this->requireVirtualTable('services'); + + $this->select->joinLeft( + ['sc' => 'icinga_service_contacts'], + 'sc.service_id = s.service_id', + [] + )->joinLeft( + ['sco' => 'icinga_objects'], + 'sco.object_id = sc.contact_object_id AND sco.is_active = 1 AND sco.objecttype_id = 10', + [] + ); + } + + /** + * Join contact groups + */ + protected function joinContactgroups() + { + $this->requireVirtualTable('services'); + + $this->select->joinLeft( + ['scg' => 'icinga_service_contactgroups'], + 'scg.service_id = s.service_id', + [] + )->joinLeft( + ['scgo' => 'icinga_objects'], + 'scgo.object_id = scg.contactgroup_object_id AND scgo.is_active = 1 AND scgo.objecttype_id = 11', + [] + ); + } + + /** + * Join host contacts + */ + protected function joinHostcontacts() + { + $this->requireVirtualTable('services'); + + $this->select->joinLeft( + ['h' => 'icinga_hosts'], + 'h.host_object_id = s.host_object_id', + [] + )->joinLeft( + ['hc' => 'icinga_host_contacts'], + 'hc.host_id = h.host_id', + [] + )->joinLeft( + ['hco' => 'icinga_objects'], + 'hco.object_id = hc.contact_object_id AND hco.is_active = 1 AND hco.objecttype_id = 10', + [] + ); + } + + /** + * Join host contact groups + */ + protected function joinHostcontactgroups() + { + $this->requireVirtualTable('services'); + + $this->select->joinLeft( + ['h' => 'icinga_hosts'], + 'h.host_object_id = s.host_object_id', + [] + )->joinLeft( + ['hcg' => 'icinga_host_contactgroups'], + 'hcg.host_id = h.host_id', + [] + )->joinLeft( + ['hcgo' => 'icinga_objects'], + 'hcgo.object_id = hcg.contactgroup_object_id AND hcgo.is_active = 1 AND hcgo.objecttype_id = 11', + [] + ); + } + + /** + * Join host groups + */ + protected function joinHostgroups() + { + $this->requireVirtualTable('services'); + $this->select->joinLeft( + array('hgm' => $this->prefix . 'hostgroup_members'), + 'hgm.host_object_id = s.host_object_id', + array() + )->joinLeft( + array('hg' => $this->prefix . 'hostgroups'), + 'hg.hostgroup_id = hgm.hostgroup_id', + array() + )->joinLeft( + array('hgo' => $this->prefix . 'objects'), + 'hgo.object_id = hg.hostgroup_object_id AND hgo.objecttype_id = 3 AND hgo.is_active = 1', + array() + ); + } + + /** + * Join hosts + * + * This is required to make filters work which filter by host custom variables. + */ + protected function joinHosts() + { + $this->requireVirtualTable('services'); + + // Host custom var filters work w/o any host related table. If a host table join is necessary here some day, + // please adjust `joinHostcontact*()` where we explicitly do this already + } + + /** + * Join instances + */ + protected function joinInstances() + { + $this->select->join( + array('i' => $this->prefix . 'instances'), + 'i.instance_id = sg.instance_id', + array() + ); + } + + /** + * Join service objects + */ + protected function joinMembers() + { + $this->select->join( + array('sgm' => $this->prefix . 'servicegroup_members'), + 'sgm.servicegroup_id = sg.servicegroup_id', + array() + )->join( + array('so' => $this->prefix . 'objects'), + 'so.object_id = sgm.service_object_id AND so.objecttype_id = 2 AND so.is_active = 1', + array() + ); + } + + /** + * Join services + */ + protected function joinServices() + { + $this->requireVirtualTable('members'); + $this->select->join( + array('s' => $this->prefix . 'services'), + 's.service_object_id = so.object_id', + array() + ); + } + + /** + * Join service status + */ + protected function joinServicestatus() + { + $this->requireVirtualTable('services'); + $this->select->join( + array('hs' => $this->prefix . 'hoststatus'), + 'hs.host_object_id = s.host_object_id', + array() + ); + $this->select->join( + array('ss' => $this->prefix . 'servicestatus'), + 'ss.service_object_id = so.object_id', + array() + ); + } + + protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter) + { + if ($name === 'hostgroup') { + $this->requireVirtualTable('members'); + + $query->joinVirtualTable('services'); + + return ['so.object_id', 'so.object_id']; + } elseif ($name === 'servicegroup') { + // Propagate that the "parent" query has to be filtered as well + $additionalFilter = clone $filter; + + $this->requireVirtualTable('members'); + + $query->joinVirtualTable('members'); + + return ['sgm.service_object_id', 'so.object_id']; + } + + return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicegroupsummaryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicegroupsummaryQuery.php new file mode 100644 index 0000000..11b62d0 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicegroupsummaryQuery.php @@ -0,0 +1,113 @@ +<?php +/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Data\Filter\Filter; +use Zend_Db_Expr; +use Zend_Db_Select; + +/** + * Query for service group summary + */ +class ServicegroupsummaryQuery extends IdoQuery +{ + + protected $allowCustomVars = true; + + protected $columnMap = array( + 'servicegroupsummary' => array( + 'servicegroup_alias' => 'servicegroup_alias', + 'servicegroup_name' => 'servicegroup_name', + 'services_critical' => 'SUM(CASE WHEN service_state = 2 THEN 1 ELSE 0 END)', + 'services_critical_handled' => 'SUM(CASE WHEN service_state = 2 AND service_handled = 1 THEN 1 ELSE 0 END)', + 'services_critical_unhandled' => 'SUM(CASE WHEN service_state = 2 AND service_handled = 0 THEN 1 ELSE 0 END)', + 'services_ok' => 'SUM(CASE WHEN service_state = 0 THEN 1 ELSE 0 END)', + 'services_pending' => 'SUM(CASE WHEN service_state = 99 THEN 1 ELSE 0 END)', + 'services_severity' => 'MAX(service_severity)', + 'services_total' => 'SUM(1)', + 'services_unknown' => 'SUM(CASE WHEN service_state = 3 THEN 1 ELSE 0 END)', + 'services_unknown_handled' => 'SUM(CASE WHEN service_state = 3 AND service_handled = 1 THEN 1 ELSE 0 END)', + 'services_unknown_unhandled' => 'SUM(CASE WHEN service_state = 3 AND service_handled = 0 THEN 1 ELSE 0 END)', + 'services_warning' => 'SUM(CASE WHEN service_state = 1 THEN 1 ELSE 0 END)', + 'services_warning_handled' => 'SUM(CASE WHEN service_state = 1 AND service_handled = 1 THEN 1 ELSE 0 END)', + 'services_warning_unhandled' => 'SUM(CASE WHEN service_state = 1 AND service_handled = 0 THEN 1 ELSE 0 END)', + ) + ); + + /** + * The union + * + * @var Zend_Db_Select + */ + protected $summaryQuery; + + /** + * Subqueries used for the summary query + * + * @var IdoQuery[] + */ + protected $subQueries = []; + + /** + * Count query + * + * @var IdoQuery + */ + protected $countQuery; + + public function addFilter(Filter $filter) + { + foreach ($this->subQueries as $sub) { + $sub->applyFilter(clone $filter); + } + $this->countQuery->applyFilter(clone $filter); + return $this; + } + + protected function joinBaseTables() + { + $this->countQuery = $this->createSubQuery( + 'Servicegroup', + array() + ); + $subQuery = $this->createSubQuery( + 'Servicegroup', + array( + 'servicegroup_alias', + 'servicegroup_name', + 'service_handled', + 'service_severity', + 'service_state' + ) + ); + $this->subQueries[] = $subQuery; + $emptyGroups = $this->createSubQuery( + 'Emptyservicegroup', + [ + 'servicegroup_alias', + 'servicegroup_name', + 'service_handled' => new Zend_Db_Expr('NULL'), + 'service_severity' => new Zend_Db_Expr('0'), + 'service_state' => new Zend_Db_Expr('NULL'), + ] + ); + $this->subQueries[] = $emptyGroups; + $this->summaryQuery = $this->db->select()->union( + [$subQuery, $emptyGroups], + Zend_Db_Select::SQL_UNION_ALL + ); + $this->select->from(['servicesgroupsummary' => $this->summaryQuery], []); + $this->group(['servicegroup_name', 'servicegroup_alias']); + $this->joinedVirtualTables['servicegroupsummary'] = true; + } + + public function getCountQuery() + { + $count = $this->countQuery->select(); + $this->countQuery->applyFilterSql($count); + $count->columns(array('sgo.object_id')); + $count->group(array('sgo.object_id')); + return $this->db->select()->from($count, array('cnt' => 'COUNT(*)')); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicenotificationQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicenotificationQuery.php new file mode 100644 index 0000000..1159e0c --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicenotificationQuery.php @@ -0,0 +1,287 @@ +<?php +/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Data\Filter\Filter; +use Icinga\Data\Filter\FilterExpression; + +/** + * Query for service notifications + */ +class ServicenotificationQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $allowCustomVars = true; + + protected $subQueryTargets = array( + 'hostgroups' => 'hostgroup', + 'servicegroups' => 'servicegroup' + ); + + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'contactnotifications' => array( + 'notification_contact_name' => 'co.name1' + ), + 'history' => array( + 'output' => null, + 'state' => 'sn.state', + 'timestamp' => 'UNIX_TIMESTAMP(sn.start_time)', + 'type' => ' + CASE sn.notification_reason + WHEN 1 THEN \'notification_ack\' + WHEN 2 THEN \'notification_flapping\' + WHEN 3 THEN \'notification_flapping_end\' + WHEN 5 THEN \'notification_dt_start\' + WHEN 6 THEN \'notification_dt_end\' + WHEN 7 THEN \'notification_dt_end\' + WHEN 8 THEN \'notification_custom\' + ELSE \'notification_state\' + END', + ), + 'hostgroups' => array( + 'hostgroup_name' => 'hgo.name1', + 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci', + 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci', + ), + 'hosts' => array( + 'host_display_name' => 'h.display_name COLLATE latin1_general_ci', + 'host_alias' => 'h.alias COLLATE latin1_general_ci', + ), + 'instances' => array( + 'instance_name' => 'i.instance_name' + ), + 'notifications' => array( + 'id' => 'sn.notification_id', + 'host' => 'so.name1 COLLATE latin1_general_ci', + 'host_name' => 'so.name1', + 'notification_output' => 'sn.output', + 'notification_reason' => 'sn.notification_reason', + 'notification_state' => 'sn.state', + 'notification_timestamp' => 'UNIX_TIMESTAMP(sn.start_time)', + 'object_type' => '(\'service\')', + 'service' => 'so.name2 COLLATE latin1_general_ci', + 'service_description' => 'so.name2', + 'service_host_name' => 'so.name1' + ), + 'servicegroups' => array( + 'servicegroup_name' => 'sgo.name1', + 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci', + 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci' + ), + 'services' => array( + 'service_display_name' => 's.display_name COLLATE latin1_general_ci' + ) + ); + + protected function requireFilterColumns(Filter $filter) + { + if ($filter instanceof FilterExpression) { + switch ($filter->getColumn()) { + case 'output': + $this->requireColumn('output'); + $filter->setColumn('sn.output'); + return null; + case 'timestamp': + case 'notification_timestamp': + $this->requireColumn($filter->getColumn()); + $filter->setColumn('sn.start_time'); + $filter->setExpression($this->timestampForSql($this->valueToTimestamp($filter->getExpression()))); + return null; + } + } + + return parent::requireFilterColumns($filter); + } + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + $concattedContacts = null; + switch ($this->ds->getDbType()) { + case 'mysql': + $concattedContacts = "GROUP_CONCAT(" + . "DISTINCT co.name1 ORDER BY co.name1 SEPARATOR ', '" + . ") COLLATE latin1_general_ci"; + break; + case 'pgsql': + // TODO: Find a way to order the contact alias list: + $concattedContacts = "ARRAY_TO_STRING(ARRAY_AGG(DISTINCT co.name1), ', ')"; + break; + } + $this->columnMap['history']['output'] = "('[' || $concattedContacts || '] ' || sn.output)"; + + $this->select->from( + array('sn' => $this->prefix . 'notifications'), + array() + )->join( + array('so' => $this->prefix . 'objects'), + 'so.object_id = sn.object_id AND so.is_active = 1 AND so.objecttype_id = 2', + array() + ); + $this->joinedVirtualTables['notifications'] = true; + } + + /** + * Join virtual table history + */ + protected function joinHistory() + { + $this->requireVirtualTable('contactnotifications'); + } + + /** + * Join contact notifications + */ + protected function joinContactnotifications() + { + $this->select->joinLeft( + array('cn' => $this->prefix . 'contactnotifications'), + 'cn.notification_id = sn.notification_id', + array() + ); + $this->select->joinLeft( + array('co' => $this->prefix . 'objects'), + 'co.object_id = cn.contact_object_id AND co.is_active = 1 AND co.objecttype_id = 10', + array() + ); + } + + /** + * Join host groups + */ + protected function joinHostgroups() + { + $this->requireVirtualTable('services'); + $this->select->joinLeft( + array('hgm' => $this->prefix . 'hostgroup_members'), + 'hgm.host_object_id = s.host_object_id', + array() + )->joinLeft( + array('hg' => $this->prefix . 'hostgroups'), + 'hg.hostgroup_id = hgm.hostgroup_id', + array() + )->joinLeft( + array('hgo' => $this->prefix . 'objects'), + 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3', + array() + ); + } + + /** + * Join hosts + */ + protected function joinHosts() + { + $this->requireVirtualTable('services'); + $this->select->join( + array('h' => $this->prefix . 'hosts'), + 'h.host_object_id = s.host_object_id', + array() + ); + } + + /** + * Join service groups + */ + protected function joinServicegroups() + { + $this->select->joinLeft( + array('sgm' => $this->prefix . 'servicegroup_members'), + 'sgm.service_object_id = so.object_id', + array() + )->joinLeft( + array('sg' => $this->prefix . 'servicegroups'), + 'sg.' . $this->servicegroup_id . ' = sgm.servicegroup_id', + array() + )->joinLeft( + array('sgo' => $this->prefix . 'objects'), + 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4', + array() + ); + } + + /** + * Join services + */ + protected function joinServices() + { + $this->select->join( + array('s' => $this->prefix . 'services'), + 's.service_object_id = so.object_id', + array() + ); + } + + /** + * Join instances + */ + protected function joinInstances() + { + $this->select->join( + array('i' => $this->prefix . 'instances'), + 'i.instance_id = sn.instance_id', + array() + ); + } + + /** + * {@inheritdoc} + */ + public function getGroup() + { + $group = array(); + + if ($this->hasJoinedVirtualTable('history') + || $this->hasJoinedVirtualTable('hostgroups') + || $this->hasJoinedVirtualTable('servicegroups') + ) { + $group = array('sn.notification_id', 'so.object_id'); + if ($this->hasJoinedVirtualTable('contactnotifications') && !$this->hasJoinedVirtualTable('history')) { + $group[] = 'co.object_id'; + } + } elseif ($this->hasJoinedVirtualTable('contactnotifications')) { + $group = array('sn.notification_id', 'co.object_id', 'so.object_id'); + } + + if (! empty($group)) { + if ($this->hasJoinedVirtualTable('hosts')) { + $group[] = 'h.host_id'; + } + + if ($this->hasJoinedVirtualTable('services')) { + $group[] = 's.service_id'; + } + + if ($this->hasJoinedVirtualTable('instances')) { + $group[] = 'i.instance_id'; + } + } + + return $group; + } + + protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter) + { + if ($name === 'hostgroup') { + $this->requireVirtualTable('services'); + + $query->joinVirtualTable('members'); + + return ['hgm.host_object_id', 's.host_object_id']; + } elseif ($name === 'servicegroup') { + $query->joinVirtualTable('members'); + + return ['sgm.service_object_id', 'so.object_id']; + } + + return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicestatehistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicestatehistoryQuery.php new file mode 100644 index 0000000..f93ca8a --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicestatehistoryQuery.php @@ -0,0 +1,220 @@ +<?php +/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Data\Filter\Filter; +use Icinga\Data\Filter\FilterExpression; + +/** + * Query for service state history records + */ +class ServicestatehistoryQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $allowCustomVars = true; + + /** + * {@inheritdoc} + */ + protected $groupBase = array('statehistory' => array('sh.statehistory_id', 'so.object_id')); + + /** + * {@inheritdoc} + */ + protected $groupOrigin = array('hostgroups', 'servicegroups'); + + /** + * Array to map type names to type ids for query optimization + * + * @var array + */ + protected $types = array( + 'soft_state' => 0, + 'hard_state' => 1 + ); + + protected $subQueryTargets = array( + 'hostgroups' => 'hostgroup', + 'servicegroups' => 'servicegroup' + ); + + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'hostgroups' => array( + 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci', + 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci', + 'hostgroup_name' => 'hgo.name1' + ), + 'hosts' => array( + 'host_alias' => 'h.alias', + 'host_display_name' => 'h.display_name COLLATE latin1_general_ci' + ), + 'instances' => array( + 'instance_name' => 'i.instance_name' + ), + 'servicegroups' => array( + 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci', + 'servicegroup_name' => 'sgo.name1', + 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci' + ), + 'services' => array( + 'service_display_name' => 's.display_name COLLATE latin1_general_ci' + ), + 'statehistory' => array( + 'id' => 'sh.statehistory_id', + 'host' => 'so.name1 COLLATE latin1_general_ci', + 'host_name' => 'so.name1', + 'object_id' => 'sh.object_id', + 'object_type' => '(\'service\')', + 'output' => '(CASE WHEN sh.state_type = 1 THEN sh.output ELSE \'[ \' || sh.current_check_attempt || \'/\' || sh.max_check_attempts || \' ] \' || sh.output END)', + 'service' => 'so.name2 COLLATE latin1_general_ci', + 'service_description' => 'so.name2', + 'service_host' => 'so.name1 COLLATE latin1_general_ci', + 'service_host_name' => 'so.name1', + 'state' => 'sh.state', + 'timestamp' => 'UNIX_TIMESTAMP(sh.state_time)', + 'type' => "(CASE WHEN sh.state_type = 1 THEN 'hard_state' ELSE 'soft_state' END)" + ), + ); + + protected function requireFilterColumns(Filter $filter) + { + if ($filter instanceof FilterExpression) { + switch ($filter->getColumn()) { + case 'timestamp': + $this->requireColumn('timestamp'); + $filter->setColumn('sh.state_time'); + $filter->setExpression($this->timestampForSql($this->valueToTimestamp($filter->getExpression()))); + return null; + case 'type': + if (! is_array($filter->getExpression())) { + $this->requireColumn('type'); + $filter->setColumn('sh.state_type'); + if (isset($this->types[$filter->getExpression()])) { + $filter->setExpression($this->types[$filter->getExpression()]); + } else { + $filter->setExpression(-1); + } + + return null; + } + } + } + + return parent::requireFilterColumns($filter); + } + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + $this->select->from( + array('sh' => $this->prefix . 'statehistory'), + array() + )->join( + array('so' => $this->prefix . 'objects'), + 'so.object_id = sh.object_id AND so.is_active = 1 AND so.objecttype_id = 2', + array() + ); + $this->joinedVirtualTables['statehistory'] = true; + } + + /** + * Join host groups + */ + protected function joinHostgroups() + { + $this->requireVirtualTable('services'); + $this->select->joinLeft( + array('hgm' => $this->prefix . 'hostgroup_members'), + 'hgm.host_object_id = s.host_object_id', + array() + )->joinLeft( + array('hg' => $this->prefix . 'hostgroups'), + 'hg.hostgroup_id = hgm.hostgroup_id', + array() + )->joinLeft( + array('hgo' => $this->prefix . 'objects'), + 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3', + array() + ); + } + + /** + * Join hosts + */ + protected function joinHosts() + { + $this->requireVirtualTable('services'); + $this->select->join( + array('h' => $this->prefix . 'hosts'), + 'h.host_object_id = s.host_object_id', + array() + ); + } + + /** + * Join instances + */ + protected function joinInstances() + { + $this->select->join( + array('i' => $this->prefix . 'instances'), + 'i.instance_id = sh.instance_id', + array() + ); + } + + /** + * Join service groups + */ + protected function joinServicegroups() + { + $this->select->joinLeft( + array('sgm' => $this->prefix . 'servicegroup_members'), + 'sgm.service_object_id = so.object_id', + array() + )->joinLeft( + array('sg' => $this->prefix . 'servicegroups'), + 'sg.' . $this->servicegroup_id . ' = sgm.servicegroup_id', + array() + )->joinLeft( + array('sgo' => $this->prefix . 'objects'), + 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4', + array() + ); + } + + /** + * Join services + */ + protected function joinServices() + { + $this->select->join( + array('s' => $this->prefix . 'services'), + 's.service_object_id = so.object_id', + array() + ); + } + + protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter) + { + if ($name === 'hostgroup') { + $query->joinVirtualTable('services'); + + return ['so.object_id', 'so.object_id']; + } elseif ($name === 'servicegroup') { + $query->joinVirtualTable('members'); + + return ['sgm.service_object_id', 'so.object_id']; + } + + return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicestatusQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicestatusQuery.php new file mode 100644 index 0000000..fafa03b --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicestatusQuery.php @@ -0,0 +1,524 @@ +<?php +/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +/** + * Query for service status + */ +class ServicestatusQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $allowCustomVars = true; + + /** + * {@inheritdoc} + */ + protected $groupBase = array('services' => array('so.object_id', 's.service_id')); + + /** + * {@inheritdoc} + */ + protected $groupOrigin = array('hostgroups', 'servicegroups', 'contacts', 'contactgroups'); + + protected $subQueryTargets = array( + 'hostgroups' => 'hostgroup', + 'servicegroups' => 'servicegroup' + ); + + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'checktimeperiods' => array( + 'service_check_timeperiod' => 'ctp.alias COLLATE latin1_general_ci' + ), + 'contacts' => [ + 'service_contact' => 'sco.name1' + ], + 'contactgroups' => [ + 'service_contactgroup' => 'scgo.name1' + ], + 'hostcontacts' => [ + 'host_contact' => 'hco.name1' + ], + 'hostcontactgroups' => [ + 'host_contactgroup' => 'hcgo.name1' + ], + 'hostgroups' => array( + 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci', + 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci', + 'hostgroup_name' => 'hgo.name1' + ), + 'hosts' => array( + 'host_action_url' => 'h.action_url', + 'host_address' => 'h.address', + 'host_address6' => 'h.address6', + 'host_alias' => 'h.alias COLLATE latin1_general_ci', + 'host_display_name' => 'h.display_name COLLATE latin1_general_ci', + 'host_icon_image' => 'h.icon_image', + 'host_icon_image_alt' => 'h.icon_image_alt', + 'host_ipv4' => 'INET_ATON(h.address)', + 'host_notes' => 'h.notes', + 'host_notes_url' => 'h.notes_url' + ), + 'hoststatus' => array( + 'host_acknowledged' => 'hs.problem_has_been_acknowledged', + 'host_acknowledgement_type' => 'hs.acknowledgement_type', + 'host_active_checks_enabled' => 'hs.active_checks_enabled', + 'host_active_checks_enabled_changed' => 'CASE WHEN hs.active_checks_enabled = h.active_checks_enabled THEN 0 ELSE 1 END', + 'host_attempt' => 'hs.current_check_attempt || \'/\' || hs.max_check_attempts', + 'host_check_command' => 'hs.check_command', + 'host_check_execution_time' => 'hs.execution_time', + 'host_check_latency' => 'hs.latency', + 'host_check_source' => 'hs.check_source', + 'host_check_timeperiod_object_id' => 'hs.check_timeperiod_object_id', + 'host_check_type' => 'hs.check_type', + 'host_current_check_attempt' => 'hs.current_check_attempt', + 'host_current_notification_number' => 'hs.current_notification_number', + 'host_event_handler' => 'hs.event_handler', + 'host_event_handler_enabled' => 'hs.event_handler_enabled', + 'host_event_handler_enabled_changed' => 'CASE WHEN hs.event_handler_enabled = h.event_handler_enabled THEN 0 ELSE 1 END', + 'host_failure_prediction_enabled' => 'hs.failure_prediction_enabled', + 'host_flap_detection_enabled' => 'hs.flap_detection_enabled', + 'host_flap_detection_enabled_changed' => 'CASE WHEN hs.flap_detection_enabled = h.flap_detection_enabled THEN 0 ELSE 1 END', + 'host_handled' => 'CASE WHEN (hs.problem_has_been_acknowledged + hs.scheduled_downtime_depth) > 0 THEN 1 ELSE 0 END', + 'host_hard_state' => 'CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 99 ELSE CASE WHEN hs.state_type = 1 THEN hs.current_state ELSE hs.last_hard_state END END', + 'host_in_downtime' => 'CASE WHEN (hs.scheduled_downtime_depth = 0) THEN 0 ELSE 1 END', + 'host_is_flapping' => 'hs.is_flapping', + 'host_is_reachable' => 'hs.is_reachable', + 'host_last_check' => 'UNIX_TIMESTAMP(hs.last_check)', + 'host_last_hard_state' => 'hs.last_hard_state', + 'host_last_hard_state_change' => 'UNIX_TIMESTAMP(hs.last_hard_state_change)', + 'host_last_notification' => 'UNIX_TIMESTAMP(hs.last_notification)', + 'host_last_state_change' => 'UNIX_TIMESTAMP(hs.last_state_change)', + 'host_last_time_down' => 'UNIX_TIMESTAMP(hs.last_time_down)', + 'host_last_time_unreachable' => 'UNIX_TIMESTAMP(hs.last_time_unreachable)', + 'host_last_time_up' => 'UNIX_TIMESTAMP(hs.last_time_up)', + 'host_long_output' => 'hs.long_output', + 'host_max_check_attempts' => 'hs.max_check_attempts', + 'host_modified_host_attributes' => 'hs.modified_host_attributes', + 'host_next_check' => 'CASE hs.should_be_scheduled WHEN 1 THEN UNIX_TIMESTAMP(hs.next_check) ELSE NULL END', + 'host_next_notification' => 'UNIX_TIMESTAMP(hs.next_notification)', + 'host_no_more_notifications' => 'hs.no_more_notifications', + 'host_normal_check_interval' => 'hs.normal_check_interval', + 'host_notifications_enabled' => 'hs.notifications_enabled', + 'host_notifications_enabled_changed' => 'CASE WHEN hs.notifications_enabled = h.notifications_enabled THEN 0 ELSE 1 END', + 'host_obsessing' => 'hs.obsess_over_host', + 'host_obsessing_changed' => 'CASE WHEN hs.obsess_over_host = h.obsess_over_host THEN 0 ELSE 1 END', + 'host_output' => 'hs.output', + 'host_passive_checks_enabled' => 'hs.passive_checks_enabled', + 'host_passive_checks_enabled_changed' => 'CASE WHEN hs.passive_checks_enabled = h.passive_checks_enabled THEN 0 ELSE 1 END', + 'host_percent_state_change' => 'hs.percent_state_change', + 'host_perfdata' => 'hs.perfdata', + 'host_problem' => 'CASE WHEN COALESCE(hs.current_state, 0) = 0 THEN 0 ELSE 1 END', + 'host_problem_has_been_acknowledged' => 'hs.problem_has_been_acknowledged', + 'host_process_performance_data' => 'hs.process_performance_data', + 'host_retry_check_interval' => 'hs.retry_check_interval', + 'host_scheduled_downtime_depth' => 'hs.scheduled_downtime_depth', + 'host_severity' => ' + CASE + WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL + THEN 16 + ELSE + CASE + WHEN hs.current_state = 0 + THEN 1 + ELSE + CASE + WHEN hs.current_state = 1 THEN 64 + WHEN hs.current_state = 2 THEN 32 + ELSE 256 + END + + + CASE + WHEN hs.problem_has_been_acknowledged = 1 THEN 2 + WHEN hs.scheduled_downtime_depth > 0 THEN 1 + ELSE 256 + END + END + END', + 'host_state' => 'CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 99 ELSE hs.current_state END', + 'host_state_type' => 'hs.state_type', + 'host_status_update_time' => 'hs.status_update_time', + 'host_unhandled' => 'CASE WHEN (hs.problem_has_been_acknowledged + hs.scheduled_downtime_depth) = 0 THEN 1 ELSE 0 END' + + ), + 'instances' => array( + 'instance_name' => 'i.instance_name' + ), + 'services' => array( + 'host' => 'so.name1 COLLATE latin1_general_ci', + 'host_name' => 'so.name1', + 'object_type' => '(\'service\')', + 'service' => 'so.name2 COLLATE latin1_general_ci', + 'service_action_url' => 's.action_url', + 'service_check_interval' => '(s.check_interval * 60)', + 'service_description' => 'so.name2', + 'service_display_name' => 's.display_name COLLATE latin1_general_ci', + 'service_host' => 'so.name1 COLLATE latin1_general_ci', + 'service_host_name' => 'so.name1', + 'service_icon_image' => 's.icon_image', + 'service_icon_image_alt' => 's.icon_image_alt', + 'service_notes_url' => 's.notes_url', + 'service_notes' => 's.notes' + ), + 'servicegroups' => array( + 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci', + 'servicegroup_name' => 'sgo.name1', + 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci' + ), + 'servicestatus' => array( + 'service_acknowledged' => 'ss.problem_has_been_acknowledged', + 'service_acknowledgement_type' => 'ss.acknowledgement_type', + 'service_active_checks_enabled' => 'ss.active_checks_enabled', + 'service_active_checks_enabled_changed' => 'CASE WHEN ss.active_checks_enabled=s.active_checks_enabled THEN 0 ELSE 1 END', + 'service_attempt' => 'ss.current_check_attempt || \'/\' || ss.max_check_attempts', + 'service_check_command' => 'ss.check_command', + 'service_check_execution_time' => 'ss.execution_time', + 'service_check_latency' => 'ss.latency', + 'service_check_source' => 'ss.check_source', + 'service_check_timeperiod_object_id' => 'ss.check_timeperiod_object_id', + 'service_check_type' => 'ss.check_type', + 'service_current_check_attempt' => 'ss.current_check_attempt', + 'service_current_notification_number' => 'ss.current_notification_number', + 'service_event_handler' => 'ss.event_handler', + 'service_event_handler_enabled' => 'ss.event_handler_enabled', + 'service_event_handler_enabled_changed' => 'CASE WHEN ss.event_handler_enabled=s.event_handler_enabled THEN 0 ELSE 1 END', + 'service_failure_prediction_enabled' => 'ss.failure_prediction_enabled', + 'service_flap_detection_enabled' => 'ss.flap_detection_enabled', + 'service_flap_detection_enabled_changed' => 'CASE WHEN ss.flap_detection_enabled=s.flap_detection_enabled THEN 0 ELSE 1 END', + 'service_handled' => 'CASE WHEN (ss.problem_has_been_acknowledged + ss.scheduled_downtime_depth + COALESCE(hs.current_state, 0)) > 0 THEN 1 ELSE 0 END', + 'service_hard_state' => 'CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 99 ELSE CASE WHEN ss.state_type = 1 THEN ss.current_state ELSE ss.last_hard_state END END', + 'service_in_downtime' => 'CASE WHEN (ss.scheduled_downtime_depth = 0 OR ss.scheduled_downtime_depth IS NULL) THEN 0 ELSE 1 END', + 'service_is_flapping' => 'ss.is_flapping', + 'service_is_passive_checked' => 'CASE WHEN ss.active_checks_enabled = 0 AND ss.passive_checks_enabled = 1 THEN 1 ELSE 0 END', + 'service_is_reachable' => 'ss.is_reachable', + 'service_last_check' => 'UNIX_TIMESTAMP(ss.last_check)', + 'service_last_hard_state' => 'ss.last_hard_state', + 'service_last_hard_state_change' => 'UNIX_TIMESTAMP(ss.last_hard_state_change)', + 'service_last_notification' => 'UNIX_TIMESTAMP(ss.last_notification)', + 'service_last_state_change' => 'UNIX_TIMESTAMP(ss.last_state_change)', + 'service_last_state_change_ts' => 'ss.last_state_change', + 'service_last_time_critical' => 'ss.last_time_critical', + 'service_last_time_ok' => 'ss.last_time_ok', + 'service_last_time_unknown' => 'ss.last_time_unknown', + 'service_last_time_warning' => 'ss.last_time_warning', + 'service_long_output' => 'ss.long_output', + 'service_max_check_attempts' => 'ss.max_check_attempts', + 'service_modified_service_attributes' => 'ss.modified_service_attributes', + 'service_next_check' => 'UNIX_TIMESTAMP(ss.next_check)', + 'service_next_notification' => 'UNIX_TIMESTAMP(ss.next_notification)', + 'service_next_update' => 'CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL + THEN + CASE ss.should_be_scheduled WHEN 1 THEN UNIX_TIMESTAMP(ss.next_check) + (ss.normal_check_interval * 60) ELSE NULL END + ELSE + UNIX_TIMESTAMP(ss.next_check) + + (CASE WHEN + COALESCE(ss.current_state, 0) > 0 AND ss.state_type = 0 + THEN + ss.retry_check_interval + ELSE + ss.normal_check_interval + END * 60) + + (CEIL(ss.execution_time + ss.latency) * 2) + END', + 'service_no_more_notifications' => 'ss.no_more_notifications', + 'service_normal_check_interval' => 'ss.normal_check_interval', + 'service_notifications_enabled' => 'ss.notifications_enabled', + 'service_notifications_enabled_changed' => 'CASE WHEN ss.notifications_enabled=s.notifications_enabled THEN 0 ELSE 1 END', + 'service_obsessing' => 'ss.obsess_over_service', + 'service_obsessing_changed' => 'CASE WHEN ss.obsess_over_service=s.obsess_over_service THEN 0 ELSE 1 END', + 'service_output' => 'ss.output', + 'service_passive_checks_enabled' => 'ss.passive_checks_enabled', + 'service_passive_checks_enabled_changed' => 'CASE WHEN ss.passive_checks_enabled=s.passive_checks_enabled THEN 0 ELSE 1 END', + 'service_percent_state_change' => 'ss.percent_state_change', + 'service_perfdata' => 'ss.perfdata', + 'service_problem' => 'CASE WHEN COALESCE(ss.current_state, 0) = 0 THEN 0 ELSE 1 END', + 'service_problem_has_been_acknowledged' => 'ss.problem_has_been_acknowledged', + 'service_process_performance_data' => 'ss.process_performance_data', + 'service_retry_check_interval' => 'ss.retry_check_interval', + 'service_scheduled_downtime_depth' => 'ss.scheduled_downtime_depth', + 'service_severity' => 'CASE WHEN ss.current_state = 0 + THEN + CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL + THEN 16 + ELSE 0 + END + + + CASE WHEN ss.problem_has_been_acknowledged = 1 + THEN 2 + ELSE + CASE WHEN ss.scheduled_downtime_depth > 0 + THEN 1 + ELSE 4 + END + END + ELSE + CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 16 + WHEN ss.current_state = 1 THEN 32 + WHEN ss.current_state = 2 THEN 128 + WHEN ss.current_state = 3 THEN 64 + ELSE 256 + END + + + CASE WHEN hs.current_state > 0 + THEN 1024 + ELSE + CASE WHEN ss.problem_has_been_acknowledged = 1 + THEN 512 + ELSE + CASE WHEN ss.scheduled_downtime_depth > 0 + THEN 256 + ELSE 2048 + END + END + END + END', + 'service_state' => 'CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 99 ELSE ss.current_state END', + 'service_state_type' => 'ss.state_type', + 'service_status_update_time' => 'ss.status_update_time', + 'service_unhandled' => 'CASE WHEN (ss.problem_has_been_acknowledged + ss.scheduled_downtime_depth + COALESCE(hs.current_state, 0)) = 0 THEN 1 ELSE 0 END', + 'problems' => 'CASE WHEN COALESCE(ss.current_state, 0) = 0 THEN 0 ELSE 1 END' + ) + ); + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + if (version_compare($this->getIdoVersion(), '1.10.0', '<')) { + $this->columnMap['hoststatus']['host_check_source'] = '(NULL)'; + $this->columnMap['servicestatus']['service_check_source'] = '(NULL)'; + } + if (version_compare($this->getIdoVersion(), '1.13.0', '<')) { + $this->columnMap['hoststatus']['host_is_reachable'] = '(NULL)'; + $this->columnMap['servicestatus']['service_is_reachable'] = '(NULL)'; + } + + $this->select->from( + array('so' => $this->prefix . 'objects'), + array() + )->join( + array('s' => $this->prefix . 'services'), + 's.service_object_id = so.object_id AND so.is_active = 1 AND so.objecttype_id = 2', + array() + ); + $this->joinedVirtualTables['services'] = true; + } + + /** + * Join check time periods + */ + protected function joinChecktimeperiods() + { + $this->select->joinLeft( + array('ctp' => $this->prefix . 'timeperiods'), + 'ctp.timeperiod_object_id = s.check_timeperiod_object_id', + array() + ); + } + + /** + * Join contacts + */ + protected function joinContacts() + { + $this->select->joinLeft( + ['sc' => 'icinga_service_contacts'], + 'sc.service_id = s.service_id', + [] + )->joinLeft( + ['sco' => 'icinga_objects'], + 'sco.object_id = sc.contact_object_id AND sco.is_active = 1 AND sco.objecttype_id = 10', + [] + ); + } + + /** + * Join contact groups + */ + protected function joinContactgroups() + { + $this->select->joinLeft( + ['scg' => 'icinga_service_contactgroups'], + 'scg.service_id = s.service_id', + [] + )->joinLeft( + ['scgo' => 'icinga_objects'], + 'scgo.object_id = scg.contactgroup_object_id AND scgo.is_active = 1 AND scgo.objecttype_id = 11', + [] + ); + } + + /** + * Join host contacts + */ + protected function joinHostcontacts() + { + $this->requireVirtualTable('hosts'); + + $this->select->joinLeft( + ['hc' => 'icinga_host_contacts'], + 'hc.host_id = h.host_id', + [] + )->joinLeft( + ['hco' => 'icinga_objects'], + 'hco.object_id = hc.contact_object_id AND hco.is_active = 1 AND hco.objecttype_id = 10', + [] + ); + } + + /** + * Join host contact groups + */ + protected function joinHostcontactgroups() + { + $this->requireVirtualTable('hosts'); + + $this->select->joinLeft( + ['hcg' => 'icinga_host_contactgroups'], + 'hcg.host_id = h.host_id', + [] + )->joinLeft( + ['hcgo' => 'icinga_objects'], + 'hcgo.object_id = hcg.contactgroup_object_id AND hcgo.is_active = 1 AND hcgo.objecttype_id = 11', + [] + ); + } + + /** + * Join host groups + */ + protected function joinHostgroups() + { + $this->select->joinLeft( + array('hgm' => $this->prefix . 'hostgroup_members'), + 'hgm.host_object_id = s.host_object_id', + array() + )->joinLeft( + array('hg' => $this->prefix . 'hostgroups'), + 'hg.hostgroup_id = hgm.hostgroup_id', + array() + )->joinLeft( + array('hgo' => $this->prefix . 'objects'), + 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3', + array() + ); + } + + /** + * Join hosts + */ + protected function joinHosts() + { + $this->select->join( + array('h' => $this->prefix . 'hosts'), + 'h.host_object_id = s.host_object_id', + array() + ); + } + + /** + * Join host status + */ + protected function joinHoststatus() + { + $this->select->join( + array('hs' => $this->prefix . 'hoststatus'), + 'hs.host_object_id = s.host_object_id', + array() + ); + } + + /** + * Join instances + */ + protected function joinInstances() + { + $this->select->join( + array('i' => $this->prefix . 'instances'), + 'i.instance_id = so.instance_id', + array() + ); + } + + /** + * Join service groups + */ + protected function joinServicegroups() + { + $this->select->joinLeft( + array('sgm' => $this->prefix . 'servicegroup_members'), + 'sgm.service_object_id = so.object_id', + array() + )->joinLeft( + array('sg' => $this->prefix . 'servicegroups'), + 'sg.servicegroup_id = sgm.servicegroup_id', + array() + )->joinLeft( + array('sgo' => $this->prefix . 'objects'), + 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4', + array() + ); + } + + /** + * Join service status + */ + protected function joinServicestatus() + { + $this->requireVirtualTable('hoststatus'); + $this->select->join( + array('ss' => $this->prefix . 'servicestatus'), + 'ss.service_object_id = so.object_id', + array() + ); + } + + /** + * {@inheritdoc} + */ + protected function registerGroupColumns($alias, $table, array &$groupedColumns, array &$groupedTables) + { + if ($alias === 'service_handled' || $alias === 'service_severity' || $alias === 'service_unhandled') { + if (! isset($groupedTables['hoststatus'])) { + $groupedColumns[] = 'hs.hoststatus_id'; + $groupedTables['hoststatus'] = true; + } + + if (! isset($groupedTables['servicestatus'])) { + $groupedColumns[] = 'ss.servicestatus_id'; + $groupedTables['servicestatus'] = true; + } + } elseif ($table === 'contacts') { + $groupedColumns[] = 'sc.service_contact_id'; + $groupedColumns[] = 'sco.object_id'; + $groupedTables[$table] = true; + } elseif ($table === 'contactgroups') { + $groupedColumns[] = 'scg.service_contactgroup_id'; + $groupedColumns[] = 'scgo.object_id'; + $groupedTables[$table] = true; + } else { + parent::registerGroupColumns($alias, $table, $groupedColumns, $groupedTables); + } + } + + protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter) + { + if ($name === 'hostgroup') { + $query->joinVirtualTable('members'); + + return ['hgm.host_object_id', 's.host_object_id']; + } elseif ($name === 'servicegroup') { + $query->joinVirtualTable('members'); + + return ['sgm.service_object_id', 'so.object_id']; + } + + return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicestatussummaryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicestatussummaryQuery.php new file mode 100644 index 0000000..4455c3f --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicestatussummaryQuery.php @@ -0,0 +1,104 @@ +<?php +/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Data\Filter\Filter; +use Icinga\Data\Filter\FilterExpression; + +/** + * Query for service status summary + * + * TODO(el): Allow to switch between hard and soft states + */ +class ServicestatussummaryQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'servicestatussummary' => array( + 'services_critical' => 'SUM(CASE WHEN state = 2 THEN 1 ELSE 0 END)', + 'services_critical_handled' => 'SUM(CASE WHEN state = 2 AND handled = 1 THEN 1 ELSE 0 END)', +// 'services_critical_handled_last_state_change' => 'MAX(CASE WHEN state = 2 AND handled = 1 THEN UNIX_TIMESTAMP(last_state_change) ELSE NULL END)', + 'services_critical_unhandled' => 'SUM(CASE WHEN state = 2 AND handled = 0 THEN 1 ELSE 0 END)', +// 'services_critical_unhandled_last_state_change' => 'MAX(CASE WHEN state = 2 AND handled = 0 THEN UNIX_TIMESTAMP(last_state_change) ELSE NULL END)', + 'services_ok' => 'SUM(CASE WHEN state = 0 THEN 1 ELSE 0 END)', +// 'services_ok_last_state_change' => 'MAX(CASE WHEN state = 0 THEN UNIX_TIMESTAMP(last_state_change) ELSE NULL END)', + 'services_pending' => 'SUM(CASE WHEN state = 99 THEN 1 ELSE 0 END)', +// 'services_pending_last_state_change' => 'MAX(CASE WHEN state = 99 THEN UNIX_TIMESTAMP(last_state_change) ELSE NULL END)', + 'services_total' => 'SUM(1)', + 'services_unknown' => 'SUM(CASE WHEN state = 3 THEN 1 ELSE 0 END)', + 'services_unknown_handled' => 'SUM(CASE WHEN state = 3 AND handled = 1 THEN 1 ELSE 0 END)', +// 'services_unknown_handled_last_state_change' => 'MAX(CASE WHEN state = 3 AND handled = 1 THEN UNIX_TIMESTAMP(last_state_change) ELSE NULL END)', + 'services_unknown_unhandled' => 'SUM(CASE WHEN state = 3 AND handled = 0 THEN 1 ELSE 0 END)', +// 'services_unknown_unhandled_last_state_change' => 'MAX(CASE WHEN state = 3 AND handled = 0 THEN UNIX_TIMESTAMP(last_state_change) ELSE NULL END)', + 'services_warning' => 'SUM(CASE WHEN state = 1 THEN 1 ELSE 0 END)', + 'services_warning_handled' => 'SUM(CASE WHEN state = 1 AND handled = 1 THEN 1 ELSE 0 END)', +// 'services_warning_handled_last_state_change' => 'MAX(CASE WHEN state = 1 AND handled = 1 THEN UNIX_TIMESTAMP(last_state_change) ELSE NULL END)', + 'services_warning_unhandled' => 'SUM(CASE WHEN state = 1 AND handled = 0 THEN 1 ELSE 0 END)', +// 'services_warning_unhandled_last_state_change' => 'MAX(CASE WHEN state = 1 AND handled = 0 THEN UNIX_TIMESTAMP(last_state_change) ELSE NULL END)' + ) + ); + + /** + * The service status sub select + * + * @var ServicestatusQuery + */ + protected $subSelect; + + /** + * {@inheritdoc} + */ + public function allowsCustomVars() + { + return $this->subSelect->allowsCustomVars(); + } + + /** + * {@inheritdoc} + */ + public function addFilter(Filter $filter) + { + $this->subSelect->applyFilter(clone $filter); + return $this; + } + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + // TODO(el): Allow to switch between hard and soft states + $this->subSelect = $this->createSubQuery( + 'servicestatus', + array( + 'handled' => 'service_handled', + 'state' => 'service_state', + 'state_change' => 'service_last_state_change' + ) + ); + $this->select->from( + array('servicestatussummary' => $this->subSelect->setIsSubQuery(true)), + array() + ); + $this->joinedVirtualTables['servicestatussummary'] = true; + } + + /** + * {@inheritdoc} + */ + public function where($condition, $value = null) + { + $this->subSelect->where($condition, $value); + return $this; + } + + public function whereEx(FilterExpression $ex) + { + $this->subSelect->whereEx($ex); + + return $this; + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatechangeeventQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatechangeeventQuery.php new file mode 100644 index 0000000..18d893f --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatechangeeventQuery.php @@ -0,0 +1,41 @@ +<?php +/* Icinga Web 2 | (c) 2017 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +/** + * Query for host and service state change events + */ +class StatechangeeventQuery extends IdoQuery +{ + protected $columnMap = array( + 'statechangeevent' => array( + 'statechangeevent_id' => 'sh.statehistory_id', + 'statechangeevent_state_time' => 'UNIX_TIMESTAMP(sh.state_time)', + 'statechangeevent_state_change' => 'sh.state_change', + 'statechangeevent_state' => 'sh.state', + 'statechangeevent_state_type' => "(CASE sh.state_type WHEN 0 THEN 'soft_state' WHEN 1 THEN 'hard_state' ELSE NULL END)", + 'statechangeevent_current_check_attempt' => 'sh.current_check_attempt', + 'statechangeevent_max_check_attempts' => 'sh.max_check_attempts', + 'statechangeevent_last_state' => 'sh.last_state', + 'statechangeevent_last_hard_state' => 'sh.last_hard_state', + 'statechangeevent_output' => 'sh.output', + 'statechangeevent_long_output' => 'sh.long_output', + 'statechangeevent_check_source' => 'sh.check_source' + ), + 'object' => array( + 'host_name' => 'o.name1', + 'service_description' => 'o.name2' + ) + ); + + protected function joinBaseTables() + { + $this->select() + ->from(array('sh' => $this->prefix . 'statehistory'), array()) + ->join(array('o' => $this->prefix . 'objects'), 'sh.object_id = o.object_id', array()); + + $this->joinedVirtualTables['statechangeevent'] = true; + $this->joinedVirtualTables['object'] = true; + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatehistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatehistoryQuery.php new file mode 100644 index 0000000..56d1e3b --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatehistoryQuery.php @@ -0,0 +1,179 @@ +<?php +/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Data\Filter\FilterExpression; +use Zend_Db_Expr; +use Zend_Db_Select; +use Icinga\Data\Filter\Filter; + +/** + * Query for host and service state history records + */ +class StatehistoryQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'statehistory' => array( + 'id' => 'sth.id', + 'object_type' => 'sth.object_type' + ), + 'history' => array( + 'type' => 'sth.type', + 'timestamp' => 'sth.timestamp', + 'object_id' => 'sth.object_id', + 'state' => 'sth.state', + 'output' => 'sth.output' + ), + 'hosts' => array( + 'host_display_name' => 'sth.host_display_name', + 'host_name' => 'sth.host_name' + ), + 'services' => array( + 'service_description' => 'sth.service_description', + 'service_display_name' => 'sth.service_display_name', + 'service_host_name' => 'sth.service_host_name' + ) + ); + + /** + * The union + * + * @var Zend_Db_Select + */ + protected $stateHistoryQuery; + + /** + * Subqueries used for the state history query + * + * @var IdoQuery[] + */ + protected $subQueries = array(); + + /** + * Whether to additionally select all history columns + * + * @var bool + */ + protected $fetchHistoryColumns = false; + + /** + * {@inheritdoc} + */ + public function allowsCustomVars() + { + foreach ($this->subQueries as $query) { + if (! $query->allowsCustomVars()) { + return false; + } + } + + return true; + } + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + $this->stateHistoryQuery = $this->db->select(); + $this->select->from( + array('sth' => $this->stateHistoryQuery), + array() + ); + $this->joinedVirtualTables['statehistory'] = true; + } + + /** + * Join history related columns and tables + */ + protected function joinHistory() + { + // TODO: Ensure that one is selecting the history columns first... + $this->fetchHistoryColumns = true; + $this->requireVirtualTable('hosts'); + $this->requireVirtualTable('services'); + } + + /** + * Join hosts + */ + protected function joinHosts() + { + $columns = array_keys( + $this->columnMap['statehistory'] + $this->columnMap['hosts'] + ); + foreach ($this->columnMap['services'] as $column => $_) { + $columns[$column] = new Zend_Db_Expr('NULL'); + } + if ($this->fetchHistoryColumns) { + $columns = array_merge($columns, array_keys($this->columnMap['history'])); + } + $hosts = $this->createSubQuery('Hoststatehistory', $columns); + $this->subQueries[] = $hosts; + $this->stateHistoryQuery->union(array($hosts), Zend_Db_Select::SQL_UNION_ALL); + } + + /** + * Join services + */ + protected function joinServices() + { + $columns = array_keys( + $this->columnMap['statehistory'] + $this->columnMap['hosts'] + $this->columnMap['services'] + ); + if ($this->fetchHistoryColumns) { + $columns = array_merge($columns, array_keys($this->columnMap['history'])); + } + $services = $this->createSubQuery('Servicestatehistory', $columns); + $this->subQueries[] = $services; + $this->stateHistoryQuery->union(array($services), Zend_Db_Select::SQL_UNION_ALL); + } + + /** + * {@inheritdoc} + */ + public function order($columnOrAlias, $dir = null) + { + foreach ($this->subQueries as $sub) { + $sub->requireColumn($columnOrAlias); + } + return parent::order($columnOrAlias, $dir); + } + + /** + * {@inheritdoc} + */ + public function where($condition, $value = null) + { + $this->requireColumn($condition); + foreach ($this->subQueries as $sub) { + $sub->where($condition, $value); + } + return $this; + } + + /** + * {@inheritdoc} + */ + public function addFilter(Filter $filter) + { + foreach ($this->subQueries as $sub) { + $sub->applyFilter(clone $filter); + } + return $this; + } + + public function whereEx(FilterExpression $ex) + { + $this->requireColumn($ex->getColumn()); + foreach ($this->subQueries as $sub) { + $sub->whereEx($ex); + } + + return $this; + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatussummaryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatussummaryQuery.php new file mode 100644 index 0000000..b1ee9e2 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatussummaryQuery.php @@ -0,0 +1,243 @@ +<?php +/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Data\Filter\FilterExpression; +use Zend_Db_Expr; +use Zend_Db_Select; +use Icinga\Data\Filter\Filter; + +/** + * Query for host and service status summary + */ +class StatussummaryQuery extends IdoQuery +{ + /** + * {@inheritdoc} + */ + protected $columnMap = array( + 'hoststatussummary' => array( + 'hosts_total' => 'SUM(CASE WHEN object_type = \'host\' THEN 1 ELSE 0 END)', + 'hosts_up' => 'SUM(CASE WHEN object_type = \'host\' AND state = 0 THEN 1 ELSE 0 END)', + 'hosts_up_not_checked' => 'SUM(CASE WHEN object_type = \'host\' AND state = 0 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)', + 'hosts_pending' => 'SUM(CASE WHEN object_type = \'host\' AND state = 99 THEN 1 ELSE 0 END)', + 'hosts_pending_not_checked' => 'SUM(CASE WHEN object_type = \'host\' AND state = 99 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)', + 'hosts_down' => 'SUM(CASE WHEN object_type = \'host\' AND state = 1 THEN 1 ELSE 0 END)', + 'hosts_down_handled' => 'SUM(CASE WHEN object_type = \'host\' AND state = 1 AND handled > 0 THEN 1 ELSE 0 END)', + 'hosts_down_unhandled' => 'SUM(CASE WHEN object_type = \'host\' AND state = 1 AND handled = 0 THEN 1 ELSE 0 END)', + 'hosts_down_passive' => 'SUM(CASE WHEN object_type = \'host\' AND state = 1 AND is_passive_checked = 1 THEN 1 ELSE 0 END)', + 'hosts_down_not_checked' => 'SUM(CASE WHEN object_type = \'host\' AND state = 1 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)', + 'hosts_unreachable' => 'SUM(CASE WHEN object_type = \'host\' AND state = 2 THEN 1 ELSE 0 END)', + 'hosts_unreachable_handled' => 'SUM(CASE WHEN object_type = \'host\' AND state = 2 AND handled > 0 THEN 1 ELSE 0 END)', + 'hosts_unreachable_unhandled' => 'SUM(CASE WHEN object_type = \'host\' AND state = 2 AND handled = 0 THEN 1 ELSE 0 END)', + 'hosts_unreachable_passive' => 'SUM(CASE WHEN object_type = \'host\' AND state = 2 AND is_passive_checked = 1 THEN 1 ELSE 0 END)', + 'hosts_unreachable_not_checked' => 'SUM(CASE WHEN object_type = \'host\' AND state = 2 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)', + 'hosts_active' => 'SUM(CASE WHEN object_type = \'host\' AND is_active_checked = 1 THEN 1 ELSE 0 END)', + 'hosts_passive' => 'SUM(CASE WHEN object_type = \'host\' AND is_passive_checked = 1 THEN 1 ELSE 0 END)', + 'hosts_not_checked' => 'SUM(CASE WHEN object_type = \'host\' AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)', + 'hosts_not_processing_event_handlers' => 'SUM(CASE WHEN object_type = \'host\' AND is_processing_events = 0 THEN 1 ELSE 0 END)', + 'hosts_not_triggering_notifications' => 'SUM(CASE WHEN object_type = \'host\' AND is_triggering_notifications = 0 THEN 1 ELSE 0 END)', + 'hosts_without_flap_detection' => 'SUM(CASE WHEN object_type = \'host\' AND is_allowed_to_flap = 0 THEN 1 ELSE 0 END)', + 'hosts_flapping' => 'SUM(CASE WHEN object_type = \'host\' AND is_flapping = 1 THEN 1 ELSE 0 END)' + ), + 'servicestatussummary' => array( + 'services_total' => 'SUM(CASE WHEN object_type = \'service\' THEN 1 ELSE 0 END)', + 'services_problem' => 'SUM(CASE WHEN object_type = \'service\' AND state > 0 THEN 1 ELSE 0 END)', + 'services_problem_handled' => 'SUM(CASE WHEN object_type = \'service\' AND state > 0 AND handled + host_problem > 0 THEN 1 ELSE 0 END)', + 'services_problem_unhandled' => 'SUM(CASE WHEN object_type = \'service\' AND state > 0 AND handled + host_problem = 0 THEN 1 ELSE 0 END)', + 'services_ok' => 'SUM(CASE WHEN object_type = \'service\' AND state = 0 THEN 1 ELSE 0 END)', + 'services_ok_not_checked' => 'SUM(CASE WHEN object_type = \'service\' AND state = 0 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)', + 'services_pending' => 'SUM(CASE WHEN object_type = \'service\' AND state = 99 THEN 1 ELSE 0 END)', + 'services_pending_not_checked' => 'SUM(CASE WHEN object_type = \'service\' AND state = 99 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)', + 'services_warning' => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 THEN 1 ELSE 0 END)', + 'services_warning_handled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 AND handled + host_problem > 0 THEN 1 ELSE 0 END)', + 'services_warning_unhandled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 AND handled + host_problem = 0 THEN 1 ELSE 0 END)', + 'services_warning_passive' => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 AND is_passive_checked = 1 THEN 1 ELSE 0 END)', + 'services_warning_not_checked' => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)', + 'services_critical' => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 THEN 1 ELSE 0 END)', + 'services_critical_handled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 AND handled + host_problem > 0 THEN 1 ELSE 0 END)', + 'services_critical_unhandled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 AND handled + host_problem = 0 THEN 1 ELSE 0 END)', + 'services_critical_passive' => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 AND is_passive_checked = 1 THEN 1 ELSE 0 END)', + 'services_critical_not_checked' => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)', + 'services_unknown' => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 THEN 1 ELSE 0 END)', + 'services_unknown_handled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 AND handled + host_problem > 0 THEN 1 ELSE 0 END)', + 'services_unknown_unhandled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 AND handled + host_problem = 0 THEN 1 ELSE 0 END)', + 'services_unknown_passive' => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 AND is_passive_checked = 1 THEN 1 ELSE 0 END)', + 'services_unknown_not_checked' => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)', + 'services_active' => 'SUM(CASE WHEN object_type = \'service\' AND is_active_checked = 1 THEN 1 ELSE 0 END)', + 'services_passive' => 'SUM(CASE WHEN object_type = \'service\' AND is_passive_checked = 1 THEN 1 ELSE 0 END)', + 'services_not_checked' => 'SUM(CASE WHEN object_type = \'service\' AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)', + 'services_not_processing_event_handlers' => 'SUM(CASE WHEN object_type = \'service\' AND is_processing_events = 0 THEN 1 ELSE 0 END)', + 'services_not_triggering_notifications' => 'SUM(CASE WHEN object_type = \'service\' AND is_triggering_notifications = 0 THEN 1 ELSE 0 END)', + 'services_without_flap_detection' => 'SUM(CASE WHEN object_type = \'service\' AND is_allowed_to_flap = 0 THEN 1 ELSE 0 END)', + 'services_flapping' => 'SUM(CASE WHEN object_type = \'service\' AND is_flapping = 1 THEN 1 ELSE 0 END)', + +/* +NOTE: in case you might wonder, please see #7303. As a quickfix I did: + +:%s/(host_state = 0 OR host_state = 99)/host_state != 1 AND host_state != 2/g +:%s/(host_state = 1 OR host_state = 2)/host_state != 0 AND host_state != 99/g + +We have to find a better solution here. + +*/ + 'services_ok_on_ok_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 1 AND host_state != 2 AND state = 0 THEN 1 ELSE 0 END)', + 'services_ok_not_checked_on_ok_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 1 AND host_state != 2 AND state = 0 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)', + 'services_pending_on_ok_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 1 AND host_state != 2 AND state = 99 THEN 1 ELSE 0 END)', + 'services_pending_not_checked_on_ok_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 1 AND host_state != 2 AND state = 99 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)', + 'services_warning_handled_on_ok_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 1 AND host_state != 2 AND state = 1 AND handled > 0 THEN 1 ELSE 0 END)', + 'services_warning_unhandled_on_ok_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 1 AND host_state != 2 AND state = 1 AND handled = 0 THEN 1 ELSE 0 END)', + 'services_warning_passive_on_ok_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 1 AND host_state != 2 AND state = 1 AND is_passive_checked = 1 THEN 1 ELSE 0 END)', + 'services_warning_not_checked_on_ok_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 1 AND host_state != 2 AND state = 1 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)', + 'services_critical_handled_on_ok_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 1 AND host_state != 2 AND state = 2 AND handled > 0 THEN 1 ELSE 0 END)', + 'services_critical_unhandled_on_ok_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 1 AND host_state != 2 AND state = 2 AND handled = 0 THEN 1 ELSE 0 END)', + 'services_critical_passive_on_ok_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 1 AND host_state != 2 AND state = 2 AND is_passive_checked = 1 THEN 1 ELSE 0 END)', + 'services_critical_not_checked_on_ok_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 1 AND host_state != 2 AND state = 2 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)', + 'services_unknown_handled_on_ok_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 1 AND host_state != 2 AND state = 3 AND handled > 0 THEN 1 ELSE 0 END)', + 'services_unknown_unhandled_on_ok_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 1 AND host_state != 2 AND state = 3 AND handled = 0 THEN 1 ELSE 0 END)', + 'services_unknown_passive_on_ok_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 1 AND host_state != 2 AND state = 3 AND is_passive_checked = 1 THEN 1 ELSE 0 END)', + 'services_unknown_not_checked_on_ok_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 1 AND host_state != 2 AND state = 3 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)', + 'services_ok_on_problem_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 0 AND host_state != 99 AND state = 0 THEN 1 ELSE 0 END)', + 'services_ok_not_checked_on_problem_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 0 AND host_state != 99 AND state = 0 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)', + 'services_pending_on_problem_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 0 AND host_state != 99 AND state = 99 THEN 1 ELSE 0 END)', + 'services_pending_not_checked_on_problem_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 0 AND host_state != 99 AND state = 99 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)', + 'services_warning_handled_on_problem_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 0 AND host_state != 99 AND state = 1 AND handled > 0 THEN 1 ELSE 0 END)', + 'services_warning_unhandled_on_problem_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 0 AND host_state != 99 AND state = 1 AND handled = 0 THEN 1 ELSE 0 END)', + 'services_warning_passive_on_problem_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 0 AND host_state != 99 AND state = 1 AND is_passive_checked = 1 THEN 1 ELSE 0 END)', + 'services_warning_not_checked_on_problem_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 0 AND host_state != 99 AND state = 1 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)', + 'services_critical_handled_on_problem_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 0 AND host_state != 99 AND state = 2 AND handled > 0 THEN 1 ELSE 0 END)', + 'services_critical_unhandled_on_problem_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 0 AND host_state != 99 AND state = 2 AND handled = 0 THEN 1 ELSE 0 END)', + 'services_critical_passive_on_problem_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 0 AND host_state != 99 AND state = 2 AND is_passive_checked = 1 THEN 1 ELSE 0 END)', + 'services_critical_not_checked_on_problem_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 0 AND host_state != 99 AND state = 2 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)', + 'services_unknown_handled_on_problem_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 0 AND host_state != 99 AND state = 3 AND handled > 0 THEN 1 ELSE 0 END)', + 'services_unknown_unhandled_on_problem_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 0 AND host_state != 99 AND state = 3 AND handled = 0 THEN 1 ELSE 0 END)', + 'services_unknown_passive_on_problem_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 0 AND host_state != 99 AND state = 3 AND is_passive_checked = 1 THEN 1 ELSE 0 END)', + 'services_unknown_not_checked_on_problem_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 0 AND host_state != 99 AND state = 3 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)' + ) + ); + + /** + * The union + * + * @var Zend_Db_Select + */ + protected $summaryQuery; + + /** + * Subqueries used for the summary query + * + * @var IdoQuery[] + */ + protected $subQueries = array(); + + /** + * {@inheritdoc} + */ + public function allowsCustomVars() + { + foreach ($this->subQueries as $query) { + if (! $query->allowsCustomVars()) { + return false; + } + } + + return true; + } + + /** + * {@inheritdoc} + */ + public function addFilter(Filter $filter) + { + foreach ($this->subQueries as $sub) { + $sub->applyFilter(clone $filter); + } + return $this; + } + + /** + * {@inheritdoc} + */ + protected function joinBaseTables() + { + // TODO(el): Allow to switch between hard and soft states + $hosts = $this->createSubQuery( + 'Hoststatus', + array( + 'handled' => 'host_handled', + 'host_problem', + 'host_state' => new Zend_Db_Expr('NULL'), + 'is_active_checked' => 'host_active_checks_enabled', + 'is_allowed_to_flap' => 'host_flap_detection_enabled', + 'is_flapping' => 'host_is_flapping', + 'is_passive_checked' => 'host_is_passive_checked', + 'is_processing_events' => 'host_event_handler_enabled', + 'is_triggering_notifications' => 'host_notifications_enabled', + 'object_type', + 'severity' => 'host_severity', + 'state_change' => 'host_last_state_change', + 'state' => 'host_state' + ) + ); + $this->subQueries[] = $hosts; + $services = $this->createSubQuery( + 'Servicestatus', + array( + 'handled' => 'service_handled', + 'host_problem', + 'host_state' => 'host_hard_state', + 'is_active_checked' => 'service_active_checks_enabled', + 'is_allowed_to_flap' => 'service_flap_detection_enabled', + 'is_flapping' => 'service_is_flapping', + 'is_passive_checked' => 'service_is_passive_checked', + 'is_processing_events' => 'service_event_handler_enabled', + 'is_triggering_notifications' => 'service_notifications_enabled', + 'object_type', + 'severity' => 'service_severity', + 'state_change' => 'service_last_state_change', + 'state' => 'service_state' + ) + ); + $this->subQueries[] = $services; + $this->summaryQuery = $this->db->select()->union(array($hosts, $services), Zend_Db_Select::SQL_UNION_ALL); + $this->select->from(array('statussummary' => $this->summaryQuery), array()); + $this->joinedVirtualTables['hoststatussummary'] = true; + $this->joinedVirtualTables['servicestatussummary'] = true; + } + + /** + * {@inheritdoc} + */ + public function order($columnOrAlias, $dir = null) + { + if (! $this->hasAliasName($columnOrAlias)) { + foreach ($this->subQueries as $sub) { + $sub->requireColumn($columnOrAlias); + } + } + return parent::order($columnOrAlias, $dir); + } + + /** + * {@inheritdoc} + */ + public function where($condition, $value = null) + { + $this->requireColumn($condition); + foreach ($this->subQueries as $sub) { + $sub->where($condition, $value); + } + return $this; + } + + public function whereEx(FilterExpression $ex) + { + $this->requireColumn($ex->getColumn()); + foreach ($this->subQueries as $sub) { + $sub->whereEx($ex); + } + + return $this; + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/UnhandledhostproblemsQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/UnhandledhostproblemsQuery.php new file mode 100644 index 0000000..f4c4e07 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/UnhandledhostproblemsQuery.php @@ -0,0 +1,48 @@ +<?php +/* Icinga Web 2 | (c) 2017 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Data\Filter\Filter; + +/** + * Query for unhandled host problems + */ +class UnhandledhostproblemsQuery extends IdoQuery +{ + protected $allowCustomVars = true; + + protected $columnMap = array( + 'problems' => array( + 'hosts_down_unhandled' => 'COUNT(*)', + ) + ); + + /** + * The service status sub select + * + * @var HoststatusQuery + */ + protected $subSelect; + + public function addFilter(Filter $filter) + { + $this->subSelect->applyFilter(clone $filter); + return $this; + } + + protected function joinBaseTables() + { + $this->subSelect = $this->createSubQuery( + 'Hoststatus', + array('host_name') + ); + $this->subSelect->where('host_handled', 0); + $this->subSelect->where('host_state', 1); + $this->select->from( + array('problems' => $this->subSelect->setIsSubQuery(true)), + array() + ); + $this->joinedVirtualTables['problems'] = true; + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/UnhandledserviceproblemsQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/UnhandledserviceproblemsQuery.php new file mode 100644 index 0000000..a218caf --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/UnhandledserviceproblemsQuery.php @@ -0,0 +1,48 @@ +<?php +/* Icinga Web 2 | (c) 2017 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend\Ido\Query; + +use Icinga\Data\Filter\Filter; + +/** + * Query for unhandled service problems + */ +class UnhandledserviceproblemsQuery extends IdoQuery +{ + protected $allowCustomVars = true; + + protected $columnMap = array( + 'problems' => array( + 'services_critical_unhandled' => 'COUNT(*)', + ) + ); + + /** + * The service status sub select + * + * @var ServicestatusQuery + */ + protected $subSelect; + + public function addFilter(Filter $filter) + { + $this->subSelect->applyFilter(clone $filter); + return $this; + } + + protected function joinBaseTables() + { + $this->subSelect = $this->createSubQuery( + 'Servicestatus', + array('service_description') + ); + $this->subSelect->where('service_handled', 0); + $this->subSelect->where('service_state', 2); + $this->select->from( + array('problems' => $this->subSelect->setIsSubQuery(true)), + array() + ); + $this->joinedVirtualTables['problems'] = true; + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/MonitoringBackend.php b/modules/monitoring/library/Monitoring/Backend/MonitoringBackend.php new file mode 100644 index 0000000..440ffa4 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/MonitoringBackend.php @@ -0,0 +1,349 @@ +<?php +/* Icinga Web 2 | (c) 2014 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Backend; + +use Icinga\Application\Config; +use Icinga\Data\ConfigObject; +use Icinga\Data\QueryInterface; +use Icinga\Data\ResourceFactory; +use Icinga\Data\ConnectionInterface; +use Icinga\Data\Queryable; +use Icinga\Data\Selectable; +use Icinga\Exception\ConfigurationError; +use Icinga\Exception\ProgrammingError; + +class MonitoringBackend implements Selectable, Queryable, ConnectionInterface +{ + /** + * Backend configuration + * + * @var ConfigObject + */ + protected $config; + + /** + * Resource + * + * @var mixed + */ + protected $resource; + + /** + * Type + * + * @var string + */ + protected $type; + + /** + * The configured name of this backend + * + * @var string + */ + protected $name; + + /** + * Already created instances + * + * @var array + */ + protected static $instances = array(); + + /** + * Create a new backend + * + * @param string $name + * @param ConfigObject $config + */ + protected function __construct($name, ConfigObject $config) + { + $this->name = $name; + $this->config = $config; + } + + /** + * Get a backend instance + * + * You may ask for a specific backend name or get the default one otherwise + * + * @param string $name Backend name + * + * @return MonitoringBackend + */ + public static function instance($name = null) + { + if (! array_key_exists($name, self::$instances)) { + list($foundName, $config) = static::loadConfig($name); + $type = $config->get('type'); + $class = implode( + '\\', + array( + __NAMESPACE__, + ucfirst($type), + ucfirst($type) . 'Backend' + ) + ); + + if (!class_exists($class)) { + throw new ConfigurationError( + mt('monitoring', 'There is no "%s" monitoring backend'), + $class + ); + } + + self::$instances[$name] = new $class($foundName, $config); + if ($name === null) { + self::$instances[$foundName] = self::$instances[$name]; + } + } + + return self::$instances[$name]; + } + + /** + * Clear all cached instances. Mostly for testing purposes. + */ + public static function clearInstances() + { + self::$instances = array(); + } + + /** + * Whether this backend is of a specific type + * + * @param string $type Backend type + * + * @return boolean + */ + public function is($type) + { + return $this->getType() === $type; + } + + /** + * Get the configured name of this backend + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * Get the backend type name + * + * @return string + */ + public function getType() + { + if ($this->type === null) { + $parts = preg_split('~\\\~', get_class($this)); + $class = array_pop($parts); + if (substr($class, -7) === 'Backend') { + $this->type = lcfirst(substr($class, 0, -7)); + } else { + throw new ProgrammingError( + '%s is not a valid monitoring backend class name', + $class + ); + } + } + return $this->type; + } + + /** + * Return the configuration for the first enabled or the given backend + */ + protected static function loadConfig($name = null) + { + $backends = Config::module('monitoring', 'backends'); + + if ($name === null) { + $count = 0; + + foreach ($backends as $name => $config) { + $count++; + if ((bool) $config->get('disabled', false) === false) { + return array($name, $config); + } + } + + if ($count === 0) { + $message = mt('monitoring', 'No backend has been configured'); + } else { + $message = mt('monitoring', 'All backends are disabled'); + } + + throw new ConfigurationError($message); + } else { + $config = $backends->getSection($name); + + if ($config->isEmpty()) { + throw new ConfigurationError( + mt('monitoring', 'No configuration for backend %s'), + $name + ); + } + + if ((bool) $config->get('disabled', false) === true) { + throw new ConfigurationError( + mt('monitoring', 'Configuration for backend %s is disabled'), + $name + ); + } + + return array($name, $config); + } + } + + /** + * Get this backend's internal resource + * + * @return mixed + */ + public function getResource() + { + if ($this->resource === null) { + $config = ResourceFactory::getResourceConfig($this->config->get('resource')); + if ($this->is('ido') && $config->type === 'db' && $config->db === 'mysql' && $config->charset === null) { + $config->charset = 'latin1'; + } + $this->resource = ResourceFactory::createResource($config); + if ($this->is('ido') && $this->resource->getDbType() !== 'oracle') { + // TODO(el): The resource should set the table prefix + $this->resource->setTablePrefix('icinga_'); + } + } + return $this->resource; + } + + /** + * Backend entry point + * + * @return $this + */ + public function select() + { + return $this; + } + + /** + * Create a data view to fetch data from + * + * @param string $name + * @param array $columns + * + * @return \Icinga\Module\Monitoring\DataView\DataView + */ + public function from($name, array $columns = null) + { + $class = $this->buildViewClassName($name); + return new $class($this, $columns); + } + + /** + * View name to class name resolution + * + * @param string $view + * + * @return string + * + * @throws ProgrammingError In case the view does not exist + */ + protected function buildViewClassName($view) + { + $class = ucfirst(strtolower($view)); + $classPath = '\\Icinga\\Module\\Monitoring\\DataView\\' . $class; + if (! class_exists($classPath)) { + throw new ProgrammingError('DataView %s does not exist', $class); + } + + return $classPath; + } + + /** + * Get a specific query class instance + * + * @param string $name Query name + * @param array $columns Optional column list + * + * @return QueryInterface + * + * @throws ProgrammingError When the query does not exist for this backend + */ + public function query($name, $columns = null) + { + $class = $this->buildQueryClassName($name); + + if (!class_exists($class)) { + throw new ProgrammingError( + 'Query "%s" does not exist for backend %s', + $name, + $this->getType() + ); + } + + return new $class($this->getResource(), $columns); + } + + /** + * Whether this backend supports the given query + * + * @param string $name Query name to check for + * + * @return bool + */ + public function hasQuery($name) + { + return class_exists($this->buildQueryClassName($name)); + } + + /** + * Query name to class name resolution + * + * @param string $query + * + * @return string + */ + protected function buildQueryClassName($query) + { + $parts = preg_split('~\\\~', get_class($this)); + array_pop($parts); + array_push($parts, 'Query', ucfirst(strtolower($query)) . 'Query'); + return implode('\\', $parts); + } + + /** + * Fetch and return the program version of the current instance + * + * @return string + */ + public function getProgramVersion() + { + return preg_replace( + '/^[vr]/', + '', + $this->select()->from('programstatus', array('program_version'))->fetchOne() + ); + } + + /** + * Get whether the backend is Icinga 2 + * + * @param string $programVersion + * + * @return bool + */ + public function isIcinga2($programVersion = null) + { + if ($programVersion === null) { + $programVersion = $this->select()->from('programstatus', array('program_version'))->fetchOne(); + } + return (bool) preg_match( + '/^[vr]?2\.\d+\.\d+.*$/', + $programVersion + ); + } +} diff --git a/modules/monitoring/library/Monitoring/BackendStep.php b/modules/monitoring/library/Monitoring/BackendStep.php new file mode 100644 index 0000000..9683392 --- /dev/null +++ b/modules/monitoring/library/Monitoring/BackendStep.php @@ -0,0 +1,208 @@ +<?php +/* Icinga Web 2 | (c) 2014 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring; + +use Exception; +use Icinga\Module\Setup\Step; +use Icinga\Application\Config; +use Icinga\Exception\IcingaException; + +class BackendStep extends Step +{ + protected $data; + + protected $backendIniError; + + protected $resourcesIniError; + + public function __construct(array $data) + { + $this->data = $data; + } + + public function apply() + { + $success = $this->createBackendsIni(); + $success &= $this->createResourcesIni(); + return $success; + } + + protected function createBackendsIni() + { + $config = array(); + $config[$this->data['backendConfig']['name']] = array( + 'type' => $this->data['backendConfig']['type'], + 'resource' => $this->data['resourceConfig']['name'] + ); + + try { + Config::fromArray($config) + ->setConfigFile(Config::resolvePath('modules/monitoring/backends.ini')) + ->saveIni(); + } catch (Exception $e) { + $this->backendIniError = $e; + return false; + } + + $this->backendIniError = false; + return true; + } + + protected function createResourcesIni() + { + $resourceConfig = $this->data['resourceConfig']; + $resourceName = $resourceConfig['name']; + unset($resourceConfig['name']); + + try { + $config = Config::app('resources', true); + $config->setSection($resourceName, $resourceConfig); + $config->saveIni(); + } catch (Exception $e) { + $this->resourcesIniError = $e; + return false; + } + + $this->resourcesIniError = false; + return true; + } + + public function getSummary() + { + $pageTitle = '<h2>' . mt('monitoring', 'Monitoring Backend', 'setup.page.title') . '</h2>'; + $backendDescription = '<p>' . sprintf( + mt( + 'monitoring', + 'Icinga Web 2 will retrieve information from your monitoring environment' + . ' using a backend called "%s" and the specified resource below:' + ), + $this->data['backendConfig']['name'] + ) . '</p>'; + + $resourceTitle = null; + $resourceHtml = null; + if ($this->data['resourceConfig']['type'] === 'db') { + $resourceTitle = '<h3>' . mt('monitoring', 'Database Resource') . '</h3>'; + $resourceHtml = '' + . '<table>' + . '<tbody>' + . '<tr>' + . '<td><strong>' . t('Resource Name') . '</strong></td>' + . '<td>' . $this->data['resourceConfig']['name'] . '</td>' + . '</tr>' + . '<tr>' + . '<td><strong>' . t('Database Type') . '</strong></td>' + . '<td>' . $this->data['resourceConfig']['db'] . '</td>' + . '</tr>' + . '<tr>' + . '<td><strong>' . t('Host') . '</strong></td>' + . '<td>' . $this->data['resourceConfig']['host'] . '</td>' + . '</tr>' + . '<tr>' + . '<td><strong>' . t('Port') . '</strong></td>' + . '<td>' . $this->data['resourceConfig']['port'] . '</td>' + . '</tr>' + . '<tr>' + . '<td><strong>' . t('Database Name') . '</strong></td>' + . '<td>' . $this->data['resourceConfig']['dbname'] . '</td>' + . '</tr>' + . '<tr>' + . '<td><strong>' . t('Username') . '</strong></td>' + . '<td>' . $this->data['resourceConfig']['username'] . '</td>' + . '</tr>' + . '<tr>' + . '<td><strong>' . t('Password') . '</strong></td>' + . '<td>' . str_repeat('*', strlen($this->data['resourceConfig']['password'])) . '</td>' + . '</tr>'; + + if (defined('\PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT') + && isset($this->data['resourceConfig']['ssl_do_not_verify_server_cert']) + && $this->data['resourceConfig']['ssl_do_not_verify_server_cert'] + ) { + $resourceHtml .= '' + . '<tr>' + . '<td><strong>' . t('SSL Do Not Verify Server Certificate') . '</strong></td>' + . '<td>' . $this->data['resourceConfig']['ssl_do_not_verify_server_cert'] . '</td>' + . '</tr>'; + } + if (isset($this->data['resourceConfig']['ssl_key']) && $this->data['resourceConfig']['ssl_key']) { + $resourceHtml .= '' + .'<tr>' + . '<td><strong>' . t('SSL Key') . '</strong></td>' + . '<td>' . $this->data['resourceConfig']['ssl_key'] . '</td>' + . '</tr>'; + } + if (isset($this->data['resourceConfig']['ssl_cert']) && $this->data['resourceConfig']['ssl_cert']) { + $resourceHtml .= '' + . '<tr>' + . '<td><strong>' . t('SSL Cert') . '</strong></td>' + . '<td>' . $this->data['resourceConfig']['ssl_cert'] . '</td>' + . '</tr>'; + } + if (isset($this->data['resourceConfig']['ssl_ca']) && $this->data['resourceConfig']['ssl_ca']) { + $resourceHtml .= '' + . '<tr>' + . '<td><strong>' . t('CA') . '</strong></td>' + . '<td>' . $this->data['resourceConfig']['ssl_ca'] . '</td>' + . '</tr>'; + } + if (isset($this->data['resourceConfig']['ssl_capath']) && $this->data['resourceConfig']['ssl_capath']) { + $resourceHtml .= '' + . '<tr>' + . '<td><strong>' . t('CA Path') . '</strong></td>' + . '<td>' . $this->data['resourceConfig']['ssl_capath'] . '</td>' + . '</tr>'; + } + if (isset($this->data['resourceConfig']['ssl_cipher']) && $this->data['resourceConfig']['ssl_cipher']) { + $resourceHtml .= '' + . '<tr>' + . '<td><strong>' . t('Cipher') . '</strong></td>' + . '<td>' . $this->data['resourceConfig']['ssl_cipher'] . '</td>' + . '</tr>'; + } + + $resourceHtml .= '' + . '</tbody>' + . '</table>'; + } + + return $pageTitle . '<div class="topic">' . $backendDescription . $resourceTitle . $resourceHtml . '</div>'; + } + + public function getReport() + { + $report = array(); + + if ($this->backendIniError === false) { + $report[] = sprintf( + mt('monitoring', 'Monitoring backend configuration has been successfully written to: %s'), + Config::resolvePath('modules/monitoring/backends.ini') + ); + } elseif ($this->backendIniError !== null) { + $report[] = sprintf( + mt( + 'monitoring', + 'Monitoring backend configuration could not be written to: %s. An error occured:' + ), + Config::resolvePath('modules/monitoring/backends.ini') + ); + $report[] = sprintf(mt('setup', 'ERROR: %s'), IcingaException::describe($this->backendIniError)); + } + + if ($this->resourcesIniError === false) { + $report[] = sprintf( + mt('monitoring', 'Resource configuration has been successfully updated: %s'), + Config::resolvePath('resources.ini') + ); + } elseif ($this->resourcesIniError !== null) { + $report[] = sprintf( + mt('monitoring', 'Resource configuration could not be udpated: %s. An error occured:'), + Config::resolvePath('resources.ini') + ); + $report[] = sprintf(mt('setup', 'ERROR: %s'), IcingaException::describe($this->resourcesIniError)); + } + + return $report; + } +} |