Merge branch 'master' into bugfix/monitoring-list-dup-entries-7057

This commit is contained in:
Alexander Fuhr 2014-10-08 12:45:14 +02:00
commit 4c23d98575
36 changed files with 57 additions and 3988 deletions

View File

@ -1,54 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Form\Config\Resource;
use Icinga\Web\Form;
use Icinga\Application\Icinga;
use Icinga\Web\Form\Validator\ReadablePathValidator;
/**
* Form class for adding/modifying statusdat resources
*/
class StatusdatResourceForm extends Form
{
/**
* Initialize this form
*/
public function init()
{
$this->setName('form_config_resource_statusdat');
}
/**
* @see Form::createElements()
*/
public function createElements(array $formData)
{
$this->addElement(
'text',
'status_file',
array(
'required' => true,
'label' => t('Filepath'),
'description' => t('Location of your icinga status.dat file'),
'value' => realpath(Icinga::app()->getApplicationDir() . '/../var/status.dat'),
'validators' => array(new ReadablePathValidator())
)
);
$this->addElement(
'text',
'object_file',
array(
'required' => true,
'label' => t('Filepath'),
'description' => t('Location of your icinga objects.cache file'),
'value' => realpath(Icinga::app()->getApplicationDir() . '/../var/objects.cache'),
'validators' => array(new ReadablePathValidator())
)
);
return $this;
}
}

View File

