Move Statusdat to backend, remove old backend from library

Except for statusdat, the library/Icinga/Backend classes were unused

refs #4417
refs #4179
This commit is contained in:
Jannis Moßhammer 2013-07-18 17:20:12 +02:00
parent 281d27255b
commit cea7cdbcaf
30 changed files with 188 additions and 2318 deletions

View File

@ -1,146 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
/**
* This file is part of Icinga 2 Web.
*
* Icinga 2 Web - Head for multiple monitoring backends.
* 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>
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
* @author Icinga Development Team <info@icinga.org>
*/
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Backend;
use Icinga\Application\Config;
/**
* Icinga Backend Abstract
*
* @package Icinga\Backend
*/
abstract class AbstractBackend
{
/**
* @var \Zend_Config
*/
protected $config;
/**
* @var array
*/
protected $extensions = array();
/**
* Backend constructor, should not be overwritten
*
* Makes sure that $this->config exists. Config is a Zend_Config
* object right now, only the main Config is an Icinga one
*
* return void
*/
final public function __construct(\Zend_Config $config = null)
{
if ($config == null) {
$config = new \Zend_Config(array());
}
$this->config = $config;
$this->init();
}
/**
* Override this function for initialization tasks
*
* return void
*/
protected function init()
{
}
/**
* Dummy function for fluent code
*
* return \Icinga\Backend\Ido
*/
public function select()
{
return $this;
}
/**
* Create a Query object instance for given virtual table and desired fields
*
* Leave fields empty to get all available properties
*
* @param string Virtual table name
* @param array $fields
* @throws \Exception
* @return
* @internal param \Icinga\Backend\Fields $array return \Icinga\Backend\Ido\Query* return \Icinga\Backend\Ido\Query
*/
public function from($virtual_table, $fields = array())
{
$classname = $this->tableToClassName($virtual_table);
if (!class_exists($classname)) {
throw new \Exception(sprintf('Asking for invalid virtual table %s', $classname));
}
$query = new $classname($this, $fields);
return $query;
}
/**
* @param $virtual_table
* @return bool
*/
public function hasView($virtual_table)
{
return class_exists($this->tableToClassName($virtual_table));
}
/**
* @param $virtual_table
* @return string
*/
protected function tableToClassName($virtual_table)
{
if (strpos($virtual_table, "/") !== false) {
list($module, $classname) = explode("/", $virtual_table, 2);
$class = array_pop(explode("\\", get_class($this)));
return 'Icinga\\' . ucfirst($module) . '\\Backend\\' . $class . '\\' . ucfirst($classname) . 'Query';
} else {
return get_class($this) . '\\' . ucfirst($virtual_table . 'Query');
}
}
/**
* @return mixed
*/
public function getName()
{
return preg_replace('~^.+\\\(.+?)$~', '$1', get_class($this));
}
/**
* @return mixed
*/
public function __toString()
{
return $this->getName();
}
}

View File

@ -1,53 +0,0 @@
<?php
namespace Icinga\Backend;
use Icinga\Backend;
class Combo extends AbstractBackend
{
protected $db;
protected $backends;
// TODO: Create a dummy query object to also catch errors with lazy connections
public function from($view, $fields = array())
{
$backends = $this->listMyBackends();
$query = null;
$msg = '';
while ($query === null) {
try {
$backend_name = array_shift($backends);
$msg .= "Trying $backend_name";
$backend = Backend::getInstance($backend_name);
if ($backend->hasView($view)) {
$query = $backend->from($view, $fields);
}
} catch (\Exception $e) {
$msg .= ' Failed: ' . $e->getMessage() . "\n";
}
if ($query !== null) $msg .= " Succeeded.\n";
if ($query === null && empty($backends)) {
throw new \Exception('All backends failed: ' . nl2br($msg));
}
}
return $query;
}
public function hasView($virtual_table)
{
$backends = $this->listMyBackends();
while ($backend_name = array_shift($backends)) {
if (Backend::getInstance($backend_name)->hasView($virtual_table)) {
return true;
}
}
return false;
}
protected function listMyBackends()
{
return preg_split('~,\s*~', $this->config->backends, -1, PREG_SPLIT_NO_EMPTY);
}
}

View File

@ -1,74 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
/**
* This file is part of Icinga 2 Web.
*
* Icinga 2 Web - Head for multiple monitoring backends.
* 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>
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
* @author Icinga Development Team <info@icinga.org>
*/
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Backend\DataView;
/**
* Class AbstractAccessorStrategy
* Basic interface for views.
* The name sound weirder than it is: Views define special get and exists operations for fields
* that are not directly available in a resultset, but exist under another name or can be
* accessed by loading an additional object during runtime.
*
* @see Icinga\Backend\DataView\ObjectRemappingView For an implementation of mapping field names
* to storage specific names, e.g. service_state being status.current_state in status.dat views.
*
* @see Icinga\Backend\MonitoringObjectList For the typical usage of this class. It is not wrapped
* around the monitoring object, so we don't use __get() or __set() and always have to give the
* item we'd like to access.
* @package Icinga\Backend\DataView
*/
interface AbstractAccessorStrategy
{
/**
* Returns a field for the item, or throws an Exception if the field doesn't exist
*
* @param $item The item to access
* @param $field The field of the item that should be accessed
* @return string The content of the field
*
* @throws \InvalidArgumentException when the field does not exist
*/
public function get(&$item, $field);
/**
* Returns the name that the field has in the specific backend. Might not be available for every field/view
* @param $field The field name that should be translated
* @return string The real name of this field
*/
public function getNormalizedFieldName($field);
/**
* Returns true if the field exists on the specific item, otherwise false
*
* @param $item The item to access
* @param $field The field to check on the $item
* @return bool True when the field exists, otherwise false
*/
public function exists(&$item, $field);
}

View File

@ -1,134 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
/**
* This file is part of Icinga 2 Web.
*
* Icinga 2 Web - Head for multiple monitoring backends.
* 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>
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
* @author Icinga Development Team <info@icinga.org>
*/
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Backend\DataView;
/**
* Class ObjectRemappingView
*
* Dataview that maps generic field names to storage specific fields or requests them via handlers.
*
* When accessing objects, every storage api returns them with other names. You can't simply say
* $object->service_state, because this field is, e.g. under status.current_state in the status.dat
* view, while IDO uses servicestate->current_state.
*
* This view is intended for normalizing these changes, so a request of service_state returns the
* right field for the backend. When implementing it, you have to fill the mappedParameters and/or
* the handlerParameters array. While mappedParameters simply translate logic field names to
* storage specific ones, handlerParameters determins functions that handle data retrieval for
* the specific fields.
*
* @package Icinga\Backend\DataView
*/
class ObjectRemappingView implements AbstractAccessorStrategy
{
/**
* When implementing your own Mapper, this contains the static mapping rules.
* @see Icinga\Backend\Statusdat\DataView\StatusdatServiceView for an example
*
* @var array
*/
protected $mappedParameters = array();
/**
* When implementing your own Mapper, this contains the handler for specific fields and allows you to lazy load
* different fields if necessary. The methods are strings that will be mapped to methods of this class
*
* @see Icinga\Backend\Statusdat\DataView\StatusdatServiceView for an example
*
* @var array
*/
protected $handlerParameters = array();
/**
*
* @see Icinga\Backend\DataView\AbstractAccessorStrategy
*
* @param The $item
* @param The $field
* @return The|string
* @throws \InvalidArgumentException
*/
public function get(&$item, $field)
{
if (isset($item->$field)) {
return $item->$field;
}
if (isset($this->mappedParameters[$field])) {
$mapped = explode(".", $this->mappedParameters[$field]);
$res = $item;
foreach ($mapped as $map) {
if (!isset($res->$map)) {
return "";
}
$res = $res->$map;
}
return $res;
}
if (isset($this->handlerParameters[$field])) {
$hdl = $this->handlerParameters[$field];
return $this->$hdl($item);
}
throw new \InvalidArgumentException("Field $field does not exist for status.dat services");
}
/**
*
* @see Icinga\Backend\DataView\AbstractAccessorStrategy
*
* @param The $field
* @return The|string
*/
public function getNormalizedFieldName($field)
{
if (isset($this->mappedParameters[$field])) {
return $this->mappedParameters[$field];
}
return $field;
}
/**
*
* @see Icinga\Backend\DataView\AbstractAccessorStrategy
*
* @param The $item
* @param The $field
* @return bool
*/
public function exists(&$item, $field)
{
return (isset($item->$field)
|| isset($this->mappedParameters[$field])
|| isset($this->handlerParameters[$field])
);
}
}

