Update the monitoring module

This commit is contained in:
Eric Lippmann 2013-07-12 14:33:17 +02:00
parent d51b00b508
commit d871b3c287
49 changed files with 1811 additions and 650 deletions

View File

@ -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 <info@icinga.org>
* @author Icinga Development Team <info@icinga.org>
*/
@ -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:

View File

@ -0,0 +1,64 @@
<?php
namespace Icinga\Web;
use Zend_View_Abstract as ZfViewAbstract;
use Icinga\Web\Url;
use Icinga\Util\Format;
class View extends ZfViewAbstract
{
private $_useViewStream = false;
public function __construct($config = array())
{
$this->_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);
}
}
}

View File

@ -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]);

View File

@ -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 '<pre>' . htmlspecialchars(wordwrap($this->view->hosts->getQuery()->dump())) . '</pre>';
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 '<pre>' . htmlspecialchars(wordwrap($this->view->services->getQuery()->dump())) . '</pre>';
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 '<pre>'
. htmlspecialchars(wordwrap($query->getQuery()->dump()))
. '</pre>';
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;
}
}

View File

@ -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 '<pre>' . htmlspecialchars($this->view->history->getQuery()->dump()) . '</pre>';
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',

View File

@ -0,0 +1,49 @@
<?php
use Icinga\Web\ModuleActionController;
use Icinga\Web\Url;
use Icinga\Monitoring\Backend;
use Zend_Soap_Server as ZfSoapServer;
use Zend_Soap_AutoDiscover as ZfSoapAutoDiscover;
class Api
{
/**
* @return array
*/
public function problems()
{
try {
$backend = Backend::getInstance('localdb');
$result = $backend->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;
}
}

View File

@ -1,8 +1,14 @@
<?php if (empty($this->hosts)): ?>
- no hosts is matching this filter -
<?php return; endif; ?>
<?php $hosts = $this->hosts->paginate(); ?>
<table class="hosts action">
<?php
$count = $hosts->count();
if (! $count) {
echo '- no host is matching this filter -';
return;
}
$hosts->paginate();
?><table class="hosts action">
<thead>
<tr>
<th style="width: 6em;" >State</th>
@ -10,8 +16,7 @@
</tr>
</thead>
<tbody>
<?php foreach ($hosts as $host): ?>
<?php
<?php foreach ($hosts->fetchAll() as $host):
$icons = array();
if ($host->host_acknowledged) {
@ -54,6 +59,6 @@ $state_title = strtoupper($this->monitoringState($host, 'host'))
array('class' => 'row-action')
) ?></td>
</tr>
<?php endforeach; ?>
<? endforeach ?>
</tbody>
</table>

View File

@ -1,7 +1,7 @@
<?= $this->tabs ?>
<?php
$this->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'];
}
?>
<?php if (! empty($fparams)): ?>
<? if (! empty($fparams)): ?>
<div style="float: right; width: 20em; font-size: 0.8em;"><b>Filters</b><br>
<?php foreach ($fparams as $k => $v): ?>
<? foreach ($fparams as $k => $v): ?>
<?= $this->qlink(
'x',
'monitoring/list/hosts',
@ -54,9 +54,9 @@ if (isset($_GET['dir'])) {
'style' => array('color' => 'red')
)
) ?> <?= $this->escape("$k = $v") ?></br>
<?php endforeach; ?>
<? endforeach ?>
</div>
<?php endif; ?>
<? endif ?>
<form method="get" action="<?= $this->qUrl(
'monitoring/list/hosts?' . http_build_query(
$this->hosts->getAppliedFilter()->toParams()
@ -69,27 +69,29 @@ Sort by <?= $this->formSelect(
$this->sort,
array('class' => 'autosubmit'),
array(
'host_severity' => 'Severity',
'host_last_state_change' => 'Last state change',
'host_name' => 'Host',
'host_severity' => 'Severity',
'host_last_state_change' => 'Last state change',
'host_name' => 'Host',
'host_last_time_up' => 'Last UP',
'host_last_time_down' => 'Last DOWN',
'host_last_time_unreachable' => 'Last UNREACHABLE',
)
) ?>
<input type="text" placeholder="Add filter..." name="search" />
<input type="text" placeholder="Add filter..." name="search" value="<?= $this->escape($this->search) ?>" />
</form>
<?php // end filter ?>
<?php if (empty($hosts)): ?>
<? if (empty($hosts)): ?>
<div class="alert alert-info fullpage_infobox">
Sorry, no host found for this search
</div>
<?php return; endif; ?>
<?= $this->paginationControl($hosts, null, null, array('preserve' => $this->preserve)) ?>
<? return; endif ?>
<?= $this->paginationControl($paginator, null, null, array('preserve' => $this->preserve)) ?>
<table class="action">
<tbody>
<?php foreach ($hosts as $host):
<? foreach ($hosts->fetchAll() as $host):
list($icons,$state_classes,$state_title) = getRowProperties($host,$this); ?>
<tr class="<?= implode(' ', $state_classes) ?>">
<td class="state" title="<?= $state_title ?>"><?= $this->qlink(

View File

@ -1,39 +1,34 @@
<?php if (empty($this->services)): ?>
<div class="alert alert-info fullpage_infobox">
Sorry, no services found for this search
</div>
<?php return; endif; ?>
<?
$services = $this->services->paginate();
?>
<table class="services action">
<thead>
<tr>
<th style="width: 6em;" >State</th>
<th >Service</th>
</tr>
</thead>
<tbody>
<?php foreach ($services as $service): ?>
<?php
$count = $services->count();
if (! $count) {
echo '- no object is matching this filter -';
return;
}
$services->paginate();
?><table class="services action">
<thead>
<tr>
<th style="width: 6em;" >State</th>
<th >Service</th>
</tr>
</thead>
<tbody>
<?php foreach ($services->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'];
}
?>
<tr class="<?= implode(' ', $state_classes) ?>">
<td class="state" title="<?= $state_title ?>">
<?= $this->qlink(
$this->timeSince($service->service_last_state_change),
'monitoring/show/history', $params, array('quote' => false)) ?>
</td>
<td>
<?= $this->qlink(
$service->host_name,
'monitoring/show/host',
$params
); ?>:
<?= $this->qlink($service->service_description, 'monitoring/show/service', $params, array('class' => 'row-action')) ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<tr class="<?= implode(' ', $state_classes) ?>">
<td class="state" title="<?= $state_title ?>"><?=
$this->qlink(
$this->timeSince($service->service_last_state_change),
'monitoring/show/history',
$params,
array('quote' => false)
) ?></td>
<td><?php
foreach ($icons as $icon => $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')
) ?></td>
</tr>
<?php endforeach ?>
</tbody>
</table>
<?php
$limit = $services->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
)
);
}
?><p><?= $this->qlink($more,$this->url()->without('page', 'limit', 'view')) ?></p>

