mirror of
https://github.com/Icinga/icingaweb2.git
synced 2025-07-29 00:34:03 +02:00
Merge branch 'master' of ssh://git.icinga.org/icinga2-web into feature/host-overview--4179
Conflicts: application/layouts/scripts/layout.phtml modules/monitoring/application/controllers/ListController.php modules/monitoring/application/controllers/ShowController.php modules/monitoring/application/views/scripts/list/hosts.phtml modules/monitoring/application/views/scripts/show/components/comments.phtml modules/monitoring/application/views/scripts/show/components/contacts.phtml modules/monitoring/application/views/scripts/show/components/customvars.phtml modules/monitoring/application/views/scripts/show/host.phtml modules/monitoring/library/Monitoring/Backend/AbstractBackend.php modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php
This commit is contained in:
commit
b045650a19
3
.gitignore
vendored
3
.gitignore
vendored
@ -20,3 +20,6 @@ test/php/bin/extcmd_test
|
||||
|
||||
# misc test output
|
||||
test/frontend/static/public
|
||||
|
||||
# Generated API documentation
|
||||
doc/api
|
||||
|
@ -1,60 +1,20 @@
|
||||
<?php
|
||||
// @codingStandardsIgnoreStart
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
/**
|
||||
* 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>
|
||||
*/
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
# namespace Icinga\Web\Form;
|
||||
|
||||
use Icinga\Web\ActionController;
|
||||
use Icinga\Application\Icinga;
|
||||
use Zend_Controller_Action_Exception as ActionException;
|
||||
use Icinga\Application\Icinga,
|
||||
Zend_Controller_Action_Exception as ActionException;
|
||||
|
||||
use Icinga\Application\Benchmark;
|
||||
/**
|
||||
* Class StaticController
|
||||
* @package Icinga\Web\Form
|
||||
*/
|
||||
class StaticController extends ActionController
|
||||
{
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $handlesAuthentication = true;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
$this->_helper->viewRenderer->setNoRender(true);
|
||||
$this->_helper->layout()->disableLayout();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function getModuleList()
|
||||
{
|
||||
$modules = Icinga::app()->moduleManager()->getLoadedModules();
|
||||
@ -64,35 +24,64 @@ class StaticController extends ActionController
|
||||
foreach ($modules as $name => $module) {
|
||||
$hasJs = file_exists($module->getBasedir() . "/public/js/$name.js");
|
||||
$result[] = array(
|
||||
'name' => $name,
|
||||
'active' => true,
|
||||
'type' => 'generic',
|
||||
'name' => $name,
|
||||
'active' => true,
|
||||
'type' => 'generic',
|
||||
'behaviour' => $hasJs
|
||||
);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function modulelistAction()
|
||||
{
|
||||
|
||||
$this->_helper->viewRenderer->setNoRender(true);
|
||||
$this->_helper->layout()->disableLayout();
|
||||
$this->getResponse()->setHeader("Content-Type", "application/json");
|
||||
echo "define(function() { return " . json_encode($this->getModuleList(), true) . "; })";
|
||||
$this->getResponse()->setHeader("Content-Type","application/json");
|
||||
echo "define(function() { return ".json_encode($this->getModuleList(),true)."; })";
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Zend_Controller_Action_Exception
|
||||
*/
|
||||
public function imgAction()
|
||||
{
|
||||
$module = $this->_getParam('moduleName');
|
||||
$file = $this->_getParam('file');
|
||||
$basedir = Icinga::app()->getModule($module)->getBaseDir();
|
||||
|
||||
$filePath = $basedir . '/public/img/' . $file;
|
||||
if (! file_exists($filePath)) {
|
||||
throw new ActionException(sprintf(
|
||||
'%s does not exist',
|
||||
$filePath
|
||||
), 404);
|
||||
}
|
||||
if (preg_match('/\.([a-z]+)$/i', $file, $m)) {
|
||||
$extension = $m[1];
|
||||
} else {
|
||||
$extension = 'fixme';
|
||||
}
|
||||
$hash = md5_file($filePath);
|
||||
if ($hash === $this->getRequest()->getHeader('If-None-Match')) {
|
||||
$this->getResponse()->setHttpResponseCode(304);
|
||||
return;
|
||||
}
|
||||
header('ETag: ' . $hash);
|
||||
header('Content-Type: image/' . $extension);
|
||||
header('Cache-Control: max-age=3600');
|
||||
header('Last-Modified: ' . gmdate(
|
||||
'D, d M Y H:i:s',
|
||||
filemtime($filePath)
|
||||
) . ' GMT');
|
||||
|
||||
readfile($filePath);
|
||||
$this->_viewRenderer->setNoRender();
|
||||
}
|
||||
|
||||
public function javascriptAction()
|
||||
{
|
||||
$module = $this->_getParam('module_name');
|
||||
$file = $this->_getParam('file');
|
||||
$module = $this->_getParam('moduleName');
|
||||
$file = $this->_getParam('file');
|
||||
$basedir = Icinga::app()->getModule($module)->getBaseDir();
|
||||
|
||||
$filePath = $basedir . '/public/js/' . $file;
|
||||
@ -126,8 +115,7 @@ class StaticController extends ActionController
|
||||
} else {
|
||||
readfile($filePath);
|
||||
}
|
||||
return;
|
||||
$this->_viewRenderer->setNoRender();
|
||||
}
|
||||
}
|
||||
|
||||
// @codingStandardsIgnoreEnd
|
||||
}
|
||||
|
@ -6,9 +6,7 @@
|
||||
|
||||
<div class="layout-main-detail collapsed">
|
||||
<div id="icinga-main" container-id="icinga-main" class="icinga-container">
|
||||
<?php echo $this->layout()->moduleStart ?>
|
||||
<?php echo $this->layout()->content ?>
|
||||
<?php echo $this->layout()->moduleEnd ?>
|
||||
<?= $this->render('inline.phtml') ?>
|
||||
</div>
|
||||
|
||||
<div id="icinga-detail" class="icinga-container " container-id="icinga-detail">
|
||||
|
@ -12,14 +12,19 @@
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<link rel="stylesheet" href="<?php echo $this->baseUrl('css/normalize.min.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo $this->baseUrl('css/vendor/bootstrap.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo $this->baseUrl('css/main.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo $this->baseUrl('css/vendor/jquery.qtip.min.css') ?>">
|
||||
<link rel="stylesheet" href="<?= $this->baseUrl('css/normalize.min.css') ?>">
|
||||
<link rel="stylesheet" href="<?= $this->baseUrl('css/vendor/bootstrap.css') ?>">
|
||||
<link rel="stylesheet" href="<?= $this->baseUrl('css/vendor/ui-lightness/jquery-ui-1.10.3.custom.min.css') ?>">
|
||||
<link rel="stylesheet" href="<?= $this->baseUrl('css/main.css') ?>">
|
||||
<link rel="stylesheet" href="<?= $this->baseUrl('css/vendor/jquery.qtip.min.css') ?>">
|
||||
<script type="text/javascript">
|
||||
var base_url = '<?php echo $this->baseUrl() ?>';
|
||||
var base_url = '<?= $this->baseUrl() ?>';
|
||||
ICINGA_DEBUG = true;
|
||||
</script>
|
||||
<? if (isset($_GET['iframe']) && $_GET['iframe'] === 'true'): ?>
|
||||
<base target="_parent" />
|
||||
<? endif ?>
|
||||
|
||||
<script src="<?php echo $this->baseUrl('js/vendor/modernizr-2.6.2.min.js') ?>"></script>
|
||||
<link rel="stylesheet" href="<?php echo $this->baseUrl('css.php') ?>">
|
||||
<link rel="stylesheet" href="<?php echo $this->baseUrl('css/vendor/bootstrap-responsive.min.css') ?>">
|
||||
@ -30,29 +35,7 @@
|
||||
<script data-main="<?php echo $this->baseUrl('js/main.js')?>" src="<?php echo $this->baseUrl('js/vendor/require.js') ?>"></script>
|
||||
|
||||
</head>
|
||||
<body class="cranberry">
|
||||
<?php echo $this->render('parts/topbar.phtml') ?>
|
||||
<div class="main">
|
||||
<div class="tabbable tabs-left" style="height:100%;">
|
||||
<?php echo $this->render('parts/navigation.phtml') ?>
|
||||
</div>
|
||||
<div class="layout-main-detail collapsed">
|
||||
<div id="icinga-main" container-id="icinga-main" class="icinga-container">
|
||||
<?php echo $this->layout()->moduleStart ?>
|
||||
<?php echo $this->layout()->content ?>
|
||||
<?php echo $this->layout()->moduleEnd ?>
|
||||
</div>
|
||||
<div id="icinga-detail" class="icinga-container " container-id="icinga-detail">
|
||||
<!--<div class="container-controls">
|
||||
<a class="container-expand-link" title="expand" target="_self" href="...">
|
||||
<i class="icon-fullscreen"></i>
|
||||
</a>
|
||||
<a class="container-detach-link" title="detach" target="popup" href="...">
|
||||
<i class="icon-share"></i>
|
||||
</a>
|
||||
</div>-->
|
||||
</div><!-- End of icinga-detail -->
|
||||
</div><!-- End of layout-main-detail -->
|
||||
</div><!-- End of main -->
|
||||
<body class="cranberry">
|
||||
<?= $this->render('just-the-body.phtml') ?>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -5,8 +5,7 @@
|
||||
|
||||
$item = $this->navigation->listAll("menu");
|
||||
?>
|
||||
<?php if (true || $this->auth()->isAuthenticated()): ?>
|
||||
|
||||
<?php if ($this->auth()->isAuthenticated()): ?>
|
||||
<ul class="nav nav-tabs icinga-navigation" >
|
||||
<?php
|
||||
$activeSet = false;
|
||||
@ -32,10 +31,10 @@
|
||||
}
|
||||
$activeSet = $activeSet || $active;
|
||||
?>
|
||||
<li class="<?php echo $active ? "active" : "" ?>"><a href="<?php echo $url ?>"><?php echo $itemName ?></a></li>
|
||||
<li class="<?= $active ? "active" : "" ?>"><a href="<?= $url ?>"><?= $itemName ?></a></li>
|
||||
<?php
|
||||
$class = "";
|
||||
}
|
||||
?>
|
||||
</ul>
|
||||
<?php endif ?>
|
||||
<? endif ?>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="navbar-inner ">
|
||||
<ul class="nav pull-left">
|
||||
<li style="float:left"><a href="<?php echo $this->baseUrl('/') ?>" class="brand" style="margin-left:0px;">Icinga</a></li>
|
||||
<li style="float:left"><a href="<?= $this->baseUrl('/') ?>" class="brand" style="margin-left:0px;">Icinga</a></li>
|
||||
</ul>
|
||||
<?php if ($this->auth()->isAuthenticated()): ?>
|
||||
<ul class="nav pull-right" >
|
||||
@ -11,13 +11,14 @@
|
||||
</form>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><?php echo
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><?=
|
||||
$this->escape($this->auth()->getUser()->getUsername())
|
||||
?> <i class="icon-user icon-white" style="margin-top:0.2em"></i>
|
||||
<b class="caret"></b>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><?php echo $this->qlink(_('Logout'), '/authentication/logout') ?></li>
|
||||
<li><?= $this->qlink($this->translate('Settings'), 'settings') ?></li>
|
||||
<li><?= $this->qlink($this->translate('Logout'), 'authentication/logout') ?></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -1,3 +1,2 @@
|
||||
<div class="clearfix" style="margin-top: 100px;">
|
||||
<h1>Bootstrap loaded!</h1>
|
||||
</div>
|
||||
<h1>Welcome to Icinga!</h1>
|
||||
You should install/configure some <?= $this->qlink('modules', 'modules/overview') ?> now!
|
||||
|
@ -1,61 +1,58 @@
|
||||
<? if ($this->pageCount > 1): ?>
|
||||
<?php
|
||||
if (is_array($this->preserve)) {
|
||||
$preserve = $this->preserve;
|
||||
} else {
|
||||
$preserve = array();
|
||||
}
|
||||
|
||||
$fromto = t('%d to %d of %d');
|
||||
if ($this->pageCount <= 1) return;
|
||||
|
||||
$fromto = $this->translate('%d to %d of %d');
|
||||
$total = $this->totalItemCount;
|
||||
?>
|
||||
<div class="pagination pagination-mini" style="margin:0px">
|
||||
$limit = $this->itemCountPerPage;
|
||||
$title_prev = sprintf(
|
||||
$fromto,
|
||||
($this->current - 2) * $limit + 1,
|
||||
($this->current - 1) * $limit,
|
||||
$total
|
||||
);
|
||||
|
||||
$title_next = sprintf(
|
||||
$fromto,
|
||||
($this->current) * $limit + 1,
|
||||
($this->current + 1) * $limit,
|
||||
$total
|
||||
);
|
||||
|
||||
?><div class="pagination pagination-mini" style="margin:0px">
|
||||
<ul>
|
||||
<!-- Previous page link -->
|
||||
<? if (isset($this->previous)): ?>
|
||||
<li><a href="<?= $this->url($preserve + array('page' => $this->previous)); ?>" title="<?=
|
||||
sprintf($fromto,
|
||||
($this->current - 2) * $this->itemCountPerPage + 1,
|
||||
($this->current - 1) * $this->itemCountPerPage,
|
||||
$this->totalItemCount)
|
||||
?>">« <?= t('Back') ?></a></li>
|
||||
<? else: ?>
|
||||
<li class="disabled"><span>« <?= t('Back') ?></span></li>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
<?php if (isset($this->previous)): ?>
|
||||
<li><a href="<?= $this->url()->setParam('page', $this->previous) ?>" title="<?= $titleprev ?>">« <?= $this->translate('Back') ?></a></li>
|
||||
<?php else: ?>
|
||||
<li class="disabled"><span>« <?= $this->translate('Back') ?></span></li>
|
||||
<?php endif ?>
|
||||
<!-- Numbered page links -->
|
||||
<? foreach ($this->pagesInRange as $page): ?>
|
||||
<?php
|
||||
|
||||
$start = ($page - 1) * $this->itemCountPerPage + 1;
|
||||
$end = $page * $this->itemCountPerPage;
|
||||
if ($end > $total) {
|
||||
$end = $total;
|
||||
}
|
||||
$title = sprintf($fromto, $start, $end, $total);
|
||||
$active_class = $page === $this->current ? ' class="active"' : '';
|
||||
foreach ($this->pagesInRange as $page):
|
||||
|
||||
?>
|
||||
<?php if ($page === '...'): ?>
|
||||
$start = ($page - 1) * $limit + 1;
|
||||
$end = $page * $limit;
|
||||
if ($end > $total) {
|
||||
$end = $total;
|
||||
}
|
||||
$title = sprintf($fromto, $start, $end, $total);
|
||||
$class = $page === $this->current ? ' class="active"' : '';
|
||||
|
||||
if ($page === '...'): ?>
|
||||
<li class="disabled"><span>...</span></li>
|
||||
<?php else: ?>
|
||||
<li<?= $active_class ?>><a href="<?= $this->url(
|
||||
$preserve + array('page' => $page)
|
||||
); ?>" title="<?= $title ?>"><?= $page; ?></a></li>
|
||||
<? endif ?>
|
||||
<? endforeach ?>
|
||||
<li<?= $class ?>><a href="<?= $this->url()->setParam('page', $page) ?>" title="<?= $title ?>"><?= $page ?></a></li>
|
||||
<?php
|
||||
endif;
|
||||
endforeach;
|
||||
?>
|
||||
<!-- Next page link -->
|
||||
<? if (isset($this->next)): ?>
|
||||
<li><a href="<?= $this->url($preserve + array('page' => $this->next)); ?>" title="<?=
|
||||
sprintf($fromto,
|
||||
($this->current) * $this->itemCountPerPage + 1,
|
||||
($this->current + 1) * $this->itemCountPerPage,
|
||||
$total)
|
||||
?>"><?= t('Next') ?> »</a></li>
|
||||
<li><a href="<?= $this->url()->setParam('page', $this->next) ?>" title="<?= $title_next ?>"><?= t('Next') ?> »</a></li>
|
||||
<? else: ?>
|
||||
<li class="disabled"><span><?= t('Next') ?> »</span></li>
|
||||
<? endif ?>
|
||||
</ul>
|
||||
</div>
|
||||
<? endif ?>
|
||||
|
64
bin/createapidoc.sh
Executable file
64
bin/createapidoc.sh
Executable file
@ -0,0 +1,64 @@
|
||||
#!/bin/sh
|
||||
|
||||
# {{{ICINGA_LICENSE_HEADER}}}
|
||||
# Icinga 2 Web - Head for multiple monitoring frontends
|
||||
# Copyright (C) %(YEAR)s 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>
|
||||
# {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
set -o nounset
|
||||
|
||||
DIR=$(readlink -f $(dirname $0)/../)
|
||||
BIN=$(basename $0)
|
||||
PHPDOC=$(which phpdoc)
|
||||
CONFIG=$DIR/doc/phpdoc.xml
|
||||
OUTPUT=$DIR/doc/api
|
||||
ARG=${1-}
|
||||
BUILD=""
|
||||
|
||||
cd $DIR
|
||||
|
||||
if [ ! -x $PHPDOC ]; then
|
||||
echo "phpDocumentor not found (phpdoc)"
|
||||
echo "Please read http://phpdoc.org/docs/latest/for-users/installation.html how to install"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -d $OUTPUT ]; then
|
||||
echo "Output directory exists"
|
||||
echo "rm -rf $OUTPUT"
|
||||
rm -rf $OUTPUT
|
||||
fi
|
||||
|
||||
if [ "$ARG" == "--build" ]; then
|
||||
BUILD="-q"
|
||||
fi
|
||||
|
||||
if [ "$ARG" == "--help" ]; then
|
||||
echo "Usage $BIN [ --build ]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --build Silent output"
|
||||
echo " --help Print this screen"
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
$PHPDOC $BUILD -c $CONFIG
|
||||
exit $?
|
@ -1,5 +1,27 @@
|
||||
#!/bin/sh
|
||||
|
||||
# {{{ICINGA_LICENSE_HEADER}}}
|
||||
# Icinga 2 Web - Head for multiple monitoring frontends
|
||||
# Copyright (C) %(YEAR)s 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>
|
||||
# {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
set -o nounset
|
||||
|
||||
SCRIPTNAME=$(readlink -f $0)
|
||||
|
27
doc/apidoc_creation.md
Normal file
27
doc/apidoc_creation.md
Normal file
@ -0,0 +1,27 @@
|
||||
# Create API documentation
|
||||
|
||||
## Prerequisites
|
||||
|
||||
You need phpDocumentor 2 installed on your system to create the api
|
||||
documentation. Please visit [phpdoc's website](http://phpdoc.org/) for more
|
||||
information. Additionally, the graphviz package is required to be installed.
|
||||
|
||||
## Configuration
|
||||
|
||||
phpDocumentator is configured with xml configuration reside in doc/phpdoc.xml.
|
||||
In there you'll find the target path where the documentation is created as
|
||||
html. Default location is doc/api/. Just point to index.html in this directory
|
||||
with a browser.
|
||||
|
||||
If you generated the documentation already, you can follow [this link](apidoc/idnex.html).
|
||||
|
||||
## Generation
|
||||
|
||||
Change to Icinga 2 Web root directory (source tree) and run:
|
||||
|
||||
bin/createapidoc.sh
|
||||
|
||||
## Options for createapidoc.sh
|
||||
|
||||
--build Optional, silent build mode
|
||||
--help Displays help message
|
22
doc/phpdoc.xml
Normal file
22
doc/phpdoc.xml
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<phpdoc>
|
||||
<title>Icinga 2 Web</title>
|
||||
<parser>
|
||||
<target>./api</target>
|
||||
<extension>php</extension>
|
||||
</parser>
|
||||
<visibility>public,private,protected</visibility>
|
||||
<transformer>
|
||||
<target>./api</target>
|
||||
</transformer>
|
||||
<logging>
|
||||
<level>quiet</level>
|
||||
</logging>
|
||||
<transformations>
|
||||
<template name="responsive" />
|
||||
</transformations>
|
||||
<files>
|
||||
<directory>../library/Icinga</directory>
|
||||
<directory>../library/application</directory>
|
||||
</files>
|
||||
</phpdoc>
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace Icinga\Application;
|
||||
|
||||
use Icinga\Application\Modules\Module;
|
||||
use Zend_Config_Ini;
|
||||
use Zend_Config;
|
||||
|
||||
@ -32,17 +33,19 @@ class Config extends Zend_Config_Ini
|
||||
return parent::__construct($filename, $section, $options);
|
||||
}
|
||||
|
||||
public function getModuleConfig($key, $module)
|
||||
public static function module($name, $file = null)
|
||||
{
|
||||
$manager = Icinga::app()->moduleManager();
|
||||
$res = null;
|
||||
if ($manager->hasInstalled($module)) {
|
||||
$filename = $manager->getModuleConfigDir($module) . "/$key.ini";
|
||||
if (file_exists($filename)) {
|
||||
return $this->$key = new Config($filename);
|
||||
}
|
||||
if ($file === null) {
|
||||
$file = $name . '.ini'; // TODO: default should be module/config.ini
|
||||
}
|
||||
return $res;
|
||||
$filename = Module::get($name)->getConfigDir() . '/' . $file;
|
||||
if (file_exists($filename)) {
|
||||
$config = new Config($filename);
|
||||
// Compat: $config->$module->$whatever
|
||||
self::getInstance()->$name = $config;
|
||||
return $config;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function __get($key)
|
||||
|
@ -3,6 +3,7 @@
|
||||
namespace Icinga\Application\Modules;
|
||||
|
||||
use Icinga\Application\ApplicationBootstrap;
|
||||
use Icinga\Application\Icinga;
|
||||
use Icinga\Web\Hook;
|
||||
use Zend_Controller_Router_Route as Route;
|
||||
|
||||
@ -38,6 +39,23 @@ class Module
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function exists($name)
|
||||
{
|
||||
return Icinga::app()->moduleManager()->hasEnabled($name);
|
||||
}
|
||||
|
||||
public static function get($name, $autoload = false)
|
||||
{
|
||||
$manager = Icinga::app()->moduleManager();
|
||||
if (! $manager->hasLoaded($name)) {
|
||||
if ($autoload === true && $manager->hasEnabled($name)) {
|
||||
$manager->loadModule($name);
|
||||
}
|
||||
}
|
||||
// @throws ProgrammingError:
|
||||
return $manager->getModule($name);
|
||||
}
|
||||
|
||||
public function hasCss()
|
||||
{
|
||||
return file_exists($this->getCssFilename());
|
||||
@ -58,6 +76,13 @@ class Module
|
||||
return $this->configdir;
|
||||
}
|
||||
|
||||
public function getConfig($file = null)
|
||||
{
|
||||
return $this->app
|
||||
->getConfig()
|
||||
->module($this->name, $file);
|
||||
}
|
||||
|
||||
protected function registerLibrary()
|
||||
{
|
||||
if (file_exists($this->libdir) && is_dir($this->libdir)) {
|
||||
@ -88,17 +113,14 @@ class Module
|
||||
}
|
||||
|
||||
$this->registerLocales()
|
||||
->registerRoutes()
|
||||
->registerMenuEntries();
|
||||
->registerRoutes();
|
||||
// ->registerMenuEntries();
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function registerMenuEntries()
|
||||
{
|
||||
$cfg = $this->app
|
||||
->getConfig()
|
||||
->getModuleConfig('menu', $this->name);
|
||||
|
||||
$cfg = $this->getConfig('menu.ini');
|
||||
$view = $this->app->getView();
|
||||
if ($cfg) {
|
||||
$view->view->navigation = $cfg->merge($view->view->navigation);
|
||||
@ -119,6 +141,17 @@ class Module
|
||||
)
|
||||
)
|
||||
);
|
||||
$this->app->frontController()->getRouter()->addRoute(
|
||||
$this->name . '_img',
|
||||
new Route(
|
||||
'img/' . $this->name . '/:file',
|
||||
array(
|
||||
'controller' => 'static',
|
||||
'action' => 'img',
|
||||
'moduleName' => $this->name
|
||||
)
|
||||
)
|
||||
);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -72,6 +72,11 @@ abstract class AbstractQuery
|
||||
$this->init();
|
||||
}
|
||||
|
||||
public function getDatasource()
|
||||
{
|
||||
return $this->ds;
|
||||
}
|
||||
|
||||
protected function getDefaultColumns()
|
||||
{
|
||||
return null;
|
||||
@ -89,6 +94,9 @@ abstract class AbstractQuery
|
||||
$this->table = $table;
|
||||
if ($columns !== null) {
|
||||
$this->columns($columns);
|
||||
} else {
|
||||
// TODO: Really?
|
||||
$this->columns = $this->getDefaultColumns();
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
@ -100,7 +108,6 @@ abstract class AbstractQuery
|
||||
} else {
|
||||
$this->columns = array($columns);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -355,6 +362,7 @@ abstract class AbstractQuery
|
||||
$limit = $request->getParam('limit', 20);
|
||||
}
|
||||
}
|
||||
$this->limit($limit, $page * $limit);
|
||||
|
||||
$paginator = new \Zend_Paginator(
|
||||
new \Icinga\Web\Paginator\Adapter\QueryAdapter($this)
|
||||
|
@ -36,6 +36,22 @@ class ArrayDatasource implements DatasourceInterface
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function fetchPairs(ArrayQuery $query)
|
||||
{
|
||||
$result = array();
|
||||
$keys = null;
|
||||
foreach ($this->getResult($query) as $row) {
|
||||
if ($keys === null) {
|
||||
$keys = array_keys((array) $row);
|
||||
if (count($keys) < 2) {
|
||||
$keys[1] = $keys[0];
|
||||
}
|
||||
}
|
||||
$result[$row->{$keys[0]}] = $row->{$keys[1]};
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function fetchAll(ArrayQuery $query)
|
||||
{
|
||||
$result = $this->getResult($query);
|
||||
@ -70,11 +86,14 @@ class ArrayDatasource implements DatasourceInterface
|
||||
$result[] = $row;
|
||||
} else {
|
||||
$c_row = (object) array();
|
||||
foreach ($columns as $key) {
|
||||
foreach ($columns as $alias => $key) {
|
||||
if (is_int($alias)) {
|
||||
$alias = $key;
|
||||
}
|
||||
if (isset($row->$key)) {
|
||||
$c_row->$key = $row->$key;
|
||||
$c_row->$alias = $row->$key;
|
||||
} else {
|
||||
$c_row->$key = null;
|
||||
$c_row->$alias = null;
|
||||
}
|
||||
}
|
||||
$result[] = $c_row;
|
||||
|
46
library/Icinga/File/Csv.php
Normal file
46
library/Icinga/File/Csv.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\File;
|
||||
|
||||
use Icinga\Data\AbstractQuery;
|
||||
|
||||
class Csv
|
||||
{
|
||||
protected $query;
|
||||
|
||||
protected function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public static function fromQuery(AbstractQuery $query)
|
||||
{
|
||||
$csv = new Csv();
|
||||
$csv->query = $query;
|
||||
return $csv;
|
||||
}
|
||||
|
||||
public function dump()
|
||||
{
|
||||
header('Content-type: text/csv');
|
||||
echo (string) $this;
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
$first = true;
|
||||
$csv = '';
|
||||
foreach ($this->query->fetchAll() as $row) {
|
||||
if ($first) {
|
||||
$csv .= implode(',', array_keys((array) $row)) . "\r\n";
|
||||
$first = false;
|
||||
}
|
||||
$out = array();
|
||||
foreach ($row as & $val) {
|
||||
$out[] = '"' . $val . '"';
|
||||
}
|
||||
$csv .= implode(',', $out) . "\r\n";
|
||||
}
|
||||
return $csv;
|
||||
}
|
||||
}
|
||||
|
0
library/Icinga/File/Csv/Query.php
Normal file
0
library/Icinga/File/Csv/Query.php
Normal file
@ -1,14 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Pdf;
|
||||
namespace Icinga\File;
|
||||
|
||||
use TCPDF;
|
||||
use Icinga\Web\Url;
|
||||
use Icinga\Application\Icinga;
|
||||
|
||||
// $_SERVER['DOCUMENT_ROOT'] = '/';
|
||||
$_SERVER['DOCUMENT_ROOT'] = Icinga::app()->getApplicationDir() . '/../public';
|
||||
define('K_TCPDF_EXTERNAL_CONFIG', true);
|
||||
|
||||
//define('K_PATH_URL', 'http://net-test-icinga-vm1.adm.netways.de/develop/'); // ???
|
||||
// define('K_PATH_URL', '/var/www/net-test-icinga-vm1.adm.netways.de/develop/public'); // ???
|
||||
define('K_PATH_URL', '/develop'); // ???
|
||||
define('K_PATH_URL', (string) Url::create('/') === '/' ? '' : (string) Url::create('/')); // ???'/'));
|
||||
define('K_PATH_MAIN', dirname(ICINGA_LIBDIR) . '/public');
|
||||
define('K_PATH_FONTS', ICINGA_LIBDIR . '/vendor/tcpdf/fonts/');
|
||||
define('K_PATH_CACHE', ICINGA_LIBDIR . '/vendor/tcpdf/cache/');
|
||||
@ -19,13 +23,13 @@ define('K_BLANK_IMAGE', K_PATH_IMAGES.'_blank.png'); // COULD be anything?
|
||||
|
||||
// define('K_CELL_HEIGHT_RATIO', 1.25);
|
||||
define('K_SMALL_RATIO', 2/3);
|
||||
define('K_TCPDF_CALLS_IN_HTML', true); // SECURITY: is false better?
|
||||
define('K_TCPDF_CALLS_IN_HTML', false); // SECURITY: is false better?
|
||||
define('K_TCPDF_THROW_EXCEPTION_ERROR', true);
|
||||
|
||||
define('K_THAI_TOPCHARS', false);
|
||||
|
||||
require_once 'vendor/tcpdf/tcpdf.php';
|
||||
|
||||
class File extends TCPDF
|
||||
class Pdf extends TCPDF
|
||||
{
|
||||
protected $cell_height_ratio = 1.25;
|
||||
public function __construct(
|
@ -1,31 +1,10 @@
|
||||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
/**
|
||||
* 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>
|
||||
*/
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
/**
|
||||
* LDAP connection handler
|
||||
*/
|
||||
namespace Icinga\Protocol\Ldap;
|
||||
|
||||
use Icinga\Exception\ConfigurationError as ConfigError;
|
||||
use Icinga\Application\Platform;
|
||||
use Icinga\Application\Config;
|
||||
use Icinga\Application\Logger as Log;
|
||||
@ -46,89 +25,65 @@ use Icinga\Application\Logger as Log;
|
||||
*
|
||||
* @copyright Copyright (c) 2013 Icinga-Web Team <info@icinga.org>
|
||||
* @author Icinga-Web Team <info@icinga.org>
|
||||
* @package Icinga\Protocol\Ldap
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
|
||||
*/
|
||||
class Connection
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
const LDAP_NO_SUCH_OBJECT = 0x20;
|
||||
|
||||
protected $ds;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $hostname;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $port = 389;
|
||||
protected $bind_dn;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $bind_pw;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $root_dn;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $count;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $ldap_extension = array(
|
||||
'1.3.6.1.4.1.1466.20037' => 'STARTTLS', // notes?
|
||||
'1.3.6.1.4.1.1466.20037' => 'STARTTLS',
|
||||
// '1.3.6.1.4.1.4203.1.11.1' => '11.1', // PASSWORD_MODIFY
|
||||
// '1.3.6.1.4.1.4203.1.11.3' => '11.3', // Whoami
|
||||
// '1.3.6.1.1.8' => '8', // Cancel Extended Request
|
||||
);
|
||||
|
||||
protected $use_tls = false;
|
||||
protected $force_tls = false;
|
||||
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $ms_capability = array(
|
||||
// Prefix LDAP_CAP_
|
||||
// Source: http://msdn.microsoft.com/en-us/library/cc223359.aspx
|
||||
|
||||
// Running Active Directory as AD DS:
|
||||
'1.2.840.113556.1.4.800' => 'ACTIVE_DIRECTORY_OID',
|
||||
'1.2.840.113556.1.4.800' => 'ACTIVE_DIRECTORY_OID',
|
||||
|
||||
// Capable of signing and sealing on an NTLM authenticated connection
|
||||
// and of performing subsequent binds on a signed or sealed connection.
|
||||
'1.2.840.113556.1.4.1791' => 'ACTIVE_DIRECTORY_LDAP_INTEG_OID',
|
||||
|
||||
// If AD DS: running at least W2K3, if AD LDS running at least W2K8
|
||||
'1.2.840.113556.1.4.1670' => 'ACTIVE_DIRECTORY_V51_OID',
|
||||
|
||||
// If AD LDS: accepts DIGEST-MD5 binds for AD LDSsecurity principals
|
||||
'1.2.840.113556.1.4.1880' => 'ACTIVE_DIRECTORY_ADAM_DIGEST',
|
||||
|
||||
// Running Active Directory as AD LDS
|
||||
'1.2.840.113556.1.4.1851' => 'ACTIVE_DIRECTORY_ADAM_OID',
|
||||
|
||||
// If AD DS: it's a Read Only DC (RODC)
|
||||
'1.2.840.113556.1.4.1920' => 'ACTIVE_DIRECTORY_PARTIAL_SECRETS_OID',
|
||||
|
||||
// Running at least W2K8
|
||||
'1.2.840.113556.1.4.1935' => 'ACTIVE_DIRECTORY_V60_OID',
|
||||
|
||||
// Running at least W2K8r2
|
||||
'1.2.840.113556.1.4.2080' => 'ACTIVE_DIRECTORY_V61_R2_OID',
|
||||
|
||||
// Running at least W2K12
|
||||
'1.2.840.113556.1.4.2237' => 'ACTIVE_DIRECTORY_W8_OID',
|
||||
|
||||
);
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $root;
|
||||
|
||||
protected $supports_v3 = false;
|
||||
protected $supports_tls = false;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
@ -139,24 +94,17 @@ class Connection
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->hostname = $config->hostname;
|
||||
$this->bind_dn = $config->bind_dn;
|
||||
$this->bind_pw = $config->bind_pw;
|
||||
$this->root_dn = $config->root_dn;
|
||||
$this->use_tls = isset($config->tls) ? $config->tls : false;
|
||||
$this->force_tls = $this->use_tls;
|
||||
$this->bind_dn = $config->bind_dn;
|
||||
$this->bind_pw = $config->bind_pw;
|
||||
$this->root_dn = $config->root_dn;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getDN()
|
||||
{
|
||||
return $this->root_dn;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Root|string
|
||||
*/
|
||||
public function root()
|
||||
{
|
||||
if ($this->root === null) {
|
||||
@ -165,36 +113,22 @@ class Connection
|
||||
return $this->root;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Query
|
||||
*/
|
||||
public function select()
|
||||
{
|
||||
return new Query($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $query
|
||||
* @param array $fields
|
||||
* @return mixed
|
||||
*/
|
||||
public function fetchOne($query, $fields = array())
|
||||
{
|
||||
$row = (array)$this->fetchRow($query, $fields);
|
||||
$row = (array) $this->fetchRow($query, $fields);
|
||||
return array_shift($row);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $query
|
||||
* @param array $fields
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function fetchDN($query, $fields = array())
|
||||
{
|
||||
$rows = $this->fetchAll($query, $fields);
|
||||
if (count($rows) !== 1) {
|
||||
throw new Exception(
|
||||
throw new \Exception(
|
||||
sprintf(
|
||||
'Cannot fetch single DN for %s',
|
||||
$query
|
||||
@ -204,11 +138,7 @@ class Connection
|
||||
return key($rows);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $query
|
||||
* @param array $fields
|
||||
* @return mixed
|
||||
*/
|
||||
|
||||
public function fetchRow($query, $fields = array())
|
||||
{
|
||||
// TODO: This is ugly, make it better!
|
||||
@ -216,31 +146,28 @@ class Connection
|
||||
return array_shift($results);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Query $query
|
||||
* @return int
|
||||
*/
|
||||
public function count(Query $query)
|
||||
{
|
||||
$results = $this->runQuery($query, '+');
|
||||
if (! $results) {
|
||||
return 0;
|
||||
}
|
||||
return ldap_count_entries($this->ds, $results);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $query
|
||||
* @param array $fields
|
||||
* @return array
|
||||
*/
|
||||
public function fetchAll($query, $fields = array())
|
||||
{
|
||||
$offset = null;
|
||||
$limit = null;
|
||||
if ($query->hasLimit()) {
|
||||
$offset = $query->getOffset();
|
||||
$limit = $query->getLimit();
|
||||
$limit = $query->getLimit();
|
||||
}
|
||||
$entries = array();
|
||||
$results = $this->runQuery($query, $fields);
|
||||
if (! $results) {
|
||||
return array();
|
||||
}
|
||||
$entry = ldap_first_entry($this->ds, $results);
|
||||
$count = 0;
|
||||
while ($entry) {
|
||||
@ -248,7 +175,8 @@ class Connection
|
||||
&& ($limit === null || ($offset + $limit) >= $count)
|
||||
) {
|
||||
$attrs = ldap_get_attributes($this->ds, $entry);
|
||||
$entries[ldap_get_dn($this->ds, $entry)] = $this->cleanupAttributes($attrs);
|
||||
$entries[ldap_get_dn($this->ds, $entry)]
|
||||
= $this->cleanupAttributes($attrs);
|
||||
}
|
||||
$count++;
|
||||
$entry = ldap_next_entry($this->ds, $entry);
|
||||
@ -257,13 +185,9 @@ class Connection
|
||||
return $entries;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $attrs
|
||||
* @return object
|
||||
*/
|
||||
public function cleanupAttributes(& $attrs)
|
||||
{
|
||||
$clean = (object)array();
|
||||
$clean = (object) array();
|
||||
for ($i = 0; $i < $attrs['count']; $i++) {
|
||||
$attr_name = $attrs[$i];
|
||||
if ($attrs[$attr_name]['count'] === 1) {
|
||||
@ -277,12 +201,6 @@ class Connection
|
||||
return $clean;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $query
|
||||
* @param $fields
|
||||
* @return resource
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function runQuery($query, $fields)
|
||||
{
|
||||
$this->connect();
|
||||
@ -293,17 +211,19 @@ class Connection
|
||||
// We do not support pagination right now, and there is no chance to
|
||||
// do so for PHP < 5.4. Warnings about "Sizelimit exceeded" will
|
||||
// therefore not be hidden right now.
|
||||
Log::debug("Query: %s", $query->__toString());
|
||||
$results = ldap_search(
|
||||
$results = @ldap_search(
|
||||
$this->ds,
|
||||
$this->root_dn,
|
||||
(string)$query,
|
||||
(string) $query,
|
||||
$fields,
|
||||
0, // Attributes and values
|
||||
0 // No limit - at least where possible
|
||||
0 // No limit - at least where possible
|
||||
);
|
||||
if (!$results) {
|
||||
throw new Exception(
|
||||
if ($results === false) {
|
||||
if (ldap_errno($this->ds) === self::LDAP_NO_SUCH_OBJECT) {
|
||||
return false;
|
||||
}
|
||||
throw new \Exception(
|
||||
sprintf(
|
||||
'LDAP query "%s" (root %s) failed: %s',
|
||||
$query,
|
||||
@ -311,7 +231,6 @@ class Connection
|
||||
ldap_error($this->ds)
|
||||
)
|
||||
);
|
||||
|
||||
die('Query failed');
|
||||
}
|
||||
$list = array();
|
||||
@ -323,186 +242,229 @@ class Connection
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $username
|
||||
* @param $password
|
||||
* @return bool
|
||||
*/
|
||||
public function testCredentials($username, $password)
|
||||
{
|
||||
Log::debug("Trying to connect to %s", $this->hostname);
|
||||
$ds = ldap_connect($this->hostname);
|
||||
Log::debug("ldap_bind (%s)", $username);
|
||||
$ds = $this->prepareNewConnection();
|
||||
|
||||
$r = @ldap_bind($ds, $username, $password);
|
||||
if ($r) {
|
||||
log::debug(
|
||||
'Successfully tested LDAP credentials (%s / %s)',
|
||||
$username,
|
||||
'***'
|
||||
);
|
||||
return true;
|
||||
} else {
|
||||
log::fatal(
|
||||
'LDAP connection (%s / %s) failed: %s',
|
||||
log::debug(
|
||||
'Testing LDAP credentials (%s / %s) failed: %s',
|
||||
$username,
|
||||
'***',
|
||||
ldap_error($ds)
|
||||
);
|
||||
return false;
|
||||
/* TODO: Log failure
|
||||
throw new Exception(sprintf(
|
||||
'LDAP connection (%s / %s) failed: %s',
|
||||
$username,
|
||||
'***',
|
||||
ldap_error($ds)
|
||||
));
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
protected function getConfigDir()
|
||||
protected function getConfigDir($sub = null)
|
||||
{
|
||||
return Config::getInstance()->getConfigDir() . '/ldap';
|
||||
$dir = Config::getInstance()->getConfigDir() . '/ldap';
|
||||
if ($sub !== null) {
|
||||
$dir .= '/' . $sub;
|
||||
}
|
||||
return $dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $domain
|
||||
*/
|
||||
protected function discoverServerlistForDomain($domain)
|
||||
{
|
||||
$ldaps_records = dns_get_record('_ldaps._tcp.' . $domain, DNS_SRV);
|
||||
$ldap_records = dns_get_record('_ldap._tcp.' . $domain, DNS_SRV);
|
||||
$ldap_records = dns_get_record('_ldap._tcp.' . $domain, DNS_SRV);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
protected function prepareTlsEnvironment()
|
||||
protected function prepareNewConnection()
|
||||
{
|
||||
$strict_tls = true;
|
||||
$use_local_ca = true;
|
||||
if (Platform::isWindows()) {
|
||||
} else {
|
||||
$cfg_dir = $this->getConfigDir();
|
||||
if ($strict_tls) {
|
||||
putenv(sprintf('LDAPRC=%s/%s', $cfg_dir, 'ldap_ca.conf'));
|
||||
$use_tls = false;
|
||||
$force_tls = true;
|
||||
$force_tls = false;
|
||||
|
||||
if ($use_tls) {
|
||||
$this->prepareTlsEnvironment();
|
||||
}
|
||||
|
||||
$ds = ldap_connect($this->hostname, $this->port);
|
||||
$cap = $this->discoverCapabilities($ds);
|
||||
|
||||
if ($use_tls) {
|
||||
if ($cap->starttls) {
|
||||
if (@ldap_start_tls($ds)) {
|
||||
Log::debug('LDAP STARTTLS succeeded');
|
||||
} else {
|
||||
Log::debug('LDAP STARTTLS failed: %s', ldap_error($ds));
|
||||
throw new \Exception(
|
||||
sprintf(
|
||||
'LDAP STARTTLS failed: %s',
|
||||
ldap_error($ds)
|
||||
)
|
||||
);
|
||||
}
|
||||
} elseif ($force_tls) {
|
||||
throw new \Exception(
|
||||
sprintf(
|
||||
'TLS is required but not announced by %s',
|
||||
$this->host_name
|
||||
)
|
||||
);
|
||||
} else {
|
||||
putenv(sprintf('LDAPRC=%s/%s', $cfg_dir, 'ldap_nocert.conf'));
|
||||
// TODO: Log noticy -> TLS enabled but not announced
|
||||
}
|
||||
}
|
||||
// file_put_contents('/tmp/tom_LDAP.conf', "TLS_REQCERT never\n");
|
||||
// ldap_rename requires LDAPv3:
|
||||
if ($cap->ldapv3) {
|
||||
if (! ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3)) {
|
||||
throw new Exception('LDAPv3 is required');
|
||||
}
|
||||
} else {
|
||||
|
||||
// TODO: remove this -> FORCING v3 for now
|
||||
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
|
||||
|
||||
Log::warn('No LDAPv3 support detected');
|
||||
}
|
||||
|
||||
// Not setting this results in "Operations error" on AD when using the
|
||||
// whole domain as search base:
|
||||
ldap_set_option($ds, LDAP_OPT_REFERRALS, 0);
|
||||
// ldap_set_option($ds, LDAP_OPT_DEREF, LDAP_DEREF_NEVER);
|
||||
return $ds;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return object
|
||||
*/
|
||||
protected function fetchRootDseDetails()
|
||||
protected function prepareTlsEnvironment()
|
||||
{
|
||||
$query = $this->select()->from('*', array('+'));
|
||||
|
||||
/*, array(
|
||||
'defaultNamingContext',
|
||||
'namingContexts',
|
||||
'supportedSaslMechanisms',
|
||||
'dnsHostName',
|
||||
'schemaNamingContext',
|
||||
'supportedLDAPVersion', // => array(3, 2)
|
||||
'supportedCapabilities'
|
||||
))*/
|
||||
$strict_tls = true;
|
||||
// TODO: allow variable known CA location (system VS Icinga)
|
||||
if (Platform::isWindows()) {
|
||||
// putenv('LDAP...')
|
||||
} else {
|
||||
if ($strict_tls) {
|
||||
$ldap_conf = $this->getConfigDir('ldap_ca.conf');
|
||||
} else {
|
||||
$ldap_conf = $this->getConfigDir('ldap_nocert.conf');
|
||||
}
|
||||
putenv('LDAPRC=' . $ldap_conf);
|
||||
if (getenv('LDAPRC') !== $ldap_conf) {
|
||||
throw new Exception('putenv failed');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function discoverCapabilities($ds)
|
||||
{
|
||||
$query = $this->select()->from(
|
||||
'*',
|
||||
array(
|
||||
'defaultNamingContext',
|
||||
'namingContexts',
|
||||
'vendorName',
|
||||
'vendorVersion',
|
||||
'supportedSaslMechanisms',
|
||||
'dnsHostName',
|
||||
'schemaNamingContext',
|
||||
'supportedLDAPVersion', // => array(3, 2)
|
||||
'supportedCapabilities',
|
||||
'supportedExtension',
|
||||
'+'
|
||||
)
|
||||
);
|
||||
$fields = $query->listFields();
|
||||
|
||||
$result = ldap_read(
|
||||
$this->ds,
|
||||
$result = @ldap_read(
|
||||
$ds,
|
||||
'',
|
||||
(string)$query,
|
||||
$query->listFields(),
|
||||
0,
|
||||
0
|
||||
(string) $query,
|
||||
$query->listFields()
|
||||
);
|
||||
|
||||
$entry = ldap_first_entry($this->ds, $result);
|
||||
$result = $this->cleanupAttributes(ldap_get_attributes($this->ds, $entry));
|
||||
if (! $result) {
|
||||
throw new Exception(
|
||||
sprintf(
|
||||
'Capability query failed: %s',
|
||||
ldap_error($ds)
|
||||
)
|
||||
);
|
||||
}
|
||||
$entry = ldap_first_entry($ds, $result);
|
||||
|
||||
$cap = (object) array(
|
||||
'ldapv3' => false,
|
||||
'starttls' => false,
|
||||
);
|
||||
|
||||
if ($entry === false) {
|
||||
// TODO: Is it OK to have no capabilities?
|
||||
return $cap;
|
||||
}
|
||||
|
||||
$result = $this->cleanupAttributes(
|
||||
ldap_get_attributes($ds, $entry)
|
||||
);
|
||||
/*
|
||||
if (isset($result->dnsHostName)) {
|
||||
ldap_set_option($ds, LDAP_OPT_HOST_NAME, $result->dnsHostName);
|
||||
}
|
||||
*/
|
||||
|
||||
if ((is_string($result->supportedLDAPVersion)
|
||||
&& (int) $result->supportedLDAPVersion === 3)
|
||||
|| (is_array($result->supportedLDAPVersion)
|
||||
&& in_array(3, $result->supportedLDAPVersion)
|
||||
)) {
|
||||
$cap->ldapv3 = true;
|
||||
}
|
||||
|
||||
if (isset($result->supportedCapabilities)) {
|
||||
foreach ($result->supportedCapabilities as $oid) {
|
||||
if (array_key_exists($oid, $this->ms_capability)) {
|
||||
echo $this->ms_capability[$oid] . "\n";
|
||||
// echo $this->ms_capability[$oid] . "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isset($result->supportedExtension)) {
|
||||
foreach ($result->supportedExtension as $oid) {
|
||||
if (array_key_exists($oid, $this->ldap_extension)) {
|
||||
// STARTTLS -> läuft mit OpenLDAP
|
||||
if ($this->ldap_extension[$oid] === 'STARTTLS') {
|
||||
$cap->starttls = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
return $cap;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function discoverCapabilities()
|
||||
{
|
||||
$this->fetchRootDseDetails();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function connect()
|
||||
{
|
||||
if ($this->ds !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->use_tls) {
|
||||
$this->prepareTlsEnvironment();
|
||||
}
|
||||
Log::debug("Trying to connect to %s", $this->hostname);
|
||||
$this->ds = ldap_connect($this->hostname, 389);
|
||||
$this->discoverCapabilities();
|
||||
if ($this->use_tls) {
|
||||
Log::debug("Trying ldap_start_tls()");
|
||||
if (@ldap_start_tls($this->ds)) {
|
||||
Log::debug("Trying ldap_start_tls() succeeded");
|
||||
} else {
|
||||
Log::warn(
|
||||
"ldap_start_tls() failed: %s. Does your ldap_ca.conf point to the certificate? ",
|
||||
ldap_error($this->ds)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ldap_rename requires LDAPv3:
|
||||
if (!ldap_set_option($this->ds, LDAP_OPT_PROTOCOL_VERSION, 3)) {
|
||||
throw new Exception('LDAPv3 is required');
|
||||
}
|
||||
|
||||
// Not setting this results in "Operations error" on AD when using the
|
||||
// whole domain as search base:
|
||||
ldap_set_option($this->ds, LDAP_OPT_REFERRALS, 0);
|
||||
|
||||
// ldap_set_option($this->ds, LDAP_OPT_DEREF, LDAP_DEREF_NEVER);
|
||||
Log::debug("Trying ldap_bind(%s)", $this->bind_dn);
|
||||
$this->ds = $this->prepareNewConnection();
|
||||
|
||||
$r = @ldap_bind($this->ds, $this->bind_dn, $this->bind_pw);
|
||||
|
||||
if (!$r) {
|
||||
log::fatal(
|
||||
'LDAP connection (%s / %s) failed: %s',
|
||||
$this->bind_dn,
|
||||
'***',
|
||||
ldap_error($this->ds)
|
||||
);
|
||||
throw new ConfigError(
|
||||
if (! $r) {
|
||||
throw new \Exception(
|
||||
sprintf(
|
||||
'Could not connect to the authentication server, please '.
|
||||
'review your LDAP connection settings.'
|
||||
'LDAP connection to %s:%s (%s / %s) failed: %s',
|
||||
$this->hostname,
|
||||
$this->port,
|
||||
$this->bind_dn,
|
||||
'***' /* $this->bind_pw */,
|
||||
ldap_error($this->ds)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
putenv('LDAPRC');
|
||||
}
|
||||
}
|
||||
|
@ -1,32 +1,12 @@
|
||||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
/**
|
||||
* 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>
|
||||
*/
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
namespace Icinga\Protocol\Ldap;
|
||||
|
||||
use Icinga\Web\Paginator\Adapter\QueryAdapter;
|
||||
|
||||
/**
|
||||
* Search class
|
||||
*
|
||||
* @package Icinga\Protocol\Ldap
|
||||
*/
|
||||
/**
|
||||
* Search abstraction class
|
||||
*
|
||||
@ -38,52 +18,24 @@ use Icinga\Web\Paginator\Adapter\QueryAdapter;
|
||||
*
|
||||
* @copyright Copyright (c) 2013 Icinga-Web Team <info@icinga.org>
|
||||
* @author Icinga-Web Team <info@icinga.org>
|
||||
* @package Icinga\Protocol\Ldap
|
||||
* @package Icinga\Protocol\Ldap
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
|
||||
* @package Icinga\Protocol\Ldap
|
||||
*/
|
||||
class Query
|
||||
{
|
||||
/**
|
||||
* @var Connection
|
||||
*/
|
||||
protected $connection;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $filters = array();
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $fields = array();
|
||||
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
protected $limit_count;
|
||||
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
protected $limit_offset;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $sort_columns = array();
|
||||
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
protected $count;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param \Icinga\Protocol\Ldap\Connection $connection LDAP Connection object
|
||||
* @return \Icinga\Protocol\Ldap\Query
|
||||
* @param Connection LDAP Connection object
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Connection $connection)
|
||||
{
|
||||
@ -106,14 +58,11 @@ class Query
|
||||
/**
|
||||
* Count result set, ignoring limits
|
||||
*
|
||||
* @param null $count
|
||||
* @param null $offset
|
||||
* @throws Exception
|
||||
* @return int
|
||||
*/
|
||||
public function limit($count = null, $offset = null)
|
||||
{
|
||||
if (!preg_match('~^\d+~', $count . $offset)) {
|
||||
if (! preg_match('~^\d+~', $count . $offset)) {
|
||||
throw new Exception(
|
||||
sprintf(
|
||||
'Got invalid limit: %s, %s',
|
||||
@ -122,8 +71,8 @@ class Query
|
||||
)
|
||||
);
|
||||
}
|
||||
$this->limit_count = (int)$count;
|
||||
$this->limit_offset = (int)$offset;
|
||||
$this->limit_count = (int) $count;
|
||||
$this->limit_offset = (int) $offset;
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -176,15 +125,12 @@ class Query
|
||||
{
|
||||
$result = $this->fetchAll();
|
||||
$sorted = array();
|
||||
$quotedDn = preg_quote($this->connection->getDN(), '/');
|
||||
foreach ($result as $key => & $item) {
|
||||
$new_key = LdapUtils::implodeDN(
|
||||
array_reverse(
|
||||
LdapUtils::explodeDN(
|
||||
preg_replace(
|
||||
'/,' . preg_quote($this->connection->getDN(), '/') . '$/',
|
||||
'',
|
||||
$key
|
||||
)
|
||||
preg_replace('/,' . $quotedDn . '$/', '', $key)
|
||||
)
|
||||
)
|
||||
);
|
||||
@ -194,7 +140,11 @@ class Query
|
||||
ksort($sorted);
|
||||
|
||||
$tree = Root::forConnection($this->connection);
|
||||
$root_dn = $tree->getDN();
|
||||
foreach ($sorted as $sort_key => & $key) {
|
||||
if ($key === $root_dn) {
|
||||
continue;
|
||||
}
|
||||
$tree->createChildByDN($key, $result[$key]);
|
||||
}
|
||||
return $tree;
|
||||
@ -246,8 +196,6 @@ class Query
|
||||
*
|
||||
* This creates an objectClass filter
|
||||
*
|
||||
* @param $objectClass
|
||||
* @param array $fields
|
||||
* @return Query
|
||||
*/
|
||||
public function from($objectClass, $fields = array())
|
||||
@ -308,8 +256,6 @@ class Query
|
||||
/**
|
||||
* Return a pagination adapter for the current query
|
||||
*
|
||||
* @param null $limit
|
||||
* @param null $page
|
||||
* @return \Zend_Paginator
|
||||
*/
|
||||
public function paginate($limit = null, $page = null)
|
||||
@ -325,7 +271,7 @@ class Query
|
||||
}
|
||||
$paginator = new \Zend_Paginator(
|
||||
// TODO: Adapter doesn't fit yet:
|
||||
new QueryAdapter($this)
|
||||
new \Icinga\Web\Paginator\Adapter\QueryAdapter($this)
|
||||
);
|
||||
$paginator->setItemCountPerPage($limit);
|
||||
$paginator->setCurrentPageNumber($page);
|
||||
@ -364,7 +310,7 @@ class Query
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
* Descructor
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
|
@ -1,6 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Protocol\Livestatus;
|
||||
|
||||
use Icinga\Application\Benchmark;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Backend class managing handling MKI Livestatus connections
|
||||
*
|
||||
* Usage example:
|
||||
*
|
||||
* <code>
|
||||
* $lconf = new Connection((object) array(
|
||||
* 'hostname' => 'localhost',
|
||||
* 'root_dn' => 'dc=monitoring,dc=...',
|
||||
* 'bind_dn' => 'cn=Mangager,dc=monitoring,dc=...',
|
||||
* 'bind_pw' => '***'
|
||||
* ));
|
||||
* </code>
|
||||
*
|
||||
* @copyright Copyright (c) 2013 Icinga-Web Team <info@icinga.org>
|
||||
* @author Icinga-Web Team <info@icinga.org>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
|
||||
*/
|
||||
class Connection
|
||||
{
|
||||
const TYPE_UNIX = 1;
|
||||
@ -49,19 +71,23 @@ class Connection
|
||||
$this->assertPhpExtensionLoaded('sockets');
|
||||
if ($socket[0] === '/') {
|
||||
if (! is_writable($socket)) {
|
||||
throw new \Exception(sprintf(
|
||||
'Cannot write to livestatus socket "%s"',
|
||||
$socket
|
||||
));
|
||||
throw new \Exception(
|
||||
sprintf(
|
||||
'Cannot write to livestatus socket "%s"',
|
||||
$socket
|
||||
)
|
||||
);
|
||||
}
|
||||
$this->socket_type = self::TYPE_UNIX;
|
||||
$this->socket_path = $socket;
|
||||
} else {
|
||||
if (! preg_match('~^tcp://([^:]+):(\d+)~', $socket, $m)) {
|
||||
throw new \Exception(sprintf(
|
||||
'Invalid TCP socket syntax: "%s"',
|
||||
$socket
|
||||
));
|
||||
throw new \Exception(
|
||||
sprintf(
|
||||
'Invalid TCP socket syntax: "%s"',
|
||||
$socket
|
||||
)
|
||||
);
|
||||
}
|
||||
// TODO: Better syntax checks
|
||||
$this->socket_host = $m[1];
|
||||
@ -80,17 +106,17 @@ class Connection
|
||||
{
|
||||
$count = clone($query);
|
||||
$count->count();
|
||||
\Icinga\Benchmark::measure('Sending Livestatus Count Query');
|
||||
$data = $this->_fetch((string) $count);
|
||||
\Icinga\Benchmark::measure('Got Livestatus count result');
|
||||
Benchmark::measure('Sending Livestatus Count Query');
|
||||
$data = $this->doFetch((string) $count);
|
||||
Benchmark::measure('Got Livestatus count result');
|
||||
return $data[0][0];
|
||||
}
|
||||
|
||||
public function fetchAll(Query $query)
|
||||
{
|
||||
\Icinga\Benchmark::measure('Sending Livestatus Query');
|
||||
$data = $this->_fetch((string) $query);
|
||||
\Icinga\Benchmark::measure('Got Livestatus Data');
|
||||
Benchmark::measure('Sending Livestatus Query');
|
||||
$data = $this->doFetch((string) $query);
|
||||
Benchmark::measure('Got Livestatus Data');
|
||||
if ($query->hasColumns()) {
|
||||
$headers = $query->getColumnAliases();
|
||||
} else {
|
||||
@ -114,12 +140,12 @@ class Connection
|
||||
$query->getLimit()
|
||||
);
|
||||
}
|
||||
\Icinga\Benchmark::measure('Data sorted, limits applied');
|
||||
Benchmark::measure('Data sorted, limits applied');
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function _fetch($raw_query)
|
||||
protected function doFetch($raw_query)
|
||||
{
|
||||
$conn = $this->getConnection();
|
||||
$this->writeToSocket($raw_query);
|
||||
@ -128,15 +154,17 @@ class Connection
|
||||
$length = (int) trim(substr($header, 4));
|
||||
$body = $this->readFromSocket($length);
|
||||
if ($status !== 200) {
|
||||
throw new \Exception(sprintf(
|
||||
'Problem while reading %d bytes from livestatus: %s',
|
||||
$length,
|
||||
$body
|
||||
));
|
||||
throw new Exception(
|
||||
sprintf(
|
||||
'Problem while reading %d bytes from livestatus: %s',
|
||||
$length,
|
||||
$body
|
||||
)
|
||||
);
|
||||
}
|
||||
$result = json_decode($body);
|
||||
if ($result === null) {
|
||||
throw new \Exception('Got invalid response body from livestatus');
|
||||
throw new Exception('Got invalid response body from livestatus');
|
||||
}
|
||||
|
||||
return $result;
|
||||
@ -147,13 +175,15 @@ class Connection
|
||||
$offset = 0;
|
||||
$buffer = '';
|
||||
|
||||
while($offset < $length) {
|
||||
while ($offset < $length) {
|
||||
$data = socket_read($this->connection, $length - $offset);
|
||||
if ($data === false) {
|
||||
throw new \Exception(sprintf(
|
||||
'Failed to read from livestatus socket: %s',
|
||||
socket_strerror(socket_last_error($this->connection))
|
||||
));
|
||||
throw new Exception(
|
||||
sprintf(
|
||||
'Failed to read from livestatus socket: %s',
|
||||
socket_strerror(socket_last_error($this->connection))
|
||||
)
|
||||
);
|
||||
}
|
||||
$size = strlen($data);
|
||||
$offset += $size;
|
||||
@ -164,10 +194,13 @@ class Connection
|
||||
}
|
||||
}
|
||||
if ($offset !== $length) {
|
||||
throw new \Exception(sprintf(
|
||||
'Got only %d instead of %d bytes from livestatus socket',
|
||||
$offset, $length
|
||||
));
|
||||
throw new \Exception(
|
||||
sprintf(
|
||||
'Got only %d instead of %d bytes from livestatus socket',
|
||||
$offset,
|
||||
$length
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return $buffer;
|
||||
@ -185,10 +218,12 @@ class Connection
|
||||
protected function assertPhpExtensionLoaded($name)
|
||||
{
|
||||
if (! extension_loaded($name)) {
|
||||
throw new \Exception(sprintf(
|
||||
'The extension "%s" is not loaded',
|
||||
$name
|
||||
));
|
||||
throw new \Exception(
|
||||
sprintf(
|
||||
'The extension "%s" is not loaded',
|
||||
$name
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -213,24 +248,28 @@ class Connection
|
||||
|
||||
$this->connection = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
|
||||
if (! @socket_connect($this->connection, $this->socket_host, $this->socket_port)) {
|
||||
throw new \Exception(sprintf(
|
||||
'Cannot connect to livestatus TCP socket "%s:%d": %s',
|
||||
$this->socket_host,
|
||||
$this->socket_port,
|
||||
socket_strerror(socket_last_error($this->connection))
|
||||
));
|
||||
throw new \Exception(
|
||||
sprintf(
|
||||
'Cannot connect to livestatus TCP socket "%s:%d": %s',
|
||||
$this->socket_host,
|
||||
$this->socket_port,
|
||||
socket_strerror(socket_last_error($this->connection))
|
||||
)
|
||||
);
|
||||
}
|
||||
socket_set_option($this->connection, SOL_TCP, TCP_NODELAY, 1);
|
||||
}
|
||||
|
||||
protected function establishSocketConnection()
|
||||
{
|
||||
$this->connection = socket_create(AF_UNIX, SOCK_STREAM, 0);
|
||||
$this->connection = socket_create(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (! socket_connect($this->connection, $this->socket_path)) {
|
||||
throw new \Exception(sprintf(
|
||||
'Cannot connect to livestatus local socket "%s"',
|
||||
$this->socket_path
|
||||
));
|
||||
throw new \Exception(
|
||||
sprintf(
|
||||
'Cannot connect to livestatus local socket "%s"',
|
||||
$this->socket_path
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -246,4 +285,3 @@ class Connection
|
||||
$this->disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Protocol\Livestatus;
|
||||
use Icinga\Protocol;
|
||||
|
||||
class Query extends Protocol\AbstractQuery
|
||||
use Icinga\Protocol\AbstractQuery;
|
||||
|
||||
class Query extends AbstractQuery
|
||||
{
|
||||
|
||||
protected $connection;
|
||||
@ -62,7 +63,10 @@ class Query extends Protocol\AbstractQuery
|
||||
|
||||
public function order($col)
|
||||
{
|
||||
if (($pos = strpos($col, ' ')) !== false) {
|
||||
if (($pos = strpos($col, ' ')) === false) {
|
||||
$col = $col;
|
||||
$dir = self::SORT_ASC;
|
||||
} else {
|
||||
$dir = strtoupper(substr($col, $pos + 1));
|
||||
if ($dir === 'DESC') {
|
||||
$dir = self::SORT_DESC;
|
||||
@ -70,8 +74,6 @@ class Query extends Protocol\AbstractQuery
|
||||
$dir = self::SORT_ASC;
|
||||
}
|
||||
$col = substr($col, 0, $pos);
|
||||
} else {
|
||||
$col = $col;
|
||||
}
|
||||
$this->order_columns[] = array($col, $dir);
|
||||
return $this;
|
||||
@ -82,11 +84,13 @@ class Query extends Protocol\AbstractQuery
|
||||
public function limit($count = null, $offset = null)
|
||||
{
|
||||
if (! preg_match('~^\d+~', $count . $offset)) {
|
||||
throw new Exception(sprintf(
|
||||
'Got invalid limit: %s, %s',
|
||||
$count,
|
||||
$offset
|
||||
));
|
||||
throw new Exception(
|
||||
sprintf(
|
||||
'Got invalid limit: %s, %s',
|
||||
$count,
|
||||
$offset
|
||||
)
|
||||
);
|
||||
}
|
||||
$this->limit_count = (int) $count;
|
||||
$this->limit_offset = (int) $offset;
|
||||
@ -116,10 +120,12 @@ class Query extends Protocol\AbstractQuery
|
||||
public function from($table, $columns = null)
|
||||
{
|
||||
if (! $this->connection->hasTable($table)) {
|
||||
throw new Exception(sprintf(
|
||||
'This livestatus connection does not provide "%s"',
|
||||
$table
|
||||
));
|
||||
throw new Exception(
|
||||
sprintf(
|
||||
'This livestatus connection does not provide "%s"',
|
||||
$table
|
||||
)
|
||||
);
|
||||
}
|
||||
$this->table = $table;
|
||||
if (is_array($columns)) {
|
||||
@ -207,4 +213,3 @@ class Query extends Protocol\AbstractQuery
|
||||
unset($this->connection);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,35 +1,13 @@
|
||||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
/**
|
||||
* 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>
|
||||
*/
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
namespace Icinga\Web;
|
||||
|
||||
use Icinga\Authentication\Manager;
|
||||
use Icinga\Authentication\Manager as AuthManager;
|
||||
use Icinga\Application\Benchmark;
|
||||
use Icinga\Exception;
|
||||
use Icinga\Application\Config;
|
||||
use Icinga\Pdf\File;
|
||||
use Icinga\Web\Notification;
|
||||
use Zend_Layout as ZfLayout;
|
||||
use Zend_Controller_Action as ZfController;
|
||||
@ -37,6 +15,11 @@ use Zend_Controller_Request_Abstract as ZfRequest;
|
||||
use Zend_Controller_Response_Abstract as ZfResponse;
|
||||
use Zend_Controller_Action_HelperBroker as ZfActionHelper;
|
||||
|
||||
/*
|
||||
* @TODO(el): There was a note from tg that the following line is temporary. Ask him why.
|
||||
*/
|
||||
use Icinga\File\Pdf;
|
||||
|
||||
/**
|
||||
* Base class for all core action controllers
|
||||
*
|
||||
@ -45,21 +28,16 @@ use Zend_Controller_Action_HelperBroker as ZfActionHelper;
|
||||
* @copyright Copyright (c) 2013 Icinga-Web Team <info@icinga.org>
|
||||
* @author Icinga-Web Team <info@icinga.org>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
|
||||
* @package Icinga\Web
|
||||
*/
|
||||
class ActionController extends ZfController
|
||||
{
|
||||
/**
|
||||
* The Icinga Config object is available in all controllers. This is the
|
||||
* modules config for module action controllers.
|
||||
*
|
||||
* @var Config
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $replaceLayout = false;
|
||||
|
||||
/**
|
||||
@ -84,20 +62,12 @@ class ActionController extends ZfController
|
||||
*/
|
||||
protected $action_name;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
// @TODO(el): Should be true, is/was disabled for testing purpose
|
||||
protected $handlesAuthentication = false;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $modifiesSession = false;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $allowAccess = false;
|
||||
private $allowAccess = false;
|
||||
|
||||
/**
|
||||
* The constructor starts benchmarking, loads the configuration and sets
|
||||
@ -113,30 +83,22 @@ class ActionController extends ZfController
|
||||
array $invokeArgs = array()
|
||||
) {
|
||||
Benchmark::measure('Action::__construct()');
|
||||
$this->module_name = $request->getModuleName();
|
||||
|
||||
$this->module_name = $request->getModuleName();
|
||||
$this->controller_name = $request->getControllerName();
|
||||
$this->action_name = $request->getActionName();
|
||||
$this->action_name = $request->getActionName();
|
||||
|
||||
$this->loadConfig();
|
||||
$this->setRequest($request)
|
||||
->setResponse($response)
|
||||
->_setInvokeArgs($invokeArgs);
|
||||
->setResponse($response)
|
||||
->_setInvokeArgs($invokeArgs);
|
||||
$this->_helper = new ZfActionHelper($this);
|
||||
|
||||
/*
|
||||
* --------------------------------------------
|
||||
* Authentication is disabled to test bootstrap
|
||||
* --------------------------------------------
|
||||
*
|
||||
* @todo remove this!
|
||||
*/
|
||||
|
||||
|
||||
if ($this->handlesAuthentication() ||
|
||||
Manager::getInstance(
|
||||
AuthManager::getInstance(
|
||||
null,
|
||||
array(
|
||||
"writeSession" => $this->modifiesSession
|
||||
'writeSession' => $this->modifiesSession
|
||||
)
|
||||
)->isAuthenticated()
|
||||
) {
|
||||
@ -171,7 +133,7 @@ class ActionController extends ZfController
|
||||
* Helper function creating a new widget
|
||||
*
|
||||
* @param string $name The widget name
|
||||
* @param array|string $properties Optional widget properties
|
||||
* @param string $properties Optional widget properties
|
||||
*
|
||||
* @return Widget\AbstractWidget
|
||||
*/
|
||||
@ -185,9 +147,8 @@ class ActionController extends ZfController
|
||||
*
|
||||
* TODO: This has not been implemented yet
|
||||
*
|
||||
* @param $uri
|
||||
* @param string $permission Permission name
|
||||
* @internal param string $object No idea what this should have been :-)
|
||||
* @param string $object No idea what this should have been :-)
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
@ -204,18 +165,31 @@ class ActionController extends ZfController
|
||||
* @param string $permission Permission name
|
||||
* @param string $object No idea what this should have been :-)
|
||||
*
|
||||
* @throws \Exception
|
||||
* @return self
|
||||
*/
|
||||
final protected function assertPermission($permission, $object = null)
|
||||
{
|
||||
if (!$this->hasPermission($permission, $object)) {
|
||||
if (! $this->hasPermission($permission, $object)) {
|
||||
// TODO: Log violation, create dedicated Exception class
|
||||
throw new \Exception('Permission denied');
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function preserve($key, $value = null)
|
||||
{
|
||||
if ($value === null) {
|
||||
$value = $this->_getParam($key);
|
||||
}
|
||||
if ($value !== null) {
|
||||
if (! isset($this->view->preserve)) {
|
||||
$this->view->preserve = array();
|
||||
}
|
||||
$this->view->preserve[$key] = $value;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Our benchmark wants to know when we started our dispatch loop
|
||||
*
|
||||
@ -224,8 +198,7 @@ class ActionController extends ZfController
|
||||
public function preDispatch()
|
||||
{
|
||||
Benchmark::measure('Action::preDispatch()');
|
||||
|
||||
if (!$this->allowAccess) {
|
||||
if (! $this->allowAccess) {
|
||||
$this->_request->setModuleName('default')
|
||||
->setControllerName('authentication')
|
||||
->setActionName('login')
|
||||
@ -237,21 +210,27 @@ class ActionController extends ZfController
|
||||
$this->view->controller_name = $this->controller_name;
|
||||
$this->view->module_name = $this->module_name;
|
||||
|
||||
// TODO(el): What is this, why do we need that here?
|
||||
$this->view->compact = $this->_request->getParam('view') === 'compact';
|
||||
|
||||
Benchmark::measure(sprintf(
|
||||
'Action::preDispatched(): %s / %s / %s',
|
||||
$this->module_name,
|
||||
$this->controller_name,
|
||||
$this->action_name
|
||||
));
|
||||
|
||||
//$this->quickRedirect('/authentication/login?a=e');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $url
|
||||
* @param array $params
|
||||
*/
|
||||
public function redirectNow($url, array $params = array())
|
||||
{
|
||||
if ($url instanceof Url) {
|
||||
$url = $url->getRelative();
|
||||
}
|
||||
$this->_helper->Redirector->gotoUrlAndExit($url);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function handlesAuthentication()
|
||||
{
|
||||
return $this->handlesAuthentication;
|
||||
@ -265,8 +244,8 @@ class ActionController extends ZfController
|
||||
protected function renderBenchmark()
|
||||
{
|
||||
return '<pre class="benchmark">'
|
||||
. Benchmark::renderToHtml()
|
||||
. '</pre>';
|
||||
. Benchmark::renderToHtml()
|
||||
. '</pre>';
|
||||
}
|
||||
|
||||
/**
|
||||
@ -284,7 +263,6 @@ class ActionController extends ZfController
|
||||
{
|
||||
Benchmark::measure('Action::postDispatch()');
|
||||
|
||||
|
||||
// TODO: Move this elsewhere, this is just an ugly test:
|
||||
if ($this->_request->getParam('filetype') === 'pdf') {
|
||||
|
||||
@ -293,40 +271,56 @@ class ActionController extends ZfController
|
||||
require_once 'vendor/lessphp/lessc.inc.php';
|
||||
$less = new \lessc;
|
||||
$cssdir = dirname(ICINGA_LIBDIR) . '/public/css';
|
||||
// TODO: We need a way to retrieve public dir, even if located elsewhere
|
||||
// TODO: We need a way to retrieve public dir, even if located elsewhere
|
||||
|
||||
$css = $less->compileFile($cssdir . '/pdfprint.less');
|
||||
/*
|
||||
foreach ($app->moduleManager()->getLoadedModules() as $name => $module) {
|
||||
if ($module->hasCss()) {
|
||||
$css .= $less->compile(
|
||||
'.icinga-module.module-'
|
||||
. $name
|
||||
. " {\n"
|
||||
. file_get_contents($module->getCssFilename())
|
||||
. "}\n\n"
|
||||
);
|
||||
}
|
||||
}
|
||||
*/
|
||||
/*
|
||||
foreach (\Icinga\Application\Icinga::app()->moduleManager()->getLoadedModules() as $name => $module) {
|
||||
if ($module->hasCss()) {
|
||||
$css .= $less->compile(
|
||||
'.icinga-module.module-'
|
||||
. $name
|
||||
. " {\n"
|
||||
. file_get_contents($module->getCssFilename())
|
||||
. "}\n\n"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
// END of CSS test
|
||||
|
||||
$this->render(
|
||||
$this->render(
|
||||
null,
|
||||
$this->_helper->viewRenderer->getResponseSegment(),
|
||||
$this->_helper->viewRenderer->getNoController()
|
||||
);
|
||||
$html = '<style>' . $css . '</style>' . (string)$this->getResponse();
|
||||
$html = (string) $this->getResponse();
|
||||
if ($this->module_name !== null) {
|
||||
$html = '<div class="icinga-module module-'
|
||||
. $this->module_name
|
||||
. '">'
|
||||
. "\n"
|
||||
. $html
|
||||
. '</div>';
|
||||
}
|
||||
|
||||
$pdf = new File();
|
||||
$html = '<style>' . $css . '</style>' . $html;
|
||||
|
||||
//$html .= $this->view->action('services', 'list', 'monitoring', array('limit' => 10));
|
||||
// $html = preg_replace('~icinga-module.module-bpapp~', 'csstest', $html);
|
||||
// echo $html; exit;
|
||||
$pdf = new Pdf();
|
||||
$pdf->AddPage();
|
||||
$pdf->writeHTMLCell(0, 0, '', '', $html, 0, 1, 0, true, '', true);
|
||||
$pdf->setFontSubsetting(false);
|
||||
$pdf->writeHTML($html); //0, 0, '', '', $html, 0, 1, 0, true, '', true);
|
||||
|
||||
$pdf->Output('docs.pdf', 'I');
|
||||
exit;
|
||||
}
|
||||
// END of PDF test
|
||||
|
||||
|
||||
if ($this->_request->isXmlHttpRequest()) {
|
||||
if ($this->replaceLayout || $this->_getParam('_render') === 'body') {
|
||||
$this->_helper->layout()->setLayout('just-the-body');
|
||||
@ -335,24 +329,23 @@ class ActionController extends ZfController
|
||||
$this->_helper->layout()->setLayout('inline');
|
||||
}
|
||||
}
|
||||
|
||||
$notification = Notification::getInstance();
|
||||
if ($notification->hasMessages()) {
|
||||
$nhtml = '<ul class="notification">';
|
||||
foreach ($notification->getMessages() as $msg) {
|
||||
$nhtml .= '<li>['
|
||||
. $msg->type
|
||||
. '] '
|
||||
. htmlspecialchars($msg->message);
|
||||
. $msg->type
|
||||
. '] '
|
||||
. htmlspecialchars($msg->message);
|
||||
}
|
||||
$nhtml .= '</ul>';
|
||||
$this->getResponse()->append('notification', $nhtml);
|
||||
}
|
||||
|
||||
/*if (Session::getInstance()->show_benchmark) {
|
||||
if (AuthManager::getInstance()->getSession()->get('show_benchmark')) {
|
||||
Benchmark::measure('Response ready');
|
||||
$this->getResponse()->append('benchmark', $this->renderBenchmark());
|
||||
}*/
|
||||
$this->_helper->layout()->benchmark = $this->renderBenchmark();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,28 +1,8 @@
|
||||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
/**
|
||||
* 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>
|
||||
*/
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
/**
|
||||
* Module action controller
|
||||
*/
|
||||
namespace Icinga\Web;
|
||||
|
||||
use Icinga\Application\Config;
|
||||
@ -84,7 +64,7 @@ class ModuleActionController extends ActionController
|
||||
*/
|
||||
protected function loadConfig()
|
||||
{
|
||||
$this->config = Config::getInstance()->{$this->module_name};
|
||||
$this->config = Config::module($this->module_name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,106 +1,47 @@
|
||||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
/**
|
||||
* 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>
|
||||
*/
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
namespace Icinga\Web;
|
||||
|
||||
use Icinga\Exception\ProgrammingError;
|
||||
use Icinga\Application\Platform;
|
||||
use Icinga\Application\Logger as Log;
|
||||
use Icinga\Authentication\Manager as AuthManager;
|
||||
|
||||
/**
|
||||
* Class Notification
|
||||
* @package Icinga\Web
|
||||
* // @TODO(eL): Use Notification not as Singleton but within request:
|
||||
* <code>
|
||||
* <?php
|
||||
* $request->[getUser()]->notify('some message', Notification::INFO);
|
||||
* </code>
|
||||
*/
|
||||
class Notification
|
||||
{
|
||||
/**
|
||||
* @var Notification
|
||||
*/
|
||||
private static $instance;
|
||||
protected static $instance;
|
||||
protected $isCli = false;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $cliFlag = false;
|
||||
|
||||
/**
|
||||
* @param boolean $cliFlag
|
||||
*/
|
||||
public function setCliFlag($cliFlag)
|
||||
{
|
||||
$this->cliFlag = $cliFlag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function getCliFlag()
|
||||
{
|
||||
return $this->cliFlag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $msg
|
||||
*/
|
||||
public static function info($msg)
|
||||
{
|
||||
self::getInstance()->addMessage($msg, 'info');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $msg
|
||||
*/
|
||||
public static function success($msg)
|
||||
{
|
||||
self::getInstance()->addMessage($msg, 'success');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $msg
|
||||
*/
|
||||
public static function warning($msg)
|
||||
{
|
||||
self::getInstance()->addMessage($msg, 'warning');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $msg
|
||||
*/
|
||||
public static function error($msg)
|
||||
{
|
||||
self::getInstance()->addMessage($msg, 'error');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $message
|
||||
* @param string $type
|
||||
* @throws \Icinga\Exception\ProgrammingError
|
||||
*/
|
||||
public function addMessage($message, $type = 'info')
|
||||
protected function addMessage($message, $type = 'info')
|
||||
{
|
||||
if (!in_array(
|
||||
if (! in_array(
|
||||
$type,
|
||||
array(
|
||||
'info',
|
||||
@ -108,8 +49,7 @@ class Notification
|
||||
'warning',
|
||||
'success'
|
||||
)
|
||||
)
|
||||
) {
|
||||
)) {
|
||||
throw new ProgrammingError(
|
||||
sprintf(
|
||||
'"%s" is not a valid notification type',
|
||||
@ -118,7 +58,7 @@ class Notification
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->cliFlag) {
|
||||
if ($this->is_cli) {
|
||||
$msg = sprintf('[%s] %s', $type, $message);
|
||||
switch ($type) {
|
||||
case 'info':
|
||||
@ -135,8 +75,8 @@ class Notification
|
||||
return;
|
||||
}
|
||||
|
||||
$mo = (object)array(
|
||||
'type' => $type,
|
||||
$mo = (object) array(
|
||||
'type' => $type,
|
||||
'message' => $message,
|
||||
);
|
||||
|
||||
@ -146,17 +86,11 @@ class Notification
|
||||
$this->session->messages = $msgs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hasMessages()
|
||||
{
|
||||
return !empty($this->session->messages);
|
||||
return ! empty($this->session->messages);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getMessages()
|
||||
{
|
||||
$msgs = $this->session->messages;
|
||||
@ -164,24 +98,18 @@ class Notification
|
||||
return $msgs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Notification object
|
||||
*/
|
||||
final private function __construct()
|
||||
{
|
||||
//$this->session = new SessionNamespace('IcingaNotification');
|
||||
//if (!is_array($this->session->messages)) {
|
||||
$this->session = AuthManager::getInstance()->getSession();
|
||||
if (!is_array($this->session->get('messages'))) {
|
||||
$this->session->messages = array();
|
||||
//}
|
||||
}
|
||||
|
||||
if (Platform::isCli()) {
|
||||
$this->cliFlag = true;
|
||||
$this->is_cli = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Notification
|
||||
*/
|
||||
public static function getInstance()
|
||||
{
|
||||
if (self::$instance === null) {
|
||||
|
@ -8,31 +8,39 @@ use Icinga\Exception\ProgrammingError;
|
||||
class Url
|
||||
{
|
||||
protected $params = array();
|
||||
protected $url;
|
||||
protected $path;
|
||||
protected $baseUrl;
|
||||
protected $request;
|
||||
|
||||
public function __construct($url, $params = null)
|
||||
public function __construct($url, $params = null, $request = null)
|
||||
{
|
||||
if (($split = strpos($url, '?')) === false) {
|
||||
$this->url = $url;
|
||||
if (! empty($params)) {
|
||||
$this->params = $params;
|
||||
}
|
||||
if ($request === null) {
|
||||
$this->request = Icinga::app()->frontController()->getRequest();
|
||||
} else {
|
||||
$this->url = substr($url, 0, $split);
|
||||
parse_str(substr($url, $split + 1), $urlParams);
|
||||
$this->params = $urlParams;
|
||||
if (! empty($params)) {
|
||||
$this->params += $params;
|
||||
// TODO: Test += behavior!
|
||||
// Tests only
|
||||
$this->request = $request;
|
||||
}
|
||||
if ($url === null) {
|
||||
$this->path = $this->request->getPathInfo();
|
||||
$this->params = $this->request->getQuery();
|
||||
} else {
|
||||
if (($split = strpos($url, '?')) === false) {
|
||||
$this->path = $url;
|
||||
} else {
|
||||
$this->path = substr($url, 0, $split);
|
||||
// TODO: Use something better than parse_str
|
||||
parse_str(substr($url, $split + 1), $urlParams);
|
||||
$this->params = $urlParams;
|
||||
}
|
||||
}
|
||||
|
||||
if (! empty($params)) {
|
||||
$this->setParams($params);
|
||||
}
|
||||
}
|
||||
|
||||
public static function create($url, $params = null)
|
||||
public static function create($url, $params = null, $request = null)
|
||||
{
|
||||
$u = new Url($url, $params);
|
||||
$u = new Url($url, $params, $request);
|
||||
return $u;
|
||||
}
|
||||
|
||||
@ -43,30 +51,15 @@ class Url
|
||||
return $this;
|
||||
}
|
||||
|
||||
public static function current()
|
||||
public static function current($request = null)
|
||||
{
|
||||
$app = Icinga::app();
|
||||
$view = $app->getView()->view;
|
||||
$request = $app->frontController()->getRequest();
|
||||
$parts = array();
|
||||
// TODO: getQuery!
|
||||
$params = $request->getParams();
|
||||
foreach (array('module', 'controller', 'action') as $param) {
|
||||
if ($view->{$param . '_name'} !== 'default') {
|
||||
$parts[] = $view->{$param . '_name'};
|
||||
}
|
||||
if (array_key_exists($param, $params)) {
|
||||
unset($params[$param]);
|
||||
}
|
||||
}
|
||||
$rel = implode('/', $parts);
|
||||
$url = new Url($rel, $params);
|
||||
$url = new Url(null, null, $request);
|
||||
return $url;
|
||||
}
|
||||
|
||||
public function getScript()
|
||||
public function getPath()
|
||||
{
|
||||
return $this->url;
|
||||
return $this->path;
|
||||
}
|
||||
|
||||
public function getRelative()
|
||||
@ -79,9 +72,9 @@ class Url
|
||||
$args[] = rawurlencode($name) . '=' . rawurlencode($value);
|
||||
}
|
||||
}
|
||||
$url = vsprintf($this->url, $params);
|
||||
$url = vsprintf($this->path, $params);
|
||||
if (! empty($args)) {
|
||||
$url .= '?' . implode('&', $args);
|
||||
$url .= '?' . implode('&', $args);
|
||||
}
|
||||
return $url;
|
||||
}
|
||||
@ -94,17 +87,19 @@ class Url
|
||||
|
||||
public function setParams($params)
|
||||
{
|
||||
$this->params = $params;
|
||||
if ($params === null) {
|
||||
$this->params = array();
|
||||
} else {
|
||||
$this->params = $params;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function set($key, $val)
|
||||
public function getParams()
|
||||
{
|
||||
$this->params[$key] = $val;
|
||||
return $this;
|
||||
return $this->params;
|
||||
}
|
||||
|
||||
|
||||
public function hasParam($key)
|
||||
{
|
||||
return array_key_exists($key, $this->params);
|
||||
@ -118,31 +113,42 @@ class Url
|
||||
return $default;
|
||||
}
|
||||
|
||||
public function getParams()
|
||||
public function setParam($key, $value)
|
||||
{
|
||||
return $this->params;
|
||||
$this->params[$key] = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function without($keys)
|
||||
public function remove()
|
||||
{
|
||||
if (! is_array($keys)) {
|
||||
$keys = array($keys);
|
||||
}
|
||||
foreach ($keys as $key) {
|
||||
if (array_key_exists($key, $this->params)) {
|
||||
unset($this->params[$key]);
|
||||
$args = func_get_args();
|
||||
foreach ($args as $keys) {
|
||||
if (! is_array($keys)) {
|
||||
$keys = array($keys);
|
||||
}
|
||||
foreach ($keys as $key) {
|
||||
if (array_key_exists($key, $this->params)) {
|
||||
unset($this->params[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function without()
|
||||
{
|
||||
$url = clone($this);
|
||||
$args = func_get_args();
|
||||
return call_user_func_array(array($url, 'remove'), $args);
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
$url = $this->getRelative();
|
||||
$base = is_null($this->baseUrl)
|
||||
? Icinga::app()->getView()->view->baseUrl()
|
||||
$base = null === $this->baseUrl
|
||||
? $this->request->getBaseUrl()
|
||||
: $this->baseUrl;
|
||||
if ($base === '') {
|
||||
if ($base === '' && $url[0]!== '/') {
|
||||
// Otherwise all URLs would be relative to wherever you are
|
||||
$base = '/';
|
||||
}
|
||||
@ -152,3 +158,4 @@ class Url
|
||||
return $base . $url;
|
||||
}
|
||||
}
|
||||
|
||||
|
64
library/Icinga/Web/View.php
Normal file
64
library/Icinga/Web/View.php
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
19
library/Icinga/Web/View/helpers/url.php
Normal file
19
library/Icinga/Web/View/helpers/url.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Web\View;
|
||||
|
||||
use Icinga\Web\Url;
|
||||
|
||||
function url($path = null, $params = null)
|
||||
{
|
||||
if ($path === null) {
|
||||
$url = Url::current();
|
||||
if ($params !== null) {
|
||||
$url->setParams($params);
|
||||
}
|
||||
} else {
|
||||
$url = Url::create($path, $params);
|
||||
}
|
||||
return $url;
|
||||
}
|
||||
|
10
library/Icinga/Web/ViewStream.php
Normal file
10
library/Icinga/Web/ViewStream.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Web;
|
||||
|
||||
use Zend_View_Stream as ZfViewStream;
|
||||
|
||||
class ViewStream extends ZfViewStream
|
||||
{
|
||||
}
|
||||
|
@ -1,28 +1,8 @@
|
||||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
/**
|
||||
* 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>
|
||||
*/
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
/**
|
||||
* Web widget class
|
||||
*/
|
||||
namespace Icinga\Web;
|
||||
|
||||
use Icinga\Exception\ProgrammingError;
|
||||
@ -45,16 +25,16 @@ use Icinga\Exception\ProgrammingError;
|
||||
*/
|
||||
class Widget
|
||||
{
|
||||
|
||||
/**
|
||||
* Create a new widget
|
||||
*
|
||||
* @param string $name Widget name
|
||||
* @param array $options Widget constructor options
|
||||
* @param array $options Widget constructor options
|
||||
*
|
||||
* @throws \Icinga\Exception\ProgrammingError
|
||||
* @return Icinga\Web\Widget\AbstractWidget
|
||||
*/
|
||||
public static function create($name, $options = array())
|
||||
public static function create($name, $options = array(), $module_name = null)
|
||||
{
|
||||
$class = 'Icinga\\Web\\Widget\\' . ucfirst($name);
|
||||
|
||||
@ -67,7 +47,7 @@ class Widget
|
||||
);
|
||||
}
|
||||
|
||||
$widget = new $class($options);
|
||||
$widget = new $class($options, $module_name);
|
||||
return $widget;
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,8 @@ namespace Icinga\Web\Widget;
|
||||
use Icinga\Exception\ProgrammingError;
|
||||
use Icinga\Web\Url;
|
||||
|
||||
use Countable;
|
||||
|
||||
/**
|
||||
* Navigation tab widget
|
||||
*
|
||||
@ -17,7 +19,7 @@ use Icinga\Web\Url;
|
||||
* @author Icinga-Web Team <info@icinga.org>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
|
||||
*/
|
||||
class Tabs extends AbstractWidget implements \Countable
|
||||
class Tabs extends AbstractWidget implements Countable
|
||||
{
|
||||
/**
|
||||
* This is where single tabs added to this container will be stored
|
||||
@ -201,25 +203,37 @@ class Tabs extends AbstractWidget implements \Countable
|
||||
|
||||
$special = array();
|
||||
$special[] = $this->view()->qlink(
|
||||
'PDF',
|
||||
$this->view()->img('img/classic/application-pdf.png') . ' PDF',
|
||||
Url::current(),
|
||||
array('filetype' => 'pdf'),
|
||||
array('target' => '_blank')
|
||||
array('target' => '_blank', 'quote' => false)
|
||||
);
|
||||
$special[] = $this->view()->qlink(
|
||||
$this->view()->img('img/classic/application-csv.png') . ' CSV',
|
||||
Url::current(),
|
||||
array('format' => 'csv'),
|
||||
array('target' => '_blank', 'quote' => false)
|
||||
);
|
||||
$special[] = $this->view()->qlink(
|
||||
$this->view()->img('img/classic/application-json.png') . ' JSON',
|
||||
Url::current(),
|
||||
array('format' => 'json', 'quote' => false),
|
||||
array('target' => '_blank', 'quote' => false)
|
||||
);
|
||||
|
||||
$special[] = $this->view()->qlink(
|
||||
'Basket',
|
||||
$this->view()->img('img/classic/basket.png') . ' URL Basket',
|
||||
Url::create('basket/add'),
|
||||
array('url' => Url::current()->getRelative())
|
||||
array('url' => Url::current()->getRelative()),
|
||||
array('quote' => false)
|
||||
);
|
||||
|
||||
$special[] = $this->view()->qlink(
|
||||
'Dashboard',
|
||||
$this->view()->img('img/classic/dashboard.png') . ' Dashboard',
|
||||
Url::create('dashboard/addurl'),
|
||||
array('url' => Url::current()->getRelative())
|
||||
array('url' => Url::current()->getRelative()),
|
||||
array('quote' => false)
|
||||
);
|
||||
|
||||
// @todo rework auth
|
||||
// $auth = Auth::getInstance();
|
||||
// if ($this->specialActions && ! empty($special) && $auth->isAuthenticated() && $auth->getUsername() === 'admin') {
|
||||
if ($this->specialActions) {
|
||||
@ -241,10 +255,6 @@ class Tabs extends AbstractWidget implements \Countable
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Counting registered tabs
|
||||
* @return int
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return count($this->tabs);
|
||||
|
@ -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]);
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
use Icinga\Web\ModuleActionController;
|
||||
use Icinga\Web\Hook;
|
||||
use Icinga\File\Csv;
|
||||
use Icinga\Monitoring\Backend;
|
||||
use Icinga\Application\Benchmark;
|
||||
|
||||
@ -83,9 +84,10 @@ class Monitoring_ListController extends ModuleActionController
|
||||
$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',
|
||||
@ -93,36 +95,12 @@ class Monitoring_ListController extends ModuleActionController
|
||||
'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');
|
||||
}
|
||||
}
|
||||
@ -181,19 +159,58 @@ class Monitoring_ListController extends ModuleActionController
|
||||
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',
|
||||
@ -214,6 +231,7 @@ class Monitoring_ListController extends ModuleActionController
|
||||
'icon' => 'img/classic/servers-network.png',
|
||||
'url' => 'monitoring/list/contactgroups',
|
||||
));
|
||||
*/
|
||||
return $tabs;
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,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
|
||||
@ -26,13 +27,18 @@ 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 !== '*') {
|
||||
@ -42,30 +48,14 @@ class Monitoring_ShowController extends ModuleActionController
|
||||
$this->view->host = $this->backend->fetchHost($host, true);
|
||||
}
|
||||
$this->view->compact = $this->_getParam('view') === 'compact';
|
||||
if ($object === null) {
|
||||
// TODO: Notification, not found
|
||||
$this->redirectNow('monitoring/list/services');
|
||||
return;
|
||||
}
|
||||
$this->view->object = $object;
|
||||
$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 (Hook::has('ticket')) {
|
||||
$params['ticket'] = '__ID__';
|
||||
$this->view->ticket_link = preg_replace(
|
||||
'~__ID__~',
|
||||
'\$1',
|
||||
$this->view->qlink(
|
||||
'#__ID__',
|
||||
'monitoring/show/ticket',
|
||||
$params
|
||||
)
|
||||
);
|
||||
// TODO: Global ticket pattern config (or per environment)
|
||||
$this->view->ticket_pattern = '~#(\d{4,6})~';
|
||||
}
|
||||
$this->prepareTicketHook();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -144,6 +134,8 @@ class Monitoring_ShowController extends ModuleActionController
|
||||
->where('object_type', 'service')
|
||||
->fetchPairs();
|
||||
Benchmark::measure('Service action done');
|
||||
$object = $this->view->object->prefetch();
|
||||
$this->prepareGrapherHook();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -243,6 +235,8 @@ class Monitoring_ShowController extends ModuleActionController
|
||||
->where('host_name', $this->view->host->host_name)
|
||||
->where('object_type', 'host')
|
||||
->fetchPairs();
|
||||
$this->view->object->prefetch();
|
||||
$this->prepareGrapherHook();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -250,9 +244,6 @@ class Monitoring_ShowController extends ModuleActionController
|
||||
*/
|
||||
public function historyAction()
|
||||
{
|
||||
if ($this->view->host) {
|
||||
$this->view->tabs->activate('history')->enableSpecialActions();
|
||||
}
|
||||
$this->view->history = $this->backend->select()
|
||||
->from(
|
||||
'eventHistory',
|
||||
@ -269,7 +260,6 @@ class Monitoring_ShowController extends ModuleActionController
|
||||
)
|
||||
)->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>';
|
||||
@ -278,6 +268,7 @@ class Monitoring_ShowController extends ModuleActionController
|
||||
if ($this->_getParam('sort')) {
|
||||
$this->view->preserve['sort'] = $this->_getParam('sort');
|
||||
}
|
||||
$this->view->preserve = $this->view->history->getAppliedFilter()->toParams();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -285,6 +276,7 @@ class Monitoring_ShowController extends ModuleActionController
|
||||
*/
|
||||
public function servicesAction()
|
||||
{
|
||||
$this->_setParam('service', null);
|
||||
// Ugly and slow:
|
||||
$this->view->services = $this->view->action(
|
||||
'services',
|
||||
@ -295,6 +287,9 @@ class Monitoring_ShowController extends ModuleActionController
|
||||
//'sort', 'service_description'
|
||||
)
|
||||
);
|
||||
$this->view->services = $this->view->action('services', 'list', 'monitoring', array(
|
||||
'view' => 'compact'
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -302,10 +297,9 @@ class Monitoring_ShowController extends ModuleActionController
|
||||
*/
|
||||
public function ticketAction()
|
||||
{
|
||||
$this->view->tabs->activate('ticket')->enableSpecialActions();
|
||||
$id = $this->_getParam('ticket');
|
||||
// Still hardcoded, TODO: get URL:
|
||||
if (Hook::has('ticket')) {
|
||||
// TODO: Still hardcoded, should ask for URL:
|
||||
$id = $this->_getParam('ticket');
|
||||
$ticketModule = 'rt';
|
||||
$this->render();
|
||||
$this->_forward(
|
||||
@ -319,12 +313,54 @@ class Monitoring_ShowController extends ModuleActionController
|
||||
}
|
||||
}
|
||||
|
||||
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__~',
|
||||
'\$1',
|
||||
$this->view->qlink('#__ID__',
|
||||
'monitoring/show/ticket',
|
||||
$params
|
||||
)
|
||||
);
|
||||
// TODO: Global ticket pattern config (or per environment)
|
||||
$this->view->ticket_pattern = '~#(\d{4,6})~';
|
||||
}
|
||||
}
|
||||
|
||||
protected function prepareGrapherHook()
|
||||
{
|
||||
if ($grapher = Hook::get('grapher')) {
|
||||
$object = $this->view->object;
|
||||
if ($grapher->hasGraph(
|
||||
$object->host_name,
|
||||
$object->service_description
|
||||
)) {
|
||||
$this->view->preview_image = $grapher->getPreviewImage(
|
||||
$object->host_name,
|
||||
$object->service_description
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creating tabs for this controller
|
||||
* @return \Icinga\Web\Widget\AbstractWidget
|
||||
*/
|
||||
protected function createTabs()
|
||||
{
|
||||
$object = $this->view->object;
|
||||
$tabs = $this->widget('tabs');
|
||||
if (!$this->view->host) {
|
||||
return $tabs;
|
||||
@ -335,11 +371,10 @@ class Monitoring_ShowController extends ModuleActionController
|
||||
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;
|
||||
}
|
||||
$tabs->add(
|
||||
'host',
|
||||
@ -347,7 +382,7 @@ class Monitoring_ShowController extends ModuleActionController
|
||||
'title' => 'Host',
|
||||
'icon' => 'img/classic/server.png',
|
||||
'url' => 'monitoring/show/host',
|
||||
'urlParams' => $hostParams,
|
||||
'urlParams' => $params,
|
||||
)
|
||||
);
|
||||
$tabs->add(
|
||||
@ -390,13 +425,16 @@ class Monitoring_ShowController extends ModuleActionController
|
||||
)
|
||||
);
|
||||
}
|
||||
/*
|
||||
$tabs->add('contacts', array(
|
||||
'title' => 'Contacts',
|
||||
'icon' => 'img/classic/customer.png',
|
||||
'url' => 'monitoring/detail/contacts',
|
||||
'urlParams' => $params,
|
||||
));
|
||||
|
||||
$tabs->activate($this->action_name)->enableSpecialActions();
|
||||
|
||||
/**
|
||||
$tabs->add('contacts', array(
|
||||
'title' => 'Contacts',
|
||||
'icon' => 'img/classic/customer.png',
|
||||
'url' => 'monitoring/detail/contacts',
|
||||
'urlParams' => $params,
|
||||
));
|
||||
*/
|
||||
// TODO: Inventory 'img/classic/facts.gif'
|
||||
// Ticket 'img/classic/ticket.gif'
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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)
|
||||
);
|
@ -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, '!'))
|
||||
) ?>
|
@ -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 {
|
||||
@ -29,4 +30,3 @@ foreach ($this->comments as $comment) {
|
||||
<blockquote> <?= implode('<br />', $list) ?></blockquote>
|
||||
</div>
|
||||
|
||||
<?php } ?>
|
||||
|
@ -30,4 +30,4 @@
|
||||
echo '<strong>Contactgroups:</strong> ';
|
||||
echo implode(', ', $contactGroupList);
|
||||
}
|
||||
?>
|
||||
?>
|
||||
|
@ -19,4 +19,4 @@
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<?php } ?>
|
||||
|
@ -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>
|
@ -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";
|
||||
|
@ -0,0 +1,4 @@
|
||||
<?= $this->expandable(
|
||||
$this->pluginOutput($object->output),
|
||||
$this->pluginOutput($object->long_output)
|
||||
) ?>
|
@ -0,0 +1,7 @@
|
||||
<? if ($object->perfdata): ?>
|
||||
<?= $this->expandable(
|
||||
'<b>Performance data</b>',
|
||||
$this->perfdata($object->perfdata),
|
||||
array('collapsed' => false)
|
||||
) ?>
|
||||
<? endif ?>
|
@ -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";
|
||||
|
@ -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 ?>
|
||||
|
@ -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 ?>
|
||||
|
@ -1 +1,2 @@
|
||||
<?= $this->services ?>
|
||||
<?= $this->render('show/components/header.phtml') ?>
|
||||
<?= $services ?>
|
||||
|
@ -1,2 +1,2 @@
|
||||
<?= $this->tabs ?>
|
||||
<?= $tabs ?>
|
||||
|
||||
|
@ -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 ?>
|
||||
|
126
modules/monitoring/bin/action/list.inc.php
Normal file
126
modules/monitoring/bin/action/list.inc.php
Normal 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;
|
||||
}
|
||||
}
|
||||
|
21
modules/monitoring/bin/soaptest.php
Normal file
21
modules/monitoring/bin/soaptest.php
Normal 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";
|
||||
}
|
@ -101,6 +101,7 @@ class AbstractBackend implements DatasourceInterface
|
||||
'host_in_downtime',
|
||||
'host_acknowledged',
|
||||
'host_check_command',
|
||||
'host_check_command',
|
||||
'host_last_state_change',
|
||||
'host_alias',
|
||||
'host_output',
|
||||
@ -138,8 +139,8 @@ class AbstractBackend implements DatasourceInterface
|
||||
'host_flap_detection_enabled',
|
||||
'host_is_flapping',
|
||||
'host_percent_state_change',
|
||||
'host_latency',
|
||||
'host_execution_time',
|
||||
'host_check_latency',
|
||||
'host_check_execution_time',
|
||||
'host_scheduled_downtime_depth',
|
||||
'host_failure_prediction_enabled',
|
||||
'host_process_performance_data',
|
||||
|
@ -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);
|
||||
|
@ -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',
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -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',
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -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',
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -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"
|
||||
),
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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'
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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()
|
||||
);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -8,13 +8,13 @@ class StatusQuery extends AbstractQuery
|
||||
|
||||
protected $columnMap = array(
|
||||
'hosts' => array(
|
||||
'host' => 'ho.name1',
|
||||
'host_name' => 'ho.name1',
|
||||
'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',
|
||||
'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',
|
||||
@ -53,8 +53,8 @@ class StatusQuery extends AbstractQuery
|
||||
'host_flap_detection_enabled' => 'hs.flap_detection_enabled',
|
||||
'host_is_flapping' => 'hs.is_flapping',
|
||||
'host_percent_state_change' => 'hs.percent_state_change',
|
||||
'host_latency' => 'hs.latency',
|
||||
'host_execution_time' => 'hs.execution_time',
|
||||
'host_check_latency' => 'hs.latency',
|
||||
'host_check_execution_time' => 'hs.execution_time',
|
||||
'host_scheduled_downtime_depth' => 'hs.scheduled_downtime_depth',
|
||||
'host_failure_prediction_enabled' => 'hs.failure_prediction_enabled',
|
||||
'host_process_performance_data' => 'hs.process_performance_data',
|
||||
@ -102,12 +102,15 @@ 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_display_name' => 's.display_name',
|
||||
'service_icon_image' => 's.icon_image',
|
||||
'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',
|
||||
@ -122,13 +125,19 @@ class StatusQuery extends AbstractQuery
|
||||
'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_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_check_command' => 'ss.check_command',
|
||||
'service_last_check' => 'UNIX_TIMESTAMP(ss.last_check)',
|
||||
'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',
|
||||
@ -165,7 +174,7 @@ class StatusQuery extends AbstractQuery
|
||||
END
|
||||
END
|
||||
END',
|
||||
)
|
||||
),
|
||||
);
|
||||
|
||||
public function group($col)
|
||||
@ -190,14 +199,14 @@ class StatusQuery extends AbstractQuery
|
||||
array('ho' => $this->prefix . 'objects'),
|
||||
array()
|
||||
)->join(
|
||||
array('hs' => $this->prefix . 'hoststatus'),
|
||||
'ho.object_id = hs.host_object_id AND ho.is_active = 1',
|
||||
array()
|
||||
)->join(
|
||||
array('h' => $this->prefix . 'hosts'),
|
||||
'hs.host_object_id = h.host_object_id',
|
||||
array()
|
||||
);
|
||||
array('hs' => $this->prefix . 'hoststatus'),
|
||||
'ho.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,
|
||||
@ -278,20 +287,22 @@ class StatusQuery extends AbstractQuery
|
||||
|
||||
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('hgo' => $this->prefix . 'objects'),
|
||||
'hgo.' . $this->object_id . ' = hg.' . $this->hostgroup_id
|
||||
. ' AND hgo.is_active = 1',
|
||||
array()
|
||||
);
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,8 @@
|
||||
namespace Icinga\Monitoring;
|
||||
|
||||
use Icinga\Application\Config;
|
||||
use Icinga\Web\Session;
|
||||
use Exception;
|
||||
|
||||
class Environment
|
||||
{
|
||||
|
146
modules/monitoring/library/Monitoring/Object/AbstractObject.php
Normal file
146
modules/monitoring/library/Monitoring/Object/AbstractObject.php
Normal 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;
|
||||
}
|
||||
}
|
||||
|
58
modules/monitoring/library/Monitoring/Object/Host.php
Normal file
58
modules/monitoring/library/Monitoring/Object/Host.php
Normal 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();
|
||||
}
|
||||
}
|
||||
|
69
modules/monitoring/library/Monitoring/Object/Service.php
Normal file
69
modules/monitoring/library/Monitoring/Object/Service.php
Normal 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();
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,9 @@ class CommentView extends MonitoringView
|
||||
'comment_author',
|
||||
'comment_timestamp',
|
||||
'comment_type',
|
||||
'host_name',
|
||||
'service_host_name',
|
||||
'service_description',
|
||||
);
|
||||
|
||||
protected $specialFilters = array();
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -1,6 +1,7 @@
|
||||
SetEnv APPLICATION_ENV development
|
||||
|
||||
RewriteEngine on
|
||||
RewriteRule ^css/icinga.css css.php
|
||||
RewriteCond %{REQUEST_FILENAME} -s [OR]
|
||||
RewriteCond %{REQUEST_FILENAME} -l [OR]
|
||||
RewriteCond %{REQUEST_FILENAME} -d
|
||||
|
@ -1,13 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Icinga\Protocol\Livestatus;
|
||||
|
||||
use Icinga\Protocol\Livestatus\Connection;
|
||||
use Icinga\Protocol\Livestatus\Query;
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
|
||||
require_once('../../library/Icinga/Protocol/AbstractQuery.php');
|
||||
require_once('../../library/Icinga/Protocol/Livestatus/Connection.php');
|
||||
require_once('../../library/Icinga/Protocol/Livestatus/Query.php');
|
||||
|
||||
/**
|
||||
*
|
||||
* Test class for Connection
|
||||
* Created Wed, 16 Jan 2013 15:15:16 +0000
|
||||
*
|
||||
**/
|
||||
class ConnectionTest extends \PHPUnit_Framework_TestCase
|
||||
class ConnectionTest extends TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
@ -25,7 +33,10 @@ class ConnectionTest extends \PHPUnit_Framework_TestCase
|
||||
**/
|
||||
public function testSelect()
|
||||
{
|
||||
$this->markTestIncomplete('testSelect is not implemented yet');
|
||||
$socket = tempnam(sys_get_temp_dir(), 'IcingaTest');
|
||||
$connection = new Connection($socket);
|
||||
$this->assertTrue($connection->select() instanceof Query);
|
||||
unlink($socket);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,13 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Icinga\Protocol\Livestatus;
|
||||
|
||||
use Icinga\Protocol\Livestatus\Connection;
|
||||
use Icinga\Protocol\Livestatus\Query;
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
|
||||
require_once('../../library/Icinga/Protocol/AbstractQuery.php');
|
||||
require_once('../../library/Icinga/Protocol/Livestatus/Query.php');
|
||||
require_once('../../library/Icinga/Protocol/Livestatus/Connection.php');
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Test class for Query
|
||||
* Created Wed, 16 Jan 2013 15:15:16 +0000
|
||||
*
|
||||
**/
|
||||
class QueryTest extends \PHPUnit_Framework_TestCase
|
||||
class QueryTest extends TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
|
@ -108,9 +108,9 @@ def main():
|
||||
command_options.append('--log-junit')
|
||||
command_options.append(os.path.join(report_directory,
|
||||
'phpunit_results.xml'))
|
||||
command_options.append('--coverage-clover')
|
||||
command_options.append('--coverage-html')
|
||||
command_options.append(os.path.join(report_directory,
|
||||
'phpunit_coverage.xml'))
|
||||
'php_html_coverage'))
|
||||
if options.include:
|
||||
command_options.append('--filter')
|
||||
command_options.append(options.include)
|
||||
|
Loading…
x
Reference in New Issue
Block a user