View File

@ -1,292 +0,0 @@
<?php
/**
* Icinga IDO Backend
*
* @package Icinga\Backend
*/
namespace Icinga\Backend;
/**
* This class provides an easy-to-use interface to the IDO database
*
* You should usually not directly use this class but go through Icinga\Backend.
*
* New MySQL indexes:
* <code>
* CREATE INDEX web2_index ON icinga_scheduleddowntime (object_id, is_in_effect);
* CREATE INDEX web2_index ON icinga_comments (object_id);
* CREATE INDEX web2_index ON icinga_objects (object_id, is_active); -- (not sure yet)
* </code>
*
* Other possible (history-related) indexes, still subject to tests:
* CREATE INDEX web2_index ON icinga_statehistory (object_id, state_time DESC);
* CREATE INDEX web2_index ON icinga_notifications (object_id, instance_id, start_time DESC);
* CREATE INDEX web2_index ON icinga_downtimehistory (object_id, actual_start_time, actual_end_time);
*
* @copyright Copyright (c) 2013 Icinga-Web Team <info@icinga.org>
* @author Icinga-Web Team <info@icinga.org>
* @package Icinga\Application
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
*/
class Ido extends AbstractBackend
{
protected $db;
protected $dbtype;
protected $prefix = 'icinga_';
/**
* Backend initialization starts here
*
* return void
*/
protected function init()
{
$this->connect();
}
/**
* Get our Zend_Db connection
*
* return \Zend_Db_Adapter_Abstract
*/
public function getAdapter()
{
return $this->db;
}
public function getDbType()
{
return $this->dbtype;
}
/**
* Get our IDO table prefix
*
* return string
*/
public function getPrefix()
{
return $this->prefix;
}
// TODO: Move elsewhere. Really? Reasons may be: other backends need IDO
// access, even in environments running state details without IDO
protected function connect()
{
$this->dbtype = $this->config->get('dbtype', 'mysql');
$options = array(
\Zend_Db::AUTO_QUOTE_IDENTIFIERS => false,
\Zend_Db::CASE_FOLDING => \Zend_Db::CASE_LOWER
);
$drv_options = array(
\PDO::ATTR_TIMEOUT => 2,
// TODO: Check whether LC is useful. Zend_Db does fetchNum for Oci:
\PDO::ATTR_CASE => \PDO::CASE_LOWER
// TODO: ATTR_ERRMODE => ERRMODE_EXCEPTION vs ERRMODE_SILENT
);
switch ($this->dbtype) {
case 'mysql':
$adapter = 'Pdo_Mysql';
$drv_options[\PDO::MYSQL_ATTR_INIT_COMMAND] =
"SET SESSION SQL_MODE='STRICT_ALL_TABLES,NO_ZERO_IN_DATE,"
. "NO_ZERO_DATE,NO_ENGINE_SUBSTITUTION';";
// Not using ONLY_FULL_GROUP_BY as of performance impact
// TODO: NO_ZERO_IN_DATE as been added with 5.1.11. Is it
// ignored by other versions?
$port = $this->config->get('port', 3306);
break;
case 'pgsql':
$adapter = 'Pdo_Pgsql';
$port = $this->config->get('port', 5432);
break;
case 'oracle':
$adapter = 'Pdo_Oci';
// $adapter = 'Oracle';
$port = $this->config->get('port', 1521);
// $drv_options[\PDO::ATTR_STRINGIFY_FETCHES] = true;
if ($adapter === 'Oracle') {
putenv('ORACLE_SID=XE');
putenv('ORACLE_HOME=/u01/app/oracle/product/11.2.0/xe');
putenv('PATH=$PATH:$ORACLE_HOME/bin');
putenv('ORACLE_BASE=/u01/app/oracle');
putenv('NLS_LANG=AMERICAN_AMERICA.UTF8');
}
$this->prefix = '';
break;
default:
throw new \Exception(sprintf(
'Backend "%s" is not supported', $type
));
}
$attributes = array(
'host' => $this->config->host,
'port' => $port,
'username' => $this->config->user,
'password' => $this->config->pass,
'dbname' => $this->config->db,
'options' => $options,
'driver_options' => $drv_options
);
if ($this->dbtype === 'oracle') {
$attributes['persistent'] = true;
}
$this->db = \Zend_Db::factory($adapter, $attributes);
if ($adapter === 'Oracle') {
$this->db->setLobAsString(false);
}
$this->db->setFetchMode(\Zend_Db::FETCH_OBJ);
// $this->db->setFetchMode(\Zend_Db::FETCH_ASSOC);
}
/// *** TODO: EVERYTHING BELOW THIS LINE WILL BE MOVED AWAY *** ///
// UGLY temporary host fetch
public function fetchHost($host)
{
$object = \Icinga\Objects\Service::fromBackend(
$this->select()
->from('servicelist')
->where('so.name1 = ?', $host)
->fetchRow()
);
$object->customvars = $this->fetchCustomvars($host);
return $object;
}
// UGLY temporary service fetch
public function fetchService($host, $service)
{
$object = \Icinga\Objects\Service::fromBackend(
$this->select()
->from('servicelist')
->where('so.name1 = ?', $host)
->where('so.name2 = ?', $service)
->fetchRow()
);
$object->customvars = $this->fetchCustomvars($host, $service);
return $object;
}
public function fetchCustomvars($host, $service = null)
{
if ($this->dbtype === 'oracle') return (object) array();
$select = $this->db->select()->from(
array('cv' => $this->prefix . 'customvariablestatus'),
array(
// 'host_name' => 'cvo.name1',
// 'service_description' => 'cvo.name2',
'name' => 'cv.varname',
'value' => 'cv.varvalue',
)
)->join(
array('cvo' => $this->prefix . 'objects'),
'cvo.object_id = cv.object_id',
array()
);
$select->where('name1 = ?', $host);
if ($service === null) {
$select->where('objecttype_id = 1');
} else {
$select->where('objecttype_id = 1');
$select->where('name2 = ?', $service);
}
$select->where('is_active = 1')->order('cv.varname');
return (object) $this->db->fetchPairs($select);
}
// TODO: Move to module!
public function fetchHardStatesForBpHosts($hosts)
{
return $this->fetchStatesForBp($hosts, 'last_hard_state');
}
public function fetchSoftStatesForBpHosts($hosts)
{
return $this->fetchStatesForBp($hosts, 'current_state');
}
public function fetchStatesForBp($hosts, $state_column = 'last_hard_state')
{
$select_hosts = $this->db->select()->from(
array('hs' => $this->prefix . 'hoststatus'),
array(
'state' => 'hs.' . $state_column,
'ack' => 'hs.problem_has_been_acknowledged',
'in_downtime' => 'CASE WHEN (d.object_id IS NULL) THEN 0 ELSE 1 END',
'combined' => 'hs.current_state << 2 + hs.problem_has_been_acknowledged << 1 + CASE WHEN (d.object_id IS NULL) THEN 0 ELSE 1 END'
)
)->joinRight(
array('o' => $this->prefix . 'objects'),
'hs.host_object_id = o.object_id',
array(
'object_id' => 'o.object_id',
'hostname' => 'o.name1',
'service' => '(NULL)'
)
)->joinLeft(
array('d' => $this->prefix . 'scheduleddowntime'),
'o.object_id = d.object_id'
. ' AND d.was_started = 1'
. ' AND d.scheduled_end_time > NOW()'
. ' AND d.actual_start_time < NOW()',
array()
)->where('o.name1 IN (?)', $hosts)
->where('o.objecttype_id = 1')
->where('o.is_active = 1');
$select_services = $this->db->select()->from(
array('ss' => $this->prefix . 'servicestatus'),
array(
'state' => 'ss.' . $state_column,
'ack' => 'ss.problem_has_been_acknowledged',
'in_downtime' => 'CASE WHEN (d.object_id IS NULL) THEN 0 ELSE 1 END',
'combined' => 'ss.current_state << 2 + ss.problem_has_been_acknowledged << 1 + CASE WHEN (d.object_id IS NULL) THEN 0 ELSE 1 END'
)
)->joinRight(
array('o' => $this->prefix . 'objects'),
'ss.service_object_id = o.object_id',
array(
'object_id' => 'o.object_id',
'hostname' => 'o.name1',
'service' => 'o.name2'
)
)->joinLeft(
array('d' => $this->prefix . 'scheduleddowntime'),
'o.object_id = d.object_id'
. ' AND d.was_started = 1'
. ' AND d.scheduled_end_time > NOW()'
. ' AND d.actual_start_time < NOW()',
array()
)->where('o.name1 IN (?)', $hosts)
->where('o.is_active = 1')
->where('o.objecttype_id = 2');
$union = $this->db->select()->union(
array(
'(' . $select_hosts . ')', // ZF-4338 :-(
'(' . $select_services . ')',
),
// At least on MySQL UNION ALL seems to be faster than UNION in
// most situations, as it doesn't care about duplicates
\Zend_Db_Select::SQL_UNION_ALL
)->order('hostname')->order('service');
return $this->db->fetchAll($union);
}
}