View File

@ -1,7 +1,7 @@
<?= $this->tabs ?>
<?php
$this->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'])) {
}
?>
<div class="dontprint">
<?php if (! empty($fparams)): ?>
<? if (! empty($fparams)): ?>
<div style="float: right; width: 20em; font-size: 0.8em;"><b>Filters</b><br>
<?php foreach ($fparams as $k => $v): ?>
<? foreach ($fparams as $k => $v): ?>
<?= $this->qlink(
'x',
'monitoring/list/services',
@ -74,9 +78,9 @@ if (isset($_GET['dir'])) {
'style' => array('color' => 'red')
)
) ?> <?= $this->escape("$k = $v") ?></br>
<?php endforeach; ?>
<? endforeach ?>
</div>
<?php endif; ?>
<? endif ?>
<form method="get" action="<?= $this->qUrl(
'monitoring/list/services?' . http_build_query(
$this->services->getAppliedFilter()->toParams()
@ -93,11 +97,21 @@ Sort by <?= $this->formSelect(
array(
'severity' => 'Severity',
'service_last_state_change' => 'Last state change',
'service_last_time_unknown' => 'Last UNKNOWN',
'service_last_time_critical' => 'Last CRITICAL',
'service_last_time_warning' => 'Last WARNING',
'service_last_time_ok' => 'Last OK',
'host_name' => 'Host',
'service_description' => 'Service',
)
) ?>
<input type="text" placeholder="Add filter..." name="search" />
<?= $this->formText(
'search',
$this->search,
array(
'placeholder' => 'Add filllter...',
)
) ?>
</form>
</div>
<?php if (empty($services)): ?>
@ -106,11 +120,11 @@ Sort by <?= $this->formSelect(
Sorry, no services found for this search
</div>
<?php return; endif; ?>
<?= $this->paginationControl($services, null, null, array('preserve' => $this->preserve )); ?>
<?php return; endif ?>
<?= $this->paginationControl($paginator, null, null, array('preserve' => $this->preserve )); ?>
<table class="action">
<tbody>
<?php foreach ($services as $service):
<?php foreach ($services->fetchAll() as $service):
list($host_col,$icons,$state_classes,$state_title,$graph) = getRowProperties($service,$last_host,$this); ?>
<tr class="<?= implode(' ', $state_classes) ?>">
<td class="state" title="<?= $state_title ?>">
@ -148,6 +162,9 @@ Sort by <?= $this->formSelect(
</span>
<?= $graph ?>
</td>
<? foreach ($this->extraColumns as $col): ?>
<td><?= $this->escape($service->$col) ?></td>
<? endforeach ?>
</tr>
<?php endforeach; ?>
</tbody>

View File

@ -0,0 +1,29 @@
<?= $this->expandable(
$this->translate('Check statistics'),
'<table style="width:100%">
<thead>
</thead>
<tbody>
<tr>
<td style="width: 25em">' . $this->translate('Last check') . '</td>
<td>' . $this->format()->timeSince($object->last_check) . '</td>
</tr>
<tr>
<td>' . $this->translate('Next check') . '</td>
<td class="icinga-uiwidget-countdown" countdown-end="' . $object->next_check . '">'
. $this->format()->timeUntil($object->next_check)
. '</td>
</tr>
<tr>
<td>' . $this->translate('Check execution time') . '</td>
<td>' . $object->check_execution_time . '</td>
</tr>
<tr>
<td>' . $this->translate('Check latency') . '</td>
<td>' . $object->check_latency . '</td>
</tr>
</tbody>
</table>
',
array('collapsed' => false)
);

View File

@ -0,0 +1,6 @@
<?= $this->expandable(
'<b>Command:</b> ' . 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, '!'))
) ?>

View File

@ -1,12 +1,13 @@
<?php
if (empty($object->comments)) return;
<?php if (! empty($this->comments)): ?>
<?
$list = array();
foreach ($this->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) {
}
?>
<b>Comments:</b><blockquote> <?= implode('<br />', $list) ?></blockquote>
<?php endif; ?>

View File

@ -1,24 +1,25 @@
<?php if (! empty($this->contacts)): ?>
<?
$list = array();
foreach ($this->contacts as $contact) {
$list[] = $this->qlink($contact->contact_alias, 'monitoring/show/contact', array(
'contact_name' => $contact->contact_name
));
}
?>
<b>Contacts:</b> <?= implode(', ', $list) ?><br />
<?php endif; ?>
<?php
<?php if (! empty($this->contactgroups)): ?>
<?
$list = array();
foreach ($this->contactgroups as $contactgroup) {
$list[] = $this->qlink($contactgroup->contactgroup_alias, 'monitoring/show/contactgroup', array(
'contactgroup_name' => $contactgroup->contactgroup_name
));
}
?>
<b>Contactgroups:</b> <?= implode(', ', $list) ?><br />
<?php endif; ?>
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 '<b>Contacts:</b> ' . implode(', ', $list) . "<br />\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 '<b>Contactgroups:</b> ' . implode(', ', $list) . "<br />\n";
}

