From d871b3c287ade9f356712ee16147a87a932a0001 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Fri, 12 Jul 2013 14:33:17 +0200 Subject: [PATCH] Update the monitoring module --- library/Icinga/Application/Web.php | 11 +- library/Icinga/Web/View.php | 64 ++++ .../controllers/CommandController.php | 2 +- .../controllers/ListController.php | 121 ++++--- .../controllers/ShowController.php | 299 ++++++------------ .../controllers/SoapController.php | 49 +++ .../views/scripts/list/hosts-compact.phtml | 21 +- .../views/scripts/list/hosts.phtml | 32 +- .../views/scripts/list/services-compact.phtml | 119 ++++--- .../views/scripts/list/services.phtml | 39 ++- .../show/components/checkstatistics.phtml | 29 ++ .../scripts/show/components/command.phtml | 6 + .../scripts/show/components/comments.phtml | 15 +- .../scripts/show/components/contacts.phtml | 45 +-- .../scripts/show/components/customvars.phtml | 12 + .../scripts/show/components/header.phtml | 28 ++ .../scripts/show/components/hostgroups.phtml | 12 + .../scripts/show/components/output.phtml | 4 + .../scripts/show/components/perfdata.phtml | 7 + .../show/components/servicegroups.phtml | 12 + .../views/scripts/show/history.phtml | 47 ++- .../application/views/scripts/show/host.phtml | 43 +-- .../views/scripts/show/service.phtml | 35 +- .../views/scripts/show/services.phtml | 3 +- .../views/scripts/show/ticket.phtml | 2 +- .../views/scripts/summary/group.phtml | 30 +- modules/monitoring/bin/action/list.inc.php | 126 ++++++++ modules/monitoring/bin/soaptest.php | 21 ++ .../Monitoring/Backend/AbstractBackend.php | 114 ------- .../Backend/Ido/Query/AbstractQuery.php | 26 +- .../Backend/Ido/Query/CommentQuery.php | 7 +- .../Backend/Ido/Query/ContactQuery.php | 8 +- .../Backend/Ido/Query/ContactgroupQuery.php | 8 +- .../Backend/Ido/Query/CustomvarQuery.php | 7 +- .../Backend/Ido/Query/EventHistoryQuery.php | 53 +++- .../Backend/Ido/Query/HostgroupQuery.php | 5 +- .../Backend/Ido/Query/HoststatusQuery.php | 197 ++++++++++++ .../Backend/Ido/Query/ServicegroupQuery.php | 11 +- .../Backend/Ido/Query/ServicestatusQuery.php | 167 ++++++++++ .../Backend/Ido/Query/StatusQuery.php | 47 ++- .../Backend/Livestatus/Query/StatusQuery.php | 32 +- .../library/Monitoring/Environment.php | 2 + .../Monitoring/Object/AbstractObject.php | 146 +++++++++ .../library/Monitoring/Object/Host.php | 58 ++++ .../library/Monitoring/Object/Service.php | 69 ++++ .../library/Monitoring/View/CommentView.php | 3 + .../Monitoring/View/HoststatusView.php | 82 +++++ .../Monitoring/View/MonitoringView.php | 162 +++++++++- .../library/Monitoring/View/StatusView.php | 23 ++ 49 files changed, 1811 insertions(+), 650 deletions(-) create mode 100644 library/Icinga/Web/View.php create mode 100644 modules/monitoring/application/controllers/SoapController.php create mode 100644 modules/monitoring/application/views/scripts/show/components/checkstatistics.phtml create mode 100644 modules/monitoring/application/views/scripts/show/components/command.phtml create mode 100644 modules/monitoring/application/views/scripts/show/components/customvars.phtml create mode 100644 modules/monitoring/application/views/scripts/show/components/header.phtml create mode 100644 modules/monitoring/application/views/scripts/show/components/hostgroups.phtml create mode 100644 modules/monitoring/application/views/scripts/show/components/output.phtml create mode 100644 modules/monitoring/application/views/scripts/show/components/perfdata.phtml create mode 100644 modules/monitoring/application/views/scripts/show/components/servicegroups.phtml create mode 100644 modules/monitoring/bin/action/list.inc.php create mode 100644 modules/monitoring/bin/soaptest.php create mode 100644 modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatusQuery.php create mode 100644 modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicestatusQuery.php create mode 100644 modules/monitoring/library/Monitoring/Object/AbstractObject.php create mode 100644 modules/monitoring/library/Monitoring/Object/Host.php create mode 100644 modules/monitoring/library/Monitoring/Object/Service.php create mode 100644 modules/monitoring/library/Monitoring/View/HoststatusView.php diff --git a/library/Icinga/Application/Web.php b/library/Icinga/Application/Web.php index b27c777f2..4da8839aa 100644 --- a/library/Icinga/Application/Web.php +++ b/library/Icinga/Application/Web.php @@ -3,21 +3,21 @@ /** * Icinga 2 Web - Head for multiple monitoring frontends * Copyright (C) 2013 Icinga Development Team - * + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * + * * @copyright 2013 Icinga Development Team * @author Icinga Development Team */ @@ -32,6 +32,7 @@ use Zend_Paginator as Paginator; use Zend_View_Helper_PaginationControl as PaginationControl; use Zend_Controller_Action_HelperBroker as ActionHelper; use Zend_Controller_Router_Route as Route; +use Icinga\Web\View as IcingaView; /** * Use this if you want to make use of Icinga funtionality in other web projects @@ -169,7 +170,7 @@ class Web extends ApplicationBootstrap protected function prepareView() { $view = ActionHelper::getStaticHelper('viewRenderer'); - $view->initView(); + $view->setView(new IcingaView()); $view->view->addHelperPath($this->appdir . '/views/helpers'); // TODO: find out how to avoid this additional helper path: diff --git a/library/Icinga/Web/View.php b/library/Icinga/Web/View.php new file mode 100644 index 000000000..80bc47e02 --- /dev/null +++ b/library/Icinga/Web/View.php @@ -0,0 +1,64 @@ +_useViewStream = (bool) ini_get('short_open_tag') ? false : true; + if ($this->_useViewStream) { + if (!in_array('zend.view', stream_get_wrappers())) { + stream_wrapper_register('zend.view', '\Icinga\Web\ViewStream'); + } + } + parent::__construct($config); + } + + public function init() + { + $this->loadGlobalHelpers(); + } + + protected function loadGlobalHelpers() + { + $pattern = dirname(__FILE__) . '/View/helpers/*.php'; + $files = glob($pattern); + foreach ($files as $file) { + require_once $file; + } + } + + protected function _run() + { + foreach ($this->getVars() as $k => $v) { + // Exporting global variables to view scripts: + $$k = $v; + } + if ($this->_useViewStream) { + include 'zend.view://' . func_get_arg(0); + } else { + include func_get_arg(0); + } + } + + public function __call($name, $args) + { + $namespaced = '\\Icinga\\Web\\View\\' . $name; + if (function_exists($namespaced)) { + return call_user_func_array( + $namespaced, + $args + ); + } else { + return parent::__call($name, $args); + } + } +} + diff --git a/modules/monitoring/application/controllers/CommandController.php b/modules/monitoring/application/controllers/CommandController.php index 1b04f8cd9..a8142fe17 100644 --- a/modules/monitoring/application/controllers/CommandController.php +++ b/modules/monitoring/application/controllers/CommandController.php @@ -29,7 +29,7 @@ class Monitoring_CommandController extends ModuleActionController throw new Exception("Invalid token given", 401); $this->_helper->viewRenderer->setNoRender(true); $this->_helper->layout()->disableLayout(); - $targets = Icinga\Application\Config::getInstance()->getModuleConfig("instances", "monitoring"); + $targets = $this->config->instances; $instance = $this->_getParam("instance"); if ($instance && isset($targets[$instance])) { $this->target = new \Icinga\Protocol\Commandpipe\CommandPipe($targets[$instance]); diff --git a/modules/monitoring/application/controllers/ListController.php b/modules/monitoring/application/controllers/ListController.php index ac5108eb9..67d496051 100644 --- a/modules/monitoring/application/controllers/ListController.php +++ b/modules/monitoring/application/controllers/ListController.php @@ -2,6 +2,7 @@ use Icinga\Web\ModuleActionController; use Icinga\Web\Hook; +use Icinga\File\Csv; use Icinga\Monitoring\Backend; class Monitoring_ListController extends ModuleActionController @@ -19,7 +20,7 @@ class Monitoring_ListController extends ModuleActionController public function hostsAction() { - $this->view->hosts = $this->backend->select()->from('status', array( + $this->view->hosts = $this->query('hoststatus', array( 'host_name', 'host_state', 'host_acknowledged', @@ -28,36 +29,9 @@ class Monitoring_ListController extends ModuleActionController 'host_handled', 'host_last_state_change' )); - - if ($search = $this->_getParam('search')) { - $this->_setParam('search', null); - if (strpos($search, '=') === false) { - $this->_setParam('host_name', $search); - } else { - list($key, $val) = preg_split('~\s*=\s*~', $search, 2); - if ($this->view->hosts->isValidFilterColumn($key) || $key[0] === '_') { - $this->_setParam($key, $val); - } - } - } - $this->view->hosts->applyRequest($this->_request); -$this->view->hosts->getQuery()->group('hs.host_object_id'); - if ($this->_getParam('dump') === 'sql') { - echo '
' . htmlspecialchars(wordwrap($this->view->hosts->getQuery()->dump())) . '
'; - exit; - } - - // TODO: Get rid of "preserve" - $preserve = array(); - if ($this->_getParam('sort')) { - $preserve['sort'] = $this->view->sort = $this->_getParam('sort'); - } - if ($this->_getParam('backend')) { - $preserve['backend'] = $this->_getParam('backend'); - } - $this->view->preserve = $preserve; - - if ($this->_getParam('view') === 'compact') { + $this->view->sort = $this->_getParam('sort'); + $this->preserve('sort')->preserve('backend'); + if ($this->view->compact) { $this->_helper->viewRenderer('hosts_compact'); } } @@ -72,9 +46,10 @@ $this->view->hosts->getQuery()->group('hs.host_object_id'); $state_column = 'service_hard_state'; $state_change_column = 'service_last_hard_state_change'; } - $this->view->services = $this->backend->select() - ->from('status', array( + + $this->view->services = $this->query('status', array( 'host_name', + 'host_problems', 'service_description', 'service_state' => $state_column, 'service_in_downtime', @@ -82,36 +57,12 @@ $this->view->hosts->getQuery()->group('hs.host_object_id'); 'service_handled', 'service_output', 'service_last_state_change' => $state_change_column - )); - - if ($search = $this->_getParam('search')) { - $this->_setParam('search', null); - if (strpos($search, '=') === false) { - $this->_setParam('service_description', $search); - } else { - list($key, $val) = preg_split('~\s*=\s*~', $search, 2); - if ($this->view->services->isValidFilterColumn($key) || $key[0] === '_') { - $this->_setParam($key, $val); - } - } - } - - $this->view->services->applyRequest($this->_request); - if ($this->_getParam('dump') === 'sql') { - echo '
' . htmlspecialchars(wordwrap($this->view->services->getQuery()->dump())) . '
'; - exit; - } - - $preserve = array(); - if ($this->_getParam('sort')) { - $preserve['sort'] = $this->view->sort = $this->_getParam('sort'); - - } - if ($this->_getParam('backend')) { - $preserve['backend'] = $this->_getParam('backend'); - } - $this->view->preserve = $preserve; - if ($this->_getParam('view') == 'compact') { + )); + $this->preserve('sort') + ->preserve('backend') + ->preserve('extracolumns'); + $this->view->sort = $this->_getParam('sort'); + if ($this->view->compact) { $this->_helper->viewRenderer('services-compact'); } } @@ -170,19 +121,58 @@ $this->view->hosts->getQuery()->group('hs.host_object_id'); exit; } + protected function query($view, $columns) + { + $extra = preg_split( + '~,~', + $this->_getParam('extracolumns', ''), + -1, + PREG_SPLIT_NO_EMPTY + ); + $this->view->extraColumns = $extra; + $query = $this->backend->select() + ->from($view, array_merge($columns, $extra)) + ->applyRequest($this->_request); + $this->handleFormatRequest($query); + return $query; + } + + protected function handleFormatRequest($query) + { + if ($this->_getParam('format') === 'sql') { + echo '
'
+                . htmlspecialchars(wordwrap($query->getQuery()->dump()))
+                . '
'; + exit; + } + if ($this->_getParam('format') === 'json' + || $this->_request->getHeader('Accept') === 'application/json') + { + header('Content-type: application/json'); + echo json_encode($query->fetchAll()); + exit; + } + if ($this->_getParam('format') === 'csv' + || $this->_request->getHeader('Accept') === 'text/csv') { + Csv::fromQuery($query)->dump(); + exit; + } + } + protected function getTabs() { $tabs = $this->widget('tabs'); $tabs->add('services', array( - 'title' => 'Services', + 'title' => 'All services', 'icon' => 'img/classic/service.png', 'url' => 'monitoring/list/services', )); $tabs->add('hosts', array( - 'title' => 'Hosts', + 'title' => 'All hosts', 'icon' => 'img/classic/server.png', 'url' => 'monitoring/list/hosts', )); +/* $tabs->add('hostgroups', array( 'title' => 'Hostgroups', 'icon' => 'img/classic/servers-network.png', @@ -203,6 +193,7 @@ $this->view->hosts->getQuery()->group('hs.host_object_id'); 'icon' => 'img/classic/servers-network.png', 'url' => 'monitoring/list/contactgroups', )); +*/ return $tabs; } } diff --git a/modules/monitoring/application/controllers/ShowController.php b/modules/monitoring/application/controllers/ShowController.php index 66e7e103d..6755b13b1 100644 --- a/modules/monitoring/application/controllers/ShowController.php +++ b/modules/monitoring/application/controllers/ShowController.php @@ -3,7 +3,8 @@ use Icinga\Monitoring\Backend; use Icinga\Web\ModuleActionController; use Icinga\Web\Hook; -use Icinga\Application\Benchmark; +use Icinga\Monitoring\Object\Host; +use Icinga\Monitoring\Object\Service; class Monitoring_ShowController extends ModuleActionController { @@ -13,33 +14,94 @@ class Monitoring_ShowController extends ModuleActionController { $host = $this->_getParam('host'); $service = $this->_getParam('service'); + $this->backend = Backend::getInstance($this->_getParam('backend')); + $object = null; + // TODO: Do not allow wildcards in names! if ($host !== null) { // TODO: $this->assertPermission('host/read', $host); + if ($this->action_name !== 'host' && $service !== null && $service !== '*') { + // TODO: $this->assertPermission('service/read', $service); + $object = Service::fetch($this->backend, $host, $service); + } else { + $object = Host::fetch($this->backend, $host); + } } - if ($service !== null) { - // TODO: $this->assertPermission('service/read', $service); - } - // TODO: don't allow wildcards - $this->backend = Backend::getInstance($this->_getParam('backend')); - if ($service !== null && $service !== '*') { - $this->view->service = $this->backend->fetchService($host, $service); - } - if ($host !== null) { - $this->view->host = $this->backend->fetchHost($host); - } $this->view->compact = $this->_getParam('view') === 'compact'; - $this->view->tabs = $this->createTabs(); - // If ticket hook: - $params = array(); - if ($host !== null) { - $params['host'] = $this->view->host->host_name; - } - if ($service !== null) { - $params['service'] = $this->view->service->service_description; + if ($object === null) { + // TODO: Notification, not found + $this->redirectNow('monitoring/list/services'); + return; } + $this->view->object = $object; + $this->view->tabs = $this->createTabs(); + $this->prepareTicketHook(); + } + + public function serviceAction() + { + $object = $this->view->object->prefetch(); + $this->prepareGrapherHook(); + } + + public function hostAction() + { + $this->view->object->prefetch(); + $this->prepareGrapherHook(); + } + + public function historyAction() + { + $this->view->history = $this->backend->select() + ->from('eventHistory', array( + 'object_type', + 'host_name', + 'service_description', + 'timestamp', + 'state', + 'attempt', + 'max_attempts', + 'output', + 'type' + ))->applyRequest($this->_request); + + $this->view->preserve = $this->view->history->getAppliedFilter()->toParams(); + } + + public function servicesAction() + { + $this->_setParam('service', null); + // Ugly and slow: + $this->view->services = $this->view->action('services', 'list', 'monitoring', array( + 'view' => 'compact' + )); + } + + public function ticketAction() + { if (Hook::has('ticket')) { + // TODO: Still hardcoded, should ask for URL: + $id = $this->_getParam('ticket'); + $ticketModule = 'rt'; + $this->render(); + $this->_forward('ticket', 'show', $ticketModule, array( + 'id' => $id + )); + } + } + + protected function prepareTicketHook() + { + if (Hook::has('ticket')) { + $object = $this->view->object; + $params = array( + 'host' => $object->host_name + ); + if ($object instanceof Service) { + $params['service'] = $object->service_description; + } + $params['ticket'] = '__ID__'; $this->view->ticket_link = preg_replace( '~__ID__~', @@ -54,209 +116,49 @@ class Monitoring_ShowController extends ModuleActionController } } - public function serviceAction() + protected function prepareGrapherHook() { - Benchmark::measure('Entered service action'); - $this->view->active = 'service'; - $this->view->tabs->activate('service')->enableSpecialActions(); - if ($grapher = Hook::get('grapher')) { + $object = $this->view->object; if ($grapher->hasGraph( - $this->view->host->host_name, - $this->view->service->service_description + $object->host_name, + $object->service_description )) { $this->view->preview_image = $grapher->getPreviewImage( - $this->view->host->host_name, - $this->view->service->service_description + $object->host_name, + $object->service_description ); } } - - $this->view->contacts = $this->backend->select() - ->from('contact', array( - 'contact_name', - 'contact_alias', - 'contact_email', - 'contact_pager', - )) - ->where('service_host_name', $this->view->host->host_name) - ->where('service_description', $this->view->service->service_description) - ->fetchAll(); - - $this->view->contactgroups = $this->backend->select() - ->from('contactgroup', array( - 'contactgroup_name', - 'contactgroup_alias', - )) - ->where('service_host_name', $this->view->host->host_name) - ->where('service_description', $this->view->service->service_description) - ->fetchAll(); - - $this->view->comments = $this->backend->select() - ->from('comment', array( - 'comment_timestamp', - 'comment_author', - 'comment_data', - 'comment_type', - )) - ->where('service_host_name', $this->view->host->host_name) - ->where('service_description', $this->view->service->service_description) - ->fetchAll(); - - $this->view->customvars = $this->backend->select() - ->from('customvar', array( - 'varname', - 'varvalue' - )) - ->where('varname', '-*PW*,-*PASS*') - ->where('host_name', $this->view->host->host_name) - ->where('service_description', $this->view->service->service_description) - ->where('object_type', 'service') - ->fetchPairs(); - Benchmark::measure('Service action done'); - } - - public function hostAction() - { - $this->view->active = 'host'; - $this->view->tabs->activate('host')->enableSpecialActions(); - - if ($grapher = Hook::get('grapher')) { - if ($grapher->hasGraph($this->view->host->host_name)) { - $this->view->preview_image = $grapher->getPreviewImage( - $this->view->host->host_name - ); - } - } - - $this->view->hostgroups = $this->backend->select() - ->from('hostgroup', array( - 'hostgroup_name', - 'hostgroup_alias' - )) - ->where('host_name', $this->view->host->host_name) - ->fetchPairs(); - - $this->view->contacts = $this->backend->select() - ->from('contact', array( - 'contact_name', - 'contact_alias', - 'contact_email', - 'contact_pager', - )) - ->where('host_name', $this->view->host->host_name) - ->fetchAll(); - - $this->view->contactgroups = $this->backend->select() - ->from('contactgroup', array( - 'contactgroup_name', - 'contactgroup_alias', - )) - ->where('host_name', $this->view->host->host_name) - ->fetchAll(); - - $this->view->comments = $this->backend->select() - ->from('comment', array( - 'comment_timestamp', - 'comment_author', - 'comment_data', - 'comment_type', - )) - ->where('host_name', $this->view->host->host_name) - ->fetchAll(); - - $this->view->customvars = $this->backend->select() - ->from('customvar', array( - 'varname', - 'varvalue' - )) - ->where('varname', '-*PW*,-*PASS*') - ->where('host_name', $this->view->host->host_name) - ->where('object_type', 'host') - ->fetchPairs(); - } - - public function historyAction() - { - if ($this->view->host) { - $this->view->tabs->activate('history')->enableSpecialActions(); - } - $this->view->history = $this->backend->select() - ->from('eventHistory', array( - 'object_type', - 'host_name', - 'service_description', - 'timestamp', - 'state', - 'attempt', - 'max_attempts', - 'output', - 'type' - ))->applyRequest($this->_request); - - - $this->view->preserve = $this->view->history->getAppliedFilter()->toParams(); - if ($this->_getParam('dump') === 'sql') { - echo '
' . htmlspecialchars($this->view->history->getQuery()->dump()) . '
'; - exit; - } - if ($this->_getParam('sort')) { - $this->view->preserve['sort'] = $this->_getParam('sort'); - } - } - - public function servicesAction() - { - // Ugly and slow: - $this->view->services = $this->view->action('services', 'list', 'monitoring', array( - 'host_name' => $this->view->host->host_name, - //'sort', 'service_description' - )); - } - - public function ticketAction() - { - $this->view->tabs->activate('ticket')->enableSpecialActions(); - $id = $this->_getParam('ticket'); - // Still hardcoded, TODO: get URL: - if (Hook::has('ticket')) { - $ticketModule = 'rt'; - $this->render(); - $this->_forward('ticket', 'show', $ticketModule, array( - 'id' => $id - )); - } } protected function createTabs() { + $object = $this->view->object; $tabs = $this->widget('tabs'); - if ( ! $this->view->host) { - return $tabs; - } - $params = array( - 'host' => $this->view->host->host_name, - ); + $params = array('host' => $object->host_name); if ($backend = $this->_getParam('backend')) { $params['backend'] = $backend; } - if (isset($this->view->service)) { - $params['service'] = $this->view->service->service_description; - $hostParams = $params + array('active' => 'host'); - } else { - $hostParams = $params; + if ($object instanceof Service) { + $params['service'] = $object->service_description; + } elseif ($service = $this->_getParam('service')) { + $params['service'] = $service; } + // TODO: Work with URL + $servicesParams = $params; + unset($servicesParams['service']); $tabs->add('host', array( 'title' => 'Host', 'icon' => 'img/classic/server.png', 'url' => 'monitoring/show/host', - 'urlParams' => $hostParams, + 'urlParams' => $params, )); $tabs->add('services', array( 'title' => 'Services', 'icon' => 'img/classic/service.png', 'url' => 'monitoring/show/services', - 'urlParams' => $params, + 'urlParams' => $servicesParams, )); if (isset($params['service'])) { $tabs->add('service', array( @@ -280,6 +182,9 @@ class Monitoring_ShowController extends ModuleActionController 'urlParams' => $params + array('ticket' => $this->_getParam('ticket')), )); } + + $tabs->activate($this->action_name)->enableSpecialActions(); + /* $tabs->add('contacts', array( 'title' => 'Contacts', diff --git a/modules/monitoring/application/controllers/SoapController.php b/modules/monitoring/application/controllers/SoapController.php new file mode 100644 index 000000000..f88f7da59 --- /dev/null +++ b/modules/monitoring/application/controllers/SoapController.php @@ -0,0 +1,49 @@ +select()->from('status', array( + 'host', 'service', 'host_state', 'service_state', 'service_output' +))->where('problems', 1)->fetchAll(); +} catch (Exception $e) { + return array('error' => $e->getMessage()); +} + return $result; + } +} + + +class Monitoring_SoapController extends ModuleActionController +{ + protected $handlesAuthentication = true; + + public function indexAction() + { + $wsdl = new ZfSoapAutoDiscover(); + $wsdl->setClass('Api'); + if (isset($_GET['wsdl'])) { + $wsdl->handle(); + } else { + $wsdl->dump('/tmp/test.wsdl'); + $uri = 'http://itenos-devel.tom.local/' . Url::create('monitoring/soap'); + $server = new Zend_Soap_Server('/tmp/test.wsdl'); + $server->setClass('Api'); + $server->handle(); + } + exit; + } +} diff --git a/modules/monitoring/application/views/scripts/list/hosts-compact.phtml b/modules/monitoring/application/views/scripts/list/hosts-compact.phtml index 833933625..644eb9aee 100644 --- a/modules/monitoring/application/views/scripts/list/hosts-compact.phtml +++ b/modules/monitoring/application/views/scripts/list/hosts-compact.phtml @@ -1,8 +1,14 @@ -hosts)): ?> -- no hosts is matching this filter - - -hosts->paginate(); ?> - +count(); +if (! $count) { + echo '- no host is matching this filter -'; + return; +} + +$hosts->paginate(); + +?>
@@ -10,8 +16,7 @@ - -fetchAll() as $host): $icons = array(); if ($host->host_acknowledged) { @@ -54,6 +59,6 @@ $state_title = strtoupper($this->monitoringState($host, 'host')) array('class' => 'row-action') ) ?> - +
State
diff --git a/modules/monitoring/application/views/scripts/list/hosts.phtml b/modules/monitoring/application/views/scripts/list/hosts.phtml index e345a3e5d..82885d5ea 100644 --- a/modules/monitoring/application/views/scripts/list/hosts.phtml +++ b/modules/monitoring/application/views/scripts/list/hosts.phtml @@ -1,7 +1,7 @@ tabs ?> hosts->limit(10); -$hosts = $this->hosts->paginate(); + +$paginator = $hosts->paginate(); function getRowProperties(& $host, $scope) { @@ -43,9 +43,9 @@ if (isset($_GET['dir'])) { $always['dir'] = $_GET['dir']; } ?> - +
Filters
- $v): ?> + $v): ?> qlink( 'x', 'monitoring/list/hosts', @@ -54,9 +54,9 @@ if (isset($_GET['dir'])) { 'style' => array('color' => 'red') ) ) ?> escape("$k = $v") ?>
- +
- +
+
- +
Sorry, no host found for this search
- - -paginationControl($hosts, null, null, array('preserve' => $this->preserve)) ?> + +paginationControl($paginator, null, null, array('preserve' => $this->preserve)) ?> -fetchAll() as $host): list($icons,$state_classes,$state_title) = getRowProperties($host,$this); ?> + + + + + +
qlink( diff --git a/modules/monitoring/application/views/scripts/list/services-compact.phtml b/modules/monitoring/application/views/scripts/list/services-compact.phtml index 2e5c87d69..8f9b34560 100644 --- a/modules/monitoring/application/views/scripts/list/services-compact.phtml +++ b/modules/monitoring/application/views/scripts/list/services-compact.phtml @@ -1,39 +1,34 @@ -services)): ?> -
- Sorry, no services found for this search -
- -services->paginate(); - -?> - - - - - - - - -count(); +if (! $count) { + echo '- no object is matching this filter -'; + return; +} + +$services->paginate(); + +?>
StateService
+ + + + + + + +fetchAll() as $service): + $icons = array(); if ($service->service_acknowledged) { $icons['ack.gif'] = 'Problem has been acknowledged'; } -if (! empty($service->service_downtimes_with_info)) { - $icons['downtime.gif'] = implode("\n", - $this->resolveComments($service->service_downtimes_with_info) - ); +if ($service->service_in_downtime) { + $icons['downtime.gif'] = 'Service is in a scheduled downtime'; } -if (! empty($service->service_comments_with_info)) { - $icons['comment.gif'] = implode("\n", - $this->resolveComments($service->service_comments_with_info) - ); +if ($service->host_problems) { + $icons['server.png'] = 'This services host has a problem'; } $state_classes = array($this->monitoringState($service, 'service')); @@ -53,21 +48,55 @@ if (isset($this->preserve['backend'])) { $params['backend'] = $this->preserve['backend']; } ?> - - - - - - -
StateService
- qlink( - $this->timeSince($service->service_last_state_change), - 'monitoring/show/history', $params, array('quote' => false)) ?> - - qlink( - $service->host_name, - 'monitoring/show/host', - $params - ); ?>: - qlink($service->service_description, 'monitoring/show/service', $params, array('class' => 'row-action')) ?> -
\ No newline at end of file +
qlink( + $this->timeSince($service->service_last_state_change), + 'monitoring/show/history', + $params, + array('quote' => false) + ) ?> $alt) { + echo $this->img('img/classic/' . $icon, array( + 'class' => 'icon', + 'title' => $alt + )); +} + +echo $this->qlink( + $service->host_name, + 'monitoring/show/host', + $params +) . ': ' . $this->qlink( + $service->service_description, + 'monitoring/show/service', + $params, + array('class' => 'row-action') +) ?>
+getLimit(); +$count = $services->count(); + +if ($limit < $count) { + $more = sprintf( + $this->translate( + 'Showing %d of %s, click here for more', + $limit, + $count + ) + ); +} else { + $more = $this->translate( + sprintf( + 'Showing %d objects, click here for details', + $count + ) + ); +} +?>

qlink($more,$this->url()->without('page', 'limit', 'view')) ?>

diff --git a/modules/monitoring/application/views/scripts/list/services.phtml b/modules/monitoring/application/views/scripts/list/services.phtml index 79e4ed436..3af9b2173 100644 --- a/modules/monitoring/application/views/scripts/list/services.phtml +++ b/modules/monitoring/application/views/scripts/list/services.phtml @@ -1,7 +1,7 @@ tabs ?> services->limit(10); -$services = $this->services->paginate(); + +$paginator = $services->paginate(); function getRowProperties(&$service, &$last_host, $scope) { if ($last_host !== $service->host_name) { @@ -21,10 +21,14 @@ function getRowProperties(&$service, &$last_host, $scope) { $icons['ack.gif'] = 'Problem has been acknowledged'; } - if (! empty($service->service_in_downtime)) { + if ($service->service_in_downtime) { $icons['downtime.gif'] = 'Service is in a scheduled downtime'; } + if ($service->host_problems) { + $icons['server.png'] = 'This services host has a problem'; + } + $state_classes = array($scope->monitoringState($service)); if ($service->service_handled) { @@ -63,9 +67,9 @@ if (isset($_GET['dir'])) { } ?>
- +
Filters
- $v): ?> + $v): ?> qlink( 'x', 'monitoring/list/services', @@ -74,9 +78,9 @@ if (isset($_GET['dir'])) { 'style' => array('color' => 'red') ) ) ?> escape("$k = $v") ?>
- +
- +
+formText( + 'search', + $this->search, + array( + 'placeholder' => 'Add filllter...', + ) +) ?>
@@ -106,11 +120,11 @@ Sort by formSelect( Sorry, no services found for this search - -paginationControl($services, null, null, array('preserve' => $this->preserve )); ?> + +paginationControl($paginator, null, null, array('preserve' => $this->preserve )); ?> -fetchAll() as $service): list($host_col,$icons,$state_classes,$state_title,$graph) = getRowProperties($service,$last_host,$this); ?> +extraColumns as $col): ?> + + diff --git a/modules/monitoring/application/views/scripts/show/components/checkstatistics.phtml b/modules/monitoring/application/views/scripts/show/components/checkstatistics.phtml new file mode 100644 index 000000000..462ae9759 --- /dev/null +++ b/modules/monitoring/application/views/scripts/show/components/checkstatistics.phtml @@ -0,0 +1,29 @@ +expandable( + $this->translate('Check statistics'), +'
@@ -148,6 +162,9 @@ Sort by formSelect( escape($service->$col) ?>
+ + + + + + + + + + + + + + + + + + + + +
' . $this->translate('Last check') . '' . $this->format()->timeSince($object->last_check) . '
' . $this->translate('Next check') . '' + . $this->format()->timeUntil($object->next_check) + . '
' . $this->translate('Check execution time') . '' . $object->check_execution_time . '
' . $this->translate('Check latency') . '' . $object->check_latency . '
+', +array('collapsed' => false) +); diff --git a/modules/monitoring/application/views/scripts/show/components/command.phtml b/modules/monitoring/application/views/scripts/show/components/command.phtml new file mode 100644 index 000000000..f036ef58b --- /dev/null +++ b/modules/monitoring/application/views/scripts/show/components/command.phtml @@ -0,0 +1,6 @@ +expandable( + 'Command: ' . array_shift(preg_split('|!|', $object->check_command)), + $this->commandArguments($object->check_command), + // TODO: no JS handler right now, should be collapsed + array('collapsed' => ! (bool) strpos($object->check_command, '!')) +) ?> diff --git a/modules/monitoring/application/views/scripts/show/components/comments.phtml b/modules/monitoring/application/views/scripts/show/components/comments.phtml index e19da1adf..0cb40c3db 100644 --- a/modules/monitoring/application/views/scripts/show/components/comments.phtml +++ b/modules/monitoring/application/views/scripts/show/components/comments.phtml @@ -1,12 +1,13 @@ +comments)) return; -comments)): ?> -comments as $comment) { - if ($this->ticket_pattern) { +foreach ($object->comments as $comment) { + if ($ticket_pattern) { $text = preg_replace( - $this->ticket_pattern, - $this->ticket_link, + $ticket_pattern, + $ticket_link, $this->escape($comment->comment_data) ); } else { @@ -22,4 +23,4 @@ foreach ($this->comments as $comment) { } ?> Comments:
', $list) ?>
- + diff --git a/modules/monitoring/application/views/scripts/show/components/contacts.phtml b/modules/monitoring/application/views/scripts/show/components/contacts.phtml index 0b34e22de..975c25bc0 100644 --- a/modules/monitoring/application/views/scripts/show/components/contacts.phtml +++ b/modules/monitoring/application/views/scripts/show/components/contacts.phtml @@ -1,24 +1,25 @@ -contacts)): ?> -contacts as $contact) { - $list[] = $this->qlink($contact->contact_alias, 'monitoring/show/contact', array( - 'contact_name' => $contact->contact_name - )); -} -?> -Contacts:
- +contactgroups)): ?> -contactgroups as $contactgroup) { - $list[] = $this->qlink($contactgroup->contactgroup_alias, 'monitoring/show/contactgroup', array( - 'contactgroup_name' => $contactgroup->contactgroup_name - )); -} -?> -Contactgroups:
- +if (! empty($object->contacts)) { + + $list = array(); + foreach ($object->contacts as $contact) { + $list[] = $this->qlink($contact->contact_alias, 'monitoring/show/contact', array( + 'contact_name' => $contact->contact_name + )); + } + echo 'Contacts: ' . implode(', ', $list) . "
\n"; +} + +if (! empty($object->contactgroups)) { + $list = array(); + foreach ($object->contactgroups as $contactgroup) { + $list[] = $this->qlink( + $contactgroup->contactgroup_alias, + 'monitoring/show/contactgroup', + array('contactgroup_name' => $contactgroup->contactgroup_name) + ); + } + echo 'Contactgroups: ' . implode(', ', $list) . "
\n"; +} diff --git a/modules/monitoring/application/views/scripts/show/components/customvars.phtml b/modules/monitoring/application/views/scripts/show/components/customvars.phtml new file mode 100644 index 000000000..7ab105fe9 --- /dev/null +++ b/modules/monitoring/application/views/scripts/show/components/customvars.phtml @@ -0,0 +1,12 @@ +customvars) return; + +foreach ($object->customvars as $name => $value) { + printf( + "%s: %s
\n", + $this->escape($name), + $this->escape($value) + ); +} + diff --git a/modules/monitoring/application/views/scripts/show/components/header.phtml b/modules/monitoring/application/views/scripts/show/components/header.phtml new file mode 100644 index 000000000..67c967483 --- /dev/null +++ b/modules/monitoring/application/views/scripts/show/components/header.phtml @@ -0,0 +1,28 @@ +service_description && $tabs->getActiveName() !== 'host' ?> + + + + + + + + + + + + + + + + +
escape($object->host_name) ?>host_address && $object->host_address !== $object->host_name): ?> + (escape($object->host_address) ?>) + + > + util()->getHostStateName($object->host_state) ?>
+ since timeSince($object->host_last_state_change) ?> +
Service: escape($object->service_description) ?> + util()->getServiceStateName($object->service_state); ?>
+ since timeSince($object->service_last_state_change) ?> +
Host state
diff --git a/modules/monitoring/application/views/scripts/show/components/hostgroups.phtml b/modules/monitoring/application/views/scripts/show/components/hostgroups.phtml new file mode 100644 index 000000000..79767c463 --- /dev/null +++ b/modules/monitoring/application/views/scripts/show/components/hostgroups.phtml @@ -0,0 +1,12 @@ +hostgroups)) return; + +$list = array(); +foreach ($object->hostgroups as $name => $alias) { + $list[] = $this->qlink($alias, 'monitoring/list/services', array( + 'hostgroups' => $name + )); +} +echo 'Hostgroups: ' . implode(', ', $list) . "
\n"; + diff --git a/modules/monitoring/application/views/scripts/show/components/output.phtml b/modules/monitoring/application/views/scripts/show/components/output.phtml new file mode 100644 index 000000000..6e3df1f3f --- /dev/null +++ b/modules/monitoring/application/views/scripts/show/components/output.phtml @@ -0,0 +1,4 @@ +expandable( + $this->pluginOutput($object->output), + $this->pluginOutput($object->long_output) +) ?> diff --git a/modules/monitoring/application/views/scripts/show/components/perfdata.phtml b/modules/monitoring/application/views/scripts/show/components/perfdata.phtml new file mode 100644 index 000000000..979c2cc8e --- /dev/null +++ b/modules/monitoring/application/views/scripts/show/components/perfdata.phtml @@ -0,0 +1,7 @@ +perfdata): ?> +expandable( + 'Performance data', + $this->perfdata($object->perfdata), + array('collapsed' => false) +) ?> + diff --git a/modules/monitoring/application/views/scripts/show/components/servicegroups.phtml b/modules/monitoring/application/views/scripts/show/components/servicegroups.phtml new file mode 100644 index 000000000..7d0e31101 --- /dev/null +++ b/modules/monitoring/application/views/scripts/show/components/servicegroups.phtml @@ -0,0 +1,12 @@ +servicegroups)) return; + +$list = array(); +foreach ($object->servicegroups as $name => $alias) { + $list[] = $this->qlink($alias, 'monitoring/list/services', array( + 'servicegroups' => $name + )); +} +echo 'Servicegroups: ' . implode(', ', $list) . "
\n"; + diff --git a/modules/monitoring/application/views/scripts/show/history.phtml b/modules/monitoring/application/views/scripts/show/history.phtml index bd408fab1..9dad5e6f0 100644 --- a/modules/monitoring/application/views/scripts/show/history.phtml +++ b/modules/monitoring/application/views/scripts/show/history.phtml @@ -1,20 +1,17 @@ -partial('show/header.phtml', array( - 'host' => $this->host, - 'service' => $this->service, - 'tabs' => $this->tabs -)); ?>history->limit(10); -$history = $this->history->paginate(); +render('show/components/header.phtml') ?> +limit(10); +$hhistory = $this->history->paginate(); ?> - + There are no matching history entries right now -paginationControl($history, null, null, array('preserve' => $this->preserve)); ?> +paginationControl($hhistory, null, null, array('preserve' => $preserve)); ?> - +object_type == 'host') { @@ -27,24 +24,24 @@ $row_class = array_key_exists($event->state, $states) ? $states[$event->state] : ?> -host)): ?> + - -service)): ?> - - + - +
timestamp ) ?> escape($event->host_name) ?>host)): ?> + + + qlink( $event->service_description, 'monitoring/show/service', array( - 'host' => $this->host->host_name, + 'host' => $object->host_name, 'service' => $event->service_description ) ) ?> - + escape($event->service_description) ?> - + type) { break; } ?> -attempt !== null): ?> +attempt !== null): ?> [ attempt ?>/max_attempts ?> ] - - ticket_pattern ? preg_replace( - $this->ticket_pattern, - $this->ticket_link, + + pluginOutput($event->output) ) : $this->pluginOutput($event->output) ?>
- + diff --git a/modules/monitoring/application/views/scripts/show/host.phtml b/modules/monitoring/application/views/scripts/show/host.phtml index 2ffe6601a..d7327f0cc 100644 --- a/modules/monitoring/application/views/scripts/show/host.phtml +++ b/modules/monitoring/application/views/scripts/show/host.phtml @@ -1,40 +1,11 @@ -partial('show/header.phtml', array( - 'host' => $this->host, - 'service' => $this->service, - 'tabs' => $this->tabs, - 'compact' => $this->compact -)); ?> -expandable( - $this->pluginOutput($this->host->host_output), - $this->pluginOutput($this->host->host_long_output) -) ?> -expandable( - 'Command: ' . array_shift(preg_split('|!|', $this->host->host_check_command)), - $this->commandArguments($this->host->host_check_command) -) ?> -hostgroups)): ?> -hostgroups as $name => $alias) { - $list[] = $this->qlink($alias, 'monitoring/list/services', array( - 'hostgroups' => $name - )); -} -?> -Hostgroups:
- +render('show/components/header.phtml') ?> +render('show/components/output.phtml') ?> +render('show/components/hostgroups.phtml') ?> render('show/components/contacts.phtml') ?> render('show/components/comments.phtml') ?> - -customvars as $name => $value): ?> -escape($name) ?>: escape($value) ?>
- -host->host_perfdata): ?> -expandable( - 'Performance data', - $this->perfdata($this->host->host_perfdata), - array('collapsed' => false) -) ?> - +render('show/components/customvars.phtml') ?> +render('show/components/perfdata.phtml') ?> +render('show/components/checkstatistics.phtml') ?> +render('show/components/command.phtml') ?> preview_image ?> diff --git a/modules/monitoring/application/views/scripts/show/service.phtml b/modules/monitoring/application/views/scripts/show/service.phtml index 5023175d5..986599d02 100644 --- a/modules/monitoring/application/views/scripts/show/service.phtml +++ b/modules/monitoring/application/views/scripts/show/service.phtml @@ -1,31 +1,10 @@ -partial('show/header.phtml', array( - 'host' => $this->host, - 'service' => $this->service, - 'tabs' => $this->tabs, - 'compact' => $this->compact -)); ?> -expandable( - $this->pluginOutput($this->service->service_output), - $this->pluginOutput($this->service->service_long_output) -) ?> - +render('show/components/header.phtml') ?> +render('show/components/output.phtml') ?> +render('show/components/servicegroups.phtml') ?> render('show/components/contacts.phtml') ?> render('show/components/comments.phtml') ?> - -customvars as $name => $value): ?> -escape($name) ?>: escape($value) ?>
- -expandable( - 'Command: ' . array_shift(preg_split('|!|', $this->service->service_check_command)), - $this->commandArguments($this->service->service_check_command) -) ?> -service->service_perfdata): ?> -expandable( - 'Performance data:', - $this->perfdata($this->service->service_perfdata), - array('collapsed' => false) -) ?> - - -partial('show/legacy-service.phtml', array('service' => $this->service)) ?> +render('show/components/customvars.phtml') ?> +render('show/components/perfdata.phtml') ?> +render('show/components/checkstatistics.phtml') ?> +render('show/components/command.phtml') ?> preview_image ?> diff --git a/modules/monitoring/application/views/scripts/show/services.phtml b/modules/monitoring/application/views/scripts/show/services.phtml index 84a566277..eb1b5f101 100644 --- a/modules/monitoring/application/views/scripts/show/services.phtml +++ b/modules/monitoring/application/views/scripts/show/services.phtml @@ -1 +1,2 @@ -services ?> +render('show/components/header.phtml') ?> + diff --git a/modules/monitoring/application/views/scripts/show/ticket.phtml b/modules/monitoring/application/views/scripts/show/ticket.phtml index b37eda8db..8e45ffd51 100644 --- a/modules/monitoring/application/views/scripts/show/ticket.phtml +++ b/modules/monitoring/application/views/scripts/show/ticket.phtml @@ -1,2 +1,2 @@ -tabs ?> + diff --git a/modules/monitoring/application/views/scripts/summary/group.phtml b/modules/monitoring/application/views/scripts/summary/group.phtml index bd14fb457..8c9547dc5 100644 --- a/modules/monitoring/application/views/scripts/summary/group.phtml +++ b/modules/monitoring/application/views/scripts/summary/group.phtml @@ -1,17 +1,17 @@ -compact): ?> +compact): ?> tabs ?> - -summary)): ?> + +summary)): ?> There are no such services right now - + -compact && $this->summary instanceof \Zend_Paginator): ?> +compact && $this->summary instanceof \Zend_Paginator): ?> paginationControl($this->summary, null, null, array('preserve' => $this->preserve)); ?> - + @@ -20,11 +20,11 @@ $now = time(); - compact): ?> + compact): ?> -summary as $row): ?> +summary as $row): ?> hostgroup_name)) { } ?> - + --> - compact): ?> + compact): ?> - +
Critical Unknown WarningOKOK
- -compact): ?>more + +compact): ?>more diff --git a/modules/monitoring/bin/action/list.inc.php b/modules/monitoring/bin/action/list.inc.php new file mode 100644 index 000000000..c46d14a81 --- /dev/null +++ b/modules/monitoring/bin/action/list.inc.php @@ -0,0 +1,126 @@ +shift('backend')); + +$query = $backend->select()->from('status', array( + 'host_name', + 'host_state', + 'host_output', + 'host_acknowledged', + 'host_in_downtime', + 'service_description', + 'service_state', + 'service_acknowledged', + 'service_in_downtime', + 'service_handled', + 'service_output', + 'service_last_state_change' +))->order('service_last_state_change ASC'); + +$endless = $params->shift('endless'); +$query->applyFilters($params->getParams()); +$host_colors = array( + 0 => '2', // UP + 1 => '1', // DOWN + 2 => '3', // UNREACH (brown) + 99 => '0', // PEND +); +$host_states = array( + 0 => 'UP', // UP + 1 => 'DOWN', // DOWN + 2 => 'UNREACHABLE', // UNREACH (brown) + 99 => 'PENDING', // PEND +); +$service_colors = array( + 0 => '2', // OK + 1 => '3', // WARN + 2 => '1', // CRIT + 3 => '5', // UNKN + 99 => '0', // PEND +); +$service_states = array( + 0 => 'OK', // OK + 1 => 'WARNING', // WARN + 2 => 'CRITICAL', // CRIT + 3 => 'UNKNOWN', // UNKN + 99 => 'PENDING', // PEND +); + +$finished = false; +while (! $finished) { +$out = ''; +$last_host = null; + +foreach ($query->fetchAll() as $key => $row) { + $host_extra = array(); + if ($row->host_in_downtime) { + $host_extra[] = 'DOWNTIME'; + } + if ($row->host_acknowledged) { + $host_extra[] = 'ACK'; + } + if (empty($host_extra)) { + $host_extra = ''; + } else { + $host_extra = " \033[34;1m[" . implode(',', $host_extra) . "]\033[0m"; + } + + $service_extra = array(); + if ($row->service_in_downtime) { + $service_extra[] = 'DOWNTIME'; + } + if ($row->service_acknowledged) { + $service_extra[] = 'ACK'; + } + if (empty($service_extra)) { + $service_extra = ''; + } else { + $service_extra = " \033[34;52;1m[" . implode(',', $service_extra) . "]\033[0m"; + } + + + if ($row->host_name !== $last_host) { + $out .= sprintf( + "\n\033[01;37;4%dm %-5s \033[0m \033[30;1m%s\033[0m%s: %s\n", + $host_colors[$row->host_state], + substr($host_states[$row->host_state], 0, 5), + $row->host_name, + $host_extra, + $row->host_output + ); + } + $last_host = $row->host_name; + $out .= sprintf( + "\033[01;37;4%dm \033[01;37;4%dm %4s \033[0m %s%s since %s: %s\n", + $host_colors[$row->host_state], + $service_colors[$row->service_state], + substr($service_states[$row->service_state] . ' ', 0, 4), + $row->service_description, + $service_extra, + Format::timeSince($row->service_last_state_change), + preg_replace('/\n/', sprintf( + "\n\033[01;37;4%dm \033[01;37;4%dm \033[0m ", + $host_colors[$row->host_state], + $service_colors[$row->service_state] + + ), substr(wordwrap(str_repeat(' ', 30) . preg_replace('~\@{3,}~', '@@@', $row->service_output), 72), 30)) + ); +} + +$out .= "\n"; + + + + + if ($endless) { + echo "\033[2J\033[1;1H\033[1S" . $out; + sleep(3); + } else { + echo $out; + $finished = true; + } +} + diff --git a/modules/monitoring/bin/soaptest.php b/modules/monitoring/bin/soaptest.php new file mode 100644 index 000000000..2b0fada80 --- /dev/null +++ b/modules/monitoring/bin/soaptest.php @@ -0,0 +1,21 @@ + 'icingaadmin', + 'password' => 'tomtom', + 'trace' => true, + 'exceptions' => true, + 'cache_wsdl' => WSDL_CACHE_NONE, + 'features' => SOAP_SINGLE_ELEMENT_ARRAYS, +// 'authentication' => SOAP_AUTHENTICATION_BASIC + +)); + +// print_r($client->__getFunctions()); +try { +print_r($client->problems()); +} catch (Exception $e) { + echo $e->getMessage() . "\n\n"; + echo $client->__getLastRequest() . "\n\n"; + echo $client->__getLastResponse() . "\n\n"; +} diff --git a/modules/monitoring/library/Monitoring/Backend/AbstractBackend.php b/modules/monitoring/library/Monitoring/Backend/AbstractBackend.php index 0dcdb278a..82ca86126 100644 --- a/modules/monitoring/library/Monitoring/Backend/AbstractBackend.php +++ b/modules/monitoring/library/Monitoring/Backend/AbstractBackend.php @@ -82,118 +82,4 @@ class AbstractBackend implements DatasourceInterface { return $this->getName(); } - - - - // UGLY temporary host fetch - public function fetchHost($host) - { - $select = $this->select() - ->from('status', array( - 'host_name', - 'host_address', - 'host_state', - 'host_handled', - 'host_in_downtime', - 'host_acknowledged', - 'host_check_command', - 'host_last_state_change', - 'host_alias', - 'host_output', - 'host_long_output', - 'host_perfdata', - )) - ->where('host_name', $host); - return $select->fetchRow(); - $object = \Icinga\Objects\Host::fromBackend( - $this->select() - ->from('status', array( - 'host_name', - 'host_address', - 'host_state', - 'host_handled', - 'host_in_downtime', - 'host_acknowledged', - 'host_check_command', - 'host_last_state_change', - 'host_alias', - 'host_output', - 'host_long_output', - 'host_perfdata', - )) - ->where('host_name', $host) - ->fetchRow() - ); - // $object->customvars = $this->fetchCustomvars($host); - return $object; - } - - // UGLY temporary service fetch - public function fetchService($host, $service) - { -Benchmark::measure('Preparing service select'); - $select = $this->select() - ->from('status', array( - - 'host_name', - 'host_state', - 'host_check_command', - 'host_last_state_change', - - 'service_description', - 'service_state', - 'service_acknowledged', - 'service_handled', - 'service_output', - 'service_long_output', - 'service_perfdata', - // '_host_satellite', - 'service_check_command', - 'service_last_state_change', - 'service_last_check', - 'service_next_check', - 'service_check_execution_time', - 'service_check_latency', - // 'service_ - )) - ->where('host_name', $host) - ->where('service_description', $service); - // Benchmark::measure((string) $select->getQuery()); -Benchmark::measure('Prepared service select'); - - return $select->fetchRow(); - $object = \Icinga\Objects\Service::fromBackend( - $this->select() - ->from('status', array( - - 'host_name', - 'host_state', - 'host_check_command', - 'host_last_state_change', - - 'service_description', - 'service_state', - 'service_acknowledged', - 'service_handled', - 'service_output', - 'service_long_output', - 'service_perfdata', - // '_host_satellite', - 'service_check_command', - 'service_last_state_change', - 'service_last_check', - 'service_next_check', - 'service_check_execution_time', - 'service_check_latency', - // 'service_ - )) - ->where('host_name', $host) - ->where('service_description', $service) - ->fetchRow() - ); - // $object->customvars = $this->fetchCustomvars($host, $service); - return $object; - } - - } diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/AbstractQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/AbstractQuery.php index f27fb1afd..3f8c877f4 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/AbstractQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/AbstractQuery.php @@ -19,6 +19,8 @@ abstract class AbstractQuery extends Query protected $joinedVirtualTables = array(); protected $object_id = 'object_id'; + protected $host_id = 'host_id'; + protected $service_id = 'service_id'; protected $hostgroup_id = 'hostgroup_id'; protected $servicegroup_id = 'servicegroup_id'; @@ -31,10 +33,18 @@ abstract class AbstractQuery extends Query $this->prefix = $this->ds->getPrefix(); if ($this->ds->getConnection()->getDbType() === 'oracle') { - $this->object_id = $this->hostgroup_id = $this->servicegroup_id = 'id'; + $this->object_id = $this->host_id = $this->service_id = $this->hostgroup_id = $this->servicegroup_id = 'id'; // REALLY? foreach ($this->columnMap as $table => & $columns) { - foreach ($column as $key => & $value) { + foreach ($columns as $key => & $value) { $value = preg_replace('/UNIX_TIMESTAMP/', 'localts2unixts', $value); + $value = preg_replace('/ COLLATE .+$/', '', $value); + } + } + } + if ($this->ds->getConnection()->getDbType() === 'pgsql') { + foreach ($this->columnMap as $table => & $columns) { + foreach ($columns as $key => & $value) { + $value = preg_replace('/ COLLATE .+$/', '', $value); } } } @@ -58,7 +68,11 @@ abstract class AbstractQuery extends Query // TODO: extend if we allow queries with only hosts / only services // ($leftcol s.host_object_id vs h.host_object_id - $leftcol = 's.' . $type . '_object_id'; + if ($this->hasJoinedVirtualTable('services')) { + $leftcol = 's.' . $type . '_object_id'; + } else { + $leftcol = 'h.' . $type . '_object_id'; + } $joinOn = $leftcol . ' = ' . $alias @@ -100,7 +114,7 @@ abstract class AbstractQuery extends Query protected function beforeCreatingSelectQuery() { $this->setRealColumns(); - Benchmark::measure(sprintf('%s is going to SELECT', get_class($this))); + Benchmark::measure(sprintf('%s ready to run', array_pop(explode('\\', get_class($this))))); } protected function applyAllFilters() @@ -274,6 +288,10 @@ abstract class AbstractQuery extends Query // Go through all given values foreach ($value as $val) { + if ($val === '') { + // TODO: REALLY?? + continue; + } // Value starting with minus: negation if ($val[0] === '-') { $val = substr($val, 1); diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommentQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommentQuery.php index 5759a1c58..49692a949 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommentQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommentQuery.php @@ -8,15 +8,16 @@ class CommentQuery extends AbstractQuery 'comments' => array( 'comment_data' => 'cm.comment_data', 'comment_author' => 'cm.author_name', - 'comment_timestamp' => 'UNIX_TIMESTAMP(cm.entry_time)', + //'comment_timestamp' => 'UNIX_TIMESTAMP(cm.entry_time)', + 'comment_timestamp' => 'UNIX_TIMESTAMP(cm.comment_time)', 'comment_type' => "CASE cm.entry_type WHEN 1 THEN 'comment' WHEN 2 THEN 'downtime' WHEN 3 THEN 'flapping' WHEN 4 THEN 'ack' END", ), 'hosts' => array( 'host_name' => 'ho.name1', ), 'services' => array( - 'service_host_name' => 'so.name1', - 'service_description' => 'so.name2', + 'service_host_name' => 'so.name1 COLLATE latin1_general_ci', + 'service_description' => 'so.name2 COLLATE latin1_general_ci', ) ); diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactQuery.php index 94e17e0f3..ca81845b5 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactQuery.php @@ -6,17 +6,17 @@ class ContactQuery extends AbstractQuery { protected $columnMap = array( 'contacts' => array( - 'contact_name' => 'co.name1', + 'contact_name' => 'co.name1 COLLATE latin1_general_ci', 'contact_alias' => 'c.alias', 'contact_email' => 'c.email_address', 'contact_pager' => 'c.pager_address', ), 'hosts' => array( - 'host_name' => 'ho.name1', + 'host_name' => 'ho.name1 COLLATE latin1_general_ci', ), 'services' => array( - 'service_host_name' => 'so.name1', - 'service_description' => 'so.name2', + 'service_host_name' => 'so.name1 COLLATE latin1_general_ci', + 'service_description' => 'so.name2 COLLATE latin1_general_ci', ) ); diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactgroupQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactgroupQuery.php index b7f1ac0fc..e4fb8e788 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactgroupQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactgroupQuery.php @@ -6,18 +6,18 @@ class ContactgroupQuery extends AbstractQuery { protected $columnMap = array( 'contactgroups' => array( - 'contactgroup_name' => 'cgo.name1', + 'contactgroup_name' => 'cgo.name1 COLLATE latin1_general_ci', 'contactgroup_alias' => 'cg.alias', ), 'contacts' => array( - 'contact_name' => 'co.name1', + 'contact_name' => 'co.name1 COLLATE latin1_general_ci', ), 'hosts' => array( 'host_name' => 'ho.name1', ), 'services' => array( - 'service_host_name' => 'so.name1', - 'service_description' => 'so.name2', + 'service_host_name' => 'so.name1 COLLATE latin1_general_ci', + 'service_description' => 'so.name2 COLLATE latin1_general_ci', ) ); diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/CustomvarQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CustomvarQuery.php index a6175373f..d12b3f416 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/CustomvarQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CustomvarQuery.php @@ -12,9 +12,10 @@ class CustomvarQuery extends AbstractQuery 'varvalue' => 'cvs.varvalue', ), 'objects' => array( - 'host_name' => 'cvo.name1', - 'service_description' => 'cvo.name2', - 'contact_name' => 'cvo.name1', + 'host_name' => 'cvo.name1 COLLATE latin1_general_ci', + 'service_host_name' => 'cvo.name1 COLLATE latin1_general_ci', + 'service_description' => 'cvo.name2 COLLATE latin1_general_ci', + 'contact_name' => 'cvo.name1 COLLATE latin1_general_ci', 'object_type' => "CASE cvo.objecttype_id WHEN 1 THEN 'host' WHEN 2 THEN 'service' WHEN 10 THEN 'contact' ELSE 'invalid' END" // '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" ), diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventHistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventHistoryQuery.php index 9c4554e99..b8ab36e46 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventHistoryQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventHistoryQuery.php @@ -10,10 +10,10 @@ class EventHistoryQuery extends AbstractQuery protected $columnMap = array( 'eventhistory' => array( - 'host' => 'eho.name1', - 'service' => 'eho.name2', - 'host_name' => 'eho.name1', - 'service_description' => 'eho.name2', + 'host' => 'eho.name1 COLLATE latin1_general_ci', + 'service' => 'eho.name2 COLLATE latin1_general_ci', + 'host_name' => 'eho.name1 COLLATE latin1_general_ci', + 'service_description' => 'eho.name2 COLLATE latin1_general_ci', 'object_type' => "CASE WHEN eho.objecttype_id = 1 THEN 'host' ELSE 'service' END", 'timestamp' => 'UNIX_TIMESTAMP(eh.state_time)', 'raw_timestamp' => 'eh.state_time', @@ -69,7 +69,8 @@ class EventHistoryQuery extends AbstractQuery 'type' => "('dt_start')", 'state' => '(NULL)', 'state_type' => '(NULL)', - 'output' => "CONCAT('[', author_name, '] ', comment_data)", +// 'output' => "CONCAT('[', author_name, '] ', comment_data)", + 'output' => "('[' || author_name || '] ' || comment_data)", 'attempt' => '(NULL)', 'max_attempts' => '(NULL)', ) @@ -90,7 +91,8 @@ class EventHistoryQuery extends AbstractQuery 'type' => "('dt_end')", 'state' => '(NULL)', 'state_type' => '(NULL)', - 'output' => "CONCAT('[', author_name, '] ', comment_data)", +// 'output' => "CONCAT('[', author_name, '] ', comment_data)", + 'output' => "('[' || author_name || '] ' || comment_data)", 'attempt' => '(NULL)', 'max_attempts' => '(NULL)', ) @@ -110,7 +112,8 @@ class EventHistoryQuery extends AbstractQuery 'type' => "(CASE entry_type WHEN 1 THEN 'comment' WHEN 2 THEN 'dt_comment' WHEN 3 THEN 'flapping' WHEN 4 THEN 'ack' END)", 'state' => '(NULL)', 'state_type' => '(NULL)', - 'output' => "CONCAT('[', author_name, '] ', comment_data)", +// 'output' => "CONCAT('[', author_name, '] ', comment_data)", + 'output' => "('[' || author_name || '] ' || comment_data)", 'attempt' => '(NULL)', 'max_attempts' => '(NULL)', ) @@ -121,14 +124,39 @@ class EventHistoryQuery extends AbstractQuery } if ($end !== null) { $comments->where('comment_time <= ?', $end); - } + } + + // This is one of the db-specific workarounds that could be abstracted + // in a better way: + switch ($this->ds->getConnection()->getDbType()) { + case 'mysql': + $concat_contacts = "GROUP_CONCAT(c.alias ORDER BY c.alias SEPARATOR ', ')"; + break; + case 'pgsql': + // TODO: Find a way to "ORDER" these: + $concat_contacts = "ARRAY_TO_STRING(ARRAY_AGG(c.alias), ', ')"; + break; + case 'oracle': + // TODO: This is only valid for Oracle >= 11g Release 2. + $concat_contacts = "LISTAGG(c.alias, ', ') WITHIN GROUP (ORDER BY c.alias)"; + // Alternatives: + // + // RTRIM(XMLAGG(XMLELEMENT(e, column_name, ',').EXTRACT('//text()')), + // + // not supported and not documented but works since 10.1, + // however it is NOT always present; + // WM_CONCAT(c.alias) + break; + default: + die('Not yet'); // TODO: Proper Exception + } $cndetails = $this->db->select()->from( array('cn' => $this->prefix . 'contactnotifications'), array( + 'notification_id' => 'notification_id', 'cnt' => 'COUNT(*)', - 'contacts' => 'GROUP_CONCAT(c.alias)', - 'notification_id' => 'notification_id' + 'contacts' => $concat_contacts ) )->join( array('c' => $this->prefix . 'contacts'), @@ -144,7 +172,8 @@ class EventHistoryQuery extends AbstractQuery 'type' => "('notify')", 'state' => 'state', 'state_type' => '(NULL)', - 'output' => "CONCAT('[', cndetails.contacts, '] ', n.output)", + // 'output' => "CONCAT('[', cndetails.contacts, '] ', n.output)", + 'output' => "('[' || cndetails.contacts || '] ' || n.output)", 'attempt' => '(NULL)', 'max_attempts' => '(NULL)', ) @@ -238,4 +267,4 @@ class EventHistoryQuery extends AbstractQuery $query->where('object_id IN (?)', $objectId); } } -} \ No newline at end of file +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostgroupQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostgroupQuery.php index e1a08f043..b5245c220 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostgroupQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostgroupQuery.php @@ -6,11 +6,12 @@ class HostgroupQuery extends AbstractQuery { protected $columnMap = array( 'hostgroups' => array( - 'hostgroup_name' => 'hgo.name1', + 'hostgroup_name' => 'hgo.name1 COLLATE latin1_general_ci', 'hostgroup_alias' => 'hg.alias', + 'id' => 'hg.hostgroup_id', ), 'hosts' => array( - 'host_name' => 'ho.name1' + 'host_name' => 'ho.name1 COLLATE latin1_general_ci' ) ); 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 000000000..a98037c5a --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatusQuery.php @@ -0,0 +1,197 @@ + array( + 'host' => 'ho.name1 COLLATE latin1_general_ci', + 'host_name' => 'ho.name1 COLLATE latin1_general_ci', + 'host_display_name' => 'h.display_name', + 'host_alias' => 'h.alias', + 'host_address' => 'h.address', + 'host_ipv4' => 'INET_ATON(h.address)', + 'host_icon_image' => 'h.icon_image', + ), + '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', + 'host_output' => 'hs.output', + 'host_long_output' => 'hs.long_output', + 'host_perfdata' => 'hs.perfdata', + 'host_problem' => 'CASE WHEN hs.current_state = 0 THEN 0 ELSE 1 END', + 'host_acknowledged' => 'hs.problem_has_been_acknowledged', + 'host_in_downtime' => 'CASE WHEN (hs.scheduled_downtime_depth = 0) 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_does_active_checks' => 'hs.active_checks_enabled', + 'host_accepts_passive_checks' => 'hs.passive_checks_enabled', + 'host_last_state_change' => 'UNIX_TIMESTAMP(hs.last_state_change)', + 'host_last_hard_state' => 'hs.last_hard_state', + 'host_check_command' => 'hs.check_command', + 'host_last_check' => 'UNIX_TIMESTAMP(hs.last_check)', + 'host_next_check' => 'CASE WHEN hs.should_be_scheduled THEN UNIX_TIMESTAMP(hs.next_check) ELSE NULL END', + 'host_check_execution_time' => 'hs.execution_time', + 'host_check_latency' => 'hs.latency', + 'host_notifications_enabled' => 'hs.notifications_enabled', + 'host_last_time_up' => 'hs.last_time_up', + 'host_last_time_down' => 'hs.last_time_down', + 'host_last_time_unreachable' => 'hs.last_time_unreachable', + + 'host_severity' => 'CASE WHEN hs.current_state = 0 + THEN + CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL + THEN 16 + ELSE 0 + END + + + CASE WHEN hs.problem_has_been_acknowledged = 1 + THEN 2 + ELSE + CASE WHEN hs.scheduled_downtime_depth > 0 + THEN 1 + ELSE 4 + END + END + ELSE + CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 16 + WHEN hs.current_state = 1 THEN 32 + WHEN hs.current_state = 2 THEN 64 + ELSE 256 + END + + + CASE WHEN hs.problem_has_been_acknowledged = 1 + THEN 2 + ELSE + CASE WHEN hs.scheduled_downtime_depth > 0 + THEN 1 + ELSE 4 + END + END + END', + ), + 'hostgroups' => array( + 'hostgroups' => 'hgo.name1', + ), + ); + + protected function getDefaultColumns() + { + return $this->columnMap['hosts'] + + $this->columnMap['hoststatus']; + } + + protected function joinBaseTables() + { + // TODO: Shall we always add hostobject? + $this->baseQuery = $this->db->select()->from( + array('ho' => $this->prefix . 'objects'), + array() + )->join( + array('hs' => $this->prefix . 'hoststatus'), + 'ho.' . $this->object_id . ' = hs.host_object_id AND ho.is_active = 1 AND ho.objecttype_id = 1', + array() + )->join( + array('h' => $this->prefix . 'hosts'), + 'hs.host_object_id = h.host_object_id', + array() + ); + $this->joinedVirtualTables = array( + 'hosts' => true, + 'hoststatus' => true, + ); + } + + protected function joinStatus() + { + $this->requireVirtualTable('services'); + } + + protected function joinServiceStatus() + { + $this->requireVirtualTable('services'); + } + + protected function joinServices() + { + $this->baseQuery->join( + array('s' => $this->prefix . 'services'), + 's.host_object_id = h.host_object_id', + array() + )->join( + array('so' => $this->prefix . 'objects'), + "so.$this->object_id = s.service_object_id AND so.is_active = 1", + array() + )->joinLeft( + array('ss' => $this->prefix . 'servicestatus'), + "so.$this->object_id = ss.service_object_id", + array() + ); + } + + protected function joinHostgroups() + { + if ($this->hasJoinedVirtualTable('services')) { + return $this->joinServiceHostgroups(); + } else { + return $this->joinHostHostgroups(); + } + } + + protected function joinHostHostgroups() + { + $this->baseQuery->join( + array('hgm' => $this->prefix . 'hostgroup_members'), + 'hgm.host_object_id = h.host_object_id', + array() + )->join( + array('hg' => $this->prefix . 'hostgroups'), + "hgm.hostgroup_id = hg.$this->hostgroup_id", + array() + ); + + return $this; + } + + protected function joinServiceHostgroups() + { + $this->baseQuery->join( + array('hgm' => $this->prefix . 'hostgroup_members'), + 'hgm.host_object_id = s.host_object_id', + array() + )->join( + array('hg' => $this->prefix . 'hostgroups'), + 'hgm.hostgroup_id = hg.' . $this->hostgroup_id, + array() + )->join( + array('hgo' => $this->prefix . 'objects'), + 'hgo.' . $this->object_id. ' = hg.hostgroup_object_id' + . ' AND hgo.is_active = 1', + array() + ); + + return $this; + } + + protected function joinServicegroups() + { + $this->requireVirtualTable('services'); + $this->baseQuery->join( + array('sgm' => $this->prefix . 'servicegroup_members'), + 'sgm.service_object_id = s.service_object_id', + array() + )->join( + array('sg' => $this->prefix . 'servicegroups'), + 'sgm.servicegroup_id = sg.' . $this->servicegroup_id, + array() + )->join( + array('sgo' => $this->prefix . 'objects'), + 'sgo.' . $this->object_id. ' = sg.servicegroup_object_id' + . ' AND sgo.is_active = 1', + array() + ); + + return $this; + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicegroupQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicegroupQuery.php index d54fa8753..5ee261010 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicegroupQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicegroupQuery.php @@ -6,12 +6,13 @@ class ServicegroupQuery extends AbstractQuery { protected $columnMap = array( 'servicegroups' => array( - 'servicegroup_name' => 'sgo.name1', + 'servicegroup_name' => 'sgo.name1 COLLATE latin1_general_ci', 'servicegroup_alias' => 'sg.alias', ), 'services' => array( - 'host_name' => 'so.name1', - 'service_description' => 'so.name2' + 'host_name' => 'so.name1 COLLATE latin1_general_ci', + 'service_host_name' => 'so.name1 COLLATE latin1_general_ci', + 'service_description' => 'so.name2 COLLATE latin1_general_ci' ) ); @@ -34,11 +35,11 @@ class ServicegroupQuery extends AbstractQuery { $this->baseQuery->join( array('sgm' => $this->prefix . 'servicegroup_members'), - 'sgm.servicegroup_id = sg.servicegroup_id', + 'sgm.' . $this->servicegroup_id . ' = sg.' . $this->servicegroup_id, array() )->join( array('so' => $this->prefix . 'objects'), - 'sgm.service_object_id = so.object_id AND so.is_active = 1', + 'sgm.service_object_id = so.' . $this->object_id . ' AND so.is_active = 1', array() ); } 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 000000000..3b24dbca8 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicestatusQuery.php @@ -0,0 +1,167 @@ + array( + 'service_host_name' => 'so.name1 COLLATE latin1_general_ci', + 'service' => 'so.name2 COLLATE latin1_general_ci', + 'service_description' => 'so.name2 COLLATE latin1_general_ci', + 'service_display_name' => 's.display_name', + 'service_icon_image' => 's.icon_image', + ), + 'servicestatus' => array( + 'current_state' => 'CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 99 ELSE ss.current_state 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_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_state_type' => 'ss.state_type', + 'service_output' => 'ss.output', + 'service_long_output' => 'ss.long_output', + 'service_perfdata' => 'ss.perfdata', + 'service_acknowledged' => 'ss.problem_has_been_acknowledged', + 'service_in_downtime' => 'CASE WHEN (ss.scheduled_downtime_depth = 0) 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_does_active_checks' => 'ss.active_checks_enabled', + 'service_accepts_passive_checks' => 'ss.passive_checks_enabled', + 'service_last_state_change' => 'UNIX_TIMESTAMP(ss.last_state_change)', + 'service_last_hard_state' => 'ss.last_hard_state', + 'service_last_hard_state_change' => 'UNIX_TIMESTAMP(ss.last_hard_state_change)', + 'service_check_command' => 'ss.check_command', + 'service_last_check' => 'UNIX_TIMESTAMP(ss.last_check)', + 'service_next_check' => 'CASE WHEN ss.should_be_scheduled THEN UNIX_TIMESTAMP(ss.next_check) ELSE NULL END', + 'service_check_execution_time' => 'ss.execution_time', + 'service_check_latency' => 'ss.latency', + 'service_notifications_enabled' => 'ss.notifications_enabled', + 'service_last_time_ok' => 'ss.last_time_ok', + 'service_last_time_warning' => 'ss.last_time_warning', + 'service_last_time_critical' => 'ss.last_time_critical', + 'service_last_time_unknown' => 'ss.last_time_unknown', + ), + 'servicegroups' => array( + 'servicegroups' => 'sgo.name1', + ), + ); + + protected function getDefaultColumns() + { + return $this->columnMap['services'] + + $this->columnMap['servicestatus']; + } + + protected function joinBaseTables() + { + // TODO: Shall we always add hostobject? + $this->baseQuery = $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() + )->join( + array('s' => $this->prefix . 'services'), + 'ss.service_object_id = s.service_object_id', + array() + ); + $this->joinedVirtualTables = array( + 'services' => true, + 'servicestatus' => true, + ); + } + + protected function joinStatus() + { + $this->requireVirtualTable('services'); + } + + protected function joinServiceStatus() + { + $this->requireVirtualTable('services'); + } + + protected function joinServices() + { + $this->baseQuery->join( + array('s' => $this->prefix . 'services'), + 's.host_object_id = h.host_object_id', + array() + )->join( + array('so' => $this->prefix . 'objects'), + "so.$this->object_id = s.service_object_id AND so.is_active = 1", + array() + )->joinLeft( + array('ss' => $this->prefix . 'servicestatus'), + "so.$this->object_id = ss.service_object_id", + array() + ); + } + + protected function joinHostgroups() + { + if ($this->hasJoinedVirtualTable('services')) { + return $this->joinServiceHostgroups(); + } else { + return $this->joinHostHostgroups(); + } + } + + protected function joinHostHostgroups() + { + $this->baseQuery->join( + array('hgm' => $this->prefix . 'hostgroup_members'), + 'hgm.host_object_id = h.host_object_id', + array() + )->join( + array('hg' => $this->prefix . 'hostgroups'), + "hgm.hostgroup_id = hg.$this->hostgroup_id", + array() + ); + + return $this; + } + + protected function joinServiceHostgroups() + { + $this->baseQuery->join( + array('hgm' => $this->prefix . 'hostgroup_members'), + 'hgm.host_object_id = s.host_object_id', + array() + )->join( + array('hg' => $this->prefix . 'hostgroups'), + 'hgm.hostgroup_id = hg.' . $this->hostgroup_id, + array() + )->join( + array('hgo' => $this->prefix . 'objects'), + 'hgo.' . $this->object_id. ' = hg.hostgroup_object_id' + . ' AND hgo.is_active = 1', + array() + ); + + return $this; + } + + protected function joinServicegroups() + { + $this->requireVirtualTable('services'); + $this->baseQuery->join( + array('sgm' => $this->prefix . 'servicegroup_members'), + 'sgm.service_object_id = s.service_object_id', + array() + )->join( + array('sg' => $this->prefix . 'servicegroups'), + 'sgm.servicegroup_id = sg.' . $this->servicegroup_id, + array() + )->join( + array('sgo' => $this->prefix . 'objects'), + 'sgo.' . $this->object_id. ' = sg.servicegroup_object_id' + . ' AND sgo.is_active = 1', + array() + ); + + return $this; + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php index 4d2ee946e..e68f64260 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php @@ -8,8 +8,8 @@ class StatusQuery extends AbstractQuery protected $columnMap = array( 'hosts' => array( - 'host' => 'ho.name1', - 'host_name' => 'ho.name1', + 'host' => 'ho.name1 COLLATE latin1_general_ci', + 'host_name' => 'ho.name1 COLLATE latin1_general_ci', 'host_display_name' => 'h.display_name', 'host_alias' => 'h.alias', 'host_address' => 'h.address', @@ -27,8 +27,18 @@ class StatusQuery extends AbstractQuery 'host_does_active_checks' => 'hs.active_checks_enabled', 'host_accepts_passive_checks' => 'hs.passive_checks_enabled', 'host_last_state_change' => 'UNIX_TIMESTAMP(hs.last_state_change)', + 'host_last_hard_state' => 'hs.last_hard_state', 'host_check_command' => 'hs.check_command', + 'host_last_check' => 'UNIX_TIMESTAMP(hs.last_check)', + 'host_next_check' => 'CASE WHEN hs.should_be_scheduled = 1 THEN UNIX_TIMESTAMP(hs.next_check) ELSE NULL END', + 'host_check_execution_time' => 'hs.execution_time', + 'host_check_latency' => 'hs.latency', 'host_problems' => 'CASE WHEN hs.current_state = 0 THEN 0 ELSE 1 END', + 'host_notifications_enabled' => 'hs.notifications_enabled', + 'host_last_time_up' => 'hs.last_time_up', + 'host_last_time_down' => 'hs.last_time_down', + 'host_last_time_unreachable' => 'hs.last_time_unreachable', + 'host_severity' => 'CASE WHEN hs.current_state = 0 THEN CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL @@ -64,10 +74,13 @@ class StatusQuery extends AbstractQuery 'hostgroups' => array( 'hostgroups' => 'hgo.name1', ), + 'servicegroups' => array( + 'servicegroups' => 'sgo.name1', + ), 'services' => array( - 'service_host_name' => 'so.name1', - 'service' => 'so.name2', - 'service_description' => 'so.name2', + 'service_host_name' => 'so.name1 COLLATE latin1_general_ci', + 'service' => 'so.name2 COLLATE latin1_general_ci', + 'service_description' => 'so.name2 COLLATE latin1_general_ci', 'service_display_name' => 's.display_name', 'service_icon_image' => 's.icon_image', ), @@ -85,12 +98,18 @@ class StatusQuery extends AbstractQuery 'service_does_active_checks' => 'ss.active_checks_enabled', 'service_accepts_passive_checks' => 'ss.passive_checks_enabled', 'service_last_state_change' => 'UNIX_TIMESTAMP(ss.last_state_change)', + 'service_last_hard_state' => 'ss.last_hard_state', 'service_last_hard_state_change' => 'UNIX_TIMESTAMP(ss.last_hard_state_change)', 'service_check_command' => 'ss.check_command', 'service_last_check' => 'UNIX_TIMESTAMP(ss.last_check)', - 'service_next_check' => 'CASE WHEN ss.should_be_scheduled THEN UNIX_TIMESTAMP(ss.next_check) ELSE NULL END', + 'service_next_check' => 'CASE WHEN ss.should_be_scheduled = 1 THEN UNIX_TIMESTAMP(ss.next_check) ELSE NULL END', 'service_check_execution_time' => 'ss.execution_time', 'service_check_latency' => 'ss.latency', + 'service_notifications_enabled' => 'ss.notifications_enabled', + 'service_last_time_ok' => 'ss.last_time_ok', + 'service_last_time_warning' => 'ss.last_time_warning', + 'service_last_time_critical' => 'ss.last_time_critical', + 'service_last_time_unknown' => 'ss.last_time_unknown', ), 'status' => array( 'problems' => 'CASE WHEN ss.current_state = 0 THEN 0 ELSE 1 END', @@ -127,12 +146,14 @@ class StatusQuery extends AbstractQuery END END END', - ) + ), ); +/* public function group($col) { $this->baseQuery->group($col); } +*/ protected function getDefaultColumns() { return $this->columnMap['hosts']; @@ -151,7 +172,7 @@ public function group($col) array() )->join( array('hs' => $this->prefix . 'hoststatus'), - 'ho.object_id = hs.host_object_id AND ho.is_active = 1', + 'ho.object_id = hs.host_object_id AND ho.is_active = 1 AND ho.objecttype_id = 1', array() )->join( array('h' => $this->prefix . 'hosts'), @@ -190,8 +211,7 @@ public function group($col) array() ); } - - // TODO: Test this one, doesn't seem to work right now + protected function joinHostgroups() { if ($this->hasJoinedVirtualTable('services')) { @@ -238,6 +258,7 @@ public function group($col) protected function joinServicegroups() { + $this->requireVirtualTable('services'); $this->baseQuery->join( array('sgm' => $this->prefix . 'servicegroup_members'), 'sgm.service_object_id = s.service_object_id', @@ -247,9 +268,9 @@ public function group($col) 'sgm.servicegroup_id = sg.' . $this->servicegroup_id, array() )->join( - array('hgo' => $this->prefix . 'objects'), - 'hgo.' . $this->object_id. ' = hg.' . $this->hostgroup_id - . ' AND hgo.is_active = 1', + array('sgo' => $this->prefix . 'objects'), + 'sgo.' . $this->object_id. ' = sg.servicegroup_object_id' + . ' AND sgo.is_active = 1', array() ); diff --git a/modules/monitoring/library/Monitoring/Backend/Livestatus/Query/StatusQuery.php b/modules/monitoring/library/Monitoring/Backend/Livestatus/Query/StatusQuery.php index cc1be7363..08fcfa1c8 100644 --- a/modules/monitoring/library/Monitoring/Backend/Livestatus/Query/StatusQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Livestatus/Query/StatusQuery.php @@ -23,6 +23,10 @@ class StatusQuery extends AbstractQuery 'host_accepts_passive_checks' => 'host_accept_passive_checks', 'host_last_state_change', + 'host_problems' => 'is_flapping', + 'service_in_downtime' => 'is_flapping', + 'service_handled' => 'is_flapping', + // Service config 'service_description' => 'description', 'service_display_name' => 'display_name', @@ -37,12 +41,34 @@ class StatusQuery extends AbstractQuery 'service_last_state_change' => 'last_state_change', // Service comments - 'comments_with_info', - 'downtimes_with_info', + //'comments_with_info', + //'downtimes_with_info', ); + public function init() + { + $this->query = $this->createQuery(); + //print_r($this->ds->getConnection()->fetchAll($this->query)); + //die('asdf'); + } + + public function count() + { + return $this->ds->getConnection()->count($this->query); + } + + public function fetchAll() + { + return $this->ds->getConnection()->fetchAll($this->query); + } + + public function fetchRow() + { + return array_shift($this->ds->getConnection()->fetchAll($this->query)); + } + protected function createQuery() { - return $this->connection->getConnection()->select()->from('services', $this->available_columns); + return $this->ds->getConnection()->select()->from('services', $this->available_columns); } } diff --git a/modules/monitoring/library/Monitoring/Environment.php b/modules/monitoring/library/Monitoring/Environment.php index 5b377b541..bf198db4f 100644 --- a/modules/monitoring/library/Monitoring/Environment.php +++ b/modules/monitoring/library/Monitoring/Environment.php @@ -3,6 +3,8 @@ namespace Icinga\Monitoring; use Icinga\Application\Config; +use Icinga\Web\Session; +use Exception; class Environment { diff --git a/modules/monitoring/library/Monitoring/Object/AbstractObject.php b/modules/monitoring/library/Monitoring/Object/AbstractObject.php new file mode 100644 index 000000000..0b1748231 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Object/AbstractObject.php @@ -0,0 +1,146 @@ + null, + // 'contacts' => null, + // 'contactgroups' => null, + // 'servicegroups' => null, + // 'customvars' => null, + // 'comments' => null, + ); + + public function __construct(AbstractBackend $backend, $name1, $name2 = null) + { + $this->backend = $backend; + $this->name1 = $name1; + $this->name2 = $name2; + $this->properties = (array) $this->fetchObject(); + } + + public static function fetch(AbstractBackend $backend, $name1, $name2 = null) + { + return new static($backend, $name1, $name2); + } + + abstract protected function fetchObject(); + + public function __isset($key) + { + return $this->$key !== null; + } + + public function __get($key) + { + if (isset($this->properties[$key])) { + return $this->properties[$key]; + } + if (array_key_exists($key, $this->foreign)) { + if ($this->foreign[$key] === null) { + $func = 'fetch' . ucfirst($key); + if (! method_exists($this, $func)) { + return null; + } + $this->$func($key); + } + return $this->foreign[$key]; + } + return null; + } + + public function prefetch() + { + return $this; + } + + abstract protected function applyObjectFilter(Query $query); + + protected function fetchHostgroups() + { + $this->foreign['hostgroups'] = $this->applyObjectFilter( + $this->backend->select()->from('hostgroup', array( + 'hostgroup_name', + 'hostgroup_alias' + )) + )->fetchPairs(); + return $this; + } + + protected function fetchServicegroups() + { + $this->foreign['servicegroups'] = $this->applyObjectFilter( + $this->backend->select()->from('servicegroup', array( + 'servicegroup_name', + 'servicegroup_alias' + )) + )->fetchPairs(); + return $this; + } + + protected function fetchContacts() + { + $this->foreign['contacts'] = $this->applyObjectFilter( + $this->backend->select()->from('contact', array( + 'contact_name', + 'contact_alias', + 'contact_email', + 'contact_pager', + )) + )->fetchAll(); + return $this; + } + + protected function fetchContactgroups() + { + $this->foreign['contactgroups'] = $this->applyObjectFilter( + $this->backend->select()->from('contactgroup', array( + 'contactgroup_name', + 'contactgroup_alias', + )) + )->fetchAll(); + return $this; + } + + protected function fetchComments() + { + $this->foreign['comments'] = $this->applyObjectFilter( + $this->backend->select()->from('comment', array( + 'comment_timestamp', + 'comment_author', + 'comment_data', + 'comment_type', + )) + )->fetchAll(); + return $this; + } + + protected function fetchCustomvars() + { + $this->foreign['customvars'] = $this->applyObjectFilter( + $this->backend->select()->from('customvar', array( + 'varname', + 'varvalue' + )) + ->where('varname', '-*PW*,-*PASS*,-*COMMUNITY*') + ->where('object_type', 'host') + )->fetchPairs(); + return $this; + } +} + diff --git a/modules/monitoring/library/Monitoring/Object/Host.php b/modules/monitoring/library/Monitoring/Object/Host.php new file mode 100644 index 000000000..b6b852273 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Object/Host.php @@ -0,0 +1,58 @@ + null, + 'contacts' => null, + 'contactgroups' => null, + 'customvars' => null, + 'comments' => null, + ); + + public function stateName() + { + // TODO + } + + protected function applyObjectFilter(Query $query) + { + return $query->where('host_name', $this->name1); + } + + public function prefetch() + { + return $this->fetchHostgroups() + ->fetchContacts() + ->fetchContactgroups() + ->fetchCustomvars() + ->fetchComments(); + } + + protected function fetchObject() + { + return $this->backend->select()->from('status', array( + 'host_name', + 'host_alias', + 'host_address', + 'host_state', + 'host_handled', + 'host_in_downtime', + 'host_acknowledged', + 'host_last_state_change', + 'last_check' => 'host_last_check', + 'next_check' => 'host_next_check', + 'check_execution_time' => 'host_check_execution_time', + 'check_latency' => 'host_check_latency', + 'output' => 'host_output', + 'long_output' => 'host_long_output', + 'check_command' => 'host_check_command', + 'perfdata' => 'host_perfdata', + ))->where('host_name', $this->name1)->fetchRow(); + } +} + diff --git a/modules/monitoring/library/Monitoring/Object/Service.php b/modules/monitoring/library/Monitoring/Object/Service.php new file mode 100644 index 000000000..aa6133146 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Object/Service.php @@ -0,0 +1,69 @@ + null, + 'contacts' => null, + 'contactgroups' => null, + 'customvars' => null, + 'comments' => null, + ); + + public function stateName() + { + // TODO + } + + protected function applyObjectFilter(Query $query) + { + return $query->where('service_host_name', $this->name1) + ->where('service_description', $this->name2); + } + + public function prefetch() + { + return $this->fetchServicegroups() + ->fetchContacts() + ->fetchContactgroups() + ->fetchCustomvars() + ->fetchComments() + ; + } + + protected function fetchObject() + { + return $this->backend->select()->from('status', array( + 'host_name', + 'host_alias', + 'host_address', + 'host_state', + 'host_handled', + 'host_in_downtime', + 'host_acknowledged', + 'host_last_state_change', + 'service_description', + 'service_state', + 'service_handled', + 'service_acknowledged', + 'service_in_downtime', + 'service_last_state_change', + 'last_check' => 'service_last_check', + 'next_check' => 'service_next_check', + 'check_execution_time' => 'service_check_execution_time', + 'check_latency' => 'service_check_latency', + 'output' => 'service_output', + 'long_output' => 'service_long_output', + 'check_command' => 'service_check_command', + 'perfdata' => 'service_perfdata', + )) + ->where('host_name', $this->name1) + ->where('service_description', $this->name2) + ->fetchRow(); + } +} + diff --git a/modules/monitoring/library/Monitoring/View/CommentView.php b/modules/monitoring/library/Monitoring/View/CommentView.php index 166c73950..b5fbaf1e4 100644 --- a/modules/monitoring/library/Monitoring/View/CommentView.php +++ b/modules/monitoring/library/Monitoring/View/CommentView.php @@ -11,6 +11,9 @@ class CommentView extends MonitoringView 'comment_author', 'comment_timestamp', 'comment_type', + 'host_name', + 'service_host_name', + 'service_description', ); protected $specialFilters = array(); diff --git a/modules/monitoring/library/Monitoring/View/HoststatusView.php b/modules/monitoring/library/Monitoring/View/HoststatusView.php new file mode 100644 index 000000000..a2a23ea45 --- /dev/null +++ b/modules/monitoring/library/Monitoring/View/HoststatusView.php @@ -0,0 +1,82 @@ + array( + 'columns' => array( + 'host_name', + ), + 'default_dir' => self::SORT_ASC + ), + 'host_address' => array( + 'columns' => array( + 'host_ipv4', + 'service_description' + ), + 'default_dir' => self::SORT_ASC + ), + 'host_last_state_change' => array( + 'default_dir' => self::SORT_DESC + ), + 'host_severity' => array( + 'columns' => array( + 'host_severity', + 'host_last_state_change', + ), + 'default_dir' => self::SORT_DESC + ) + ); + + public function isValidFilterColumn($column) + { + if ($column[0] === '_' + && preg_match('~^_host~', $column) + ) { + return true; + } + return parent::isValidFilterColumn($column); + } +} diff --git a/modules/monitoring/library/Monitoring/View/MonitoringView.php b/modules/monitoring/library/Monitoring/View/MonitoringView.php index 6987c0e82..11aad5101 100644 --- a/modules/monitoring/library/Monitoring/View/MonitoringView.php +++ b/modules/monitoring/library/Monitoring/View/MonitoringView.php @@ -5,43 +5,169 @@ namespace Icinga\Monitoring\View; use Icinga\Data\AbstractQuery; use Icinga\Data\Filter; +/** + * MonitoringView provides consistent views to our Icinga Backends + * + * TODO: * This could be renamed to AbstractView + * * We might need more complex filters (let's do the simple ones first) + * + * You should not directly instantiate such a view but always go through the + * Monitoring Backend. Using the Backend's select() method selecting from + * 'virtualtable' returns a Icinga\Monitoring\View\VirtualtableView instance. + * + * Usage example: + * + * use Icinga\Monitoring\Backend; + * $backend = Backend::getInstance(); + * $query = $backend->select()->from('viewname', array( + * 'one_column', + * 'another_column', + * 'alias' => 'whatever_column', + * ))->where('any_column', $search); + * + * print_r($query->fetchAll()); + * + * + * What we see in the example is that: + * * you can (and should) use a defined set of columns when issueing a query + * * you can use proper alias names to have an influence on column names + * in the result set + * * the MonitoringView behaves like any Query object and provides useful + * methods such as fetchAll, count, fetchPairs and so on + * + * If you want to fill a dropdown form element with all your hostgroups + * starting with "net", using the hostgroup name as the form elements value but + * showing the hostgroup aliases in the dropdown you would probably do this as + * follows: + * + * + * $pairs = $backend->select->from( + * 'hostgroups', + * array('hostgroup_name', 'hostgroup_alias') + * )->where('hostgroup_name', 'net*')->fetchPairs(); + * $formElement->setMultiOptions($pairs); + * + * + * MonitoringView is a proxy to your Backend Query. While both are Query objects + * providing partially the same interface, they are not directly related to + * each other. + */ class MonitoringView extends AbstractQuery { + /** + * Stores the backend-specific Query Object + * @var AbstractQuery + */ protected $query; + /** + * All the columns provided by this View MUST be specified here + * @var Array + */ protected $availableColumns = array(); + /** + * Columns available for search only but not in result sets + * @var Array + */ protected $specialFilters = array(); + /** + * All views COULD have a generic column called 'search', if available the + * real column name is defined here. + * TODO: This may be subject to change as a "search" could involve multiple + * columns + * @var string + */ + protected $searchColumn; + + /** + * Defines default sorting rules for specific column names. This helps in + * providing "intelligent" sort defaults for different columns (involving + * also other columns where needed) + * @var Array + */ protected $sortDefaults = array(); + /** + * Whether this view provides a specific column name + * + * @param string $column Column name + * @return bool + */ public function hasColumn($column) { return in_array($column, $this->availableColumns); } + /** + * Get a list of all available column names + * + * This might be useful for dynamic frontend tables or similar + * + * @return Array + */ public function getAvailableColumns() { return $this->availableColumns; } + /** + * Extract and apply filters and sort rules from a given request object + * + * TODO: Enforce Icinga\Web\Request (or similar) as soon as we replaced + * Zend_Controller_Request + * + * @param mixed $request The request object + * @return self + */ public function applyRequest($request) { return $this->applyRequestFilters($request) ->applyRequestSorting($request); } + /** + * Extract and apply sort column and directon from given request object + * + * @param mixed $request The request object + * @return self + */ protected function applyRequestSorting($request) { return $this->order( + // TODO: Use first sortDefaults entry if available, fall back to + // column if not $request->getParam('sort', $this->availableColumns[0]), $request->getParam('dir') ); } + /** + * Extract and apply filters from a given request object + * + * Columns not fitting any defined available column or special filter column + * will be silently ignored. + * + * @param mixed $request The request object + * @return self + */ protected function applyRequestFilters($request) { foreach ($request->getParams() as $key => $value) { + if ($key === 'search' && $value !== '') { + if (strpos($value, '=') === false) { + if ($this->searchColumn !== null) { + $this->where($this->searchColumn, $value); + } + } else { + list($k, $v) = preg_split('~\s*=\s*~', $value, 2); + if ($this->isValidFilterColumn($k)) { + $this->where($k, $v); + } + } + continue; + } if ($this->isValidFilterColumn($key)) { $this->where($key, $value); } @@ -50,7 +176,16 @@ class MonitoringView extends AbstractQuery } // TODO: applyAuthFilters(Auth $auth = null) + // MonitoringView will enforce restrictions as provided by the Auth + // backend + /** + * Apply an array of filters. This might become obsolete or even improved + * and accept Filter objects - this is still to be defined. + * + * @param Array $filters Filter array + * @return self + */ public function applyFilters($filters) { foreach ($filters as $col => $filter) { @@ -59,11 +194,26 @@ class MonitoringView extends AbstractQuery return $this; } + /** + * Gives you a filter object with all applied filters excluding auth filters + * Might be used to build URLs fitting query objects. + * + * Please take care, as Url has been improved the Filter object might + * become subject to change + * + * @return Filter + */ public function getAppliedFilter() { return new Filter($this->filters); } + /** + * Default sort direction for given column, ASCending if not defined + * + * @param String $col Column name + * @return int + */ protected function getDefaultSortDir($col) { if (isset($this->sortDefaults[$col]['default_dir'])) { @@ -72,11 +222,21 @@ class MonitoringView extends AbstractQuery return self::SORT_ASC; } + /** + * getQuery gives you an instance of the Query object implementing this + * view for the chosen backend. + * + * @return AbstractQuery + */ public function getQuery() { if ($this->query === null) { - $class = substr(array_pop(preg_split('|\\\|', get_class($this))), 0, -4) . 'Query'; + $class = substr( + array_pop(preg_split('|\\\|', get_class($this))), + 0, + -4 + ) . 'Query'; $class = '\\' . get_class($this->ds) . '\\Query\\' . $class; $query = new $class($this->ds, $this->columns); diff --git a/modules/monitoring/library/Monitoring/View/StatusView.php b/modules/monitoring/library/Monitoring/View/StatusView.php index 35b00d315..7c8a67dc1 100644 --- a/modules/monitoring/library/Monitoring/View/StatusView.php +++ b/modules/monitoring/library/Monitoring/View/StatusView.php @@ -5,9 +5,11 @@ namespace Icinga\Monitoring\View; class StatusView extends MonitoringView { protected $query; + // protected $searchColumn = 'host'; -> besser in der Query, 'search' mitgeben protected $availableColumns = array( // Hosts + 'host', 'host_name', 'host_display_name', 'host_alias', @@ -29,9 +31,15 @@ class StatusView extends MonitoringView 'host_does_active_checks', 'host_accepts_passive_checks', 'host_last_state_change', + 'host_last_hard_state', 'host_last_hard_state_change', + 'host_notifications_enabled', + 'host_last_time_up', + 'host_last_time_down', + 'host_last_time_unreachable', // Services + 'service', 'service_description', 'service_display_name', @@ -49,7 +57,15 @@ class StatusView extends MonitoringView 'service_does_active_checks', 'service_accepts_passive_checks', 'service_last_state_change', + 'service_last_hard_state', 'service_last_hard_state_change', + 'service_notifications_enabled', + 'service_last_time_ok', + 'service_last_time_warning', + 'service_last_time_critical', + 'service_last_time_unknown', + + 'object_type', // Status 'problems', @@ -66,6 +82,12 @@ class StatusView extends MonitoringView 'host_name' => array( 'columns' => array( 'host_name', + ), + 'default_dir' => self::SORT_ASC + ), + 'service_host_name' => array( + 'columns' => array( + 'service_host_name', 'service_description' ), 'default_dir' => self::SORT_ASC @@ -86,6 +108,7 @@ class StatusView extends MonitoringView 'severity' => array( 'columns' => array( 'severity', + 'host_name', 'service_last_state_change', ), 'default_dir' => self::SORT_DESC