View File

@ -1,191 +0,0 @@
<?php
namespace Icinga\Backend\Ido;
abstract class GroupsummaryQuery extends Query
{
protected $name_alias;
protected $sub_group_column;
protected $sub_query;
protected $sub_count_query;
protected $available_columns = array(
'ok' => 'SUM(CASE WHEN state = 0 THEN 1 ELSE 0 END)',
'critical' => 'SUM(CASE WHEN state = 2 AND downtime = 0 AND ack = 0 THEN 1 ELSE 0 END)',
'critical_dt' => 'SUM(CASE WHEN state = 2 AND downtime = 1 THEN 1 ELSE 0 END)',
'critical_ack' => 'SUM(CASE WHEN state = 2 AND downtime = 0 AND ack = 1 THEN 1 ELSE 0 END)',
'unknown' => 'SUM(CASE WHEN state = 3 AND downtime = 0 AND ack = 0 THEN 1 ELSE 0 END)',
'unknown_dt' => 'SUM(CASE WHEN state = 3 AND downtime = 1 THEN 1 ELSE 0 END)',
'unknown_ack' => 'SUM(CASE WHEN state = 3 AND downtime = 0 AND ack = 1 THEN 1 ELSE 0 END)',
'warning' => 'SUM(CASE WHEN state = 1 AND downtime = 0 AND ack = 0 THEN 1 ELSE 0 END)',
'warning_dt' => 'SUM(CASE WHEN state = 1 AND downtime = 1 THEN 1 ELSE 0 END)',
'warning_ack' => 'SUM(CASE WHEN state = 1 AND downtime = 0 AND ack = 1 THEN 1 ELSE 0 END)',
'last_state_change' => 'UNIX_TIMESTAMP(MAX(last_state_change))',
);
protected $order_columns = array(
'state' => array(
'ASC' => array(
'ok ASC',
'warning_dt ASC',
'warning_ack ASC',
'warning ASC',
'unknown_dt ASC',
'unknown_ack ASC',
'unknown ASC',
'critical_dt ASC',
'critical_ack ASC',
'critical ASC',
),
'DESC' => array(
'critical DESC',
'unknown DESC',
'warning DESC',
'critical_ack DESC',
'critical_dt DESC',
'unknown_ack DESC',
'unknown_dt DESC',
'warning_ack DESC',
'warning_dt DESC',
'ok DESC',
),
'default' => 'DESC'
)
);
abstract protected function addSummaryJoins($query);
protected function init()
{
parent::init();
if ($this->dbtype === 'oracle') {
$this->columns['last_state_change'] = 'localts2unixts(MAX(last_state_change))';
}
}
protected function createQuery()
{
$this->columns[$this->name_alias] = $this->name_alias;
$this->order_columns['state']['ASC'][] = $this->name_alias . ' ASC';
$this->order_columns['state']['DESC'][] = $this->name_alias . ' DESC';
$this->order_columns['name'] = array(
'ASC' => array( $this->name_alias . ' ASC'),
'DESC' => array( $this->name_alias . ' DESC'),
'default' => 'ASC'
);
$sub_query = $this->createSubQuery();
// $sub_query->group($this->sub_group_column);
// $sub_query->columns(array($this->name_alias => 'MAX(' . $this->sub_group_column . ')'));
$sub_query->columns(array($this->name_alias => $this->sub_group_column ));
$this->addSummaryJoins($sub_query);
$query = $this->db->select()->from(
array('sub' => $sub_query),
array()
);
$query->group($this->name_alias);
$this->sub_query = $sub_query;
return $query;
}
protected function createCountQuery()
{
$this->sub_count_query = $this->createCountSubQuery();
$this->sub_count_query->group($this->sub_group_column);
$this->addSummaryJoins($this->sub_count_query);
$count = $this->db->select()->from(
array('cnt' => $this->sub_count_query),
array()
);
return $count;
}
protected function createSubQuery()
{
$query = $this->db->select()
->from(
array('so' => $this->prefix . 'objects'),
array(
// MAX seems to be useless, but is required as of the GROUP below
// 'state' => 'MAX(ss.current_state)',
'state' => 'ss.current_state',
// 'ack' => 'MAX(ss.problem_has_been_acknowledged)',
'ack' => 'ss.problem_has_been_acknowledged',
// 'downtime' => 'MAX(CASE WHEN (dt.object_id IS NULL) THEN 0 ELSE 1 END)',
// 'downtime' => 'MAX(CASE WHEN (scheduled_downtime_depth = 0) THEN 0 ELSE 1 END)',
'downtime' => 'CASE WHEN (scheduled_downtime_depth = 0) THEN 0 ELSE 1 END',
// 'last_state_change' => 'MAX(ss.last_state_change)',
'last_state_change' => 'ss.last_state_change',
)
)->joinLeft(
array('ss' => $this->prefix . 'servicestatus'),
"so.$this->object_id = ss.service_object_id",
array()
)->join(
array('s' => $this->prefix . 'services'),
's.service_object_id = ss.service_object_id',
array()
)/*->joinLeft(
array('dt' => $this->prefix . 'scheduleddowntime'),
"so.$this->object_id = dt.object_id"
. ' AND dt.is_in_effect = 1',
array()
)->joinLeft(
array('co' => $this->prefix . 'comments'),
"so.$this->object_id = co.object_id",
array()
)*/
->where('so.is_active = 1')
->where('so.objecttype_id = 2')
// Group is required as there could be multiple comments:
// ->group('so.' . $this->object_id)
;
return $query;
}
protected function createCountSubQuery()
{
return $this->db->select()
->from(
array('so' => $this->prefix . 'objects'),
array('state' => 'MAX(ss.current_state)')
)->joinLeft(
array('ss' => $this->prefix . 'servicestatus'),
"so.$this->object_id = ss.service_object_id",
array()
)->join(
array('s' => $this->prefix . 'services'),
's.service_object_id = ss.service_object_id',
array()
);
}
public function where($column, $value = null)
{
if ($column === 'problems') {
if ($value === 'true') {
$this->query->having('(SUM(CASE WHEN state = 2 AND downtime = 0 AND ack = 0 THEN 1 ELSE 0 END) +
SUM(CASE WHEN state = 2 AND downtime = 1 THEN 1 ELSE 0 END) +
SUM(CASE WHEN state = 2 AND downtime = 0 AND ack = 1 THEN 1 ELSE 0 END) +
SUM(CASE WHEN state = 3 AND downtime = 0 AND ack = 0 THEN 1 ELSE 0 END) +
SUM(CASE WHEN state = 3 AND downtime = 1 THEN 1 ELSE 0 END) +
SUM(CASE WHEN state = 3 AND downtime = 0 AND ack = 1 THEN 1 ELSE 0 END) +
SUM(CASE WHEN state = 1 AND downtime = 0 AND ack = 0 THEN 1 ELSE 0 END) +
SUM(CASE WHEN state = 1 AND downtime = 1 THEN 1 ELSE 0 END) +
SUM(CASE WHEN state = 1 AND downtime = 0 AND ack = 1 THEN 1 ELSE 0 END)) > 0');
$this->sub_count_query->where('ss.current_state > 0');
$this->sub_query->where('ss.current_state > 0');
}
} elseif ($column === 'search') {
if ($value) {
// $this->sub_query->where($this->name_alias . ' LIKE ?', '%' . $value . '%');
$this->sub_query->where($this->sub_group_column . ' LIKE ?', '%' . $value . '%');
$this->sub_count_query->where($this->sub_group_column . ' LIKE ?', '%' . $value . '%');
}
} else {
parent::where($column, $value);
}
return $this;
}
}