View File

@ -0,0 +1,12 @@
<?php
if (! $object->customvars) return;
foreach ($object->customvars as $name => $value) {
printf(
"<b>%s:</b> %s<br />\n",
$this->escape($name),
$this->escape($value)
);
}

View File

@ -0,0 +1,28 @@
<? $showService = $object->service_description && $tabs->getActiveName() !== 'host' ?>
<? if (! $compact): ?>
<?= $tabs ?>
<? endif ?>
<table style="margin-bottom: 1em">
<tr class="<?= $this->monitoringState($object, 'host') ?><?= $object->host_handled ? ' handled' : '' ?>">
<td><b><?= $this->escape($object->host_name) ?><?
if ($object->host_address && $object->host_address !== $object->host_name): ?>
(<?= $this->escape($object->host_address) ?>)
<? endif ?>
</b></td>
<td class="state"<?= $showService ? '' : ' rowspan="2"' ?>>
<?= $this->util()->getHostStateName($object->host_state) ?><br />
since <?= $this->timeSince($object->host_last_state_change) ?>
</td>
</tr>
<? if ($showService): ?>
<tr class="<?= $this->monitoringState($object, 'service') ?><?= $object->service_handled ? ' handled' : '' ?>">
<td><b>Service: <?= $this->escape($object->service_description) ?></b></td>
<td class="state">
<?= $this->util()->getServiceStateName($object->service_state); ?><br />
since <?= $this->timeSince($object->service_last_state_change) ?>
</td>
</tr>
<? else: ?>
<tr><td><b>Host state</b></td></tr>
<? endif ?>
</table>