@ -12,7 +12,6 @@ use Icinga\Form\Config\Resource\DbResourceForm;
use Icinga\Form\Config\Resource\FileResourceForm;
use Icinga\Form\Config\Resource\LdapResourceForm;
use Icinga\Form\Config\Resource\LivestatusResourceForm;
use Icinga\Form\Config\Resource\StatusdatResourceForm;
use Icinga\Application\Platform;
use Icinga\Exception\ConfigurationError;
@ -42,8 +41,6 @@ class ResourceConfigForm extends ConfigForm
return new LdapResourceForm();
} elseif ($type === 'livestatus') {
return new LivestatusResourceForm();
} elseif ($type === 'statusdat') {
return new StatusdatResourceForm();
} elseif ($type === 'file') {
return new FileResourceForm();
} else {
@ -214,7 +211,6 @@ class ResourceConfigForm extends ConfigForm
$resourceTypes = array(
'file' => t('File'),
'statusdat' => 'Status.dat',
'livestatus' => 'Livestatus',
);
if ($resourceType === 'ldap' || Platform::extensionLoaded('ldap')) {

View File

@ -10,7 +10,6 @@ use Icinga\Util\ConfigAwareFactory;
use Icinga\Exception\ConfigurationError;
use Icinga\Data\Db\DbConnection;
use Icinga\Protocol\Livestatus\Connection as LivestatusConnection;
use Icinga\Protocol\Statusdat\Reader as StatusdatReader;
use Icinga\Protocol\Ldap\Connection as LdapConnection;
use Icinga\Protocol\File\FileReader;
@ -102,7 +101,7 @@ class ResourceFactory implements ConfigAwareFactory
*
* @param Zend_Config $config The configuration for the created resource.
*
* @return DbConnection|LdapConnection|LivestatusConnection|StatusdatReader An objects that can be used to access
* @return DbConnection|LdapConnection|LivestatusConnection An object that can be used to access
* the given resource. The returned class depends on the configuration property 'type'.
* @throws ConfigurationError When an unsupported type is given
*/
@ -115,9 +114,6 @@ class ResourceFactory implements ConfigAwareFactory
case 'ldap':
$resource = new LdapConnection($config);
break;
case 'statusdat':
$resource = new StatusdatReader($config);
break;
case 'livestatus':
$resource = new LivestatusConnection($config->socket);
break;
@ -137,7 +133,7 @@ class ResourceFactory implements ConfigAwareFactory
* Create a resource from name
*
* @param string $resourceName
* @return DbConnection|LdapConnection|LivestatusConnection|StatusdatReader
* @return DbConnection|LdapConnection|LivestatusConnection
*/
public static function create($resourceName)
{

View File

@ -1,13 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Protocol\Statusdat\Exception;
/**
* Class ParsingException
* @package Icinga\Protocol\Statusdat\Exception
*/
class ParsingException extends \RuntimeException
{
}

View File

@ -1,20 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Protocol\Statusdat;
interface IReader
{
/**
* @return mixed
*/
public function getState();
/**
* @param $type
* @param $name
* @return mixed
*/
public function getObjectByName($type, $name);
}

View File

@ -1,51 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Protocol\Statusdat;
/**
* Class ObjectContainer
* @package Icinga\Protocol\Statusdat
*/
class ObjectContainer extends \stdClass
{
/**
* @var \stdClass
*/
public $ref;
/**
* @var IReader
*/
public $reader;
/**
* @param \stdClass $obj
* @param IReader $reader
*/
public function __construct(&$obj, IReader &$reader)
{
$this->ref = & $obj;
$this->reader = & $reader;
}
/**
* @param $attribute
* @return \stdClass
*/
public function __get($attribute)
{
$exploded = explode(".", $attribute);
$result = $this->ref;
foreach ($exploded as $elem) {
if (isset($result->$elem)) {
$result = $result->$elem;
} else {
return null;
}
}
return $result;
}
}

View File

@ -1,422 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Protocol\Statusdat;
use Icinga\Util\File;
use Icinga\Exception\ProgrammingError;
use Icinga\Protocol\Statusdat\Exception\ParsingException as ParsingException;
/**
* Status.dat and object.cache parser implementation
*/
class Parser
{
/**
* An array of objects that couldn't be resolved yet due to missing dependencies
*
* @var array
*/
private $deferred = array();
/**
* The currently read file
*
* @var File
*/
private $file;
/**
* String representation of the currently parsed object type
*
* @var string
*/
private $currentObjectType;
/**
* The current state type (host, service)
*
* @var string
*/
private $currentStateType;
/**
* The internal representation of the icinga statue
*
* @var array
*/
private $icingaState;
/**
* The current line being read
*
* @var int
*/
private $lineCtr = 0;
/**
* Create a new parser using the given file
*
* @param File $file The file to parse
* @param array $baseState The state to use for the base
*/
public function __construct(File $file, $baseState = null)
{
$this->file = $file;
$this->icingaState = $baseState;
}
/**
* Parse the given file handle as an objects file and read object information
*/
public function parseObjectsFile()
{
$DEFINE = strlen('define ');
$this->icingaState = array();
foreach ($this->file as $line) {
$line = trim($line);
$this->lineCtr++;
if ($line === '' || $line[0] === '#') {
continue;
}
$this->currentObjectType = trim(substr($line, $DEFINE, -1));
if (!isset($this->icingaState[$this->currentObjectType])) {
$this->icingaState[$this->currentObjectType] = array();
}
$this->readCurrentObject();
}
$this->processDeferred();
}
/**
* Parse the given file as an status.dat file and read runtime information
*
* @param File $file The file to parse or null to parse the one passed to the constructor
*/
public function parseRuntimeState(File $file = null)
{
if ($file != null) {
$this->file = $file;
} else {
$file = $this->file;
}
if (!$this->icingaState) {
throw new ProgrammingError('Tried to read runtime state without existing objects data');
}
$this->overwrites = array();
foreach ($file as $line) {
$line = trim($line);
$this->lineCtr++;
if ($line === '' || $line[0] === '#') {
continue;
}
$this->currentStateType = trim(substr($line, 0, -1));
$this->readCurrentState();
}
}
/**
* Read the next object from the object.cache file handle
*
* @throws ParsingException
*/
private function readCurrentObject()
{
$monitoringObject = new PrintableObject();
foreach ($this->file as $line) {
$line = explode("\t", trim($line), 2);
$this->lineCtr++;
if (!$line) {
continue;
}
// End of object
if ($line[0] === '}') {
$this->registerObject($monitoringObject);
return;
}
if (!isset($line[1])) {
$line[1] = '';
}
$monitoringObject->{$line[0]} = trim($line[1]);
}
throw new ParsingException('Unexpected EOF in objects.cache, line ' . $this->lineCtr);
}
/**
* Read the next state from the status.dat file handler
*
* @throws Exception\ParsingException
*/
private function readCurrentState()
{
$statusdatObject = new RuntimeStateContainer();
$objectType = $this->getObjectTypeForState();
if ($objectType != 'host' && $objectType != 'service') {
$this->skipObject(); // ignore unknown objects
return;
}
if (!isset($this->icingaState[$this->currentObjectType])) {
throw new ParsingException("No $this->currentObjectType objects registered in objects.cache");
}
$base = & $this->icingaState[$this->currentObjectType];
$state = $this->skipObject(true);
$statusdatObject->runtimeState = & $state;
$name = $this->getObjectIdentifier($statusdatObject);
if (!isset($base[$name])) {
throw new ParsingException(
"Unknown object $name " . $this->currentObjectType . ' - '
. print_r(
$statusdatObject,
true
)
. "\n" . print_r($base, true)
);
}
$type = substr($this->currentStateType, strlen($objectType));
if ($type == 'status') {
// directly set the status to the status field of the given object
$base[$name]->status = & $statusdatObject;
} else {
if (!isset($base[$name]->$type) || !in_array($base[$name]->$type, $this->overwrites)) {
$base[$name]->$type = array();
$this->overwrites[] = & $base[$name]->$type;
}
array_push($base[$name]->$type, $statusdatObject);
$this->currentObjectType = $type;
if (!isset($this->icingaState[$type])) {
$this->icingaState[$type] = array();
}
$this->icingaState[$type][] = &$statusdatObject;
$id = $this->getObjectIdentifier($statusdatObject);
if ($id !== false && isset($this->icingaState[$objectType][$id])) {
$statusdatObject->$objectType = $this->icingaState[$objectType][$id];
}
}
return;
}
/**
* Get the corresponding object type name for the given state
*
* @return string
*/
private function getObjectTypeForState()
{
$pos = strpos($this->currentStateType, 'service');
if ($pos === false) {
$pos = strpos($this->currentStateType, 'host');
} else {
$this->currentObjectType = 'service';
return 'service';
}
if ($pos === false) {
return $this->currentStateType;
} else {
$this->currentObjectType = 'host';
return 'host';
}
return $this->currentObjectType;
}
/**
* Skip the current object definition
*
* @param bool $returnString If true, the object string will be returned
* @return string The skipped object if $returnString is true
*/
protected function skipObject($returnString = false)
{
if (!$returnString) {
while (trim($this->file->fgets()) !== '}') {
}
return null;
} else {
$str = '';
while (($val = trim($this->file->fgets())) !== '}') {
$str .= $val . "\n";
}
return $str;
}
}
/**
* Register the given object in the icinga state
*
* @param object $object The monitoring object to register
*/
protected function registerObject(&$object)
{
$name = $this->getObjectIdentifier($object);
if ($name !== false) {
$this->icingaState[$this->currentObjectType][$name] = &$object;
}
$this->registerObjectAsProperty($object);
}
/**
* Register the given object as a property in related objects
*
* This registers for example hosts underneath their hostgroup and vice cersa
*
* @param object $object The object to register as a property
*/
protected function registerObjectAsProperty(&$object)
{
if ($this->currentObjectType == 'service'
|| $this->currentObjectType == 'host'
|| $this->currentObjectType == 'contact') {
return null;
}
$isService = strpos($this->currentObjectType, 'service') !== false;
$isHost = strpos($this->currentObjectType, 'host') !== false;
$isContact = strpos($this->currentObjectType, 'contact') !== false;
$name = $this->getObjectIdentifier($object);
if ($isService === false && $isHost === false && $isContact === false) {
// this would be error in the parser implementation
return null;
}
$property = $this->currentObjectType;
if ($isService) {
$this->currentObjectType = 'service';
$property = substr($property, strlen('service'));
} elseif ($isHost) {
$this->currentObjectType = 'host';
$property = substr($property, strlen('host'));
} elseif ($isContact) {
$this->currentObjectType = 'contact';
$property = substr($property, strlen('contact'));
}
if (!isset($this->icingaState[$this->currentObjectType])) {
return $this->deferRegistration($object, $this->currentObjectType . $property);
}
// @TODO: Clean up, this differates between 1:n and 1:1 references
if (strpos($property, 'group') !== false) {
$sourceIdentifier = $this->getMembers($object);
foreach ($sourceIdentifier as $id) {
$source = $this->icingaState[$this->currentObjectType][$id];
if (!isset($source->$property)) {
$source->$property = array();
}
$type = $this->currentObjectType;
if (!isset($object->$type)) {
$object->$type = array();
}
// add the member to the group object
array_push($object->$type, $source);
// add the group to the member object
array_push($source->$property, $name);
}
} else {
$source = $this->icingaState[$this->currentObjectType][$this->getObjectIdentifier($object)];
if (!isset($source->$property)) {
$source->$property = array();
}
array_push($source->$property, $object);
}
return null;
}
/**
* Defer registration of the given object
*
* @param object $object The object to defer
* @param String $objType The name of the object type
*/
protected function deferRegistration($object, $objType)
{
$this->deferred[] = array($object, $objType);
}
/**
* Process deferred objects
*/
protected function processDeferred()
{
foreach ($this->deferred as $obj) {
$this->currentObjectType = $obj[1];
$this->registerObjectAsProperty($obj[0]);
}
}
/**
* Return the resolved members directive of an object
*
* @param object $object The object to get the members from
* @return array An array of member names
*/
protected function getMembers(&$object)
{
if (!isset($object->members)) {
return array();
}
$members = explode(',', $object->members);
if ($this->currentObjectType == 'service') {
$res = array();
for ($i = 0; $i < count($members); $i += 2) {
$res[] = $members[$i] . ';' . $members[$i + 1];
}
return $res;
} else {
return $members;
}
}
/**
* Return the unique name of the given object
*
* @param object $object The object to retrieve the name from
* @return string The name of the object or null if no name can be retrieved
*/
protected function getObjectIdentifier(&$object)
{
if ($this->currentObjectType == 'contact') {
return $object->contact_name;
}
if ($this->currentObjectType == 'service') {
return $object->host_name . ';' . $object->service_description;
}
$name = $this->currentObjectType . '_name';
if (isset($object->{$name})) {
return $object->{$name};
}
if (isset($object->service_description)) {
return $object->host_name . ';' . $object->service_description;
} elseif (isset($object->host_name)) {
return $object->host_name;
}
return null;
}
/**
* Return the internal state of the parser
*
* @return null
*/
public function getRuntimeState()
{
return $this->icingaState;
}
}

View File

@ -1,20 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Protocol\Statusdat;
class PrintableObject
{
public function __toString()
{
if (isset($this->contact_name)) {
return $this->contact_name;
} elseif (isset($this->service_description)) {
return $this->service_description;
} elseif (isset($this->host_name)) {
return $this->host_name;
}
return '';
}
}

View File

@ -1,460 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Protocol\Statusdat;
use Exception;
use Icinga\Exception\ProgrammingError;
use Icinga\Data\SimpleQuery;
use Icinga\Protocol\Statusdat\View\MonitoringObjectList;
use Icinga\Protocol\Statusdat\Query\IQueryPart;
use Icinga\Exception\IcingaException;
/**
* Base implementation for Statusdat queries.
*/
class Query extends SimpleQuery
{
/**
* An array denoting valid targets by mapping the query target to
* the 'define' directives found in the status.dat/objects.cache files
*
* @var array
*/
public static $VALID_TARGETS = array(
'hosts' => array('host'),
'services' => array('service'),
'downtimes' => array('downtime'),
'groups' => array('hostgroup', 'servicegroup'),
'hostgroups' => array('hostgroup'),
'servicegroups' => array('servicegroup'),
'comments' => array('comment'),
'contacts' => array('contact'),
'contactgroups' => array('contactgroup')
);
/**
* The current StatusDat query that will be applied upon calling fetchAll
*
* @var IQueryPart
*/
private $queryFilter = null;
/**
* The current query source being used
*
* @var string
*/
private $source = '';
/**
* An array containing all columns used for sorting
*
* @var array
*/
protected $orderColumns = array();
/**
* An array containig all columns used for (simple) grouping
*
* @var array
*/
private $groupColumns = array();
/**
* An optional function callback to use for more specific grouping
*
* @var array
*/
private $groupByFn = null;
/**
* The scope index for the callback function
*/
const FN_SCOPE = 0;
/**
* The name index for the callback function
*/
const FN_NAME = 1;
/**
* Return true if columns are set for this query
*
* @return bool
*/
public function hasColumns()
{
$columns = $this->getColumns();
return !empty($columns);
}
/**
* Set the status.dat specific IQueryPart filter to use
*
* @param IQueryPart $filter
*/
public function setQueryFilter($filter)
{
$this->queryFilter = $filter;
}
/**
* Order the query result by the given columns
*
* @param String|array $columns An array of columns to order by
* @param String $dir The direction (asc or desc) in string form
*
* @return $this Fluent interface
*/
public function order($columns, $dir = null, $isFunction = false)
{
if ($dir && strtolower($dir) == 'desc') {
$dir = self::SORT_DESC;
} else {
$dir = self::SORT_ASC;
}
if (!is_array($columns)) {
$columns = array($columns);
}
foreach ($columns as $col) {
if (($pos = strpos($col, ' ')) !== false) {
$dir = strtoupper(substr($col, $pos + 1));
if ($dir === 'DESC') {
$dir = self::SORT_DESC;
} else {
$dir = self::SORT_ASC;
}
$col = substr($col, 0, $pos);
} else {
$col = $col;
}
$this->orderColumns[] = array($col, $dir);
}
return $this;
}
/**
* Order the query result using the callback to retrieve values for items
*
* @param array $columns A scope, function array to use for retrieving the values when ordering
* @param String $dir The direction (asc or desc) in string form
*
* @return $this Fluent interface
*/
public function orderByFn(array $callBack, $dir = null)
{
if ($dir && strtolower($dir) == 'desc') {
$dir = self::SORT_DESC;
} else {
$dir = self::SORT_ASC;
}
$this->orderColumns[] = array($callBack, $dir);
}
/**
* Set the query target
*
* @param String $table The table/target to select the query from
* @param array $columns An array of attributes to use (required for fetchPairs())
*
* @return $this Fluent interface
* @throws IcingaException If the target is unknonw
*/
public function from($table, array $attributes = null)
{
if (!$this->getColumns() && $attributes) {
$this->setColumns($attributes);
}
if (isset(self::$VALID_TARGETS[$table])) {
$this->source = $table;
} else {
throw new IcingaException(
'Unknown from target for status.dat :%s',
$table
);
}
return $this;
}
/**
* Return an index of all objects matching the filter of this query
*
* This index will be used for ordering, grouping and limiting
*/
private function getFilteredIndices($classType = '\Icinga\Protocol\Statusdat\Query\Group')
{
$baseGroup = $this->queryFilter;
$state = $this->ds->getState();
$result = array();
$source = self::$VALID_TARGETS[$this->source];
foreach ($source as $target) {
if (! isset($state[$target])) {
continue;
}
$indexes = array_keys($state[$target]);
if ($baseGroup) {
$baseGroup->setQuery($this);
$idx = array_keys($state[$target]);
$indexes = $baseGroup->filter($state[$target], $idx);
}
if (!isset($result[$target])) {
$result[$target] = $indexes;
} else {
array_merge($result[$target], $indexes);
}
}
return $result;
}
/**
* Order the given result set
*
* @param array $indices The result set of the query that should be ordered
*/
private function orderIndices(array &$indices)
{
if (!empty($this->orderColumns)) {
foreach ($indices as $type => &$subindices) {
$this->currentType = $type;
usort($subindices, array($this, 'orderResult'));
}
}
}
/**
* Start a query
*
* This is just a dummy function to allow a more convenient syntax
*
* @return self Fluent interface
*/
public function select()
{
return $this;
}
/**
* Order implementation called by usort
*
* @param String $a The left object index
* @param Strinv $b The right object index
* @return int 0, 1 or -1, see usort for detail
*/
private function orderResult($a, $b)
{
$o1 = $this->ds->getObjectByName($this->currentType, $a);
$o2 = $this->ds->getObjectByName($this->currentType, $b);
$result = 0;
foreach ($this->orderColumns as &$col) {
if (is_array($col[0])) {
// sort by function
$result += $col[1] * strnatcasecmp(
$col[0][0]->$col[0][1]($o1),
$col[0][0]->$col[0][1]($o2)
);
} else {
$result += $col[1] * strnatcasecmp($o1->{$col[0]}, $o2->{$col[0]});
}
}
return $result;
}
/**
* Limit the given resultset
*
* @param array $indices The filtered, ordered indices
*/
private function limitIndices(array &$indices)
{
foreach ($indices as $type => $subindices) {
$indices[$type] = array_slice($subindices, $this->getOffset(), $this->getLimit());
}
}
/**
* Register the given function for grouping the result
*
* @param String $fn The function to use for grouping
* @param Object $scope An optional scope to use instead of $this
*
* @return self Fluent interface
*/
public function groupByFunction($fn, $scope = null)
{
$this->groupByFn = array($scope ? $scope : $this, $fn);
return $this;
}
/**
* Group by the given column
*
* @param array|string $columns The columns to use for grouping
* @return self Fluent interface
* @see Query::columnGroupFn() The implementation used for grouping
*/
public function groupByColumns($columns)
{
if (!is_array($columns)) {
$columns = array($columns);
}
$this->groupColumns = $columns;
$this->groupByFn = array($this, 'columnGroupFn');
return $this;
}
/**
* The internal handler function used by the group function
*
* @param array $indices The indices to group
* @return array The grouped result set
*/
private function columnGroupFn(array &$indices)
{
$cols = $this->groupColumns;
$result = array();
foreach ($indices as $type => $subindices) {
foreach ($subindices as $objectIndex) {
$r = $this->ds->getObjectByName($type, $objectIndex);
$hash = '';
$cols = array();
foreach ($this->groupColumns as $col) {
$hash = md5($hash . $r->$col);
$cols[$col] = $r->$col;
}
if (!isset($result[$hash])) {
$result[$hash] = (object)array(
'columns' => (object)$cols,
'count' => 0
);
}
$result[$hash]->count++;
}
}
return array_values($result);
}
/**
* Query Filter, Order, Group, Limit and return the result set
*
* @return array The resultset matching this query
*/
public function getResult()
{
$indices = $this->getFilteredIndices();
$this->orderIndices($indices);
if ($this->groupByFn) {
$scope = $this->groupByFn[self::FN_SCOPE];
$fn = $this->groupByFn[self::FN_NAME];
return $scope->$fn($indices);
}
$this->limitIndices($indices);
$result = array();
$state = $this->ds->getState();
foreach ($indices as $type => $subindices) {
foreach ($subindices as $index) {
$result[] = & $state[$type][$index];
}
}
return $result;
}
/**
* Apply all filters of this filterable on the datasource
*/
public function applyFilter()
{
$parser = new TreeToStatusdatQueryParser();
if ($this->getFilter()) {
$query = $parser->treeToQuery($this->getFilter(), $this);
$this->setQueryFilter($query);
}
}
/**
* Return only the first row fetched from the result set
*
* @return MonitoringObjectList The monitoring object matching this query
*/
public function fetchRow()
{
$rs = $this->fetchAll();
$rs->rewind();
return $rs->current();
}
/**
* Fetch the result as an associative array using the first column as the key and the second as the value
*
* @return array An associative array with the result
* @throws IcingaException If no attributes are defined
*/
public function fetchPairs()
{
$result = array();
if (count($this->getColumns()) < 2) {
throw new IcingaException(
'Status.dat "fetchPairs()" query expects at least columns to be set in the query expression'
);
}
$attributes = $this->getColumns();
$param1 = $attributes[0];
$param2 = $attributes[1];
foreach ($this->fetchAll() as $resultList) {
$result[$resultList->$param1] = $resultList->$param2;
}
return $result;
}
/**
* Fetch all results
*
* @return MonitoringObjectList An MonitoringObjectList wrapping the given resultset
*/
public function fetchAll()
{
$this->applyFilter();
if (!isset($this->cursor)) {
$result = $this->getResult();
$this->cursor = new MonitoringObjectList($result, $this);
}
return $this->cursor;
}
/**
* Return the value of the first column for the first row fetched from the result set
*/
public function fetchOne()
{
throw new ProgrammingError('Statusdat/Query::fetchOne() is not implemented yet');
}
/**
* Count the number of results
*
* @return int
*/
public function count()
{
$q = clone $this;
$q->limit(null, null);
return count($q->fetchAll());
}
}

View File

@ -1,415 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Protocol\Statusdat\Query;
use Icinga\Exception\IcingaException;
class Expression implements IQueryPart
{
/**
*
*/
const ENC_NUMERIC = 0;
/**
*
*/
const ENC_SET = 0;
/**
*
*/
const ENC_STRING = 0;
/**
* @var string
*/
private $expression;
/**
* @var null
*/
private $field = null;
/**
* @var array
*/
private $basedata = array();
/**
* @var null
*/
private $function = null;
/**
* @var string
*/
private $value = "";
/**
* @var null
*/
private $operator = null;
/**
* Optional query information
*
* @var null
*/
private $query = null;
/**
* @var null
*/
private $name = null;
/**
* @var null
*/
public $CB = null;
/**
* @param $token
* @throws IcingaException
*/
private function getOperatorType($token)
{
switch (strtoupper($token)) {
case ">":
$this->CB = "isGreater";
break;
case "<":
$this->CB = "isLess";
break;
case ">=":
$this->CB = "isGreaterEq";
break;
case "<=":
$this->CB = "isLessEq";
break;
case "=":
$this->CB = "isEqual";
break;
case "LIKE":
$this->CB = "isLike";
break;
case "NOT_LIKE":
$this->CB = "isNotLike";
break;
case "!=":
$this->CB = "isNotEqual";
break;
case "IN":
$this->CB = "isIn";
break;
case "NOT_IN":
$this->CB = "isNotIn";
break;
default:
throw new IcingaException(
'Unknown operator %s in expression %s !',
$token,
$this->expression
);
}
}
/**
* @param $tokens
* @return mixed
*/
private function extractAggregationFunction(&$tokens)
{
$token = $tokens[0];
$value = array();
if (preg_match("/COUNT\{(.*)\}/", $token, $value) == false) {
return $token;
}
$this->function = "count";
$tokens[0] = $value[1];
return null;
}
/**
* @param $values
*/
private function parseExpression(&$values)
{
$tokenized = preg_split("/ +/", trim($this->expression), 3);
$this->extractAggregationFunction($tokenized);
if (count($tokenized) != 3) {
echo(
"Currently statusdat query expressions must be in "
. "the format FIELD OPERATOR ? or FIELD OPERATOR :value_name"
);
}
$this->fields = explode(".", trim($tokenized[0]));
$this->field = $this->fields[count($this->fields) - 1];
$this->getOperatorType(trim($tokenized[1]));
$tokenized[2] = trim($tokenized[2]);
if ($tokenized[2][0] === ":") {
$this->name = substr($tokenized, 1);
$this->value = $values[$this->name];
} else {
if ($tokenized[2] === "?") {
$this->value = array_shift($values);
} else {
$this->value = trim($tokenized[2]);
}
}
}
/**
* @param $expression
* @param $values
* @return $this
*/
public function fromString($expression, &$values)
{
$this->expression = $expression;
$this->parseExpression($values);
return $this;
}
/**
* @param null $expression
* @param array $values
*/
public function __construct($expression = null, &$values = array())
{
if ($expression) {
if (!is_array($values)) {
$values = array($values);
}
$this->fromString($expression, $values);
}
}
/**
* @param array $base
* @param array $idx
* @return array|mixed
*/
public function filter(array &$base, &$idx = array())
{
if (!$idx) {
$idx = array_keys($base);
}
$this->basedata = $base;
return array_filter($idx, array($this, "filterFn"));
}
/**
* @return string
*/
public function getValue()
{
return $this->value;
}
/**
* @return null
*/
public function getField()
{
return $this->field;
}
/**
* @param $idx
* @return bool
*/
protected function filterFn($idx)
{
$values = $this->getFieldValues($idx);
if ($values === false) {
return false;
}
if ($this->CB == "isIn" || $this->CB == "isNotIn") {
$cmpValues = is_array($this->value) ? $this->value : array($this->value);
foreach ($cmpValues as $cmpValue) {
$this->value = $cmpValue;
foreach ($values as $value) {
if ($this->CB == "isIn" && $this->isLike($value)) {
$this->value = $cmpValues;
return true;
} elseif ($this->CB == "isNotIn" && $this->isNotLike($value)) {
$this->value = $cmpValues;
return true;
}
}
}
$this->value = $cmpValues;
return false;
}
if ($this->function) {
$values = call_user_func($this->function, $values);
if (!is_array($values)) {
$values = array($values);
}
}
foreach ($values as $val) {
if (!is_string($val) && !is_numeric($val) && is_object($val)) {
if (isset($val->service_description)) {
$val = $val->service_description;
} elseif (isset($val->host_name)) {
$val = $val->host_name;
} else {
return false;
}
}
if ($this->{$this->CB}($val)) {
return true;
}
}
return false;
}
/**
* @param $idx
* @return array
*/
private function getFieldValues($idx)
{
$res = $this->basedata[$idx];
foreach ($this->fields as $field) {
if (!is_array($res)) {
if ($this->query) {
$res = $this->query->get($res, $field);
continue;
}
if (!isset($res->$field)) {
$res = array();
break;
}
$res = $res->$field;
continue;
}
// it can be that an element contains more than one value, like it
// happens when using comments, in this case we have to create a new
// array that contains the values/objects we're searching
$swap = array();
foreach ($res as $sub) {
if ($this->query) {
$swap[] = $this->query->get($sub, $field);
continue;
}
if (!isset($sub->$field)) {
continue;
}
if (!is_array($sub->$field)) {
$swap[] = $sub->$field;
} else {
$swap = array_merge($swap, $sub->$field);
}
}
$res = $swap;
}
if (!is_array($res)) {
return array($res);
}
return $res;
}
/**
* @param $value
* @return bool
*/
public function isGreater($value)
{
return $value > $this->value;
}
/**
* @param $value
* @return bool
*/
public function isLess($value)
{
return $value < $this->value;
}
/**
* @param $value
* @return bool
*/
public function isLike($value)
{
return preg_match("/^" . str_replace("%", ".*", $this->value) . "$/", $value) ? true : false;
}
/**
* @param $value
* @return bool
*/
public function isNotLike($value)
{
return !preg_match("/^" . str_replace("%", ".*", $this->value) . "$/", $value) ? true : false;
}
/**
* @param $value
* @return bool
*/
public function isEqual($value)
{
if (!is_numeric($value)) {
return strtolower($value) == strtolower($this->value);
}
return $value == $this->value;
}
/**
* @param $value
* @return bool
*/
public function isNotEqual($value)
{
return $value != $this->value;
}
/**
* @param $value
* @return bool
*/
public function isGreaterEq($value)
{
return $value >= $this->value;
}
/**
* @param $value
* @return bool
*/
public function isLessEq($value)
{
return $value <= $this->value;
}
/**
* Add additional information about the query this filter belongs to
*
* @param $query
* @return mixed
*/
public function setQuery($query)
{
$this->query = $query;
}
}

View File

@ -1,397 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Protocol\Statusdat\Query;
use Icinga\Exception\IcingaException;
/**
* Class Group
* @package Icinga\Protocol\Statusdat\Query
*/
class Group implements IQueryPart
{
/**
*
*/
const GROUP_BEGIN = "(";
/**
*
*/
const GROUP_END = ")";
/**
*
*/
const CONJUNCTION_AND = "AND ";
/**
*
*/
const CONJUNCTION_OR = "OR ";
/**
*
*/
const EXPRESSION = 0;
/**
*
*/
const EOF = -1;
/**
*
*/
const TYPE_AND = "AND";
/**
*
*/
const TYPE_OR = "OR";
/**
* @var array
*/
private $items = array();
/**
* @var int
*/
private $parsePos = 0;
/**
* @var string
*/
private $expression = "";
/**
* @var null
*/
private $expressionClass = null;
/**
* @var string
*/
private $type = "";
/**
* @var int
*/
private $subExpressionStart = 0;
/**
* @var int
*/
private $subExpressionLength = 0;
/**
* Optional query to use
*
* @var Query
*/
private $query = null;
/**
* @var
*/
private $value;
/**
* @param $value
*/
public function setValue($value)
{
$this->value = $value;
}
/**
* @return array
*/
public function getItems()
{
return $this->items;
}
/**
* @return string
*/
public function getType()
{
return $this->type ? $this->type : self::TYPE_AND;
}
/**
* @param $type
*/
public function setType($type)
{
$this->type = $type;
}
/**
* @throws IcingaException
*/
private function tokenize()
{
$token = 0;
$subgroupCount = 0;
while ($token != self::EOF) {
$token = $this->getNextToken();
if ($token === self::GROUP_BEGIN) {
/**
* check if this is a nested group, if so then it's
* considered part of the subexpression
*/
if ($subgroupCount == 0) {
$this->startNewSubExpression();
}
$subgroupCount++;
continue;
}
if ($token === self::GROUP_END) {
if ($subgroupCount < 1) {
throw new IcingaException(
'Invalid Query: unexpected \')\' at pos %s',
$this->parsePos
);
}
$subgroupCount--;
/*
* check if this is a nested group, if so then it's
* considered part of the subexpression
*/
if ($subgroupCount == 0) {
$this->addSubgroupFromExpression();
}
continue;
}
if ($token === self::CONJUNCTION_AND && $subgroupCount == 0) {
$this->startNewSubExpression();
if ($this->type != self::TYPE_AND && $this->type != "") {
$this->createImplicitGroup(self::TYPE_AND);
break;
} else {
$this->type = self::TYPE_AND;
}
continue;
}
if ($token === self::CONJUNCTION_OR && $subgroupCount == 0) {
$this->startNewSubExpression();
if ($this->type != self::TYPE_OR && $this->type != "") {
$this->createImplicitGroup(self::TYPE_OR);
break;
} else {
$this->type = self::TYPE_OR;
}
continue;
}
$this->subExpressionLength = $this->parsePos - $this->subExpressionStart;
}
if ($subgroupCount > 0) {
throw new IcingaException('Unexpected end of query, are you missing a parenthesis?');
}
$this->startNewSubExpression();
}
/**
* @param $type
*/
private function createImplicitGroup($type)
{
$group = new Group();
$group->setType($type);
$group->addItem(array_pop($this->items));
$group->fromString(substr($this->expression, $this->parsePos), $this->value, $this->expressionClass);
$this->items[] = $group;
$this->parsePos = strlen($this->expression);
}
/**
*
*/
private function startNewSubExpression()
{
if ($this->getCurrentSubExpression() != "") {
if (!$this->expressionClass) {
$this->items[] = new Expression($this->getCurrentSubExpression(), $this->value);
} else {
$this->items[] = new $this->expressionClass($this->getCurrentSubExpression(), $this->value);
}
}
$this->subExpressionStart = $this->parsePos;
$this->subExpressionLength = 0;
}
/**
* @return string
*/
private function getCurrentSubExpression()
{
return substr($this->expression, $this->subExpressionStart, $this->subExpressionLength);
}
/**
*
*/
private function addSubgroupFromExpression()
{
if (!$this->expressionClass) {
$this->items[] = new Group($this->getCurrentSubExpression(), $this->value);
} else {
$group = new Group();
$group->fromString($this->getCurrentSubExpression(), $this->value, $this->expressionClass);
$this->items[] = $group;
}
$this->subExpressionStart = $this->parsePos;
$this->subExpressionLength = 0;
}
/**
* @return bool
*/
private function isEOF()
{
if ($this->parsePos >= strlen($this->expression)) {
return true;
}
return false;
}
/**
* @return int|string
*/
private function getNextToken()
{
if ($this->isEOF()) {
return self::EOF;
}
// skip whitespaces
while ($this->expression[$this->parsePos] == " ") {
$this->parsePos++;
if ($this->isEOF()) {
return self::EOF;
}
}
if ($this->expression[$this->parsePos] == self::GROUP_BEGIN) {
$this->parsePos++;
return self::GROUP_BEGIN;
}
if ($this->expression[$this->parsePos] == self::GROUP_END) {
$this->parsePos++;
return self::GROUP_END;
}
if (substr_compare(
$this->expression,
self::CONJUNCTION_AND,
$this->parsePos,
strlen(self::CONJUNCTION_AND),
true
) === 0) {
$this->parsePos += strlen(self::CONJUNCTION_AND);
return self::CONJUNCTION_AND;
}
if (substr_compare(
$this->expression,
self::CONJUNCTION_OR,
$this->parsePos,
strlen(self::CONJUNCTION_OR),
true
) === 0) {
$this->parsePos += strlen(self::CONJUNCTION_OR);
return self::CONJUNCTION_OR;
}
$this->parsePos++;
return self::EXPRESSION;
}
/**
* @param $ex
* @return $this
*/
public function addItem($ex)
{
$this->items[] = $ex;
return $this;
}
/**
* @param $expression
* @param array $value
* @param null $expressionClass
* @return $this
*/
public function fromString($expression, &$value = array(), $expressionClass = null)
{
$this->expression = $expression;
$this->value = & $value;
$this->expressionClass = $expressionClass;
$this->tokenize();
return $this;
}
/**
* @param null $expression
* @param array $value
*/
public function __construct($expression = null, &$value = array())
{
if ($expression) {
$this->fromString($expression, $value);
}
}
/**
* @param array $base
* @param null $idx
* @return array|null
*/
public function filter(array &$base, &$idx = null)
{
if ($this->type == self::TYPE_OR) {
$idx = array();
foreach ($this->items as &$subFilter) {
$baseKeys = array_keys($base);
$subFilter->setQuery($this->query);
$idx += $subFilter->filter($base, $baseKeys);
}
} else {
if (!$idx) {
$idx = array_keys($base);
}
foreach ($this->items as $subFilter) {
$subFilter->setQuery($this->query);
$idx = array_intersect($idx, $subFilter->filter($base, $idx));
}
}
return $idx;
}
/**
* Add additional information about the query this filter belongs to
*
* @param $query
* @return mixed
*/
public function setQuery($query)
{
$this->query = $query;
}
}

View File

@ -1,36 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Protocol\Statusdat\Query;
/**
* Class IQueryPart
* @package Icinga\Protocol\Statusdat\Query
*/
interface IQueryPart
{
/**
* Create a new query part with an optional expression to be parse
*
* @param string $expression An optional expression string to use
* @param array $value The values fot the optional expression
*/
public function __construct($expression = null, &$value = array());
/**
* Filter the given resultset
*
* @param array $base The resultset to use for filtering
* @param array $idx An optional array containing prefiltered indices
*/
public function filter(array &$base, &$idx = null);
/**
* Add additional information about the query this filter belongs to
*
* @param $query
* @return mixed
*/
public function setQuery($query);
}

View File

@ -1,330 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Protocol\Statusdat;
use Icinga\Util\File;
use Icinga\Logger\Logger;
use Icinga\Data\Selectable;
use Icinga\Exception\ConfigurationError;
/**
* Class Reader
* @package Icinga\Protocol\Statusdat
*/
class Reader implements IReader, Selectable
{
/**
* The default lifetime of the cache in milliseconds
*/
const DEFAULT_CACHE_LIFETIME = 30;
/**
* The folder for the statusdat cache
*/
const STATUSDAT_DEFAULT_CACHE_PATH = '/tmp';
/**
* The last state from the cache
*
* @var array
*/
private $lastState;
/**
* True when this reader has already acquired the current runtime state (i.e. Status.dat)
*
* @var bool
*/
private $hasRuntimeState = false;
/**
* The representation of the object.cache file
*
* @var array
*/
private $objectCache ;
/**
* The representation of the status.dat file
* @var array
*/
private $statusCache;
/**
* True when the icinga state differs from the cache
*
* @var bool
*/
private $newState = false;
/**
* The Parser object to use for parsing
*
* @var Parser
*/
private $parser;
/**
* Whether to disable the cache
*
* @var bool
*/
private $noCache;
/**
* Create a new Reader from the given configuraion
*
* @param Zend_Config $config The configuration to read the status.dat information from
* @param Parser $parser The parser to use (for testing)
* @param bool $noCache Whether to disable the cache
*/
public function __construct($config = \Zend_Config, $parser = null, $noCache = false)
{
$this->noCache = $noCache;
if (isset($config->no_cache)) {
$this->noCache = $config->no_cache;
}
$this->config = $config;
$this->parser = $parser;
if (!$this->noCache) {
$this->cache = $this->initializeCaches($config);
if ($this->fromCache()) {
$this->createHostServiceConnections();
return;
}
}
if (!$this->lastState) {
$this->parseObjectsCacheFile();
}
if (!$this->hasRuntimeState) {
}
$this->parseStatusDatFile();
if (!$noCache && $this->newState) {
$this->statusCache->save($this->parser->getRuntimeState(), 'object' . md5($this->config->object_file));
}
$this->createHostServiceConnections();
}
/**
* Initialize the internal caches if enabled
*
* @throws ConfigurationError
*/
private function initializeCaches()
{
$defaultCachePath = self::STATUSDAT_DEFAULT_CACHE_PATH;
$cachePath = $this->config->get('cache_path', $defaultCachePath);
$maxCacheLifetime = intval($this->config->get('cache_path', self::DEFAULT_CACHE_LIFETIME));
$cachingEnabled = true;
if (!is_writeable($cachePath)) {
Logger::warning(
'Can\'t cache Status.dat backend; make sure cachepath %s is writable by the web user. '
. 'Caching is now disabled',
$cachePath
);
$cachePath = null;
}
$backendOptions = array(
'cache_dir' => $cachePath
);
// the object cache might exist for months and is still valid
$this->objectCache = $this->initCache($this->config->object_file, $backendOptions, null, $cachingEnabled);
$this->statusCache = $this->initCache(
$this->config->status_file,
$backendOptions,
$maxCacheLifetime,
$cachingEnabled
);
}
/**
* Init the Cache backend in Zend
*
* @param String $file The file to use as the cache master file
* @param Zend_Config $backend The backend configuration to use
* @param integer $lifetime The lifetime of the cache
*
* @return \Zend_Cache_Core|\Zend_Cache_Frontend
*/
private function initCache($file, $backendConfig, $lifetime)
{
$frontendOptions = array(
'lifetime' => $lifetime,
'automatic_serialization' => true,
'master_files' => array($file)
);
return \Zend_Cache::factory('Core', 'File', $frontendOptions, $backendConfig);
}
/**
* Read the current cache state
*
* @return bool True if the state is the same as the icinga state
*/
private function fromCache()
{
if (!$this->readObjectsCache()) {
$this->newState = true;
return false;
}
if (!$this->readStatusCache()) {
$this->newState = true;
return false;
}
return true;
}
/**
* Read the object.cache file from the Zend_Cache backend
*
* @return bool True if the file could be loaded from cache
*/
private function readObjectsCache()
{
$this->lastState = $this->objectCache->load('object' . md5($this->config->object_file));
if ($this->lastState == false) {
return false;
}
return true;
}
/**
* Read the status.dat file from the Zend_Cache backend
*
* @return bool True if the file could be loaded from cache
*/
private function readStatusCache()
{
if (!isset($this->stateCache)) {
return true;
}
$statusInfo = $this->stateCache->load('state' . md5($this->config->status_file));
if ($statusInfo == false) {
return false;
}
$this->hasRuntimeState = true;
return true;
}
/**
* Take the status.dat and objects.cache and connect all services to hosts
*
*/
private function createHostServiceConnections()
{
if (!isset($this->lastState["service"])) {
return;
}
foreach ($this->lastState["host"] as &$host) {
$host->host = $host;
}
foreach ($this->lastState["service"] as &$service) {
$service->service = &$service; // allow easier querying
$host = &$this->lastState["host"][$service->host_name];
if (!isset($host->services)) {
$host->services = array();
}
$host->services[$service->service_description] = & $service;
$service->host = & $host;
}
}
/**
* Parse the object.cache file and update the current state
*
* @throws ConfigurationError If the object.cache couldn't be read
*/
private function parseObjectsCacheFile()
{
if (!is_readable($this->config->object_file)) {
throw new ConfigurationError(
'Can\'t read object-file "%s", check your configuration',
$this->config->object_file
);
}
if (!$this->parser) {
$this->parser = new Parser(new File($this->config->object_file, 'r'));
}
$this->parser->parseObjectsFile();
$this->lastState = $this->parser->getRuntimeState();
}
/**
* Parse the status.dat file and update the current state
*
* @throws ConfigurationError If the status.dat couldn't be read
*/
private function parseStatusDatFile()
{
if (!is_readable($this->config->status_file)) {
throw new ConfigurationError(
'Can\'t read status-file %s, check your configuration',
$this->config->status_file
);
}
if (!$this->parser) {
$this->parser = new Parser(new File($this->config->status_file, 'r'), $this->lastState);
}
$this->parser->parseRuntimeState(new File($this->config->status_file, 'r'));
$this->lastState = $this->parser->getRuntimeState();
if (!$this->noCache) {
$this->statusCache->save(array("true" => true), "state" . md5($this->config->object_file));
}
}
/**
* Create a new Query
*
* @return Query The query to operate on
*/
public function select()
{
return new Query($this);
}
/**
* Return the internal state of the status.dat
*
* @return mixed The internal status.dat representation
*/
public function getState()
{
return $this->lastState;
}
/**
* Return the object with the given name and type
*
* @param String $type The type of the object to return (service, host, servicegroup...)
* @param String $name The name of the object
*
* @return ObjectContainer An object container wrapping the result or null if the object doesn't exist
*/
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;
}
/**
* Get an array containing all names of monitoring objects with the given type
*
* @param String $type The type of object to get the names for
* @return array An array of names or null if the type does not exist
*/
public function getObjectNames($type)
{
return isset($this->lastState[$type]) ? array_keys($this->lastState[$type]) : null;
}
}

View File

@ -1,72 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Protocol\Statusdat;
/**
* Container class containing the runtime state of an object
*
* This class contains the state of the object as a string and parses it
* on the fly as soon as values should be retrieved. This reduces memory usage,
* as most runtime information is never received and only lives for a very short time.
*
*/
class RuntimeStateContainer extends \stdClass
{
/**
* The state string
*
* @var string
*/
public $runtimeState = "";
/**
* Create a new runtime state container from the givven string
*
* @param string $str
*/
public function __construct($str = "")
{
$this->runtimeState = $str;
}
/**
* Return true if the argument exists
*
* @param String $attr The argument to retrieve
* @return bool True if it exists, otherwise false
*/
public function __isset($attr)
{
try {
$this->__get($attr);
return true;
} catch (\InvalidArgumentException $e) {
return false;
}
}
/**
* Return the given attribute
*
* If the container string is not yet parsed, this will happen here
*
* @param String $attr The attribute to retrieve
* @return mixed The value of the attribute
* @throws \InvalidArgumentException When the attribute does not exist
*/
public function __get($attr)
{
$start = strpos($this->runtimeState, $attr . "=");
if ($start === false) {
throw new \InvalidArgumentException("Unknown property $attr");
}
$start += strlen($attr . "=");
$len = strpos($this->runtimeState, "\n", $start) - $start;
$this->$attr = trim(substr($this->runtimeState, $start, $len));
return $this->$attr;
}
}

View File

@ -1,42 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Protocol\Statusdat\View;
/**
* Interface for statusdat classes that provide a specific view on the dataset
*
* 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.
*/
interface AccessorStrategy
{
/**
* 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 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,143 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Protocol\Statusdat\View;
use Iterator;
use Countable;
use ArrayAccess;
use Exception;
use Icinga\Exception\IcingaException;
/**
* Wrapper around an array of monitoring objects that can be enhanced with an optional
* object that extends AccessorStrategy. 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.
*
*/
class MonitoringObjectList implements Iterator, Countable, ArrayAccess
{
private $dataSet = array();
private $position = 0;
private $dataView = null;
public function __construct(array &$dataset, AccessorStrategy $dataView = null)
{
$this->dataSet = $dataset;
$this->position = 0;
$this->dataView = $dataView;
}
public function count()
{
return count($this->dataSet);
}
public function setPosition($pos)
{
$this->position = $pos;
}
/**
* (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);
}
public function __get($name)
{
return $this->dataView->get($this->dataSet[$this->position], $name);
}
public function __set($name, $value)
{
throw new IcingaException('Setting is currently not available for objects');
}
public function offsetExists($offset)
{
return count($this->dataSet) < $offset;
}
public function offsetGet($offset)
{
$res = new MonitoringObjectList($this->dataSet, $this->dataView);
$res->position = $offset;
return $res;
}
public function offsetSet($offset, $value)
{
// non mutable
}
public function offsetUnset($offset)
{
// non mutable
}
}

View File

@ -265,6 +265,9 @@ class Monitoring_ListController extends Controller
*/
public function downtimesAction()
{
if ($url = $this->hasBetterUrl()) {
return $this->redirectNow($url);
}
$this->addTitleTab('downtimes');
$this->setAutorefreshInterval(12);
$query = $this->backend->select()->from('downtime', array(
@ -309,6 +312,9 @@ class Monitoring_ListController extends Controller
*/
public function notificationsAction()
{
if ($url = $this->hasBetterUrl()) {
return $this->redirectNow($url);
}
$this->addTitleTab('notifications');
$this->setAutorefreshInterval(15);
$query = $this->backend->select()->from('notification', array(
@ -328,6 +334,9 @@ class Monitoring_ListController extends Controller
public function contactsAction()
{
if ($url = $this->hasBetterUrl()) {
return $this->redirectNow($url);
}
$this->addTitleTab('contacts');
$query = $this->backend->select()->from('contact', array(
'contact_name',
@ -364,6 +373,9 @@ class Monitoring_ListController extends Controller
public function statehistorysummaryAction()
{
if ($url = $this->hasBetterUrl()) {
return $this->redirectNow($url);
}
$this->addTitleTab('statehistorysummary', 'State Summary');
$form = new StatehistoryForm();
@ -401,6 +413,9 @@ class Monitoring_ListController extends Controller
public function contactgroupsAction()
{
if ($url = $this->hasBetterUrl()) {
return $this->redirectNow($url);
}
$this->addTitleTab('contactgroups');
$query = $this->backend->select()->from('contactgroup', array(
'contactgroup_name',
@ -430,6 +445,9 @@ class Monitoring_ListController extends Controller
public function commentsAction()
{
if ($url = $this->hasBetterUrl()) {
return $this->redirectNow($url);
}
$this->addTitleTab('comments');
$this->setAutorefreshInterval(12);
$query = $this->backend->select()->from('comment', array(
@ -550,6 +568,9 @@ class Monitoring_ListController extends Controller
public function servicematrixAction()
{
if ($url = $this->hasBetterUrl()) {
return $this->redirectNow($url);
}
$this->addTitleTab('servicematrix');
$this->setAutorefreshInterval(15);
$query = $this->backend->select()->from('serviceStatus', array(

View File

@ -45,8 +45,8 @@ class BackendConfigForm extends ConfigForm
{
$resources = array();
foreach ($resourceConfig as $name => $resource) {
if ($resource->type === 'db' || $resource->type === 'statusdat' || $resource->type === 'livestatus') {
$resources[$resource->type === 'db' ? 'ido' : strtolower($resource->type)][$name] = $name;
if ($resource->type === 'db' || $resource->type === 'livestatus') {
$resources[$resource->type === 'db' ? 'ido' : 'livestatus'][$name] = $name;
}
}
@ -192,9 +192,6 @@ class BackendConfigForm extends ConfigForm
if ($resourceType === 'ido' || array_key_exists('ido', $this->resources)) {
$resourceTypes['ido'] = 'IDO Backend';
}
if ($resourceType === 'statusdat' || array_key_exists('statusdat', $this->resources)) {
$resourceTypes['statusdat'] = 'Status.dat';
}
if ($resourceType === 'livestatus' || array_key_exists('livestatus', $this->resources)) {
$resourceTypes['livestatus'] = 'Livestatus';
}

View File

@ -1,33 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
// TODO: Throw away as soon as our backends are handling things better
class Zend_View_Helper_ResolveComments extends Zend_View_Helper_Abstract
{
public function resolveComments($infos)
{
$ret = array();
if (is_array($infos)) {
foreach ($infos as $info) {
if (! is_array($info) || empty($info)) continue;
if (is_int(key($info))) {
// livestatus
$ret[] = '[' . $info[1] . '] ' . $info[2];
} else {
// statusdat - doesn't seem to work?!
$ret[] = '[' . $info['author'] . '] '
. (isset($info['comment'])
? $info['comment']
: $info['comment_data']
);
}
}
} else {
// ido
$ret = preg_split('~\|~', $infos);
}
return $ret;
}
}

View File

@ -5,7 +5,7 @@ if (! empty($object->contacts)) {
$list = array();
foreach ($object->contacts as $contact) {
$list[] = $this->qlink($contact->contact_alias, 'monitoring/show/contact', array(
'contact_name' => $contact->contact_name
'contact' => $contact->contact_name
));
}
@ -24,7 +24,7 @@ if (! empty($object->contactgroups)) {
$list[] = $this->qlink(
$contactgroup->contactgroup_alias,
'monitoring/list/contactgroups',
array('contactgroup_name' => $contactgroup->contactgroup_name)
array('contactgroup' => $contactgroup->contactgroup_name)
);
}

View File

@ -8,39 +8,39 @@ class ContactgroupQuery extends IdoQuery
{
protected $columnMap = array(
'contactgroups' => array(
'contactgroup_name' => 'cgo.name1 COLLATE latin1_general_ci',
'contactgroup_alias' => 'cg.alias',
'contactgroup' => 'cgo.name1 COLLATE latin1_general_ci',
'contactgroup_name' => 'cgo.name1 COLLATE latin1_general_ci',
'contactgroup_alias' => 'cg.alias',
),
'contacts' => array(
'contact_name' => 'co.name1 COLLATE latin1_general_ci',
'contact_alias' => 'c.alias',
'contact_email' => 'c.email_address',
'contact_pager' => 'c.pager_address',
'contact_has_host_notfications' => 'c.host_notifications_enabled',
'contact_has_service_notfications' => 'c.service_notifications_enabled',
'contact_can_submit_commands' => 'c.can_submit_commands',
'contact_notify_service_recovery' => 'c.notify_service_recovery',
'contact_notify_service_warning' => 'c.notify_service_warning',
'contact_notify_service_critical' => 'c.notify_service_critical',
'contact_notify_service_unknown' => 'c.notify_service_unknown',
'contact_notify_service_flapping' => 'c.notify_service_flapping',
'contact_notify_service_downtime' => 'c.notify_service_recovery',
'contact_notify_host_recovery' => 'c.notify_host_recovery',
'contact_notify_host_down' => 'c.notify_host_down',
'contact_notify_host_unreachable' => 'c.notify_host_unreachable',
'contact_notify_host_flapping' => 'c.notify_host_flapping',
'contact_notify_host_downtime' => 'c.notify_host_downtime',
'contact' => 'co.name1 COLLATE latin1_general_ci',
'contact_name' => 'co.name1 COLLATE latin1_general_ci',
'contact_alias' => 'c.alias',
'contact_email' => 'c.email_address',
'contact_pager' => 'c.pager_address',
'contact_has_host_notfications' => 'c.host_notifications_enabled',
'contact_has_service_notfications' => 'c.service_notifications_enabled',
'contact_can_submit_commands' => 'c.can_submit_commands',
'contact_notify_service_recovery' => 'c.notify_service_recovery',
'contact_notify_service_warning' => 'c.notify_service_warning',
'contact_notify_service_critical' => 'c.notify_service_critical',
'contact_notify_service_unknown' => 'c.notify_service_unknown',
'contact_notify_service_flapping' => 'c.notify_service_flapping',
'contact_notify_service_downtime' => 'c.notify_service_recovery',
'contact_notify_host_recovery' => 'c.notify_host_recovery',
'contact_notify_host_down' => 'c.notify_host_down',
'contact_notify_host_unreachable' => 'c.notify_host_unreachable',
'contact_notify_host_flapping' => 'c.notify_host_flapping',
'contact_notify_host_downtime' => 'c.notify_host_downtime',
),
'hosts' => array(
'host_object_id' => 'ho.object_id',
'host_name' => 'ho.name1',
'host' => 'ho.name1'
'host' => 'ho.name1',
'host_name' => 'ho.name1'
),
'services' => array(
'service_object_id' => 'so.object_id',
'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' => 'so.name2 COLLATE latin1_general_ci',
'service_description' => 'so.name2 COLLATE latin1_general_ci',
'service_host_name' => 'so.name1 COLLATE latin1_general_ci'
)
);

View File

@ -1,83 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Module\Monitoring\Backend\Statusdat\Query;
/**
* Query map for comments
*/
class CommentQuery extends StatusdatQuery
{
public static $mappedParameters = array(
'comment_id' => 'comment_id',
'comment_internal_id' => 'comment_id',
'comment_data' => 'comment_data',
'comment_author' => 'author',
'comment_timestamp' => 'entry_time',
'comment_is_persistent' => 'persistent',
'host_name' => 'host_name',
'host' => 'host_name',
);
public static $handlerParameters = array(
'comment_objecttype_id' => 'getCommentObjectType',
'comment_type' => 'getCommentType',
'comment_expiration_timestamp' => 'getExpirationTime',
'service' => 'getServiceDescription',
'service_name' => 'getServiceDescription',
'service_description' => 'getServiceDescription'
);
public function getServiceDescription(&$obj)
{
if (isset($obj->service_description)) {
return $obj->service_description;
}
return '';
}
public function getExpirationTime(&$obj)
{
if ($obj->expires) {
return $obj->expire_time;
} else {
return null;
}
}
public function getCommentObjectType(&$obj)
{
if (isset($obj->service_description)) {
return 2;
} else {
return 1;
}
}
public function getCommentType(&$obj)
{
switch ($obj->entry_type) {
case 1:
return 'comment';
case 2:
return 'downtime';
case 3:
return 'flapping';
case 4:
return 'ack';
}
return '';
}
public function getObjectType(&$obj)
{
return isset($obj->service_description) ? 'service ': 'host';
}
public function selectBase()
{
$this->select()->from("comments", array());
}
}

View File

@ -1,133 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Module\Monitoring\Backend\Statusdat\Query;
class ContactQuery extends StatusdatQuery
{
public static $mappedParameters = array(
'contact_name' => 'contact_name',
'contact_alias' => 'alias',
'contact_email' => 'email',
'contact_pager' => 'pager',
'contact_has_host_notfications' => 'host_notifications_enabled',
'contact_has_service_notfications' => 'service_notifications_enabled',
'contact_can_submit_commands' => 'can_submit_commands',
'contact_notify_host_timeperiod' => 'host_notification_period',
'contact_notify_service_timeperiod'=> 'service_notification_period',
'contact_service_notification_options' => 'service_notification_options',
'contact_host_notification_options' => 'host_notification_options',
'contactgroup_name' => 'group.contactgroup_name',
'contactgroup_alias' => 'group.alias'
);
public static $handlerParameters = array(
'contact_notify_service_recovery' => 'getServiceRecoveryFlag',
'contact_notify_service_warning' => 'getServiceWarningFlag',
'contact_notify_service_critical' => 'getServiceCriticalFlag',
'contact_notify_service_unknown' => 'getServiceUnknownFlag',
'contact_notify_service_flapping' => 'getServiceFlappingFlag',
'contact_notify_service_downtime' => 'getServiceDowntimeFlag',
'contact_notify_host_recovery' => 'getHostRecoveryFlag',
'contact_notify_host_down' => 'getHostDownFlag',
'contact_notify_host_unreachable' => 'getHostUnreachableFlag',
'contact_notify_host_flapping' => 'getHostFlappingFlag',
'contact_notify_host_downtime' => 'getHostDowntimeFlag',
'host_name' => 'getHost',
'host' => 'getHost',
'service_host_name' => 'getHost',
'service' => 'getService',
'service_description' => 'getService'
);
public function getHost(&$obj)
{
$result = array();
foreach ($this->state['host'] as $values) {
if (!isset($values->contacts)) {
continue;
}
if (stripos($values->contacts, $obj->contacts) !== false) {
$result[] = $values;
}
}
return $result;
}
public function getService(&$obj)
{
$result = array();
foreach ($this->state['service'] as $values) {
if (!isset($values->contacts)) {
continue;
}
if (stripos($values->contact_groups, $obj->contacts) !== false) {
$result[] = $values;
}
}
return $result;
}
public function getServiceRecoveryFlag(&$obj)
{
return stripos($obj->service_notification_options, 'r') === false ? 0 : 1;
}
public function getServiceWarningFlag(&$obj)
{
return stripos($obj->service_notification_options, 'w') === false ? 0 : 1;
}
public function getServiceCriticalFlag(&$obj)
{
return stripos($obj->service_notification_options, 'c') === false ? 0 : 1;
}
public function getServiceUnknownFlag(&$obj)
{
return stripos($obj->service_notification_options, 'u') === false ? 0 : 1;
}
public function getServiceFlappingFlag(&$obj)
{
return stripos($obj->service_notification_options, 'f') === false ? 0 : 1;
}
public function getServiceDowntimeFlag(&$obj)
{
return stripos($obj->service_notification_options, 's') === false ? 0 : 1;
}
public function getHostRecoveryFlag(&$obj)
{
return stripos($obj->host_notification_options, 'r') === false ? 0 : 1;
}
public function getHostDownFlag(&$obj)
{
return stripos($obj->host_notification_options, 'd') === false ? 0 : 1;
}
public function getHostUnreachableFlag(&$obj)
{
return stripos($obj->host_notification_options, 'u') === false ? 0 : 1;
}
public function getHostFlappingFlag(&$obj)
{
return stripos($obj->host_notification_options, 'f') === false ? 0 : 1;
}
public function getHostDowntimeFlag(&$obj)
{
return strpos($obj->host_notification_options, 's') === false ? 0 : 1;
}
public function selectBase()
{
$this->state = $this->ds->getState();
$this->select()->from("contacts", array());
}
}

View File

@ -1,61 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Module\Monitoring\Backend\Statusdat\Query;
class ContactgroupQuery extends StatusdatQuery
{
public static $mappedParameters = array(
'contactgroup_name' => 'contactgroup_name',
'contactgroup_alias' => 'alias',
'contact_name' => 'contact.contact_name',
'contact_alias' => 'contact.alias',
'contact_email' => 'contact.email',
'contact_pager' => 'contact.pager',
'contact_has_host_notfications' => 'contact.host_notifications_enabled',
'contact_has_service_notfications' => 'contact.service_notifications_enabled',
'contact_can_submit_commands' => 'contact.can_submit_commands',
'contact_notify_host_timeperiod' => 'contact.host_notification_period',
'contact_notify_service_timeperiod' => 'contact.service_notification_period',
'contact_service_notification_options' => 'contact.service_notification_options',
'contact_host_notification_options' => 'contact.host_notification_options',
);
public static $handlerParameters = array(
'host_name' => 'getHosts',
'host' => 'getHosts',
'service_host_name' => 'getHosts',
'service' => 'getService',
'service_description' => 'getService'
);
public function getHosts(&$obj)
{
$result = array();
foreach ($this->state['host'] as $values) {
if (stripos($values->contact_groups, $obj->contactgroup_name) !== false) {
$result[] = $values;
}
}
return $result;
}
public function getService(&$obj)
{
$result = array();
foreach ($this->state['service'] as $values) {
if (stripos($values->contact_groups, $obj->contactgroup_name) !== false) {
$result[] = $values;
}
}
return $result;
}
public function selectBase()
{
$this->state = $this->ds->getState();
return $this->select()->from("contactgroups", array());
}
}

View File

@ -1,79 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Module\Monitoring\Backend\Statusdat\Query;
/**
* Handling downtime queries
*/
class DowntimeQuery extends StatusdatQuery
{
/**
* Column map
* @var array
*/
public static $mappedParameters = array(
'downtime_author' => 'author',
'downtime_comment' => 'comment',
'downtime_duration' => 'duration',
'downtime_end' => 'end_time',
'downtime_was_started' => 'was_started',
'downtime_is_fixed' => 'fixed',
'downtime_is_in_effect' => 'is_in_effect',
'downtime_trigger_time' => 'trigger_time',
'downtime_triggered_by_id' => 'triggered_by_id',
'downtime_internal_downtime_id' => 'downtime_id',
'downtime_scheduled_start_time' => 'start_time',
'host' => 'host_name',
'host_name' => 'host_name',
'service_host_name' => 'host_name'
);
public static $handlerParameters = array(
'object_type' => 'getObjectType',
'downtime_start' => 'getDowntimeStart',
'downtime_is_flexible' => 'getFlexibleFlag',
'service_description' => 'getServiceDescription'
);
public static $fieldTypes = array(
'downtime_end' => self::TIMESTAMP,
'downtime_trigger_time' => self::TIMESTAMP,
'downtime_start' => self::TIMESTAMP
);
public function getServiceDescription(&$obj)
{
if (isset ($obj->service_description)) {
return $obj->service_description;
}
return '';
}
public function getDowntimeStart(&$obj)
{
if ($obj->trigger_time != '0') {
return $obj->trigger_time;
} else {
return $obj->start_time;
}
}
public function getFlexibleFlag(&$obj)
{
return $obj->fixed ? 0 : 1;
}
public function getObjectType(&$obj)
{
return isset($obj->service_description) ? 'service ': 'host';
}
public function selectBase()
{
$this->select()->from("downtimes", array());
}
}

View File

@ -1,248 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Module\Monitoring\Backend\Statusdat\Query;
class GroupsummaryQuery extends StatusdatQuery
{
public static $mappedParameters = array(
'hostgroup' => 'hostgroup_name',
'servicegroup' => 'servicegroup_name'
);
public static $handlerParameters = array(
'hosts_up' => 'getHostUpSum',
'hosts_unreachable_handled' => 'getHostUnreachableSum',
'hosts_unreachable_unhandled' => 'getHostUnreachableUnhandledSum',
'hosts_down_handled' => 'getHostDownSum',
'hosts_down_unhandled' => 'getHostDownUnhandledSum',
'hosts_pending' => 'getHostPendingSum',
'services_ok' => 'getServiceOkSum',
'services_unknown_handled' => 'getServiceUnknownSum',
'services_unknown_unhandled' => 'getServiceUnknownUnhandledSum',
'services_critical_handled' => 'getServiceCriticalSum',
'services_critical_unhandled' => 'getServiceCriticalUnhandledSum',
'services_warning_handled' => 'getServiceWarningSum',
'services_warning_unhandled' => 'getServiceWarningUnhandledSum',
'services_pending' => 'getServicePendingSum',
);
private function getMembers(&$obj, $hint = null)
{
if (!isset($obj->service) && !isset($obj->host)) {
return null;
}
$memberList = isset($obj->service) ? $obj->service : $obj->host;
if (isset($obj->host) && $hint == 'service') {
$result = array();
foreach ($memberList as &$member) {
if (isset($member->services)) {
$result = $result + $member->services;
}
}
return $result;
}
return $memberList;
}
private function getMembersByCriteria(&$obj, $type, $namefield, $criteriaFn)
{
$memberList = $this->getMembers($obj, $type);
if ($memberList === null) {
return 0;
}
$ids = array();
foreach ($memberList as $member) {
$name = $member->$type->$namefield;
if ($namefield === 'service_description') {
$name .= ';' . $member->$type->host_name;
}
if (isset($ids[$name])) {
continue;
} else {
if ($criteriaFn($member->$type)) {
$ids[$name] = true;
}
}
}
return count(array_keys($ids));
}
public function getHostUpSum(&$obj)
{
return $this->getMembersByCriteria($obj, 'host', 'host_name', function($member) {
return ($member->status->current_state == 0
&& $member->status->has_been_checked);
});
}
public function getHostUnreachableSum(&$obj)
{
return $this->getMembersByCriteria($obj, 'host', 'host_name', function($member) {
return ($member->status->current_state == 2
&& $member->status->has_been_checked
&& (
$member->status->problem_has_been_acknowledged
|| $member->status->scheduled_downtime_depth
)
);
});
}
public function getHostUnreachableUnhandledSum(&$obj)
{
return $this->getMembersByCriteria($obj, 'host', 'host_name', function($member) {
return ($member->status->current_state == 2
&& $member->status->has_been_checked
&& !(
$member->status->problem_has_been_acknowledged
|| $member->status->scheduled_downtime_depth
)
);
});
}
public function getHostDownSum(&$obj)
{
return $this->getMembersByCriteria($obj, 'host', 'host_name', function($member) {
return ($member->status->current_state == 1
&& $member->status->has_been_checked
&& (
$member->status->problem_has_been_acknowledged
|| $member->status->scheduled_downtime_depth
)
);
});
}
public function getHostDownUnhandledSum(&$obj)
{
return $this->getMembersByCriteria($obj, 'host', 'host_name', function($member) {
return ($member->status->current_state == 1
&& $member->status->has_been_checked
&& !(
$member->status->problem_has_been_acknowledged
|| $member->status->scheduled_downtime_depth
)
);
});
}
public function getHostPendingSum(&$obj)
{
return $this->getMembersByCriteria($obj, 'host', 'host_name', function($member) {
return (!$member->status->has_been_checked);
});
}
public function getServiceOkSum(&$obj)
{
return $this->getMembersByCriteria($obj, 'service', 'service_description', function($member) {
return ($member->status->current_state == 0
&& $member->status->has_been_checked);
});
}
public function getServiceUnknownSum(&$obj)
{
return $this->getMembersByCriteria($obj, 'service', 'service_description', function($member) {
return ($member->status->current_state == 3
&& $member->status->has_been_checked
&& (
$member->status->problem_has_been_acknowledged
|| $member->status->scheduled_downtime_depth
)
);
});
}
public function getServiceUnknownUnhandledSum(&$obj)
{
return $this->getMembersByCriteria($obj, 'service', 'service_description', function($member) {
return ($member->status->current_state == 3
&& $member->status->has_been_checked
&& !(
$member->status->problem_has_been_acknowledged
|| $member->status->scheduled_downtime_depth
)
);
});
}
public function getServiceCriticalSum(&$obj)
{
return $this->getMembersByCriteria($obj, 'service', 'service_description', function($member) {
return ($member->status->current_state == 2
&& $member->status->has_been_checked
&& (
$member->status->problem_has_been_acknowledged
|| $member->status->scheduled_downtime_depth
)
);
});
}
public function getServiceCriticalUnhandledSum(&$obj)
{
return $this->getMembersByCriteria($obj, 'service', 'service_description', function($member) {
return ($member->status->current_state == 2
&& $member->status->has_been_checked
&& !(
$member->status->problem_has_been_acknowledged
|| $member->status->scheduled_downtime_depth
)
);
});
}
public function getServiceWarningSum(&$obj)
{
return $this->getMembersByCriteria($obj, 'service', 'service_description', function($member) {
return ($member->status->current_state == 1
&& $member->status->has_been_checked
&& !(
$member->status->problem_has_been_acknowledged
|| $member->status->scheduled_downtime_depth
)
);
});
}
public function getServiceWarningUnhandledSum(&$obj)
{
return $this->getMembersByCriteria($obj, 'service', 'service_description', function($member) {
return ($member->status->current_state == 1
&& $member->status->has_been_checked
&& (
$member->status->problem_has_been_acknowledged
|| $member->status->scheduled_downtime_depth
)
);
});
}
public function getServicePendingSum(&$obj)
{
return $this->getMembersByCriteria($obj, 'service', 'service_description', function($member) {
return (!$member->status->has_been_checked);
});
}
private function getTarget()
{
if (in_array('servicegroup', $this->getColumns())) {
return 'servicegroups';
}
return 'hostgroups';
}
public function selectBase()
{
$this->select()->from($this->getTarget(), array());
}
}

View File

@ -1,25 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Module\Monitoring\Backend\Statusdat\Query;
/**
* Class HostgroupsummaryQuery
* @package Icinga\Backend\Statusdat
*/
class HostgroupQuery extends StatusdatQuery
{
public static $mappedParameters = array(
'hostgroups' => 'hostgroup_name',
'hostgroup_name' => 'hostgroup_name',
'hostgroup_alias' => 'alias',
'host' => 'host.host_name',
'host_name' => 'host.host_name'
);
public function selectBase()
{
$this->select()->from("hostgroups", array());
}
}

View File

@ -1,33 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Module\Monitoring\Backend\Statusdat\Query;
use Icinga\Protocol\Statusdat;
use Icinga\Exception;
/**
* Class HostListQuery
* @package Icinga\Backend\Statusdat
*/
class HostListQuery extends StatusdatQuery
{
/**
* @var \Icinga\Protocol\Statusdat\Query
*/
protected $query;
/**
* @var string
*/
protected $view = 'Icinga\Backend\Statusdat\DataView\StatusdatHostView';
/**
* @return mixed|void
*/
public function selectBase()
{
$this->select()->from("hosts", array());
}
}

View File

@ -1,28 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Module\Monitoring\Backend\Statusdat\Query;
/**
* Class HostgroupsummaryQuery
* @package Icinga\Backend\Statusdat
*/
class ServicegroupQuery extends StatusdatQuery
{
public static $mappedParameters = array(
'servicegroups' => 'servicegroup_name',
'servicegroup_name' => 'servicegroup_name',
'servicegroup_alias' => 'alias',
'host' => 'service.host_name',
'host_name' => 'service.host_name',
'service' => 'service.service_description',
'service_description'=> 'service.service_description'
);
public function selectBase()
{
$this->select()->from("servicegroups", array());
}
}

View File

@ -1,22 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Module\Monitoring\Backend\Statusdat\Query;
/**
* Class ServicegroupsummaryQuery
* @package Icinga\Backend\Statusdat
*/
class ServicegroupsummaryQuery extends GroupsummaryQuery
{
/**
* @var string
*/
protected $groupType = "servicegroup";
/**
* @var string
*/
protected $base = "services";
}

View File

@ -1,30 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Module\Monitoring\Backend\Statusdat\Query;
use Icinga\Protocol\Statusdat;
use Icinga\Exception;
/**
* Class ServicelistQuery
* @package Icinga\Backend\Statusdat
*/
class ServicelistQuery extends StatusdatQuery
{
/**
* @var \Icinga\Protocol\Statusdat\Query
*/
protected $query;
/**
* @var string
*/
protected $view = 'Icinga\Backend\Statusdat\DataView\StatusdatServiceView';
public function selectBase()
{
$this->select()->from("services", array());
}
}

View File

@ -1,361 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Module\Monitoring\Backend\Statusdat\Query;
use Icinga\Protocol\Statusdat;
use Icinga\Protocol\Statusdat\IReader;
use Icinga\Exception;
class StatusQuery extends StatusdatQuery
{
/**
* @var array
*/
public static $mappedParameters = array(
'host' => 'host.host_name',
'host_name' => 'host.host_name',
'host_display_name' => 'host.host_name',
'host_alias' => 'host.alias',
'host_address' => 'host.address',
'host_icon_image' => 'host.icon_image',
'host_action_url' => 'host.action_url',
'host_notes_url' => 'host.notes_url',
'host_output' => 'host.status.plugin_output',
'host_long_output' => 'host.status.long_plugin_output',
'host_perfdata' => 'host.status.performance_data',
'host_check_source' => 'host.status.check_source',
'host_acknowledged' => 'host.status.problem_has_been_acknowledged',
'host_last_state_change' => 'host.status.last_state_change',
'host_last_hard_state' => 'host.status.last_hard_state',
'host_last_hard_state_change' => 'host.status.last_hard_state_change',
'host_check_command' => 'host.status.check_command',
'host_last_check' => 'host.status.last_check',
'host_next_check' => 'host.status.next_check',
'host_check_execution_time' => 'host.status.check_execution_time',
'host_check_latency' => 'host.status.check_latency',
'host_notifications_enabled' => 'host.status.notifications_enabled',
'host_last_time_up' => 'host.status.last_time_up',
'host_last_time_down' => 'host.status.last_time_down',
'host_last_time_unreachable' => 'host.status.last_time_unreachable',
'host_current_check_attempt' => 'host.status.current_attempt',
'host_max_check_attempts' => 'host.status.max_attempts',
'host_check_type' => 'host.status.check_type',
'host_state_type' => 'host.status.state_type',
'host_last_notification' => 'host.status.last_notification',
'host_next_notification' => 'host.status.next_notification',
'host_no_more_notifications' => 'host.status.no_more_notifications',
'host_problem_has_been_acknowledged' => 'host.status.problem_has_been_acknowledged',
'host_acknowledgement_type' => 'host.status.acknowledgement_type',
'host_current_notification_number' => 'host.status.current_notification_number',
'host_passive_checks_enabled' => 'host.status.passive_checks_enabled',
'host_active_checks_enabled' => 'host.status.active_checks_enabled',
'host_event_handler_enabled' => 'host.status.event_handler_enabled',
'host_flap_detection_enabled' => 'host.status.flap_detection_enabled',
'host_is_flapping' => 'host.status.is_flapping',
'host_percent_state_change' => 'host.status.percent_state_change',
'host_scheduled_downtime_depth' => 'host.status.scheduled_downtime_depth',
'host_failure_prediction_enabled' => 'host.status.failure_prediction_enabled',
'host_process_performance_data' => 'host.status.process_performance_data',
'host_obsessing' => 'host.status.obsess_over_host',
'host_modified_host_attributes' => 'host.status.modified_host_attributes',
'host_event_handler' => 'host.status.event_handler',
'host_check_command' => 'host.status.check_command',
'host_normal_check_interval' => 'host.status.normal_check_interval',
'host_retry_check_interval' => 'host.status.retry_check_interval',
'host_check_timeperiod_object_id' => 'host.status.check_timeperiod_object_id',
'host_status_update_time' => 'host.status.status_update_time',
'service_host_name' => 'service.host_name',
'service' => 'service.service_description',
'service_description' => 'service.service_description',
'service_display_name' => 'service.service_description',
'service_icon_image' => 'service.icon_image',
'service_action_url' => 'service.action_url',
'service_notes_url' => 'service.notes_url',
'service_state_type' => 'service.status.state_type',
'service_output' => 'service.status.output',
'service_long_output' => 'service.status.long_output',
'service_perfdata' => 'service.status.perfdata',
'service_check_source' => 'service.status.check_source',
'service_acknowledged' => 'service.status.problem_has_been_acknowledged',
'service_last_state_change' => 'service.status.last_state_change',
'service_check_command' => 'service.status.check_command',
'service_last_time_ok' => 'service.status.last_time_ok',
'service_last_time_warning' => 'service.status.last_time_warning',
'service_last_time_critical' => 'service.status.last_time_critical',
'service_last_time_unknown' => 'service.status.last_time_unknown',
'service_current_check_attempt' => 'service.status.current_check_attempt',
'service_max_check_attempts' => 'service.status.max_check_attempts',
'service_last_check' => 'service.status.last_check',
'service_next_check' => 'service.status.next_check',
'service_check_type' => 'service.status.check_type',
'service_last_hard_state_change' => 'service.status.last_hard_state_change',
'service_last_hard_state' => 'service.status.last_hard_state',
'service_last_notification' => 'service.status.last_notification',
'service_next_notification' => 'service.status.next_notification',
'service_no_more_notifications' => 'service.status.no_more_notifications',
'service_notifications_enabled' => 'service.status.notifications_enabled',
'service_problem_has_been_acknowledged' => 'service.status.problem_has_been_acknowledged',
'service_acknowledgement_type' => 'service.status.acknowledgement_type',
'service_current_notification_number' => 'service.status.current_notification_number',
'service_passive_checks_enabled' => 'service.status.passive_checks_enabled',
'service_active_checks_enabled' => 'service.status.active_checks_enabled',
'service_event_handler_enabled' => 'service.status.event_handler_enabled',
'service_flap_detection_enabled' => 'service.status.flap_detection_enabled',
'service_is_flapping' => 'service.status.is_flapping',
'service_percent_state_change' => 'service.status.percent_state_change',
'service_check_latency' => 'service.status.latency',
'service_check_execution_time' => 'service.status.execution_time',
'service_scheduled_downtime_depth' => 'service.status.scheduled_downtime_depth',
'service_failure_prediction_enabled' => 'service.status.failure_prediction_enabled',
'service_process_performance_data' => 'service.status.process_performance_data',
'service_obsessing' => 'service.status.obsess_over_service',
'service_modified_service_attributes' => 'service.status.modified_service_attributes',
'service_event_handler' => 'service.status.event_handler',
'service_check_command' => 'service.status.check_command',
'service_normal_check_interval' => 'service.status.normal_check_interval',
'service_retry_check_interval' => 'service.status.retry_check_interval',
'service_check_timeperiod_object_id' => 'service.status.check_timeperiod_object_id',
'service_status_update_time' => 'service.status.status_update_time',
'hostgroup' => 'host.group',
'servicegroup' => 'service.group'
);
/**
* @var mixed
*/
private $state;
/**
* @var array
*/
public static $handlerParameters = array(
'host_ipv4' => 'getAddress',
'host_unhandled_service_count' => 'getNrOfUnhandledServices',
'host_last_comment' => 'getLastComment',
'service_last_comment' => 'getLastComment',
'host_state' => 'getStateForHost',
'host_hard_state' => 'getHardStateForHost',
'host_handled' => 'isHandledForHost',
'host_unhandled' => 'isHostUnhandled',
'host_severity' => 'getSeverityForHost',
'host_in_downtime' => 'isInDowntimeForHost',
'host_problem' => 'isProblemForHost',
'host_attempt' => 'getAttemptStringForHost',
'service_state' => 'getState',
'service_hard_state' => 'getHardState',
'service_handled' => 'isHandled',
'service_unhandled' => 'isUnhandled',
'service_severity' => 'getSeverity',
'service_in_downtime' => 'isInDowntime',
'service_problem' => 'isProblem',
'service_attempt' => 'getAttemptString',
);
public static $fieldTypes = array(
'host_last_state_change' => self::TIMESTAMP,
'host_last_hard_state_change' => self::TIMESTAMP,
'host_last_check' => self::TIMESTAMP,
'host_next_check' => self::TIMESTAMP,
'host_last_time_up' => self::TIMESTAMP,
'host_last_time_down' => self::TIMESTAMP,
'host_last_time_unreachable' => self::TIMESTAMP,
'host_status_update_time' => self::TIMESTAMP,
'service_last_state_change' => self::TIMESTAMP,
'service_last_hard_state_change' => self::TIMESTAMP,
'service_last_check' => self::TIMESTAMP,
'service_next_check' => self::TIMESTAMP,
'service_last_time_ok' => self::TIMESTAMP,
'service_last_time_warning' => self::TIMESTAMP,
'service_last_time_critical' => self::TIMESTAMP,
'service_last_time_unknown' => self::TIMESTAMP,
'service_status_update_time' => self::TIMESTAMP
);
public function selectBase()
{
$target = $this->getTarget();
$this->select()->from($target."s", array());
}
public function getAttemptString(&$obj)
{
return $obj->status->current_attempt . '/' . $obj->status->max_attempts;
}
public function isProblem(&$obj)
{
return $obj->status->current_state > 0 ? 1 : 0;
}
public function isInDowntime(&$obj)
{
return $obj->status->scheduled_downtime_depth > 0 ? 1 : 0;
}
public function getAddress(&$obj)
{
return inet_pton($obj->host->address);
}
public function getState(&$obj)
{
if (!$obj->status->has_been_checked) {
return 99;
}
return $obj->status->current_state;
}
public function getHardState(&$obj)
{
if (!$obj->status->has_been_checked) {
return 99;
} else {
if ($obj->status->state_type == 1) {
return $this->status->current_state;
} else {
return $this->status->last_hard_state;
}
}
}
public function getSeverity(&$host)
{
$status = $host->status;
$severity = 0;
if (!$status->has_been_checked) {
$severity += 16;
} elseif($status->current_state == 0) {
return $severity;
} elseif ($status->current_state == 1) {
$severity += 32;
} elseif ($status->current_state == 2) {
$severity += 64;
} else {
$severity += 256;
}
if ($status->problem_has_been_acknowledged == 1) {
$severity += 2;
} elseif ($status->scheduled_downtime_depth > 0) {
$severity += 1;
} else {
$severity += 4;
}
return $severity;
}
public function isHandled(&$host)
{
return ($host->status->current_state == 0 ||
$host->status->problem_has_been_acknowledged == 1 ||
$host->status->scheduled_downtime_depth > 0) ? 1 : 0;
}
public function isUnhandled(&$hostOrService)
{
return +!$this->isHandled($hostOrService);
}
public function getNrOfUnhandledServices(&$obj)
{
$host = &$obj->host;
$ct = 0;
if (!isset($host->services)) {
return $ct;
}
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;
}
/**
* @param $item
* @return null
*/
public function getHost(&$item)
{
if (!isset($this->state['service'][$item->host_name])) {
return null;
}
if (!isset($this->state['host'][$item->host_name])) {
return null;
}
return $this->state['host'][$item->host_name];
}
private function getTarget()
{
foreach ($this->getColumns() as $column) {
if (preg_match("/^service/",$column)) {
return "service";
}
}
return "host";
}
public function getStateForHost(&$obj)
{
return $this->getState($obj->host);
}
public function getHardStateForHost(&$obj)
{
return $this->getHardState($obj->host);
}
public function isHandledForHost(&$obj)
{
return $this->isHandled($obj->host);
}
public function isHostUnhandled(&$obj)
{
return $this->isUnhandled($obj->host);
}
public function getSeverityForHost(&$obj)
{
return $this->getSeverity($obj->host);
}
public function isInDowntimeForHost(&$obj)
{
return $this->isInDowntime($obj->host);
}
public function isProblemForHost(&$obj)
{
return $this->isProblem($obj->host);
}
public function getAttemptStringForHost(&$obj)
{
return $this->getAttemptStringForHost($obj->host);
}
}

View File

@ -1,115 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Module\Monitoring\Backend\Statusdat\Query;
class StatusSummaryQuery extends StatusdatQuery
{
public function selectBase()
{
$this->select()->from('hosts', array())->groupByFunction(
'groupByStatus',
$this
);
}
public function groupByStatus(&$indices)
{
$hostsPending = 0;
$hostsUp = 0;
$hostsDownHandled = 0;
$hostsDownUnhandled = 0;
$hostsUnreachableHandled = 0;
$hostsUnreachableUnhandled = 0;
$servicesPending = 0;
$servicesOk = 0;
$servicesCriticalHandled = 0;
$servicesCriticalUnhandled = 0;
$servicesWarningHandled = 0;
$servicesWarningUnhandled = 0;
$servicesUnknownHandled = 0;
$servicesUnknownUnhandled = 0;
foreach ($indices['host'] as $hostName) {
$host = $this->ds->getObjectByName('host', $hostName);
$hostStatus = $host->status;
if ($hostStatus->has_been_checked !== '1') {
++$hostsPending;
} elseif ($hostStatus->current_state === '0') {
++$hostsUp;
} elseif ($hostStatus->current_state === '2') {
if ($hostStatus->problem_has_been_acknowledged === '1'
|| $hostStatus->scheduled_downtime_depth === '1'
) {
++$hostsDownHandled;
} else {
++$hostsDownUnhandled;
}
} elseif ($hostStatus->current_state === '1') {
if ($hostStatus->problem_has_been_acknowledged === '1'
|| $hostStatus->scheduled_downtime_depth === '1'
) {
++$hostsUnreachableHandled;
} else {
++$hostsUnreachableUnhandled;
}
}
if ($host->services === null) {
// Host does not have any service associated
continue;
}
foreach ($host->services as $service) {
$serviceStatus = $service->status;
if ($serviceStatus->has_been_checked !== '1') {
++$servicesPending;
} elseif ($serviceStatus->current_state === '0') {
++$servicesOk;
} elseif ($serviceStatus->current_state === '2') {
if ($serviceStatus->problem_has_been_acknowledged === '1'
|| $serviceStatus->scheduled_downtime_depth === '1'
|| $hostStatus->current_state !== '0'
) {
++$servicesCriticalHandled;
} else {
++$servicesCriticalUnhandled;
}
} elseif ($serviceStatus->current_state === '1') {
if ($serviceStatus->problem_has_been_acknowledged === '1'
|| $serviceStatus->scheduled_downtime_depth === '1'
|| $hostStatus->current_state !== '0'
) {
++$servicesWarningHandled;
} else {
++$servicesWarningUnhandled;
}
} elseif ($serviceStatus->current_state === '3') {
if ($serviceStatus->problem_has_been_acknowledged === '1'
|| $serviceStatus->scheduled_downtime_depth === '1'
|| $hostStatus->current_state !== '0'
) {
++$servicesUnknownHandled;
} else {
++$servicesUnknownUnhandled;
}
}
}
}
$rs = array(
'hosts_up' => $hostsUp,
'hosts_unreachable_handled' => $hostsUnreachableHandled,
'hosts_unreachable_unhandled' => $hostsUnreachableUnhandled,
'hosts_down_handled' => $hostsDownHandled,
'hosts_down_unhandled' => $hostsDownUnhandled,
'hosts_pending' => $hostsPending,
'services_ok' => $servicesOk,
'services_unknown_handled' => $servicesUnknownHandled,
'services_unknown_unhandled' => $servicesUnknownUnhandled,
'services_critical_handled' => $servicesCriticalHandled,
'services_critical_unhandled' => $servicesCriticalUnhandled,
'services_warning_handled' => $servicesWarningHandled,
'services_warning_unhandled' => $servicesWarningUnhandled,
'services_pending' => $servicesPending
);
return array((object) array_intersect_key($rs, array_flip($this->getColumns())));
}
}

View File

@ -1,218 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Module\Monitoring\Backend\Statusdat\Query;
use Icinga\Logger\Logger;
use Icinga\Data\Optional;
use Icinga\Data\The;
use Icinga\Filter\Query\Node;
use Icinga\Filter\Query\Tree;
use Icinga\Protocol\Statusdat;
use Icinga\Exception;
use Icinga\Data\SimpleQuery;
use Icinga\Protocol\Statusdat\Query as Query;
use Icinga\Protocol\Statusdat\View\AccessorStrategy;
use Icinga\Filter\Filterable;
/**
* Class Query
* @package Icinga\Backend\Statusdat
*/
abstract class StatusdatQuery extends Query implements Filterable, AccessorStrategy
{
const TIMESTAMP = 'timestamp';
/**
* An array containing the mappi
*
* When implementing your own Mapper, this contains the static mapping rules.
*
* @see Icinga\Module\Monitoring\Backend\Statusdat\DataView\StatusdatServiceView for an example
* @var array
*/
public static $mappedParameters = array();
/**
* An array containing all properties that are retrieved by a function
*
* 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
*
* @var array
* @see Icinga\Backend\Statusdat\DataView\StatusdatServiceView for an example
*/
public static $handlerParameters = array();
public static $fieldTypes = array();
/**
* @var null
*/
private $cursor = null;
public function init()
{
parent::init();
$this->selectBase();
}
abstract public function selectBase();
/**
* Orders the resultset
*
* @param string $column Either a string in the 'FIELD ASC/DESC format or only the field
* @param null $dir 'asc' or 'desc'
* @return Query Returns this query,for fluent interface
*/
public function order($column, $dir = null, $isFunction = false)
{
if ($column) {
$column = strval($column);
if (isset(static::$mappedParameters[$column])) {
parent::order(static::$mappedParameters[$column], strtolower($dir));
} elseif (isset(static::$handlerParameters[$column])) {
parent::orderByFn(array($this, static::$handlerParameters[$column]), strtolower($dir));
} else {
Logger::info("Tried to sort by unknown column %s", $column);
}
}
return $this;
}
private $functionMap = array(
"TO_DATE" => "toDateFormat"
);
/**
*
* @see Icinga\Backend\DataView\AccessorStrategy
*
* @param The $item
* @param The $field
* @return The|string
* @throws \InvalidArgumentException
*/
public function get(&$item, $field)
{
$result = null;
if (isset($item->$field)) {
$result = $item->$field;
} elseif (isset(static::$mappedParameters[$field])) {
$result = $this->getMappedParameter($item, $field);
} elseif (isset(static::$handlerParameters[$field])) {
$hdl = static::$handlerParameters[$field];
$result = $this->$hdl($item);
}
return $result;
}
private function applyPropertyFunction($function, $value)
{
if (!isset($this->functionMap[$function])) {
return $value;
}
$fn = $this->functionMap[$function];
return $this->$fn($value);
}
private function toDateFormat($value)
{
if (is_numeric($value)) {
return date("Y-m-d H:i:s", intval($value));
} else {
return $value;
}
}
private function getMappedParameter(&$item, $field)
{
$matches = array();
$fieldDef = static::$mappedParameters[$field];
$function = false;
if (preg_match_all('/(?P<FUNCTION>\w+)\((?P<PARAMETER>.*)\)/', $fieldDef, $matches)) {
$function = $matches["FUNCTION"][0];
$fieldDef = $matches["PARAMETER"][0];
}
$mapped = explode(".", $fieldDef);
$res = $item;
foreach ($mapped as $map) {
if (is_array($res)) {
$subResult = array();
foreach ($res as $subitem) {
if (!isset($subitem->$map)) {
continue;
}
$subResult[] = $subitem->$map;
}
$res = join(',', $subResult);
} else {
if (!isset($res->$map)) {
return "";
}
$res = $res->$map;
}
}
if ($function) {
return $this->applyPropertyFunction($function, $res);
}
return $res;
}
/**
*
* @see Icinga\Backend\DataView\AccessorStrategy
*
* @param The $field
* @return The|string
*/
public function getMappedField($field)
{
if (isset(static::$mappedParameters[$field])) {
return static::$mappedParameters[$field];
}
return $field;
}
/**
*
* @see Icinga\Backend\DataView\AccessorStrategy
*
* @param The $item
* @param The $field
* @return bool
*/
public function exists(&$item, $field)
{
return (isset($item->$field)
|| isset(static::$mappedParameters[$field])
|| isset(static::$handlerParameters[$field])
);
}
public function isValidFilterTarget($field)
{
return true;
}
public function isTimestamp($field)
{
return isset(static::$fieldTypes[$field]) && static::$fieldTypes[$field] === self::TIMESTAMP;
}
}

View File

@ -18,6 +18,7 @@ class Contact extends DataView
public function getColumns()
{
return array(
'contact',
'contact_name',
'contact_alias',
'contact_email',

View File

@ -18,7 +18,9 @@ class Contactgroup extends DataView
public function getColumns()
{
return array(
'contact',
'contact_name',
'contactgroup',
'contactgroup_name',
'contactgroup_alias',
'host',