View File

@ -1,14 +0,0 @@
<?php
namespace Icinga\Backend\Ido;
class HostgroupsummaryQuery extends GroupsummaryQuery
{
protected $name_alias = 'hostgroup_name';
protected $sub_group_column = 'hg.alias';
protected function addSummaryJoins($query)
{
$this->joinServiceHostgroups($query);
}
}

View File

@ -1,521 +0,0 @@
<?php
namespace Icinga\Backend\Ido;
abstract class Query extends \Icinga\Backend\Query
{
protected $db;
protected $prefix;
protected $query;
protected $count_query;
protected $count_columns;
protected $ordered = false;
protected $finalized = false;
protected $object_id = 'object_id';
protected $hostgroup_id = 'hostgroup_id';
protected $servicegroup_id = 'servicegroup_id';
protected $custom_cols = array();
/**
* Available sort combinations
*/
protected $order_columns = array(
'host' => array(
'ASC' => array(
'host_name ASC',
'service_description ASC'
),
'DESC' => array(
'host_name DESC',
'service_description ASC'
),
'default' => 'ASC'
),
'host_address' => array(
'ASC' => array(
'host_ipv4 ASC',
'service_description ASC'
),
'DESC' => array(
'host_ipv4 ASC',
'service_description ASC'
),
'default' => 'ASC'
),
'service' => array(
'ASC' => array(
'service_description ASC'
),
'DESC' => array(
'service_description DESC'
),
'default' => 'ASC'
),
'service_state_change' => array(
'ASC' => array(
'ss.last_state_change ASC'
),
'DESC' => array(
'ss.last_state_change DESC'
),
'default' => 'DESC'
),
'service_state' => array(
'ASC' => array(
'CASE WHEN (ss.current_state = 3) THEN 2 WHEN (ss.current_state = 2) THEN 3 ELSE ss.current_state END DESC', // TODO: distinct severity in a better way
'ss.problem_has_been_acknowledged ASC',
// 'CASE WHEN (ss.scheduled_downtime_depth = 0) THEN 0 ELSE 1 END ASC',
'service_in_downtime ASC', // TODO: Check if all dbs allow sorting by alias
'ss.last_state_change DESC',
'so.name1 ASC',
'so.name2 ASC'
),
'DESC' => array(
'CASE WHEN (ss.current_state = 3) THEN 2 WHEN (ss.current_state = 2) THEN 3 ELSE ss.current_state END ASC',
'ss.problem_has_been_acknowledged ASC',
// 'CASE WHEN (ss.scheduled_downtime_depth = 0) THEN 0 ELSE 1 END ASC',
'service_in_downtime ASC',
'ss.last_state_change DESC'
),
'default' => 'ASC'
)
);
abstract protected function createQuery();
public function dump()
{
$this->finalize();
return "QUERY\n=====\n"
. $this->query
. "\n\nCOUNT\n=====\n"
. $this->count_query
. "\n\n";
}
public function getCountQueryObject()
{
return $this->finalize()->count_query;
}
public function getQueryObject()
{
return $this->finalize()->query;
}
protected function createCountQuery()
{
return clone($this->query);
}
protected function init()
{
$this->db = $this->backend->getAdapter();
$this->dbtype = $this->backend->getDbType();
if ($this->dbtype === 'oracle') {
$this->object_id = $this->hostgroup_id = $this->servicegroup_id = 'id';
}
$this->prefix = $this->backend->getPrefix();
$this->query = $this->createQuery();
$this->count_query = $this->createCountQuery();
}
protected function finalize()
{
if ($this->finalized) return $this;
$this->finalized = true;
$this->query->columns($this->columns);
if ($this->count_columns === null) {
$this->count_columns = array('cnt' => 'COUNT(*)');
}
if (! $this->ordered) {
$this->order();
}
$this->count_query->columns($this->count_columns);
return $this;
}
protected function prepareServiceStatesQuery()
{
$query = $this->db->select()
->from(
array('hs' => $this->prefix . 'hoststatus'),
array()
)->join(
array('h' => $this->prefix . 'hosts'),
'hs.host_object_id = h.host_object_id',
array()
)->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()
);
// $this->joinServiceDowntimes($query);
// $query->group('so.object_id');
return $query;
}
protected function prepareServicesCount()
{
// TODO: Depends on filter, some cols could be avoided
$query = $this->db->select()->from(
array('hs' => $this->prefix . 'hoststatus'),
array()
)->join(
array('h' => $this->prefix . 'hosts'),
'hs.host_object_id = h.host_object_id',
array()
)->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",
"COUNT(so.$this->object_id)"
)->joinLeft(
array('ss' => $this->prefix . 'servicestatus'),
"so.$this->object_id = ss.service_object_id",
array()
);
// $this->joinServiceDowntimes($query);
return $query;
}
protected function joinHostgroups($query = null)
{
if ($query === null) $query = $this->query;
$query->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($query)
{
if ($query === null) $query = $this->query;
$query->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()
);
return $this;
}
protected function joinServicegroups($query)
{
if ($query === null) $query = $this->query;
$query->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()
);
return $this;
}
protected function joinServiceDowntimes($query)
{
$query->joinLeft(
array('dt' => $this->prefix . 'scheduleddowntime'),
"so.$this->object_id = dt.object_id"
. ' AND dt.is_in_effect = 1',
array()
);
// NDO compat (doesn't work correctly like this):
// $now = "'" . date('Y-m-d H:i:s') . "'";
// . ' AND dt.was_started = 1'
// . ' AND dt.scheduled_end_time > ' . $now
// . ' AND dt.actual_start_time < ' . $now,
return $query;
}
public function where($column, $value = null)
{
// Ugly temporary hack:
foreach (array($this->query, $this->count_query) as $query) {
if ($column === 'search') {
if ($this->dbtype === 'mysql') {
$query->where($this->db->quoteInto(
'so.name2 COLLATE latin1_general_ci LIKE ?'
. ' OR so.name1 COLLATE latin1_general_ci LIKE ?',
'%' . $value . '%',
'%' . $value . '%'
));
} else {
$query->where($this->db->quoteInto(
'LOWER(so.name2) LIKE ?'
. ' OR LOWER(so.name1) LIKE ?',
'%' . strtolower($value) . '%',
'%' . strtolower($value) . '%'
));
}
continue;
}
// TODO: Check if this also works based on column:
if ($column === 'hostgroups') {
$this->appendHostgroupLimit($query, $value);
continue;
}
if (preg_match('~^_([^_]+)_(.+)$~', $column, $m)) {
switch($m[1]) {
case 'host':
$this->appendHostCustomVarLimit($query, $m[2], $value);
break;
case 'service':
$this->appendServiceCustomVarLimit($query, $m[2], $value);
break;
}
continue;
}
//$column = preg_replace('~^current_state~', 'ss.current_state', $column);
if (array_key_exists($column, $this->available_columns)) {
$column = $this->available_columns[$column];
}
$query->where($this->prepareFilterStringForColumn($column, $value));
}
/*->orWhere('last_state_change > ?', $new)*/
return $this;
}
public function order($column = '', $dir = null)
{
$this->ordered = true;
return $this->applyOrder($column, $dir);
}
protected function applyOrder($order = '', $order_dir = null)
{
if (! array_key_exists($order, $this->order_columns)) {
$order = key($this->order_columns);
}
if ($order_dir === null) {
$order_dir = $this->order_columns[$order]['default'];
}
foreach ($this->order_columns[$order][$order_dir] as $col) {
$this->query->order($col);
}
return $this;
}
protected function addServiceComments($query = null)
{
if ($query === null) {
$query = $this->query;
}
$query->joinLeft(
array('co' => $this->prefix . 'comments'),
"so.$this->object_id = co.object_id",
array()
)
->group('so.object_id')
;
return $this;
}
/**
* $column = col
* $value = abc,cde,cd*,!egh,!*hh*
* -> (col IN ('abc', 'cde') OR col LIKE 'cd%') AND (col != 'egh' AND col NOT LIKE '%hh%')
*/
protected function prepareFilterStringForColumn($column, $value)
{
$filter = '';
$filters = array();
$or = array();
$and = array();
if (strpos($value, ',') !== false) {
$value = preg_split('~,~', $value, -1, PREG_SPLIT_NO_EMPTY);
}
if (! is_array($value)) {
$value = array($value);
}
// Go through all given values
foreach ($value as $val) {
// Value starting with - means negation
if ($val[0] === '-') {
$val = substr($val, 1);
if (strpos($val, '*') === false) {
$and[] = $this->db->quoteInto($column . ' != ?', $val);
} else {
$and[] = $this->db->quoteInto(
$column . ' NOT LIKE ?',
str_replace('*', '%', $val)
);
}
// Starting with + enforces AND
} elseif ($val[0] === '+') {
$val = substr($val, 1);
if (strpos($val, '*') === false) {
$and[] = $this->db->quoteInto($column . ' = ?', $val);
} else {
$and[] = $this->db->quoteInto(
$column . ' LIKE ?',
str_replace('*', '%', $val)
);
}
// All others ar ORs:
} else {
if (strpos($val, '*') === false) {
$or[] = $this->db->quoteInto($column . ' = ?', $val);
} else {
$or[] = $this->db->quoteInto(
$column . ' LIKE ?',
str_replace('*', '%', $val)
);
}
}
}
if (! empty($or)) { $filters[] = implode(' OR ', $or); }
if (! empty($and)) { $filters[] = implode(' AND ', $and); }
if (! empty($filters)) {
$filter = '(' . implode(') AND (', $filters) . ')';
}
return $filter;
}
protected function addCustomVarColumn($query, $alias, $name, $filter = null)
{
// TODO: Improve this:
if (! preg_match('~^[a-zA-Z0-9_]+$~', $name)) {
throw new \Exception(sprintf(
'Got invalid custom var: "%s"',
$name
));
}
$qobj = spl_object_hash($query);
if (! array_key_exists($qobj, $this->custom_cols)) {
$this->custom_cols[$qobj] = array();
}
if (array_key_exists($alias, $this->custom_cols[$qobj])) {
if ($name !== $this->custom_cols[$qobj][$alias]) {
throw new \Exception(sprintf(
'Cannot add CV alias "%s" twice with different target',
$alias
));
}
return $this;
}
$query->join(
// TODO: Allow multiple limits with different aliases
array($alias => $this->prefix . 'customvariablestatus'),
's.host_object_id = ' . $alias . '.object_id'
. ' AND ' . $alias . '.varname = '
. $this->db->quote(strtoupper($name))
//. ($filter === null ? '' : ' AND ' . $filter),
,
array()
);
$this->custom_cols[$qobj][$alias] = $name;
return $this;
}
protected function appendHostCustomVarLimit($query, $key, $value)
{
$alias = 'hcv_' . strtolower($key);
$filter = $this->prepareFilterStringForColumn($alias . '.varvalue', $value);
$this->addCustomVarColumn($query, $alias, $key);
$query->where($filter);
return $query;
}
protected function appendHostgroupLimit($query, $hostgroups)
{
return $query->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()
)
->where('hg.alias IN (?)', $hostgroups);
}
public function count()
{
return $this->db->fetchOne(
$this->finalize()->count_query
);
}
public function fetchAll()
{
return $this->db->fetchAll($this->finalize()->query);
}
public function fetchRow()
{
return $this->db->fetchRow($this->finalize()->query);
}
public function fetchOne()
{
return $this->db->fetchOne($this->finalize()->query);
}
public function fetchPairs()
{
return $this->db->fetchPairs($this->finalize()->query);
}
/**
* Sets a limit count and offset to the query
*
* @param int $count Number of rows to return
* @param int $offset Row offset to start from
* @return \Icinga\Backend\Query This Query object
*/
public function limit($count = null, $offset = null)
{
$this->query->limit($count, $offset);
return $this;
}
public function __toString()
{
$this->finalize();
return (string) $this->query;
}
}