View File

@ -0,0 +1,12 @@
<?php
if (empty($object->hostgroups)) return;
$list = array();
foreach ($object->hostgroups as $name => $alias) {
$list[] = $this->qlink($alias, 'monitoring/list/services', array(
'hostgroups' => $name
));
}
echo '<b>Hostgroups:</b> ' . implode(', ', $list) . "<br />\n";

View File

@ -0,0 +1,4 @@
<?= $this->expandable(
$this->pluginOutput($object->output),
$this->pluginOutput($object->long_output)
) ?>

View File

@ -0,0 +1,7 @@
<? if ($object->perfdata): ?>
<?= $this->expandable(
'<b>Performance data</b>',
$this->perfdata($object->perfdata),
array('collapsed' => false)
) ?>
<? endif ?>

View File

@ -0,0 +1,12 @@
<?php
if (empty($object->servicegroups)) return;
$list = array();
foreach ($object->servicegroups as $name => $alias) {
$list[] = $this->qlink($alias, 'monitoring/list/services', array(
'servicegroups' => $name
));
}
echo '<b>Servicegroups:</b> ' . implode(', ', $list) . "<br />\n";

View File

@ -1,20 +1,17 @@
<?= $this->partial('show/header.phtml', array(
'host' => $this->host,
'service' => $this->service,
'tabs' => $this->tabs
)); ?><?php
$this->history->limit(10);
$history = $this->history->paginate();
<?= $this->render('show/components/header.phtml') ?>
<?php
$history->limit(10);
$hhistory = $this->history->paginate();
?>
<?php if (empty($history)): ?>
<?php if (empty($hhistory)): ?>
There are no matching history entries right now
<?php else: ?>
<?= $this->paginationControl($history, null, null, array('preserve' => $this->preserve)); ?>
<?= $this->paginationControl($hhistory, null, null, array('preserve' => $preserve)); ?>
<table class="paginatable">
<tbody>
<?php foreach ($history as $event): ?>
<?php foreach ($hhistory as $event): ?>
<?php
if ($event->object_type == 'host') {
@ -27,24 +24,24 @@ $row_class = array_key_exists($event->state, $states) ? $states[$event->state] :
?>
<tr class="<?= $row_class ?>"><td class="state"><?= date('d.m. H:i', $event->timestamp ) ?></td>
<?php if (! isset($this->host)): ?>
<? if (! $object): ?>
<td><?= $this->escape($event->host_name) ?></td>
<?php endif; ?>
<?php if (! isset($this->service)): ?>
<td><?php if (isset($this->host)): ?>
<? endif ?>
<? if (! $object instanceof Icinga\Monitoring\Object\Service): ?>
<td><? if ($object): ?>
<?= $this->qlink(
$event->service_description,
'monitoring/show/service',
array(
'host' => $this->host->host_name,
'host' => $object->host_name,
'service' => $event->service_description
)
) ?>
<?php else: ?>
<? else: ?>
<?= $this->escape($event->service_description) ?>
<?php endif; ?>
<? endif ?>
</td>
<?php endif; ?>
<? endif ?>
<td style="padding: 0.2em;"><?php
$imgparams = array(
@ -83,17 +80,17 @@ switch ($event->type) {
break;
}
?>
<?php if ($event->attempt !== null): ?>
<? if ($event->attempt !== null): ?>
[ <?= $event->attempt ?>/<?=$event->max_attempts ?> ]
<?php endif; ?>
<?= $this->ticket_pattern ? preg_replace(
$this->ticket_pattern,
$this->ticket_link,
<? endif ?>
<?= $ticket_pattern ? preg_replace(
$ticket_pattern,
$ticket_link,
$this->pluginOutput($event->output)
) : $this->pluginOutput($event->output) ?>
</td>
</tr>
<?php endforeach; ?>
<? endforeach ?>
</tbody>
</table>
<?php endif; ?>
<? endif ?>

View File

@ -1,40 +1,11 @@
<?= $this->partial('show/header.phtml', array(
'host' => $this->host,
'service' => $this->service,
'tabs' => $this->tabs,
'compact' => $this->compact
)); ?>
<?= $this->expandable(
$this->pluginOutput($this->host->host_output),
$this->pluginOutput($this->host->host_long_output)
) ?>
<?= $this->expandable(
'<b>Command:</b> ' . array_shift(preg_split('|!|', $this->host->host_check_command)),
$this->commandArguments($this->host->host_check_command)
) ?>
<?php if (! empty($this->hostgroups)): ?>
<?
$list = array();
foreach ($this->hostgroups as $name => $alias) {
$list[] = $this->qlink($alias, 'monitoring/list/services', array(
'hostgroups' => $name
));
}
?>
<b>Hostgroups:</b> <?= implode(', ', $list) ?><br />
<?php endif; ?>
<?= $this->render('show/components/header.phtml') ?>
<?= $this->render('show/components/output.phtml') ?>
<?= $this->render('show/components/hostgroups.phtml') ?>
<?= $this->render('show/components/contacts.phtml') ?>
<?= $this->render('show/components/comments.phtml') ?>
<?php foreach ($this->customvars as $name => $value): ?>
<b><?= $this->escape($name) ?>:</b> <?= $this->escape($value) ?><br />
<?php endforeach; ?>
<?php if ($this->host->host_perfdata): ?>
<?= $this->expandable(
'<b>Performance data</b>',
$this->perfdata($this->host->host_perfdata),
array('collapsed' => false)
) ?>
<?php endif; ?>
<?= $this->render('show/components/customvars.phtml') ?>
<?= $this->render('show/components/perfdata.phtml') ?>
<?= $this->render('show/components/checkstatistics.phtml') ?>
<?= $this->render('show/components/command.phtml') ?>
<?= $this->preview_image ?>

View File

@ -1,31 +1,10 @@
<?= $this->partial('show/header.phtml', array(
'host' => $this->host,
'service' => $this->service,
'tabs' => $this->tabs,
'compact' => $this->compact
)); ?>
<?= $this->expandable(
$this->pluginOutput($this->service->service_output),
$this->pluginOutput($this->service->service_long_output)
) ?>
<?= $this->render('show/components/header.phtml') ?>
<?= $this->render('show/components/output.phtml') ?>
<?= $this->render('show/components/servicegroups.phtml') ?>
<?= $this->render('show/components/contacts.phtml') ?>
<?= $this->render('show/components/comments.phtml') ?>
<?php foreach ($this->customvars as $name => $value): ?>
<b><?= $this->escape($name) ?>:</b> <?= $this->escape($value) ?><br />
<?php endforeach; ?>
<?= $this->expandable(
'<b>Command:</b> ' . array_shift(preg_split('|!|', $this->service->service_check_command)),
$this->commandArguments($this->service->service_check_command)
) ?>
<?php if ($this->service->service_perfdata): ?>
<?= $this->expandable(
'<b>Performance data</b>:',
$this->perfdata($this->service->service_perfdata),
array('collapsed' => false)
) ?>
<?php endif; ?>
<?= $this->partial('show/legacy-service.phtml', array('service' => $this->service)) ?>
<?= $this->render('show/components/customvars.phtml') ?>
<?= $this->render('show/components/perfdata.phtml') ?>
<?= $this->render('show/components/checkstatistics.phtml') ?>
<?= $this->render('show/components/command.phtml') ?>
<?= $this->preview_image ?>

View File

@ -1 +1,2 @@
<?= $this->services ?>
<?= $this->render('show/components/header.phtml') ?>
<?= $services ?>

View File

@ -1,2 +1,2 @@
<?= $this->tabs ?>
<?= $tabs ?>

View File

@ -1,17 +1,17 @@
<?php if (! $this->compact): ?>
<? if (! $this->compact): ?>
<?= $this->tabs ?>
<?php endif; ?>
<?php if (empty($this->summary)): ?>
<? endif ?>
<? if (empty($this->summary)): ?>
There are no such services right now
<?php else: ?>
<? else: ?>
<?php
$now = time();
?>
<?php if (! $this->compact && $this->summary instanceof \Zend_Paginator): ?>
<? if (! $this->compact && $this->summary instanceof \Zend_Paginator): ?>
<?= $this->paginationControl($this->summary, null, null, array('preserve' => $this->preserve)); ?>
<?php endif; ?>
<? endif ?>
<table class="pivot action">
<thead>
<tr>
@ -20,11 +20,11 @@ $now = time();
<th style="width: 5em;">Critical</th>
<th style="width: 5em;">Unknown</th>
<th style="width: 5em;">Warning</th>
<?php if (! $this->compact): ?> <th style="width: 9%;">OK</th><?php endif; ?>
<? if (! $this->compact): ?> <th style="width: 9%;">OK</th><? endif ?>
</tr>
</thead>
<tbody>
<?php foreach ($this->summary as $row): ?>
<? foreach ($this->summary as $row): ?>
<?php
$class_ok = '';
@ -149,19 +149,19 @@ if (isset($row->hostgroup_name)) {
}
?>
<tr>
<!-- <td class="<?= $name_class ?>"><?php if ($row->last_state_change + 600 > $now): ?>
<!-- <td class="<?= $name_class ?>"><? if ($row->last_state_change + 600 > $now): ?>
<blink><?= $this->timeSince($row->last_state_change) ?></blink>
<?php else: ?>
<? else: ?>
<?= $this->timeSince($row->last_state_change) ?>
<?php endif; ?></td>-->
<? endif ?></td>-->
<td style="text-align: left;"><?= $name_html ?></td>
<td class="<?= $class_critical ?>"><?= $html_critical ?></td>
<td class="<?= $class_unknown ?>"><?= $html_unknown ?></td>
<td class="<?= $class_warning ?>"><?= $html_warning ?></td>
<?php if (! $this->compact): ?><td class="ok"><?= $html_ok ?></td><?php endif; ?>
<? if (! $this->compact): ?><td class="ok"><?= $html_ok ?></td><? endif ?>
</tr>
<?php endforeach; ?>
<? endforeach ?>
</tbody>
</table>
<?php endif; ?>
<?php if ($this->compact): ?><a href="<?= $this->baseUrl('monitoring/summary/group') ?>">more</a><?php endif; ?>
<? endif ?>
<? if ($this->compact): ?><a href="<?= $this->baseUrl('monitoring/summary/group') ?>">more</a><? endif ?>

View File

@ -0,0 +1,126 @@
<?php
use Icinga\Monitoring\Backend;
use Icinga\Util\Format;
$backend = Backend::getInstance($params->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;
}
}

View File

@ -0,0 +1,21 @@
<?php
$client = new SoapClient('http://itenos-devel.tom.local/monitoring/soap?wsdl', array(
'login' => '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";
}

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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',
)
);

View File

@ -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',
)
);

