2013-06-03 16:14:46 +02:00
|
|
|
<?php
|
2013-06-07 13:29:11 +02:00
|
|
|
// {{{ICINGA_LICENSE_HEADER}}}
|
2013-06-28 16:47:30 +02:00
|
|
|
/**
|
2013-07-15 12:26:10 +02:00
|
|
|
* This file is part of Icinga 2 Web.
|
2013-09-04 18:27:16 +02:00
|
|
|
*
|
2013-07-15 12:26:10 +02:00
|
|
|
* Icinga 2 Web - Head for multiple monitoring backends.
|
2013-06-28 16:47:30 +02:00
|
|
|
* Copyright (C) 2013 Icinga Development Team
|
2013-09-04 18:27:16 +02:00
|
|
|
*
|
2013-06-28 16:47:30 +02:00
|
|
|
* 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.
|
2013-09-04 18:27:16 +02:00
|
|
|
*
|
2013-06-28 16:47:30 +02:00
|
|
|
* 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.
|
2013-09-04 18:27:16 +02:00
|
|
|
*
|
2013-06-28 16:47:30 +02:00
|
|
|
* 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.
|
2013-09-04 18:27:16 +02:00
|
|
|
*
|
2013-06-28 16:47:30 +02:00
|
|
|
* @copyright 2013 Icinga Development Team <info@icinga.org>
|
2013-07-15 12:26:10 +02:00
|
|
|
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
|
|
|
|
* @author Icinga Development Team <info@icinga.org>
|
2013-06-28 16:47:30 +02:00
|
|
|
*/
|
2013-06-07 13:29:11 +02:00
|
|
|
// {{{ICINGA_LICENSE_HEADER}}}
|
|
|
|
|
2013-06-03 16:14:46 +02:00
|
|
|
namespace Icinga\Protocol\Statusdat;
|
|
|
|
|
2013-07-19 17:45:51 +02:00
|
|
|
use Icinga\Data\DatasourceInterface;
|
2013-09-02 17:33:12 +02:00
|
|
|
use Icinga\Exception;
|
|
|
|
use Icinga\Benchmark;
|
2013-07-19 11:29:51 +02:00
|
|
|
use Icinga\Protocol\Statusdat\View\MonitoringObjectList;
|
2013-09-02 17:33:12 +02:00
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
|
|
|
* Class Reader
|
|
|
|
* @package Icinga\Protocol\Statusdat
|
|
|
|
*/
|
2013-07-19 17:45:51 +02:00
|
|
|
class Reader implements IReader, DatasourceInterface
|
2013-06-03 16:14:46 +02:00
|
|
|
{
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
*/
|
2013-06-03 16:14:46 +02:00
|
|
|
const DEFAULT_CACHE_LIFETIME = 300;
|
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
const STATUSDAT_DEFAULT_CACHE_PATH = "/cache";
|
2013-06-03 16:14:46 +02:00
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
|
|
|
* @var null
|
|
|
|
*/
|
2013-06-03 16:14:46 +02:00
|
|
|
private $lastState = null;
|
2013-06-07 13:29:11 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @var bool
|
|
|
|
*/
|
2013-06-03 16:14:46 +02:00
|
|
|
private $hasRuntimeState = false;
|
2013-06-07 13:29:11 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @var null
|
|
|
|
*/
|
2013-06-03 16:14:46 +02:00
|
|
|
private $objectCache = null;
|
2013-06-07 13:29:11 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @var null
|
|
|
|
*/
|
2013-06-03 16:14:46 +02:00
|
|
|
private $statusCache = null;
|
2013-06-07 13:29:11 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @var bool
|
|
|
|
*/
|
2013-06-03 16:14:46 +02:00
|
|
|
private $newState = false;
|
2013-06-07 13:29:11 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @var null
|
|
|
|
*/
|
2013-06-03 16:14:46 +02:00
|
|
|
private $parser = null;
|
2013-06-07 13:29:11 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @var bool
|
|
|
|
*/
|
2013-06-03 16:14:46 +02:00
|
|
|
private $noCache = false;
|
2013-06-07 13:29:11 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @param $config
|
|
|
|
* @param null $parser
|
|
|
|
* @param bool $noCache
|
|
|
|
*/
|
2013-06-03 16:14:46 +02:00
|
|
|
public function __construct($config = \Zend_Config, $parser = null, $noCache = false)
|
|
|
|
{
|
|
|
|
$this->noCache = $noCache;
|
2013-07-19 11:29:51 +02:00
|
|
|
if (isset($config->no_cache)) {
|
|
|
|
$this->noCache = $config->no_cache;
|
|
|
|
}
|
2013-06-03 16:14:46 +02:00
|
|
|
$this->config = $config;
|
|
|
|
$this->parser = $parser;
|
2013-07-19 11:29:51 +02:00
|
|
|
if (!$this->noCache) {
|
2013-06-03 16:14:46 +02:00
|
|
|
$this->cache = $this->initializeCaches($config);
|
2013-06-07 13:29:11 +02:00
|
|
|
if ($this->fromCache()) {
|
2013-06-03 16:14:46 +02:00
|
|
|
$this->createHostServiceConnections();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2013-06-07 13:29:11 +02:00
|
|
|
if (!$this->lastState) {
|
2013-06-03 16:14:46 +02:00
|
|
|
$this->parseObjectsCacheFile();
|
2013-06-07 13:29:11 +02:00
|
|
|
}
|
|
|
|
if (!$this->hasRuntimeState) {
|
2013-07-19 11:29:51 +02:00
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
}
|
|
|
|
$this->parseStatusDatFile();
|
|
|
|
if (!$noCache && $this->newState) {
|
|
|
|
$this->statusCache->save($this->parser->getRuntimeState(), 'objects' . md5($this->config->objects_file));
|
|
|
|
}
|
2013-06-03 16:14:46 +02:00
|
|
|
$this->createHostServiceConnections();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
|
|
|
* @throws Exception\ConfigurationError
|
|
|
|
*/
|
|
|
|
private function initializeCaches()
|
2013-06-03 16:14:46 +02:00
|
|
|
{
|
2013-06-10 17:45:13 +02:00
|
|
|
$defaultCachePath = "/tmp" . self::STATUSDAT_DEFAULT_CACHE_PATH;
|
2013-06-07 13:29:11 +02:00
|
|
|
|
|
|
|
$cachePath = $this->config->get('cache_path', $defaultCachePath);
|
|
|
|
$maxCacheLifetime = intval($this->config->get('cache_path', self::DEFAULT_CACHE_LIFETIME));
|
|
|
|
if (!is_writeable($cachePath)) {
|
|
|
|
throw new Exception\ConfigurationError(
|
|
|
|
"Cache path $cachePath is not writable, check your configuration"
|
|
|
|
);
|
2013-06-03 16:14:46 +02:00
|
|
|
}
|
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
$backendOptions = array(
|
|
|
|
'cache_dir' => $cachePath
|
2013-06-03 16:14:46 +02:00
|
|
|
);
|
2013-06-07 13:29:11 +02:00
|
|
|
// the objects cache might exist for months and is still valid
|
|
|
|
$this->objectCache = $this->initCache($this->config->objects_file, $backendOptions, null);
|
|
|
|
$this->statusCache = $this->initCache($this->config->status_file, $backendOptions, $maxCacheLifetime);
|
2013-06-03 16:14:46 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
|
|
|
* @param $file
|
|
|
|
* @param $backend
|
|
|
|
* @param $lifetime
|
|
|
|
* @return \Zend_Cache_Core|\Zend_Cache_Frontend
|
|
|
|
*/
|
|
|
|
private function initCache($file, $backend, $lifetime)
|
2013-06-03 16:14:46 +02:00
|
|
|
{
|
2013-06-07 13:29:11 +02:00
|
|
|
$frontendOptions = array(
|
|
|
|
'lifetime' => $lifetime,
|
|
|
|
'automatic_serialization' => true,
|
|
|
|
'master_files' => array($file)
|
|
|
|
);
|
|
|
|
return \Zend_Cache::factory('Core', 'File', $frontendOptions, $backend);
|
2013-06-03 16:14:46 +02:00
|
|
|
}
|
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
|
|
|
* @return bool
|
|
|
|
*/
|
2013-06-03 16:14:46 +02:00
|
|
|
private function fromCache()
|
|
|
|
{
|
2013-06-07 13:29:11 +02:00
|
|
|
if (!$this->readObjectsCache()) {
|
2013-06-03 16:14:46 +02:00
|
|
|
$this->newState = true;
|
|
|
|
return false;
|
|
|
|
}
|
2013-06-07 13:29:11 +02:00
|
|
|
if (!$this->readStatusCache()) {
|
2013-06-03 16:14:46 +02:00
|
|
|
$this->newState = true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
|
|
|
* @return bool
|
|
|
|
*/
|
2013-06-03 16:14:46 +02:00
|
|
|
private function readObjectsCache()
|
|
|
|
{
|
2013-06-07 13:29:11 +02:00
|
|
|
$this->lastState = $this->objectCache->load('objects' . md5($this->config->objects_file));
|
|
|
|
if ($this->lastState == false) {
|
2013-06-03 16:14:46 +02:00
|
|
|
return false;
|
2013-06-07 13:29:11 +02:00
|
|
|
}
|
2013-06-07 13:35:03 +02:00
|
|
|
|
|
|
|
return true;
|
2013-06-03 16:14:46 +02:00
|
|
|
}
|
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
|
|
|
* @return bool
|
|
|
|
*/
|
2013-06-03 16:14:46 +02:00
|
|
|
private function readStatusCache()
|
|
|
|
{
|
2013-06-10 17:45:13 +02:00
|
|
|
if (!isset($this->stateCache)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
$statusInfo = $this->stateCache->load('state' . md5($this->config->status_file));
|
2013-06-10 17:45:13 +02:00
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
if ($statusInfo == false) {
|
2013-06-03 16:14:46 +02:00
|
|
|
return false;
|
2013-06-07 13:29:11 +02:00
|
|
|
}
|
2013-06-10 17:45:13 +02:00
|
|
|
|
2013-06-03 16:14:46 +02:00
|
|
|
$this->hasRuntimeState = true;
|
2013-06-07 13:35:03 +02:00
|
|
|
return true;
|
2013-06-03 16:14:46 +02:00
|
|
|
}
|
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
private function createHostServiceConnections()
|
2013-06-03 16:14:46 +02:00
|
|
|
{
|
2013-06-07 13:29:11 +02:00
|
|
|
if (!isset($this->lastState["service"])) {
|
|
|
|
return;
|
|
|
|
}
|
2013-06-03 16:14:46 +02:00
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
foreach ($this->lastState["service"] as &$service) {
|
|
|
|
$host = & $this->lastState["host"][$service->host_name];
|
|
|
|
if (!isset($host->services)) {
|
|
|
|
$host->services = array();
|
|
|
|
}
|
|
|
|
$host->services[$service->service_description] = & $service;
|
|
|
|
$service->host = & $host;
|
|
|
|
}
|
|
|
|
}
|
2013-06-03 16:14:46 +02:00
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
|
|
|
* @throws Exception\ConfigurationError
|
|
|
|
*/
|
|
|
|
private function parseObjectsCacheFile()
|
|
|
|
{
|
|
|
|
if (!is_readable($this->config->objects_file)) {
|
|
|
|
throw new Exception\ConfigurationError(
|
|
|
|
"Can't read objects-file {$this->config->objects_file}, check your configuration"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
if (!$this->parser) {
|
|
|
|
$this->parser = new Parser(fopen($this->config->objects_file, "r"));
|
|
|
|
}
|
|
|
|
$this->parser->parseObjectsFile();
|
2013-07-23 12:18:27 +02:00
|
|
|
$this->lastState = $this->parser->getRuntimeState();
|
2013-06-07 13:29:11 +02:00
|
|
|
}
|
2013-06-03 16:14:46 +02:00
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
|
|
|
* @throws Exception\ConfigurationError
|
|
|
|
*/
|
|
|
|
private function parseStatusDatFile()
|
|
|
|
{
|
|
|
|
if (!is_readable($this->config->status_file)) {
|
|
|
|
throw new Exception\ConfigurationError(
|
|
|
|
"Can't read status-file {$this->config->status_file}, check your configuration"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
if (!$this->parser) {
|
|
|
|
$this->parser = new Parser(fopen($this->config->status_file, "r"), $this->lastState);
|
|
|
|
}
|
|
|
|
$this->parser->parseRuntimeState(fopen($this->config->status_file, "r"));
|
2013-07-23 12:18:27 +02:00
|
|
|
$this->lastState = $this->parser->getRuntimeState();
|
2013-06-07 13:29:11 +02:00
|
|
|
if (!$this->noCache) {
|
|
|
|
$this->statusCache->save(array("true" => true), "state" . md5($this->config->objects_file));
|
|
|
|
}
|
|
|
|
}
|
2013-06-03 16:14:46 +02:00
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
|
|
|
* @return Query
|
|
|
|
*/
|
|
|
|
public function select()
|
|
|
|
{
|
|
|
|
return new Query($this);
|
2013-06-03 16:14:46 +02:00
|
|
|
}
|
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
|
|
|
* @param Query $query
|
2013-06-07 13:35:03 +02:00
|
|
|
* @return MonitoringObjectList
|
2013-06-07 13:29:11 +02:00
|
|
|
*/
|
|
|
|
public function fetchAll(Query $query)
|
2013-06-03 16:14:46 +02:00
|
|
|
{
|
2013-07-19 11:29:51 +02:00
|
|
|
return $query->getResult();
|
2013-06-03 16:14:46 +02:00
|
|
|
}
|
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
|
|
|
* @return mixed|null
|
|
|
|
*/
|
|
|
|
public function getState()
|
2013-06-03 16:14:46 +02:00
|
|
|
{
|
2013-06-07 13:29:11 +02:00
|
|
|
return $this->lastState;
|
2013-06-03 16:14:46 +02:00
|
|
|
}
|
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
|
|
|
* @return mixed|null
|
|
|
|
*/
|
|
|
|
public function getObjects()
|
2013-06-03 16:14:46 +02:00
|
|
|
{
|
2013-06-07 13:29:11 +02:00
|
|
|
return $this->lastState;
|
2013-06-03 16:14:46 +02:00
|
|
|
}
|
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
|
|
|
* @param $type
|
|
|
|
* @param $name
|
|
|
|
* @return ObjectContainer|mixed|null
|
|
|
|
*/
|
|
|
|
public function getObjectByName($type, $name)
|
|
|
|
{
|
|
|
|
if (isset($this->lastState[$type]) && isset($this->lastState[$type][$name])) {
|
|
|
|
return new ObjectContainer($this->lastState[$type][$name], $this);
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
2013-06-03 16:14:46 +02:00
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
|
|
|
* @param $type
|
|
|
|
* @return array|null
|
|
|
|
*/
|
|
|
|
public function getObjectNames($type)
|
|
|
|
{
|
|
|
|
return isset($this->lastState[$type]) ? array_keys($this->lastState[$type]) : null;
|
|
|
|
}
|
2013-06-03 16:14:46 +02:00
|
|
|
}
|