View File

@ -1,14 +0,0 @@
<?php
namespace Icinga\Backend\Ido;
class ServicegroupsummaryQuery extends GroupsummaryQuery
{
protected $name_alias = 'servicegroup_name';
protected $sub_group_column = 'sg.alias';
protected function addSummaryJoins($query)
{
$this->joinServicegroups($query);
}
}

View File

@ -1,95 +0,0 @@
<?php
namespace Icinga\Backend\Ido;
class ServicelistQuery extends Query
{
protected $available_columns = array(
// Host config
'host_name' => 'so.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 state
'host_state' => 'hs.current_state',
'host_output' => 'hs.output',
'host_perfdata' => 'hs.perfdata',
'host_acknowledged' => 'hs.problem_has_been_acknowledged',
'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)',
// Service config
'service_description' => 'so.name2',
'service_display_name' => 's.display_name',
// Service state
'current_state' => 'ss.current_state',
'service_state' => 'ss.current_state',
'service_output' => 'ss.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 > 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 comments
//'service_downtimes_with_info' => "IF(dt.object_id IS NULL, NULL, GROUP_CONCAT(CONCAT('[', dt.author_name, '] ', dt.comment_data) ORDER BY dt.entry_time DESC SEPARATOR '|'))",
//'service_comments_with_info' => "IF(co.object_id IS NULL, NULL, GROUP_CONCAT(CONCAT('[', co.author_name, '] ', co.comment_data) ORDER BY co.entry_time DESC SEPARATOR '|'))",
// SLA Example:
// 'sla' => "icinga_availability(so.object_id,"
// . " '2012-12-01 00:00:00', '2012-12-31 23:59:59')",
);
protected function init()
{
parent::init();
if ($this->dbtype === 'oracle') {
$this->columns['host_last_state_change'] =
'localts2unixts(ss.last_state_change)';
$this->columns['service_last_state_change'] =
'localts2unixts(ss.last_state_change)';
}
}
public function where($column, $value = null)
{
// Ugly temporary hack:
if ($column === 'problems') {
if ($value === true || $value === 'true') {
parent::where('current_state', '-0');
} elseif ($value === false || $value === 'false') {
parent::where('current_state', '0');
}
return $this;
}
if ($column === 'handled') $column = 'service_handled';
parent::where($column, $value);
return $this;
}
protected function createQuery()
{
$query = $this->prepareServiceStatesQuery();
if ($this->dbtype === 'mysql') {
// $this->addServiceComments($query);
} else {
$this->columns['host_ipv4'] = 'h.address';
$this->columns['service_downtimes_with_info'] = '(NULL)';
$this->columns['service_comments_with_info'] = '(NULL)';
}
return $query;
}
protected function createCountQuery()
{
return $this->prepareServicesCount();
}
}