View File

@ -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',
)
);

View File

@ -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"
),

View File

@ -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);
}
}
}
}

View File

@ -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'
)
);

View File

@ -0,0 +1,197 @@
<?php
namespace Icinga\Monitoring\Backend\Ido\Query;
class HoststatusQuery extends AbstractQuery
{
protected $allowCustomVars = true;
protected $columnMap = array(
'hosts' => 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;
}
}

View File

@ -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()
);
}

View File

@ -0,0 +1,167 @@
<?php
namespace Icinga\Monitoring\Backend\Ido\Query;
class ServicestatusQuery extends AbstractQuery
{
protected $allowCustomVars = true;
protected $columnMap = array(
'services' => 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;
}
}

View File

@ -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()
);

View File

@ -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);
}
}

View File

@ -3,6 +3,8 @@
namespace Icinga\Monitoring;
use Icinga\Application\Config;
use Icinga\Web\Session;
use Exception;
class Environment
{

View File

@ -0,0 +1,146 @@
<?php
namespace Icinga\Monitoring\Object;
use Icinga\Data\AbstractQuery as Query;
use Icinga\Monitoring\Backend\AbstractBackend;
abstract class AbstractObject
{
protected $backend;
protected $type;
protected $name1;
protected $name2;
protected $properties;
protected $foreign = array(
// 'hostgroups' => 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;
}
}

View File

@ -0,0 +1,58 @@
<?php
namespace Icinga\Monitoring\Object;
use Icinga\Data\AbstractQuery as Query;
class Host extends AbstractObject
{
protected $foreign = array(
'hostgroups' => 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();
}
}

View File

@ -0,0 +1,69 @@
<?php
namespace Icinga\Monitoring\Object;
use Icinga\Data\AbstractQuery as Query;
class Service extends AbstractObject
{
protected $foreign = array(
'servicegroups' => 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();
}
}

View File

@ -11,6 +11,9 @@ class CommentView extends MonitoringView
'comment_author',
'comment_timestamp',
'comment_type',
'host_name',
'service_host_name',
'service_description',
);
protected $specialFilters = array();

View File

@ -0,0 +1,82 @@
<?php
namespace Icinga\Monitoring\View;
class HoststatusView extends MonitoringView
{
protected $query;
protected $searchColumn = 'host';
protected $availableColumns = array(
// Hosts
'host',
'host_name',
'host_display_name',
'host_alias',
'host_address',
'host_ipv4',
'host_icon_image',
// Hoststatus
'host_state',
'host_problem',
'host_severity',
'host_state_type',
'host_output',
'host_long_output',
'host_perfdata',
'host_acknowledged',
'host_in_downtime',
'host_handled',
'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',
);
protected $specialFilters = array(
'hostgroups',
'servicegroups'
);
protected $sortDefaults = array(
'host_name' => 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);
}
}

View File

@ -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:
* <code>
* 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());
* </code>
*
* 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:
*
* <code>
* $pairs = $backend->select->from(
* 'hostgroups',
* array('hostgroup_name', 'hostgroup_alias')
* )->where('hostgroup_name', 'net*')->fetchPairs();
* $formElement->setMultiOptions($pairs);
* </code>
*
* 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);

View File

@ -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