View File

@ -1,86 +0,0 @@
<?php
namespace Icinga\Backend\Ido;
class StatehistoryQuery extends Query
{
protected $available_columns = array(
// Host config
'host_name' => 'sho.name1',
'service_description' => 'sho.name2',
'object_type' => "CASE WHEN sho.objecttype_id = 1 THEN 'host' ELSE 'service' END",
'timestamp' => 'UNIX_TIMESTAMP(sh.state_time)',
'state' => 'sh.state',
'last_state' => 'sh.last_state',
'last_hard_state' => 'sh.last_hard_state',
'attempt' => 'sh.current_check_attempt',
'max_attempts' => 'sh.max_check_attempts',
'output' => 'sh.output', // no long_output in browse
);
protected $order_columns = array(
'timestamp' => array(
'ASC' => array(
'state_time ASC',
),
'DESC' => array(
'state_time DESC',
),
'default' => 'DESC'
)
);
protected function init()
{
parent::init();
if ($this->dbtype === 'oracle') {
$this->columns['timestamp'] =
'localts2unixts(sh.state_time)';
}
}
public function where($column, $value = null)
{
if ($column === 'problems') {
if ($value === 'true') {
foreach (array($this->query, $this->count_query) as $query) {
$query->where('sh.state > 0');
}
}
return $this;
}
if ($column === 'host') {
foreach (array($this->query, $this->count_query) as $query) {
$query->where('sho.name1 = ?', $value);
}
return $this;
}
if ($column === 'service') {
foreach (array($this->query, $this->count_query) as $query) {
$query->where('sho.name2 = ?', $value);
}
return $this;
}
parent::where($column, $value);
return $this;
}
protected function createQuery()
{
$query = $this->db->select()->from(
array('sh' => $this->prefix . 'statehistory'),
array()
// )->join(
)->joinLeft( // LEFT is bullshit but greatly helps MySQL
// Problem -> has to be INNER once permissions are in effect
// Therefore this should probably be "flexible" or handled in another
// way
array('sho' => $this->prefix . 'objects'),
'sho.' . $this->object_id . ' = sh.object_id AND sho.is_active = 1',
array()
);
return $query;
}
}

View File

@ -1,45 +0,0 @@
<?php
/**
* Icinga Livestatus Backend
*
* @package Icinga\Backend
*/
namespace Icinga\Backend;
use Icinga\Protocol\Livestatus\Connection;
/**
* This class provides an easy-to-use interface to the Livestatus socket library
*
* You should usually not directly use this class but go through Icinga\Backend.
*
* @copyright Copyright (c) 2013 Icinga-Web Team <info@icinga.org>
* @author Icinga-Web Team <info@icinga.org>
* @package Icinga\Application
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
*/
class Livestatus extends AbstractBackend
{
protected $connection;
/**
* Backend initialization starts here
*
* return void
*/
protected function init()
{
$this->connection = new Connection($this->config->socket);
}
/**
* Get our Livestatus connection
*
* return \Icinga\Protocol\Livestatus\Connection
*/
public function getConnection()
{
return $this->connection;
}
}

View File

@ -1,213 +0,0 @@
<?php
namespace Icinga\Backend\Livestatus;
abstract class Query extends \Icinga\Backend\Query
{
protected $connection;
protected $query;
protected $ordered = false;
protected $finalized = false;
/**
* Available sort combinations
*/
protected $order_columns = array(
'host' => array(
'ASC' => array(
'host_name ASC',
'service_description ASC'
),
'DESC' => array(
'host_name DESC',
'service_description ASC'
),
'default' => 'ASC'
),
'host_address' => array(
'ASC' => array(
'host_ipv4 ASC',
'service_description ASC'
),
'DESC' => array(
'host_ipv4 ASC',
'service_description ASC'
),
'default' => 'ASC'
),
'service' => array(
'ASC' => array(
'service_description ASC'
),
'DESC' => array(
'service_description DESC'
),
'default' => 'ASC'
),
'service_state_change' => array(
'ASC' => array(
'ss.last_state_change ASC'
),
'DESC' => array(
'ss.last_state_change DESC'
),
'default' => 'DESC'
),
'service_state' => array(
'ASC' => array(
'IF (ss.current_state = 3, 2, IF(ss.current_state = 2, 3, ss.current_state)) DESC',
'ss.problem_has_been_acknowledged ASC',
'IF(dt.object_id IS NULL, 0, 1) ASC',
'ss.last_state_change DESC'
),
'DESC' => array(
'IF (ss.current_state = 3, 2, IF(ss.current_state = 3, 2, ss.current_state)) DESC',
'ss.problem_has_been_acknowledged ASC',
'IF(dt.object_id IS NULL, 0, 1) ASC',
'ss.last_state_change DESC'
),
'default' => 'ASC'
)
);
abstract protected function createQuery();
protected function init()
{
$this->connection = $this->backend->getConnection();
$this->query = $this->createQuery();
}
public function where($column, $value = null)
{
if ($column === 'problems') {
if ($value === 'true') {
$this->query->where('state > 0');
} elseif ($value === 'false') {
$this->query->where('state = 0');
}
return $this;
}
if ($column === 'handled') {
if ($value === 'true') {
// TODO: Not yet
} elseif ($value === 'false') {
// TODO: Not yet
}
return $this;
}
// Ugly temporary hack:
$colcheck = preg_replace('~[\s=><].+$~', '', $column);
if (array_key_exists($colcheck, $this->available_columns)) {
$query->where(preg_replace(
'~' . $colcheck . '~',
$this->available_columns[$colcheck],
$column
), $value);
} else {
$this->query->where($column, $value);
}
return $this;
}
protected function finalize()
{
return $this;
if ($this->finalized) return $this;
$this->finalized = true;
$this->query->columns($this->columns);
if ($this->count_columns === null) {
$this->count_columns = array('cnt' => 'COUNT(*)');
}
if (! $this->ordered) {
$this->order();
}
$this->count_query->columns($this->count_columns);
return $this;
}
public function applyFilters($filters = array())
{
foreach ($filters as $key => $val) {
$this->where($key, $val);
}
return $this;
}
public function order($column = '', $dir = null)
{
$this->ordered = true;
return $this->applyOrder($column, $dir);
}
protected function applyOrder($order = '', $order_dir = null)
{
return $this;
if (! array_key_exists($order, $this->order_columns)) {
$order = key($this->order_columns);
}
if ($order_dir === null) {
$order_dir = $this->order_columns[$order]['default'];
}
foreach ($this->order_columns[$order][$order_dir] as $col) {
$this->query->order($col);
}
return $this;
}
public function count()
{
return $this->connection->count(
$this->finalize()->query
);
}
public function fetchAll()
{
return $this->connection->fetchAll($this->finalize()->query);
}
public function fetchRow()
{
return $this->db->fetchRow($this->finalize()->query);
}
public function fetchOne()
{
return $this->db->fetchOne($this->finalize()->query);
}
public function fetchPairs()
{
return $this->db->fetchPairs($this->finalize()->query);
}
/**
* Sets a limit count and offset to the query
*
* @param int $count Number of rows to return
* @param int $offset Row offset to start from
* @return \Icinga\Backend\Query This Query object
*/
public function limit($count = null, $offset = null)
{
$this->query->limit($count, $offset);
return $this;
}
// For debugging and testing only:
public function __toString()
{
$this->finalize();
return (string) $this->query;
}
}

View File

@ -1,46 +0,0 @@
<?php
namespace Icinga\Backend\Livestatus;
class ServicelistQuery extends Query
{
protected $available_columns = array(
'host_name',
'host_display_name',
'host_alias',
'host_address',
'host_ipv4' => 'host_address', // TODO
'host_icon_image',
// Host state
'host_state',
'host_output' => 'host_plugin_output',
'host_perfdata' => 'host_perf_data',
'host_acknowledged',
'host_does_active_checks' => 'host_active_checks_enabled',
'host_accepts_passive_checks' => 'host_accept_passive_checks',
'host_last_state_change',
// Service config
'service_description' => 'description',
'service_display_name' => 'display_name',
// Service state
'service_state' => 'state',
'service_output' => 'plugin_output',
'service_perfdata' => 'perf_data',
'service_acknowledged' => 'acknowledged',
'service_does_active_checks' => 'active_checks_enabled',
'service_accepts_passive_checks' => 'accept_passive_checks',
'service_last_state_change' => 'last_state_change',
// Service comments
'comments_with_info',
'downtimes_with_info',
);
protected function createQuery()
{
return $this->connection->select()->from('services', $this->available_columns);
}
}

View File

@ -1,110 +0,0 @@
<?php
namespace Icinga\Backend;
/**
* Wrapper around an array of monitoring objects that can be enhanced with an optional
* object that extends AbstractAccessorStrategy. This will act as a dataview and provide
* normalized access to the underlying data (mapping properties, retrieving additional data)
*
* If not Accessor is set, this class just behaves like a normal Iterator and returns
* the underlying objects.
*
* If the dataset contains arrays instead of objects, they will be cast to objects.
*
*/
use Icinga\Backend\DataView as DataView;
class MonitoringObjectList implements \Iterator, \Countable
{
private $dataSet = array();
private $position = 0;
private $dataView = null;
function __construct(array &$dataset, DataView\AbstractAccessorStrategy $dataView = null)
{
$this->dataSet = $dataset;
$this->position = 0;
$this->dataView = $dataView;
}
public function count()
{
return count($this->dataSet);
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Return the current element
* @link http://php.net/manual/en/iterator.current.php
* @return mixed Can return any type.
*/
public function current()
{
if ($this->dataView)
return $this;
return $this->dataSet[$this->position];
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Move forward to next element
* @link http://php.net/manual/en/iterator.next.php
* @return void Any returned value is ignored.
*/
public function next()
{
$this->position++;
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Return the key of the current element
* @link http://php.net/manual/en/iterator.key.php
* @return mixed scalar on success, or null on failure.
*/
public function key()
{
return $this->position;
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Checks if current position is valid
* @link http://php.net/manual/en/iterator.valid.php
* @return boolean The return value will be casted to boolean and then evaluated.
* Returns true on success or false on failure.
*/
public function valid()
{
return $this->position < count($this->dataSet);
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Rewind the Iterator to the first element
* @link http://php.net/manual/en/iterator.rewind.php
* @return void Any returned value is ignored.
*/
public function rewind()
{
$this->position = 0;
}
public function __isset($name)
{
return $this->dataView->exists($this->dataSet[$this->position],$name);
}
function __get($name)
{
return $this->dataView->get($this->dataSet[$this->position],$name);
}
function __set($name, $value)
{
throw new \Exception("Setting is currently not available for objects");
}
}

View File

@ -1,165 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
/**
* This file is part of Icinga 2 Web.
*
* Icinga 2 Web - Head for multiple monitoring backends.
* 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>
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
* @author Icinga Development Team <info@icinga.org>
*/
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Backend;
use Icinga\Web\Paginator\Adapter\QueryAdapter;
/**
* Class Query
* @package Icinga\Backend
*/
abstract class Query
{
/**
* @var AbstractBackend
*/
protected $backend;
/**
* @var array
*/
protected $columns = array();
/**
* @var array
*/
protected $available_columns = array();
/**
* @param null $count
* @param null $offset
* @return mixed
*/
abstract public function limit($count = null, $offset = null);
/**
* @param $column
* @param null $value
* @return mixed
*/
abstract public function where($column, $value = null);
/**
* @param string $column
* @param null $dir
* @return mixed
*/
abstract public function order($column = '', $dir = null);
/**
* @return mixed
*/
abstract public function fetchAll();
/**
* @return mixed
*/
abstract public function fetchRow();
/**
* @return mixed
*/
abstract public function fetchPairs();
/**
* @return mixed
*/
abstract public function fetchOne();
/**
* @return mixed
*/
abstract public function count();
/**
* @param AbstractBackend $backend
* @param array $columns
* @return \Icinga\Backend\Query
*/
public function __construct(AbstractBackend $backend, $columns = array())
{
$this->backend = $backend;
if (empty($columns) || $columns === '*') {
$this->columns = $this->available_columns;
} else {
$this->columns = $columns;
}
$this->init();
}
/**
* @param array $filters
* @return $this
*/
public function applyFilters($filters = array())
{
foreach ($filters as $key => $val) {
$this->where($key, $val);
}
return $this;
}
/**
* @return mixed
*/
abstract protected function init();
/*
*
*/
protected function finalize()
{
}
/**
* Return a pagination adapter for the current query
*
* @param null $limit
* @param null $page
* @return \Zend_Paginator
*/
public function paginate($limit = null, $page = null)
{
$this->finalize();
$request = \Zend_Controller_Front::getInstance()->getRequest();
if ($page === null) {
$page = $request->getParam('page', 0);
}
if ($limit === null) {
$limit = $request->getParam('limit', 20);
}
$paginator = new \Zend_Paginator(
new QueryAdapter($this)
);
$paginator->setItemCountPerPage($limit);
$paginator->setCurrentPageNumber($page);
return $paginator;
}
}

View File

@ -1,97 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
/**
* This file is part of Icinga 2 Web.
*
* Icinga 2 Web - Head for multiple monitoring backends.
* 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>
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
* @author Icinga Development Team <info@icinga.org>
*/
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Backend\Statusdat\DataView;
use Icinga\Backend\DataView\ObjectRemappingView;
use \Icinga\Protocol\Statusdat\IReader;
/**
* Class StatusdatHostView
* @package Icinga\Backend\Statusdat\DataView
*/
class StatusdatHostView extends ObjectRemappingView
{
/**
* @var mixed
*/
private $state;
/**
* @var array
*/
protected $handlerParameters = array(
"host" => "getHost",
"downtimes_with_info" => "getDowntimes",
"comments_with_info" => "getComments"
);
/**
* @var array
*/
protected $mappedParameters = array(
"host_address" => "host_name",
"host_name" => "host_name",
"host_state" => "status.current_state",
"host_output" => "status.plugin_output",
"host_perfdata" => "status.long_plugin_output",
"host_last_state_change" => "status.last_state_change",
"host_check_command" => "check_command",
"host_last_check" => "status.last_check",
"host_next_check" => "status.next_check",
"host_check_latency" => "status.check_latency",
"host_check_execution_time" => "status.check_execution_time",
"active_checks_enabled" => "status.active_checks_enabled",
"acknowledged" => "status.problem_has_been_acknowledged",
"host_acknowledged" => "status.problem_has_been_acknowledged",
// "state" => "current_state"
);
/**
* @param $item
* @return null
*/
public function getHost(&$item)
{
if (!isset($this->state["host"][$item->host_name])) {
return null;
}
if (!isset($this->state["host"][$item->host_name])) {
return null;
}
return $this->state["host"][$item->host_name];
}
/**
* @param IReader $reader
*/
public function __construct(IReader $reader)
{
$this->state = & $reader->getState();
}
}

View File

@ -324,7 +324,7 @@ class StatusQuery extends AbstractQuery
$this->baseQuery->joinleft(
array ('sps' => new \Zend_Db_Expr(
'(SELECT COUNT(s.service_object_id) as unhandled_service_count, s.host_object_id as host_object_id '.
'FROM icinga_services s INNER JOIN icinga_servicestatus ss ON '.
'FROM icinga_services s INNER JOIN icinga_servicestatus ss ON ss.current_state != 0 AND '.
'ss.problem_has_been_acknowledged = 0 AND ss.scheduled_downtime_depth = 0 AND '.
'ss.service_object_id = s.service_object_id '.
'GROUP BY s.host_object_id'.

View File

@ -26,10 +26,9 @@
*/
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Backend;
namespace Monitoring\Backend;
use Icinga\Backend\Statusdat\DataView\StatusdatHostView;
use Icinga\Backend\Statusdat\DataView\StatusdatServiceView;
use Icinga\Protocol\Statusdat as StatusdatProtocol;
/**

View File

@ -1,6 +1,6 @@
<?php
namespace Icinga\Backend\Criteria;
namespace Monitoring\Backend\Statusdat\Criteria;
/**
* Constants for filter definitions.

View File

@ -26,7 +26,7 @@
*/
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Backend\Criteria;
namespace Monitoring\Backend\Statusdat\Criteria;
/**
* Class Order

View File

@ -0,0 +1,133 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
/**
* This file is part of Icinga 2 Web.
*
* Icinga 2 Web - Head for multiple monitoring backends.
* 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>
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
* @author Icinga Development Team <info@icinga.org>
*/
// {{{ICINGA_LICENSE_HEADER}}}
namespace Monitoring\Backend\Statusdat\DataView;
use Icinga\Protocol\Statusdat\View\ObjectRemappingView;
use Icinga\Protocol\Statusdat\IReader;
/**
* Class StatusdatHostView
* @package Icinga\Backend\Statusdat\DataView
*/
class StatusdatHostView extends ObjectRemappingView
{
/**
* @var mixed
*/
private $state;
/**
* @var array
*/
protected $handlerParameters = array(
"host" => "getHost",
"host_unhandled_service_count" => "getNrOfUnhandledServices",
"host_last_comment" => "getLastComment",
'host_handled' => "checkIfHandled"
);
public function checkIfHandled(&$host)
{
return $host->status->current_state == 0 ||
$host->status->problem_has_been_acknowledged ||
$host->status->scheduled_downtime_depth;
}
public function getNrOfUnhandledServices(&$host)
{
$ct = 0;
foreach ($host->services as &$service) {
if ($service->status->current_state > 0
&& $service->status->problem_has_been_acknowledged == 0
&& $service->status->scheduled_downtime_depth == 0) {
$ct++;
}
}
return $ct;
}
public function getLastComment(&$host)
{
if (!isset($host->comment) || empty($host->comment)) {
return null;
}
$comment = end($host->comment);
return $comment->comment_id;
}
/**
* @var array
*/
protected $mappedParameters = array(
"host_address" => "address",
"host_name" => "host_name",
"host_state" => "status.current_state",
"host_output" => "status.plugin_output",
"host_long_output" => "status.long_plugin_output",
"host_perfdata" => "status.pluign",
"host_last_state_change" => "status.last_state_change",
"host_check_command" => "check_command",
"host_last_check" => "TO_DATE(status.last_check)",
"host_next_check" => "status.next_check",
"host_check_latency" => "status.check_latency",
"host_check_execution_time" => "status.check_execution_time",
"active_checks_enabled" => "status.active_checks_enabled",
"host_in_downtime" => "status.scheduled_downtime_depth",
"host_is_flapping" => "status.is_flapping",
"host_notifications_enabled"=> "status.notifications_enabled",
"host_state_type" => "status.state_type",
"host_icon_image" => "icon_image",
"host_action_url" => "action_url",
"host_notes_url" => "notes_url",
"host_acknowledged" => "status.problem_has_been_acknowledged",
// "state" => "current_state"
);
/**
* @param $item
* @return null
*/
public function getHost(&$item)
{
if (!isset($this->state["host"][$item->host_name])) {
return null;
}
if (!isset($this->state["host"][$item->host_name])) {
return null;
}
return $this->state["host"][$item->host_name];
}
/**
* @param IReader $reader
*/
public function __construct(IReader $reader)
{
$this->state = & $reader->getState();
}
}

View File

@ -26,9 +26,9 @@
*/
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Backend\Statusdat\DataView;
namespace Monitoring\Backend\Statusdat\DataView;
use Icinga\Backend\DataView\ObjectRemappingView;
use Icinga\Protocol\Statusdat\View\ObjectRemappingView;
use \Icinga\Protocol\Statusdat\IReader;
class StatusdatServiceView extends ObjectRemappingView

View File

@ -26,7 +26,7 @@
*/
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Backend\Statusdat;
namespace Monitoring\Backend\Statusdat\Query;
abstract class GroupsummaryQuery extends Query
{

View File

@ -26,7 +26,7 @@
*/
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Backend\Statusdat;
namespace Monitoring\Backend\Statusdat\Query;
/**
* Class HostgroupsummaryQuery

View File

@ -26,7 +26,7 @@
*/
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Backend\Statusdat;
namespace Monitoring\Backend\Statusdat\Query;
use Icinga\Protocol\Statusdat;
use Icinga\Exception;

View File

@ -26,19 +26,18 @@
*/
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Backend\Statusdat;
namespace Monitoring\Backend\Statusdat\Query;
use Icinga\Backend\Criteria\Order;
use Icinga\Backend\MonitoringObjectList as MList;
use Monitoring\Backend\Statusdat\Criteria\Order;
use Icinga\Protocol\Statusdat;
use Icinga\Exception;
use Icinga\Backend\Query as BaseQuery;
use Icinga\Data\AbstractQuery;
use Icinga\Protocol\Statusdat\View\MonitoringObjectList as MList;
/**
* Class Query
* @package Icinga\Backend\Statusdat
*/
abstract class Query extends BaseQuery
abstract class Query extends AbstractQuery
{
/**
* @var null
@ -48,7 +47,7 @@ abstract class Query extends BaseQuery
/**
* @var string
*/
protected $view = 'Icinga\Backend\Statusdat\DataView\StatusdatServiceView';
protected $view = 'Monitoring\Statusdat\DataView\StatusdatServiceView';
/**
* @var array Mapping of order to field names
@ -283,6 +282,7 @@ abstract class Query extends BaseQuery
*/
public function count()
{
return count($this->query->getResult());
}
}

View File

@ -26,7 +26,7 @@
*/
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Backend\Statusdat;
namespace Monitoring\Backend\Statusdat\Query;
/**
* Class ServicegroupsummaryQuery

View File

@ -26,11 +26,9 @@
*/
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Backend\Statusdat;
namespace Monitoring\Backend\Statusdat\Query;
use Icinga\Backend\MonitoringObjectList as MList;
use Icinga\Protocol\Statusdat;
use Icinga\Backend\Statusdat\DataView\StatusdatServiceView as StatusdatServiceView;
use Icinga\Exception;
/**

View File

@ -0,0 +1,36 @@
<?php
/**
* Created by JetBrains PhpStorm.
* User: moja
* Date: 7/17/13
* Time: 1:29 PM
* To change this template use File | Settings | File Templates.
*/
namespace Monitoring\Backend\Statusdat\Query;
use Icinga\Protocol\Statusdat;
use Icinga\Exception;
class StatusQuery extends Query
{
/**
* @var \Icinga\Protocol\Statusdat\Query
*/
protected $query;
/**
* @var string
*/
protected $view = 'Monitoring\Backend\Statusdat\DataView\StatusdatHostView';
public function init()
{
$this->reader = $this->ds->getReader();
$this->query = $this->reader->select()->from("hosts", array());
}
}