diff --git a/library/Icinga/Data/BaseQuery.php b/library/Icinga/Data/BaseQuery.php index 559386099..d96ca0e96 100644 --- a/library/Icinga/Data/BaseQuery.php +++ b/library/Icinga/Data/BaseQuery.php @@ -222,15 +222,6 @@ abstract class BaseQuery implements Filterable $this->filter = $filter; } - /** - * Parse a backend specific filter expression and return a Query\Node object - * - * @param $expression The expression to parse - * @param $parameters Optional parameters for the expression - * @return Node A query node or null if it's an invalid expression - */ - abstract protected function parseFilterExpression($expression, $parameters = null); - /** * Return all default columns * @@ -422,6 +413,33 @@ abstract class BaseQuery implements Filterable return $paginator; } + + /** + * Parse a backend specific filter expression and return a Query\Node object + * + * @param $expression The expression to parse + * @param $parameters Optional parameters for the expression + * + * @return Node A query node or null if it's an invalid expression + */ + protected function parseFilterExpression($expression, $parameter = null) + { + $splitted = explode(' ', $expression, 3); + if (count($splitted) === 1 && $parameter) { + return Node::createOperatorNode(Node::OPERATOR_EQUALS, $splitted[0], $parameter); + } elseif (count($splitted) === 2 && $parameter) { + Node::createOperatorNode($splitted[0], $splitted[1], is_string($parameter)); + return Node::createOperatorNode(Node::OPERATOR_EQUALS, $splitted[0], $parameter); + } elseif (count($splitted) === 3) { + if (trim($splitted[2]) === '?' && is_string($parameter)) { + return Node::createOperatorNode($splitted[1], $splitted[0], $parameter); + } else { + return Node::createOperatorNode($splitted[1], $splitted[0], $splitted[2]); + } + } + return null; + } + /** * Total result size regardless of limit and offset * diff --git a/library/Icinga/Data/Db/Query.php b/library/Icinga/Data/Db/Query.php index 92f37448b..bd381c997 100644 --- a/library/Icinga/Data/Db/Query.php +++ b/library/Icinga/Data/Db/Query.php @@ -287,32 +287,6 @@ class Query extends BaseQuery return strval($this->getSelectQuery()); } - /** - * Parse a backend specific filter expression and return a Query\Node object - * - * @param $expression The expression to parse - * @param $parameters Optional parameters for the expression - * - * @return Node A query node or null if it's an invalid expression - */ - protected function parseFilterExpression($expression, $parameter = null) - { - $splitted = explode(' ', $expression, 3); - if (count($splitted) === 1 && $parameter) { - return Node::createOperatorNode(Node::OPERATOR_EQUALS, $splitted[0], $parameter); - } elseif (count($splitted) === 2 && $parameter) { - Node::createOperatorNode($splitted[0], $splitted[1], is_string($parameter)); - return Node::createOperatorNode(Node::OPERATOR_EQUALS, $splitted[0], $parameter); - } elseif (count($splitted) === 3) { - if (trim($splitted[2]) === '?' && is_string($parameter)) { - return Node::createOperatorNode($splitted[1], $splitted[0], $parameter); - } else { - return Node::createOperatorNode($splitted[1], $splitted[0], $splitted[2]); - } - } - return null; - } - public function applyFilter() { $parser = new TreeToSqlParser($this); diff --git a/library/Icinga/Data/ResourceFactory.php b/library/Icinga/Data/ResourceFactory.php index efae7ac8e..bfd5afcab 100644 --- a/library/Icinga/Data/ResourceFactory.php +++ b/library/Icinga/Data/ResourceFactory.php @@ -25,7 +25,7 @@ class ResourceFactory implements ConfigAwareFactory public static function getResourceConfig($resourceName) { if (($resourceConfig = self::$resources->get($resourceName)) === null) { - throw new ConfigurationError('BLUBB?!'); + throw new ConfigurationError('Resource "' . $resourceName . '" couldn\'t be retrieved'); } return $resourceConfig; } @@ -40,7 +40,7 @@ class ResourceFactory implements ConfigAwareFactory $resource = new StatusdatReader($config); break; default: - throw new ConfigurationError('BLUBB2?!'); + throw new ConfigurationError('Unsupported Backend "' + $config->type + '"'); } return $resource; diff --git a/library/Icinga/Protocol/Commandpipe/CommandPipe.php b/library/Icinga/Protocol/Commandpipe/CommandPipe.php index f42f0fc14..462fcbb86 100644 --- a/library/Icinga/Protocol/Commandpipe/CommandPipe.php +++ b/library/Icinga/Protocol/Commandpipe/CommandPipe.php @@ -142,7 +142,7 @@ class CommandPipe * @param Command $command * @param array $objects */ - public function sendCommand(Command $command, array $objects) + public function sendCommand(Command $command, array $objects = array()) { if ($command->provideGlobalCommand() === true) { $this->transport->send($command->getGlobalCommand()); diff --git a/library/Icinga/Protocol/Statusdat/IReader.php b/library/Icinga/Protocol/Statusdat/IReader.php index 4dae2e929..607923c04 100755 --- a/library/Icinga/Protocol/Statusdat/IReader.php +++ b/library/Icinga/Protocol/Statusdat/IReader.php @@ -35,11 +35,6 @@ interface IReader */ public function getState(); - /** - * @return mixed - */ - public function getObjects(); - /** * @param $type * @param $name diff --git a/library/Icinga/Protocol/Statusdat/ObjectContainer.php b/library/Icinga/Protocol/Statusdat/ObjectContainer.php index 384b0211e..96f91572c 100644 --- a/library/Icinga/Protocol/Statusdat/ObjectContainer.php +++ b/library/Icinga/Protocol/Statusdat/ObjectContainer.php @@ -48,7 +48,7 @@ class ObjectContainer extends \stdClass * @param \stdClass $obj * @param IReader $reader */ - public function __construct(\stdClass &$obj, IReader &$reader) + public function __construct(&$obj, IReader &$reader) { $this->ref = & $obj; $this->reader = & $reader; @@ -62,10 +62,13 @@ class ObjectContainer extends \stdClass { $exploded = explode(".", $attribute); $result = $this->ref; - foreach ($exploded as $elem) { - $result = $result->$elem; + foreach ($exploded as $elem) { + if (isset($result->$elem)) { + $result = $result->$elem; + } } + return $result; } } diff --git a/library/Icinga/Protocol/Statusdat/Parser.php b/library/Icinga/Protocol/Statusdat/Parser.php index fa8418559..541384c62 100755 --- a/library/Icinga/Protocol/Statusdat/Parser.php +++ b/library/Icinga/Protocol/Statusdat/Parser.php @@ -34,45 +34,59 @@ use Icinga\Exception\ProgrammingError; use Icinga\Protocol\Statusdat\Exception\ParsingException as ParsingException; /** - * Class Parser - * @package Icinga\Protocol\Statusdat + * 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(); /** - * @var null|resource + * The resource pointing to the currently read file + * + * @var resource */ - private $filehandle = null; + private $filehandle; /** - * @var null + * String representation of the currently parsed object type + * + * @var string */ - private $currentObjectType = null; + private $currentObjectType; /** - * @var null + * The current state type (host, service) + * + * @var string */ - private $currentStateType = null; + private $currentStateType; /** - * @var null + * The internal representation of the icinga statue + * + * @var array */ - private $icingaState = null; + private $icingaState; /** + * The current line being read + * * @var int */ private $lineCtr = 0; /** - * @param null $filehandle - * @param null $baseState - * @throws \Icinga\Exception\ConfigurationError + * Create a new parser using the given file + * + * @param resource $filehandle The file handle to usefor parsing + * @param array $baseState The state using for the base + * + * @throws ConfigurationError When the file can't be used */ public function __construct($filehandle = null, $baseState = null) { @@ -85,11 +99,10 @@ class Parser } /** - * + * Parse the given file handle as an objects file and read object information */ public function parseObjectsFile() { - Logger::debug("Reading new objects file"); $DEFINE = strlen("define "); $filehandle = $this->filehandle; $this->icingaState = array(); @@ -111,8 +124,7 @@ class Parser } /** - * @param null $filehandle - * @throws ProgrammingError + * Parse the given file handle as an status.dat file and read runtime information */ public function parseRuntimeState($filehandle = null) { @@ -127,27 +139,25 @@ class Parser } $this->overwrites = array(); while (!feof($filehandle)) { - $line = trim(fgets($filehandle)); - $this->lineCtr++; if ($line === "" || $line[0] === "#") { continue; } - $this->currentStateType = trim(substr($line, 0, -1)); $this->readCurrentState(); } - } /** - * @throws Exception\ParsingException + * Read the next object from the object.cache file handle + * + * @throws ParsingException */ private function readCurrentObject() { $filehandle = $this->filehandle; - $monitoringObject = new \stdClass(); + $monitoringObject = new PrintableObject(); while (!feof($filehandle)) { $line = explode("\t", trim(fgets($filehandle)), 2); $this->lineCtr++; @@ -169,7 +179,8 @@ class Parser } /** - * TODO: Discard old runtime data + * Read the next state from the status.dat file handler + * * @throws Exception\ParsingException */ private function readCurrentState() @@ -204,6 +215,7 @@ class Parser $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)) { @@ -211,13 +223,25 @@ class Parser $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; } /** - * @return null|string + * Get the corresponding object type name for the given state + * + * @return string */ private function getObjectTypeForState() { @@ -241,8 +265,10 @@ class Parser } /** - * @param bool $returnString - * @return string + * 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) { @@ -260,42 +286,54 @@ class Parser } /** - * @param $object + * 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->icingaState[$this->currentObjectType][$name] = &$object; } $this->registerObjectAsProperty($object); } /** - * @param $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") { + 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) { // this would be error in the parser implementation + + 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")); - } else { + } 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); } @@ -308,6 +346,13 @@ class Parser 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 { @@ -315,6 +360,7 @@ class Parser if (!isset($source->$property)) { $source->$property = array(); } + array_push($source->$property, $object); } @@ -322,8 +368,10 @@ class Parser } /** - * @param $object - * @param $objType + * 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) { @@ -331,7 +379,7 @@ class Parser } /** - * + * Process deferred objects */ protected function processDeferred() { @@ -342,8 +390,10 @@ class Parser } /** - * @param $object - * @return array + * 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) { @@ -366,11 +416,17 @@ class Parser } /** - * @param $object - * @return bool|string + * 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; } @@ -378,11 +434,18 @@ class Parser if (isset($object->{$name})) { return $object->{$name}; } - return false; + 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() diff --git a/library/Icinga/Protocol/Statusdat/PrintableObject.php b/library/Icinga/Protocol/Statusdat/PrintableObject.php new file mode 100644 index 000000000..456a79010 --- /dev/null +++ b/library/Icinga/Protocol/Statusdat/PrintableObject.php @@ -0,0 +1,44 @@ + + * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 + * @author Icinga Development Team + */ +// {{{ICINGA_LICENSE_HEADER}}} + +namespace Icinga\Protocol\Statusdat; + +class PrintableObject +{ + public function __toString() + { + if (isset($this->contact_name)) { + return $this->contact_name; + } else if (isset($this->service_description)) { + return $this->service_description; + } else if (isset($this->host_name)) { + return $this->host_name; + } + return ''; + } +} \ No newline at end of file diff --git a/library/Icinga/Protocol/Statusdat/Query.php b/library/Icinga/Protocol/Statusdat/Query.php index cec76996b..4f844a896 100755 --- a/library/Icinga/Protocol/Statusdat/Query.php +++ b/library/Icinga/Protocol/Statusdat/Query.php @@ -28,93 +28,85 @@ namespace Icinga\Protocol\Statusdat; -use Icinga\Data\Optional; -use Icinga\Data\The; +use Exception; use Icinga\Filter\Query\Node; use Icinga\Protocol; use Icinga\Data\BaseQuery; +use Icinga\Protocol\Statusdat\View\MonitoringObjectList; +use Icinga\Protocol\Statusdat\Query\IQueryPart; /** - * Class Query - * @package Icinga\Protocol\Statusdat + * Base implementation for Statusdat queries. + * */ class Query extends BaseQuery { /** + * 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("hostdowntime", "servicedowntime"), - "hostdowntimes" => array("hostdowntime"), - "servicedowntimes" => array("servicedowntime"), - "hostgroups" => array("hostgroup"), - "servicegroups" => array("servicegroup"), - "comments" => array("servicecomment", "hostcomment"), - "hostcomments" => array("hostcomment"), - "servicecomments" => array("servicecomment") + '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') ); /** - * @var IReader|null + * The current StatusDat query that will be applied upon calling fetchAll + * + * @var IQueryPart */ - private $reader = null; + private $queryFilter = null; /** + * The current query source being used + * * @var string */ - private $source = ""; - - /** - * @var null - */ - private $limit = null; - - /** - * @var int - */ - private $offset = 0; + 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(); /** - * @var null + * An optional function callback to use for more specific grouping + * + * @var array */ private $groupByFn = null; /** - * @var array - */ - private $filter = array(); - - /** - * + * The scope index for the callback function */ const FN_SCOPE = 0; /** - * + * The name index for the callback function */ const FN_NAME = 1; /** - * @return bool - */ - public function hasOrder() - { - return !empty($this->orderColumns); - } - - /** + * Return true if columns are set for this query + * * @return bool */ public function hasColumns() @@ -123,59 +115,27 @@ class Query extends BaseQuery return !empty($columns); } - - /** - * @return bool + * Set the status.dat specific IQueryPart filter to use + * + * @param IQueryPart $filter */ - public function hasLimit() + public function setQueryFilter($filter) { - return $this->limit !== false; + $this->queryFilter = $filter; } /** - * @return bool + * 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 hasOffset() + public function order($columns, $dir = null, $isFunction = false) { - return $this->offset !== false; - } - - /** - * @return null - */ - public function getLimit() - { - return $this->limit; - } - - /** - * @return int|null - */ - public function getOffset() - { - return $this->offset; - } - - /** - * @param $key - * @param null $val - * @return $this - */ - public function where($key, $val = null) - { - $this->filter[] = array($key, $val); - return $this; - } - - /** - * @param $columns - * @param null $dir - * @return $this - */ - public function order($columns, $dir = null) - { - if ($dir && strtolower($dir) == "desc") { + if ($dir && strtolower($dir) == 'desc') { $dir = self::SORT_DESC; } else { $dir = self::SORT_ASC; @@ -183,8 +143,8 @@ class Query extends BaseQuery if (!is_array($columns)) { $columns = array($columns); } - foreach ($columns as $col) { + foreach ($columns as $col) { if (($pos = strpos($col, ' ')) !== false) { $dir = strtoupper(substr($col, $pos + 1)); if ($dir === 'DESC') { @@ -203,60 +163,68 @@ class Query extends BaseQuery } /** - * @param null $count - * @param int $offset - * @return $this - * @throws Exception + * 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 limit($count = null, $offset = 0) + public function orderByFn(array $callBack, $dir = null) { - if ((is_null($count) || is_integer($count)) && (is_null($offset) || is_integer($offset))) { - $this->offset = $offset; - $this->limit = $count; + if ($dir && strtolower($dir) == 'desc') { + $dir = self::SORT_DESC; } else { - throw new Exception("Got invalid limit $count, $offset"); + $dir = self::SORT_ASC; } - return $this; + $this->orderColumns[] = array($callBack, $dir); } + /** - * @param $table - * @param null $columns - * @return $this - * @throws \Exception + * 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 \Exception 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 \Exception("Unknown from target for status.dat :" . $table); + throw new \Exception('Unknown from target for status.dat :' . $table); } return $this; } /** + * Return an index of all objects matching the filter of this query * - * @throws Exception + * This index will be used for ordering, grouping and limiting */ - private function getFilteredIndices($classType = "\Icinga\Protocol\Statusdat\Query\Group") + private function getFilteredIndices($classType = '\Icinga\Protocol\Statusdat\Query\Group') { - $baseGroup = null; - if (!empty($this->filter)) { - $baseGroup = new $classType(); - - foreach ($this->filter as $values) { - $baseGroup->addItem(new $classType($values[0], $values[1])); - } - } - - $state = $this->ds->getObjects(); + $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); $indexes = $baseGroup->filter($state[$target]); } if (!isset($result[$target])) { @@ -269,54 +237,78 @@ class Query extends BaseQuery } /** - * @param array $indices + * 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; // we're singlethreaded, so let's do it a bit dirty - usort($subindices, array($this, "orderResult")); + $this->currentType = $type; + usort($subindices, array($this, 'orderResult')); } } } /** - * @param $a - * @param $b - * @return int + * 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) { - $result += $col[1] * strnatcasecmp($o1->{$col[0]}, $o2->{$col[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]}); + } } - if ($result > 0) { - return 1; - } - if ($result < 0) { - return -1; - } - return 0; + return $result; } /** - * @param array $indices + * 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->offset, $this->limit); + $indices[$type] = array_slice($subindices, $this->getOffset(), $this->getLimit()); } } /** - * @param $fn - * @param null $scope - * @return $this + * 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) { @@ -325,8 +317,11 @@ class Query extends BaseQuery } /** - * @param $columns - * @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) { @@ -334,13 +329,15 @@ class Query extends BaseQuery $columns = array($columns); } $this->groupColumns = $columns; - $this->groupByFn = array($this, "columnGroupFn"); + $this->groupByFn = array($this, 'columnGroupFn'); return $this; } /** - * @param array $indices - * @return array + * 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) { @@ -349,7 +346,7 @@ class Query extends BaseQuery foreach ($indices as $type => $subindices) { foreach ($subindices as $objectIndex) { $r = $this->ds->getObjectByName($type, $objectIndex); - $hash = ""; + $hash = ''; $cols = array(); foreach ($this->groupColumns as $col) { $hash = md5($hash . $r->$col); @@ -357,8 +354,8 @@ class Query extends BaseQuery } if (!isset($result[$hash])) { $result[$hash] = (object)array( - "columns" => (object)$cols, - "count" => 0 + 'columns' => (object)$cols, + 'count' => 0 ); } $result[$hash]->count++; @@ -368,11 +365,12 @@ class Query extends BaseQuery } /** - * @return array + * 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) { @@ -385,9 +383,9 @@ class Query extends BaseQuery $this->limitIndices($indices); $result = array(); - $state = $this->ds->getObjects(); - foreach ($indices as $type => $subindices) { + $state = $this->ds->getState(); + foreach ($indices as $type => $subindices) { foreach ($subindices as $index) { $result[] = & $state[$type][$index]; } @@ -395,21 +393,92 @@ class Query extends BaseQuery return $result; } + /** - * Parse a backend specific filter expression and return a Query\Node object - * - * @param $expression The expression to parse - * @param $parameters Optional parameters for the expression - * @return Node A query node or null if it's an invalid expression + * Apply all filters of this filterable on the datasource */ - protected function parseFilterExpression($expression, $parameters = null) - { - // TODO: Implement parseFilterExpression() method. - } - public function applyFilter() { - // TODO: Implement applyFilter() method. + $parser = new TreeToStatusdatQueryParser(); + if ($this->getFilter()) { + $query = $parser->treeToQuery($this->getFilter(), $this); + $this->setQueryFilter($query); + } + + } + + /** + * Fetch the first result row + * + * @return MonitoringObjectList The monitoring object matching this query + */ + public function fetchRow() + { + $result = $this->fetchAll(); + return $result; + } + + /** + * 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 \Exception If no attributes are defined + */ + public function fetchPairs() + { + $result = array(); + if (count($this->getColumns()) < 2) { + throw new Exception( + '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; + } + + /** + * Fetch one result + * + * @return mixed + */ + public function fetchOne() + { + return next($this->fetchAll()); + } + + /** + * Count the number of results + * + * @return int + */ + public function count() + { + $q = clone $this; + $q->limit(null, null); + return count($q->fetchAll()); } diff --git a/library/Icinga/Protocol/Statusdat/Query/Expression.php b/library/Icinga/Protocol/Statusdat/Query/Expression.php index a7a7e9961..1087eabca 100755 --- a/library/Icinga/Protocol/Statusdat/Query/Expression.php +++ b/library/Icinga/Protocol/Statusdat/Query/Expression.php @@ -75,6 +75,13 @@ class Expression implements IQueryPart */ private $operator = null; + /** + * Optional query information + * + * @var null + */ + private $query = null; + /** * @var null */ @@ -154,6 +161,7 @@ class Expression implements IQueryPart $this->fields = explode(".", trim($tokenized[0])); $this->field = $this->fields[count($this->fields) - 1]; + $this->getOperatorType(trim($tokenized[1])); $tokenized[2] = trim($tokenized[2]); @@ -189,6 +197,9 @@ class Expression implements IQueryPart public function __construct($expression = null, &$values = array()) { if ($expression) { + if (!is_array($values)) { + $values = array($values); + } $this->fromString($expression, $values); } @@ -205,6 +216,7 @@ class Expression implements IQueryPart $idx = array_keys($base); } $this->basedata = $base; + return array_filter($idx, array($this, "filterFn")); } @@ -249,11 +261,20 @@ class Expression implements IQueryPart } } 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; } @@ -264,8 +285,14 @@ class Expression implements IQueryPart 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; @@ -279,6 +306,10 @@ class Expression implements IQueryPart // 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; } @@ -293,6 +324,7 @@ class Expression implements IQueryPart if (!is_array($res)) { return array($res); } + return $res; } @@ -361,4 +393,17 @@ class Expression implements IQueryPart { 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; + } + + } diff --git a/library/Icinga/Protocol/Statusdat/Query/Group.php b/library/Icinga/Protocol/Statusdat/Query/Group.php index 2fc40c42f..b5a26086a 100755 --- a/library/Icinga/Protocol/Statusdat/Query/Group.php +++ b/library/Icinga/Protocol/Statusdat/Query/Group.php @@ -109,6 +109,13 @@ class Group implements IQueryPart */ private $subExpressionLength = 0; + /** + * Optional query to use + * + * @var Query + */ + private $query = null; + /** * @var */ @@ -380,6 +387,7 @@ class Group implements IQueryPart $idx = array(); foreach ($this->items as &$subFilter) { $baseKeys = array_keys($base); + $subFilter->setQuery($this->query); $idx += $subFilter->filter($base, $baseKeys); } } else { @@ -387,10 +395,24 @@ class Group implements IQueryPart $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; + } + + } diff --git a/library/Icinga/Protocol/Statusdat/Query/IQueryPart.php b/library/Icinga/Protocol/Statusdat/Query/IQueryPart.php index bf8b19ba3..a06d9b92d 100755 --- a/library/Icinga/Protocol/Statusdat/Query/IQueryPart.php +++ b/library/Icinga/Protocol/Statusdat/Query/IQueryPart.php @@ -35,15 +35,27 @@ namespace Icinga\Protocol\Statusdat\Query; interface IQueryPart { /** - * @param null $expression - * @param array $value + * 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()); /** - * @param array $base - * @param null $idx - * @return mixed + * 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); + } diff --git a/library/Icinga/Protocol/Statusdat/Reader.php b/library/Icinga/Protocol/Statusdat/Reader.php index e099e2ff6..f31a71027 100755 --- a/library/Icinga/Protocol/Statusdat/Reader.php +++ b/library/Icinga/Protocol/Statusdat/Reader.php @@ -29,6 +29,7 @@ namespace Icinga\Protocol\Statusdat; use Icinga\Data\DatasourceInterface; +use Icinga\Exception\ConfigurationError; use Icinga\Exception; use Icinga\Benchmark; use Icinga\Protocol\Statusdat\View\MonitoringObjectList; @@ -40,54 +41,70 @@ use Icinga\Protocol\Statusdat\View\MonitoringObjectList; class Reader implements IReader, DatasourceInterface { /** - * + * The default lifetime of the cache in milliseconds */ - const DEFAULT_CACHE_LIFETIME = 300; + const DEFAULT_CACHE_LIFETIME = 30; /** + * The folder for the statusdat cache * */ const STATUSDAT_DEFAULT_CACHE_PATH = "/cache"; /** - * @var null + * The last state from the cache + * + * @var array */ - private $lastState = null; + private $lastState; /** + * True when this reader has already acquired the current runtime state (i.e. Status.dat) + * * @var bool */ private $hasRuntimeState = false; /** - * @var null + * The representation of the object.cache file + * + * @var array */ - private $objectCache = null; + private $objectCache ; /** - * @var null + * The representation of the status.dat file + * @var array */ - private $statusCache = null; + private $statusCache; /** + * True when the icinga state differs from the cache + * * @var bool */ private $newState = false; /** - * @var null + * The Parser object to use for parsing + * + * @var Parser */ - private $parser = null; + private $parser; /** + * Whether to disable the cache + * * @var bool */ - private $noCache = false; + private $noCache; /** - * @param $config - * @param null $parser - * @param bool $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) { @@ -97,6 +114,7 @@ class Reader implements IReader, DatasourceInterface } $this->config = $config; $this->parser = $parser; + if (!$this->noCache) { $this->cache = $this->initializeCaches($config); if ($this->fromCache()) { @@ -104,6 +122,7 @@ class Reader implements IReader, DatasourceInterface return; } } + if (!$this->lastState) { $this->parseObjectsCacheFile(); } @@ -112,14 +131,16 @@ class Reader implements IReader, DatasourceInterface } $this->parseStatusDatFile(); if (!$noCache && $this->newState) { - $this->statusCache->save($this->parser->getRuntimeState(), 'objects' . md5($this->config->objects_file)); + $this->statusCache->save($this->parser->getRuntimeState(), 'object' . md5($this->config->object_file)); } $this->createHostServiceConnections(); } /** - * @throws Exception\ConfigurationError + * Initialize the internal caches if enabled + * + * @throws ConfigurationError */ private function initializeCaches() { @@ -128,7 +149,7 @@ class Reader implements IReader, DatasourceInterface $cachePath = $this->config->get('cache_path', $defaultCachePath); $maxCacheLifetime = intval($this->config->get('cache_path', self::DEFAULT_CACHE_LIFETIME)); if (!is_writeable($cachePath)) { - throw new Exception\ConfigurationError( + throw new ConfigurationError( "Cache path $cachePath is not writable, check your configuration" ); } @@ -136,16 +157,19 @@ class Reader implements IReader, DatasourceInterface $backendOptions = array( 'cache_dir' => $cachePath ); - // the objects cache might exist for months and is still valid - $this->objectCache = $this->initCache($this->config->objects_file, $backendOptions, null); + // the object cache might exist for months and is still valid + $this->objectCache = $this->initCache($this->config->object_file, $backendOptions, null); $this->statusCache = $this->initCache($this->config->status_file, $backendOptions, $maxCacheLifetime); } /** - * @param $file - * @param $backend - * @param $lifetime + * 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, $backend, $lifetime) @@ -159,7 +183,9 @@ class Reader implements IReader, DatasourceInterface } /** - * @return bool + * Read the current cache state + * + * @return bool True if the state is the same as the icinga state */ private function fromCache() { @@ -171,16 +197,17 @@ class Reader implements IReader, DatasourceInterface $this->newState = true; return false; } - return true; } /** - * @return bool + * 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('objects' . md5($this->config->objects_file)); + $this->lastState = $this->objectCache->load('object' . md5($this->config->object_file)); if ($this->lastState == false) { return false; } @@ -189,16 +216,16 @@ class Reader implements IReader, DatasourceInterface } /** - * @return bool + * 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; } @@ -208,6 +235,7 @@ class Reader implements IReader, DatasourceInterface } /** + * Take the status.dat and objects.cache and connect all services to hosts * */ private function createHostServiceConnections() @@ -215,9 +243,12 @@ class Reader implements IReader, DatasourceInterface if (!isset($this->lastState["service"])) { return; } - + foreach ($this->lastState["host"] as &$host) { + $host->host = $host; + } foreach ($this->lastState["service"] as &$service) { - $host = & $this->lastState["host"][$service->host_name]; + $service->service = &$service; // allow easier querying + $host = &$this->lastState["host"][$service->host_name]; if (!isset($host->services)) { $host->services = array(); } @@ -227,29 +258,33 @@ class Reader implements IReader, DatasourceInterface } /** - * @throws Exception\ConfigurationError + * 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->objects_file)) { - throw new Exception\ConfigurationError( - "Can't read objects-file {$this->config->objects_file}, check your configuration" + if (!is_readable($this->config->object_file)) { + throw new ConfigurationError( + 'Can\'t read object-file "' . $this->config->object_file . '", check your configuration' ); } if (!$this->parser) { - $this->parser = new Parser(fopen($this->config->objects_file, "r")); + $this->parser = new Parser(fopen($this->config->object_file, "r")); } $this->parser->parseObjectsFile(); $this->lastState = $this->parser->getRuntimeState(); } /** - * @throws Exception\ConfigurationError + * 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 Exception\ConfigurationError( + throw new ConfigurationError( "Can't read status-file {$this->config->status_file}, check your configuration" ); } @@ -259,12 +294,14 @@ class Reader implements IReader, DatasourceInterface $this->parser->parseRuntimeState(fopen($this->config->status_file, "r")); $this->lastState = $this->parser->getRuntimeState(); if (!$this->noCache) { - $this->statusCache->save(array("true" => true), "state" . md5($this->config->objects_file)); + $this->statusCache->save(array("true" => true), "state" . md5($this->config->object_file)); } } /** - * @return Query + * Create a new Query + * + * @return Query The query to operate on */ public function select() { @@ -272,34 +309,23 @@ class Reader implements IReader, DatasourceInterface } /** - * @param Query $query - * @return MonitoringObjectList - */ - public function fetchAll(Query $query) - { - return $query->getResult(); - } - - /** - * @return mixed|null + * Return the internal state of the status.dat + * + * @return mixed The internal status.dat representation */ public function getState() { return $this->lastState; } - /** - * @return mixed|null - */ - public function getObjects() - { - return $this->lastState; - } /** - * @param $type - * @param $name - * @return ObjectContainer|mixed|null + * 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) { @@ -310,8 +336,10 @@ class Reader implements IReader, DatasourceInterface } /** - * @param $type - * @return array|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) { diff --git a/library/Icinga/Protocol/Statusdat/RuntimeStateContainer.php b/library/Icinga/Protocol/Statusdat/RuntimeStateContainer.php index 178cf1f55..50b86cc13 100755 --- a/library/Icinga/Protocol/Statusdat/RuntimeStateContainer.php +++ b/library/Icinga/Protocol/Statusdat/RuntimeStateContainer.php @@ -29,17 +29,25 @@ namespace Icinga\Protocol\Statusdat; /** - * Class RuntimeStateContainer - * @package 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 = "") @@ -48,8 +56,10 @@ class RuntimeStateContainer extends \stdClass } /** - * @param $attr - * @return bool + * 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) { @@ -62,9 +72,13 @@ class RuntimeStateContainer extends \stdClass } /** - * @param $attr - * @return mixed - * @throws \InvalidArgumentException + * 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) { diff --git a/library/Icinga/Protocol/Statusdat/TreeToStatusdatQueryParser.php b/library/Icinga/Protocol/Statusdat/TreeToStatusdatQueryParser.php new file mode 100644 index 000000000..f1a2dcf17 --- /dev/null +++ b/library/Icinga/Protocol/Statusdat/TreeToStatusdatQueryParser.php @@ -0,0 +1,73 @@ + + * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 + * @author Icinga Development Team + */ +// {{{ICINGA_LICENSE_HEADER}}} + + +namespace Icinga\Protocol\Statusdat; + + +use Icinga\Filter\Filterable; +use Icinga\Filter\Query\Node; +use Icinga\Filter\Query\Tree; +use Icinga\Protocol\Statusdat\Query\Expression; +use Icinga\Protocol\Statusdat\Query\Group; + +class TreeToStatusdatQueryParser +{ + + private function nodeToQuery(Node $node, Filterable $source) + { + if ($node->type === Node::TYPE_OPERATOR) { + $op = $node->operator; + $value = $node->right; + $node->left = $source->getMappedField($node->left); + if (stripos($node->right, '*') !== false) { + $op = 'LIKE'; + $value = str_replace('*', '%', $value); + } + return new Expression($node->left . ' ' . $op . ' ?', $value); + } else { + $group = new Group(); + $group->setType(($node->type === Node::TYPE_OR) ? Group::TYPE_OR : Group::TYPE_AND); + $group->addItem($this->nodeToQuery($node->left, $source)); + $group->addItem($this->nodeToQuery($node->right, $source)); + return $group; + } + } + + + public function treeToQuery(Tree $tree, Filterable $source) + { + + $tree = $tree->getCopyForFilterable($source); + if ($tree->root !== null) { + $tree->root = $tree->normalizeTree($tree->root); + return $this->nodeToQuery($tree->root, $source); + } + return null; + } +} \ No newline at end of file diff --git a/library/Icinga/Protocol/Statusdat/View/AccessorStrategy.php b/library/Icinga/Protocol/Statusdat/View/AccessorStrategy.php index dde5c7aba..be9ea9ab0 100644 --- a/library/Icinga/Protocol/Statusdat/View/AccessorStrategy.php +++ b/library/Icinga/Protocol/Statusdat/View/AccessorStrategy.php @@ -55,13 +55,6 @@ interface AccessorStrategy */ public function get(&$item, $field); - /** - * Returns the name that the field has in the specific backend. Might not be available for every field/view - * @param $field The field name that should be translated - * @return string The real name of this field - */ - public function getNormalizedFieldName($field); - /** * Returns true if the field exists on the specific item, otherwise false * diff --git a/library/Icinga/Protocol/Statusdat/View/MonitoringObjectList.php b/library/Icinga/Protocol/Statusdat/View/MonitoringObjectList.php index 441ae61aa..8cdda5351 100755 --- a/library/Icinga/Protocol/Statusdat/View/MonitoringObjectList.php +++ b/library/Icinga/Protocol/Statusdat/View/MonitoringObjectList.php @@ -1,5 +1,12 @@ dataView) { return $this; } + return $this->dataSet[$this->position]; } diff --git a/modules/monitoring/application/controllers/CommandController.php b/modules/monitoring/application/controllers/CommandController.php index e0f6279cc..e364e2c7e 100644 --- a/modules/monitoring/application/controllers/CommandController.php +++ b/modules/monitoring/application/controllers/CommandController.php @@ -189,15 +189,20 @@ class Monitoring_CommandController extends ActionController $query = Backend::createBackend($this->_getParam('backend'))->select()->from("status", $fields); $data = $query->fetchAll(); + $out = array(); foreach ($data as $o) { - $test = (array)$o; - if ($test['host_name'] === $hostname) { + if ($o->host_name === $hostname) { if (!$servicename) { - $out[] = (object) $o; - } elseif ($servicename && strtolower($test['service_description']) === strtolower($servicename)) { - $out[] = (object) $o; + $out[] = (object) array( + "host_name" => $o->host_name + ); + } elseif ($servicename && strtolower($o->service_description) === strtolower($servicename)) { + $out[] = (object) array( + "host_name" => $o->host_name, + "service_description" => $o->service_description + ); } } } @@ -208,6 +213,7 @@ class Monitoring_CommandController extends ActionController "CommandController: SQL Query '%s' failed (message %s) ", $query ? (string) $query->getQuery()->dump() : '--', $e->getMessage() ); + return array(); } } diff --git a/modules/monitoring/application/controllers/MultiController.php b/modules/monitoring/application/controllers/MultiController.php index 0d892ea67..abc51d6fa 100644 --- a/modules/monitoring/application/controllers/MultiController.php +++ b/modules/monitoring/application/controllers/MultiController.php @@ -125,7 +125,7 @@ class Monitoring_MultiController extends ActionController * * @return array */ - private function getUniqueValues(array $values, $key) + private function getUniqueValues($values, $key) { $unique = array(); foreach ($values as $value) @@ -144,7 +144,7 @@ class Monitoring_MultiController extends ActionController * * @param $object array The hosts or services */ - private function getProblems(array $objects) + private function getProblems($objects) { $problems = 0; foreach ($objects as $object) { diff --git a/modules/monitoring/application/controllers/ShowController.php b/modules/monitoring/application/controllers/ShowController.php index 977aaa1b2..dcfe84cee 100644 --- a/modules/monitoring/application/controllers/ShowController.php +++ b/modules/monitoring/application/controllers/ShowController.php @@ -58,9 +58,9 @@ class Monitoring_ShowController extends MonitoringController if ($this->getRequest()->getActionName() === 'host') { $this->view->object = new Host($this->getRequest()); - } elseif ($this->getRequest()->getActionName() === 'service') { + } elseif ($this->getRequest()->getActionName() === 'service' + || $this->getRequest()->getActionName() === 'services' ) { $this->view->object = new Service($this->getRequest()); - } else { $this->view->object = AbstractObject::fromRequest($this->getRequest()); } diff --git a/modules/monitoring/application/views/helpers/CommandForm.php b/modules/monitoring/application/views/helpers/CommandForm.php index 91e4e7c10..096179190 100644 --- a/modules/monitoring/application/views/helpers/CommandForm.php +++ b/modules/monitoring/application/views/helpers/CommandForm.php @@ -19,7 +19,7 @@ class Zend_View_Helper_CommandForm extends Zend_View_Helper_Abstract * * @return Form Form to modify */ - private function simpleForm($commandName, array $arguments = array()) + public function simpleForm($commandName, array $arguments = array()) { $form = new Form(); $form->setIgnoreChangeDiscarding(true); diff --git a/modules/monitoring/application/views/helpers/ContactFlags.php b/modules/monitoring/application/views/helpers/ContactFlags.php index e2a9187fd..367f2d47d 100644 --- a/modules/monitoring/application/views/helpers/ContactFlags.php +++ b/modules/monitoring/application/views/helpers/ContactFlags.php @@ -25,6 +25,11 @@ class Zend_View_Helper_ContactFlags extends Zend_View_Helper_Abstract */ public function contactFlags($contact, $type, $glue = ', ') { + + $optionName = 'contact_' . $type . '_notification_options'; + if (isset($contact->$optionName)) { + return $contact->$optionName; + } $out = array(); foreach ($contact as $key => $value) { if (preg_match('/^contact_notify_' . $type . '_.*/', $key) && $value == True) { diff --git a/modules/monitoring/application/views/scripts/list/contactgroups.phtml b/modules/monitoring/application/views/scripts/list/contactgroups.phtml index 040a0751e..a085a61f9 100644 --- a/modules/monitoring/application/views/scripts/list/contactgroups.phtml +++ b/modules/monitoring/application/views/scripts/list/contactgroups.phtml @@ -18,8 +18,8 @@ $knownGroups = array() - + href('monitoring/show/contacts', array('contact' => $contact->contact_name)); ?> getHelper('CommandForm'); service)): ?> service ?> on host ?> host ?> + 'host' => $downtime->host_name + )); ?>">host ?>
downtime_author ?>: downtime_comment ?> diff --git a/modules/monitoring/application/views/scripts/list/services.phtml b/modules/monitoring/application/views/scripts/list/services.phtml index c8190a9fe..98a63a2ae 100644 --- a/modules/monitoring/application/views/scripts/list/services.phtml +++ b/modules/monitoring/application/views/scripts/list/services.phtml @@ -106,7 +106,7 @@ $viewHelper = $this->getHelper('MonitoringState'); service_state): ?>
Attempt: - current_check_attempt; ?>/max_check_attempts; ?> + service_attempt; ?> (service_state_type === '1') ? 'Hard' : 'Soft'; ?>) diff --git a/modules/monitoring/application/views/scripts/show/components/status.phtml b/modules/monitoring/application/views/scripts/show/components/status.phtml index e99f306e2..bbad328d0 100644 --- a/modules/monitoring/application/views/scripts/show/components/status.phtml +++ b/modules/monitoring/application/views/scripts/show/components/status.phtml @@ -36,7 +36,7 @@ - util()->getServiceStateName($object->service_state); ?> - since timeSince($object->service_last_state_change); ?> + since timeSince($object->service_slast_state_change); ?> diff --git a/modules/monitoring/application/views/scripts/show/header.phtml b/modules/monitoring/application/views/scripts/show/header.phtml index c769fa4ef..622d7cada 100644 --- a/modules/monitoring/application/views/scripts/show/header.phtml +++ b/modules/monitoring/application/views/scripts/show/header.phtml @@ -1,4 +1,5 @@ config->type) + ); + } return new $queryClass($this->resource, $columns); } @@ -142,6 +150,7 @@ class Backend implements ConfigAwareFactory, DatasourceInterface } $config = self::$backendConfigs[$name]; + self::$backendInstances[$name] = $backend = new self($config, ResourceFactory::getResourceConfig($config->resource)); switch (strtolower($config->type)) { case 'ido': diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatusQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatusQuery.php deleted file mode 100644 index e86b141ba..000000000 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatusQuery.php +++ /dev/null @@ -1,341 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Icinga\Module\Monitoring\Backend\Ido\Query; - -class HoststatusQuery extends IdoQuery -{ - protected $allowCustomVars = true; - protected $columnMap = array( - 'hosts' => array( - 'host' => 'ho.name1 COLLATE latin1_general_ci', - 'host_name' => 'ho.name1 COLLATE latin1_general_ci', - 'host_display_name' => 'h.display_name', - 'host_alias' => 'h.alias', - 'host_address' => 'h.address', - 'host_ipv4' => 'INET_ATON(h.address)', - 'host_icon_image' => 'h.icon_image', - ), - 'hoststatus' => array( - 'problems' => 'CASE WHEN hs.current_state = 0 THEN 0 ELSE 1 END', - 'handled' => 'CASE WHEN (hs.problem_has_been_acknowledged + hs.scheduled_downtime_depth) > 0 THEN 1 ELSE 0 END', - 'unhandled' => 'CASE WHEN (hs.problem_has_been_acknowledged + hs.scheduled_downtime_depth) = 0 THEN 1 ELSE 0 END', - 'host_state' => 'CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 99 ELSE hs.current_state END', - 'host_output' => 'hs.output', - 'host_long_output' => 'hs.long_output', - 'host_perfdata' => 'hs.perfdata', - 'host_problem' => 'CASE WHEN hs.current_state = 0 THEN 0 ELSE 1 END', - 'host_acknowledged' => 'hs.problem_has_been_acknowledged', - 'host_in_downtime' => 'CASE WHEN (hs.scheduled_downtime_depth = 0) THEN 0 ELSE 1 END', - 'host_handled' => 'CASE WHEN (hs.problem_has_been_acknowledged + hs.scheduled_downtime_depth) > 0 THEN 1 ELSE 0 END', - 'host_does_active_checks' => 'hs.active_checks_enabled', - 'host_accepts_passive_checks' => 'hs.passive_checks_enabled', - 'host_last_state_change' => 'UNIX_TIMESTAMP(hs.last_state_change)', - 'host_last_hard_state' => 'hs.last_hard_state', - 'host_check_command' => 'hs.check_command', - 'host_last_check' => 'UNIX_TIMESTAMP(hs.last_check)', - 'host_next_check' => 'CASE WHEN hs.should_be_scheduled THEN UNIX_TIMESTAMP(hs.next_check) ELSE NULL END', - 'host_check_execution_time' => 'hs.execution_time', - 'host_check_latency' => 'hs.latency', - 'host_notifications_enabled' => 'hs.notifications_enabled', - 'host_last_time_up' => 'hs.last_time_up', - 'host_last_time_down' => 'hs.last_time_down', - 'host_last_time_unreachable' => 'hs.last_time_unreachable', - 'host_current_check_attempt' => 'hs.current_check_attempt', - 'host_max_check_attempts' => 'hs.max_check_attempts', - 'host_severity' => 'CASE WHEN hs.current_state = 0 - THEN - CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL - THEN 16 - ELSE 0 - END - + - CASE WHEN hs.problem_has_been_acknowledged = 1 - THEN 2 - ELSE - CASE WHEN hs.scheduled_downtime_depth > 0 - THEN 1 - ELSE 4 - END - END - ELSE - CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 16 - WHEN hs.current_state = 1 THEN 32 - WHEN hs.current_state = 2 THEN 64 - ELSE 256 - END - + - CASE WHEN hs.problem_has_been_acknowledged = 1 - THEN 2 - ELSE - CASE WHEN hs.scheduled_downtime_depth > 0 - THEN 1 - ELSE 4 - END - END - END', - ), - 'hostgroups' => array( - 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci', - ), - 'contactgroups' => array( - 'contactgroup' => 'contactgroup', - ), - 'contacts' => array( - 'contact' => 'hco.name1 COLLATE latin1_general_ci', - ), - 'services' => array( - 'services_cnt' => 'SUM(1)', - 'services_ok' => 'SUM(CASE WHEN ss.current_state = 0 THEN 1 ELSE 0 END)', - 'services_warning' => 'SUM(CASE WHEN ss.current_state = 1 THEN 1 ELSE 0 END)', - 'services_critical' => 'SUM(CASE WHEN ss.current_state = 2 THEN 1 ELSE 0 END)', - 'services_unknown' => 'SUM(CASE WHEN ss.current_state = 3 THEN 1 ELSE 0 END)', - 'services_pending' => 'SUM(CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 1 ELSE 0 END)', - 'services_problem' => 'SUM(CASE WHEN ss.current_state > 0 THEN 1 ELSE 0 END)', - 'services_problem_handled' => 'SUM(CASE WHEN ss.current_state > 0 AND (ss.problem_has_been_acknowledged = 1 OR ss.scheduled_downtime_depth > 0) THEN 1 ELSE 0 END)', - 'services_problem_unhandled' => 'SUM(CASE WHEN ss.current_state > 0 AND (ss.problem_has_been_acknowledged = 0 AND ss.scheduled_downtime_depth = 0) THEN 1 ELSE 0 END)', - 'services_warning_handled' => 'SUM(CASE WHEN ss.current_state = 1 AND (ss.problem_has_been_acknowledged = 1 OR ss.scheduled_downtime_depth > 0) THEN 1 ELSE 0 END)', - 'services_critical_handled' => 'SUM(CASE WHEN ss.current_state = 2 AND (ss.problem_has_been_acknowledged = 1 OR ss.scheduled_downtime_depth > 0) THEN 1 ELSE 0 END)', - 'services_unknown_handled' => 'SUM(CASE WHEN ss.current_state = 3 AND (ss.problem_has_been_acknowledged = 1 OR ss.scheduled_downtime_depth > 0) THEN 1 ELSE 0 END)', - 'services_warning_unhandled' => 'SUM(CASE WHEN ss.current_state = 1 AND (ss.problem_has_been_acknowledged = 0 AND ss.scheduled_downtime_depth = 0) THEN 1 ELSE 0 END)', - 'services_critical_unhandled' => 'SUM(CASE WHEN ss.current_state = 2 AND (ss.problem_has_been_acknowledged = 0 AND ss.scheduled_downtime_depth = 0) THEN 1 ELSE 0 END)', - 'services_unknown_unhandled' => 'SUM(CASE WHEN ss.current_state = 3 AND (ss.problem_has_been_acknowledged = 0 AND ss.scheduled_downtime_depth = 0) THEN 1 ELSE 0 END)', - ), - ); - protected $aggregateColumnIdx = array( - 'services_cnt' => true, - 'services_problem' => true, - 'services_problem_handled' => true, - 'services_problem_unhandled' => true, - ); - protected $hcgSub; - - public function getDefaultColumns() - { - return $this->columnMap['hosts'] + $this->columnMap['hoststatus']; - } - - protected function joinBaseTables() - { - // TODO: Shall we always add hostobject? - $this->baseQuery = $this->db->select()->from( - array('ho' => $this->prefix . 'objects'), - array() - )->join( - array('hs' => $this->prefix . 'hoststatus'), - 'ho.' . $this->object_id . ' = hs.host_object_id AND ho.is_active = 1 AND ho.objecttype_id = 1', - array() - )->join( - array('h' => $this->prefix . 'hosts'), - 'hs.host_object_id = h.host_object_id', - array() - ); - $this->joinedVirtualTables = array( - 'hosts' => true, - 'hoststatus' => true, - ); - } - - protected function joinStatus() - { - $this->requireVirtualTable('services'); - } - - protected function joinServiceStatus() - { - $this->requireVirtualTable('services'); - } - - protected function joinServices() - { - $this->baseQuery->join( - array('s' => $this->prefix . 'services'), - 's.host_object_id = h.host_object_id', - array() - )->join( - array('so' => $this->prefix . 'objects'), - "so.$this->object_id = s.service_object_id AND so.is_active = 1", - array() - )->joinLeft( - array('ss' => $this->prefix . 'servicestatus'), - "so.$this->object_id = ss.service_object_id", - array() - ); - foreach ($this->getColumns() as $col) { - $real = $this->aliasToColumnName($col); - if (substr($real, 0, 4) === 'SUM(') { - continue; - } - $this->baseQuery->group($real); - } - $this->useSubqueryCount = true; - } - - protected function joinHostgroups() - { - if ($this->hasJoinedVirtualTable('services')) { - return $this->joinServiceHostgroups(); - } else { - return $this->joinHostHostgroups(); - } - } - - protected function joinServiceHostgroups() - { - $this->baseQuery->join( - array('hgm' => $this->prefix . 'hostgroup_members'), - 'hgm.host_object_id = s.host_object_id', - array() - )->join( - array('hg' => $this->prefix . 'hostgroups'), - 'hgm.hostgroup_id = hg.' . $this->hostgroup_id, - array() - )->join( - array('hgo' => $this->prefix . 'objects'), - 'hgo.' . $this->object_id . ' = hg.hostgroup_object_id' - . ' AND hgo.is_active = 1', - array() - ); - - return $this; - } - - protected function joinHostHostgroups() - { - $this->baseQuery->join( - array('hgm' => $this->prefix . 'hostgroup_members'), - 'hgm.host_object_id = h.host_object_id', - array() - )->join( - array('hg' => $this->prefix . 'hostgroups'), - "hgm.hostgroup_id = hg.$this->hostgroup_id", - array() - )->join( - array('hgo' => $this->prefix . 'objects'), - 'hgo.' . $this->object_id . ' = hg.hostgroup_object_id' - . ' AND hgo.is_active = 1', - array() - ); - - return $this; - } - - protected function joinContacts() - { - $this->hcgcSub = $this->db->select()->distinct()->from( - array('hcgc' => $this->prefix . 'host_contactgroups'), - array('host_name' => 'ho.name1') - )->join( - array('cgo' => $this->prefix . 'objects'), - 'hcg.contactgroup_object_id = cgo.' . $this->object_id - . ' AND cgo.is_active = 1', - array() - )->join( - array('h' => $this->prefix . 'hosts'), - 'hcg.host_id = h.host_id', - array() - )->join( - array('ho' => $this->prefix . 'objects'), - 'h.host_object_id = ho.' . $this->object_id . ' AND ho.is_active = 1', - array() - ); - $this->baseQuery->join( - array('hcg' => $this->hcgSub), - 'hcg.host_name = ho.name1', - array() - ); - - return $this; - } - - protected function filterContactgroup($value) - { - $this->hcgSub->where( - $this->prepareFilterStringForColumn( - 'cgo.name1 COLLATE latin1_general_ci', - $value - ) - ); - return $this; - } - - protected function joinContactgroups() - { - $this->hcgSub = $this->createContactgroupFilterSubselect(); - $this->baseQuery->join( - array('hcg' => $this->hcgSub), - 'hcg.object_id = ho.object_id', - array() - ); - - return $this; - } - - protected function createContactgroupFilterSubselect() - { - die((string)$this->db->select()->distinct()->from( - array('hcg' => $this->prefix . 'host_contactgroups'), - array('object_id' => 'ho.object_id') - )->join( - array('cgo' => $this->prefix . 'objects'), - 'hcg.contactgroup_object_id = cgo.' . $this->object_id - . ' AND cgo.is_active = 1', - array() - )->join( - array('h' => $this->prefix . 'hosts'), - 'hcg.host_id = h.host_id', - array() - )->join( - array('ho' => $this->prefix . 'objects'), - 'h.host_object_id = ho.' . $this->object_id . ' AND ho.is_active = 1', - array() - )); - } - - protected function joinServicegroups() - { - // TODO: Only hosts with services having such servicegroups - $this->requireVirtualTable('services'); - $this->baseQuery->join( - array('sgm' => $this->prefix . 'servicegroup_members'), - 'sgm.service_object_id = s.service_object_id', - array() - )->join( - array('sg' => $this->prefix . 'servicegroups'), - 'sgm.servicegroup_id = sg.' . $this->servicegroup_id, - array() - )->join( - array('sgo' => $this->prefix . 'objects'), - 'sgo.' . $this->object_id . ' = sg.servicegroup_object_id' - . ' AND sgo.is_active = 1', - array() - ); - - return $this; - } -} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicestatusQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicestatusQuery.php deleted file mode 100644 index 2c8d4ac43..000000000 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicestatusQuery.php +++ /dev/null @@ -1,167 +0,0 @@ - array( - 'service_host_name' => 'so.name1 COLLATE latin1_general_ci', - 'service' => 'so.name2 COLLATE latin1_general_ci', - 'service_description' => 'so.name2 COLLATE latin1_general_ci', - 'service_display_name' => 's.display_name', - 'service_icon_image' => 's.icon_image', - ), - 'servicestatus' => array( - 'current_state' => 'CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 99 ELSE ss.current_state END', - 'service_state' => 'CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 99 ELSE ss.current_state END', - 'service_hard_state' => 'CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 99 ELSE CASE WHEN ss.state_type = 1 THEN ss.current_state ELSE ss.last_hard_state END END', - 'service_state_type' => 'ss.state_type', - 'service_output' => 'ss.output', - 'service_long_output' => 'ss.long_output', - 'service_perfdata' => 'ss.perfdata', - 'service_acknowledged' => 'ss.problem_has_been_acknowledged', - 'service_in_downtime' => 'CASE WHEN (ss.scheduled_downtime_depth = 0) THEN 0 ELSE 1 END', - 'service_handled' => 'CASE WHEN (ss.problem_has_been_acknowledged + ss.scheduled_downtime_depth + COALESCE(hs.current_state, 0)) > 0 THEN 1 ELSE 0 END', - 'service_does_active_checks' => 'ss.active_checks_enabled', - 'service_accepts_passive_checks' => 'ss.passive_checks_enabled', - 'service_last_state_change' => 'UNIX_TIMESTAMP(ss.last_state_change)', - 'service_last_hard_state' => 'ss.last_hard_state', - 'service_last_hard_state_change' => 'UNIX_TIMESTAMP(ss.last_hard_state_change)', - 'service_check_command' => 'ss.check_command', - 'service_last_check' => 'UNIX_TIMESTAMP(ss.last_check)', - 'service_next_check' => 'CASE WHEN ss.should_be_scheduled THEN UNIX_TIMESTAMP(ss.next_check) ELSE NULL END', - 'service_check_execution_time' => 'ss.execution_time', - 'service_check_latency' => 'ss.latency', - 'service_notifications_enabled' => 'ss.notifications_enabled', - 'service_last_time_ok' => 'ss.last_time_ok', - 'service_last_time_warning' => 'ss.last_time_warning', - 'service_last_time_critical' => 'ss.last_time_critical', - 'service_last_time_unknown' => 'ss.last_time_unknown', - ), - 'servicegroups' => array( - 'servicegroups' => 'sgo.name1', - ) - ); - - public function getDefaultColumns() - { - return $this->columnMap['services'] - + $this->columnMap['servicestatus']; - } - - protected function joinBaseTables() - { - // TODO: Shall we always add hostobject? - $this->baseQuery = $this->db->select()->from( - array('so' => $this->prefix . 'objects'), - array() - )->join( - array('ss' => $this->prefix . 'servicestatus'), - 'so.object_id = ss.service_object_id AND so.is_active = 1 AND so.objecttype_id = 2', - array() - )->join( - array('s' => $this->prefix . 'services'), - 'ss.service_object_id = s.service_object_id', - array() - ); - $this->joinedVirtualTables = array( - 'services' => true, - 'servicestatus' => true, - ); - } - - protected function joinStatus() - { - $this->requireVirtualTable('services'); - } - - protected function joinServiceStatus() - { - $this->requireVirtualTable('services'); - } - - protected function joinServices() - { - $this->baseQuery->join( - array('s' => $this->prefix . 'services'), - 's.host_object_id = h.host_object_id', - array() - )->join( - array('so' => $this->prefix . 'objects'), - "so.$this->object_id = s.service_object_id AND so.is_active = 1", - array() - )->joinLeft( - array('ss' => $this->prefix . 'servicestatus'), - "so.$this->object_id = ss.service_object_id", - array() - ); - } - - protected function joinHostgroups() - { - if ($this->hasJoinedVirtualTable('services')) { - return $this->joinServiceHostgroups(); - } else { - return $this->joinHostHostgroups(); - } - } - - protected function joinHostHostgroups() - { - $this->baseQuery->join( - array('hgm' => $this->prefix . 'hostgroup_members'), - 'hgm.host_object_id = h.host_object_id', - array() - )->join( - array('hg' => $this->prefix . 'hostgroups'), - "hgm.hostgroup_id = hg.$this->hostgroup_id", - array() - ); - - return $this; - } - - protected function joinServiceHostgroups() - { - $this->baseQuery->join( - array('hgm' => $this->prefix . 'hostgroup_members'), - 'hgm.host_object_id = s.host_object_id', - array() - )->join( - array('hg' => $this->prefix . 'hostgroups'), - 'hgm.hostgroup_id = hg.' . $this->hostgroup_id, - array() - )->join( - array('hgo' => $this->prefix . 'objects'), - 'hgo.' . $this->object_id. ' = hg.hostgroup_object_id' - . ' AND hgo.is_active = 1', - array() - ); - - return $this; - } - - protected function joinServicegroups() - { - $this->requireVirtualTable('services'); - $this->baseQuery->join( - array('sgm' => $this->prefix . 'servicegroup_members'), - 'sgm.service_object_id = s.service_object_id', - array() - )->join( - array('sg' => $this->prefix . 'servicegroups'), - 'sgm.servicegroup_id = sg.' . $this->servicegroup_id, - array() - )->join( - array('sgo' => $this->prefix . 'objects'), - 'sgo.' . $this->object_id. ' = sg.servicegroup_object_id' - . ' AND sgo.is_active = 1', - array() - ); - - return $this; - } -} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php index 280031397..d6255a9fb 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php @@ -23,6 +23,7 @@ class StatusQuery extends IdoQuery ), 'hoststatus' => array( 'host_state' => 'CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 99 ELSE hs.current_state END', + 'host_hard_state' => 'CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 99 ELSE CASE WHEN hs.state_type = 1 THEN hs.current_state ELSE hs.last_hard_state END END', 'host_output' => 'hs.output', 'host_long_output' => 'hs.long_output', 'host_perfdata' => 'hs.perfdata', @@ -220,7 +221,40 @@ class StatusQuery extends IdoQuery 'service_normal_check_interval' => 'ss.normal_check_interval', 'service_retry_check_interval' => 'ss.retry_check_interval', 'service_check_timeperiod_object_id' => 'ss.check_timeperiod_object_id', - 'service_status_update_time' => 'ss.status_update_time' + 'service_status_update_time' => 'ss.status_update_time', + 'service_problem' => 'CASE WHEN ss.current_state = 0 THEN 0 ELSE 1 END', + 'service_severity' => 'CASE WHEN ss.current_state = 0 + THEN + CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL + THEN 16 + ELSE 0 + END + + + CASE WHEN ss.problem_has_been_acknowledged = 1 + THEN 2 + ELSE + CASE WHEN ss.scheduled_downtime_depth > 0 + THEN 1 + ELSE 4 + END + END + ELSE + CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 16 + WHEN ss.current_state = 1 THEN 32 + WHEN ss.current_state = 2 THEN 128 + WHEN ss.current_state = 3 THEN 64 + ELSE 256 + END + + + CASE WHEN ss.problem_has_been_acknowledged = 1 + THEN 2 + ELSE + CASE WHEN ss.scheduled_downtime_depth > 0 + THEN 1 + ELSE 4 + END + END + END' ), 'serviceproblemsummary' => array( 'host_unhandled_service_count' => 'sps.unhandled_service_count' @@ -230,44 +264,7 @@ class StatusQuery extends IdoQuery ), 'lastservicecomment' => array( 'service_last_comment' => 'slc.comment_id' - ), - 'status' => array( - 'service_problems' => 'CASE WHEN ss.current_state = 0 THEN 0 ELSE 1 END', - 'service_handled' => 'CASE WHEN ss.problem_has_been_acknowledged = 1 OR ss.scheduled_downtime_depth > 0 THEN 1 ELSE 0 END', - 'service_unhandled' => 'CASE WHEN ss.problem_has_been_acknowledged = 0 AND ss.scheduled_downtime_depth = 0 THEN 1 ELSE 0 END', - 'service_severity' => 'CASE WHEN ss.current_state = 0 - THEN - CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL - THEN 16 - ELSE 0 - END - + - CASE WHEN ss.problem_has_been_acknowledged = 1 - THEN 2 - ELSE - CASE WHEN ss.scheduled_downtime_depth > 0 - THEN 1 - ELSE 4 - END - END - ELSE - CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 16 - WHEN ss.current_state = 1 THEN 32 - WHEN ss.current_state = 2 THEN 128 - WHEN ss.current_state = 3 THEN 64 - ELSE 256 - END - + - CASE WHEN ss.problem_has_been_acknowledged = 1 - THEN 2 - ELSE - CASE WHEN ss.scheduled_downtime_depth > 0 - THEN 1 - ELSE 4 - END - END - END', - ), + ) ); protected function joinBaseTables() diff --git a/modules/monitoring/library/Monitoring/Backend/Statusdat/Criteria/Filter.php b/modules/monitoring/library/Monitoring/Backend/Statusdat/Criteria/Filter.php deleted file mode 100755 index 484740c46..000000000 --- a/modules/monitoring/library/Monitoring/Backend/Statusdat/Criteria/Filter.php +++ /dev/null @@ -1,46 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Icinga\Module\Monitoring\Backend\Statusdat\Criteria; - -/** - * Class Order - * - * Constants for order definitions. - * These only describe logical orders without going into storage specific - * details, like which fields are used for ordering. It's completely up to the query to determine what to do with these - * constants (although the result should be consistent among the different storage apis). - * - * @package Icinga\Backend\Criteria - */ -class Order -{ - /** - * Order by the newest events. What this means has to be determined in the context. - * Mostly this affects last_state_change - * - * @var string - */ - const STATE_CHANGE = "state_change"; - - /** - * Order by the state of service objects. Mostly this is critical->unknown->warning->ok, - * but also might take acknowledgments and downtimes in account - * - * @var string - */ - const SERVICE_STATE = "service_state"; - - /** - * Order by the state of host objects. Mostly this is critical->unknown->warning->ok, - * but also might take acknowledgments and downtimes in account - * - * @var string - */ - const HOST_STATE = "host_state"; - - /** - * @var string - */ - const HOST_NAME = "host_name"; - - /** - * - * @var string - */ - const SERVICE_NAME = "service_description"; -} diff --git a/modules/monitoring/library/Monitoring/Backend/Statusdat/DataView/HostStatusView.php b/modules/monitoring/library/Monitoring/Backend/Statusdat/DataView/HostStatusView.php deleted file mode 100644 index 167690857..000000000 --- a/modules/monitoring/library/Monitoring/Backend/Statusdat/DataView/HostStatusView.php +++ /dev/null @@ -1,135 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Icinga\Module\Monitoring\Backend\Statusdat\DataView; - -use Icinga\Protocol\Statusdat\View\ObjectRemappingView; -use Icinga\Protocol\Statusdat\IReader; - -/** - * Class StatusdatHostView - * @package Icinga\Backend\Statusdat\DataView - */ -class HostStatusView extends ObjectRemappingView -{ - /** - * @var mixed - */ - private $state; - - /** - * @var array - */ - protected $handlerParameters = array( - "host" => "getHost", - "host_unhandled_service_count" => "getNrOfUnhandledServices", - "host_last_comment" => "getLastComment", - 'host_handled' => "checkIfHandled", - - ); - - public function checkIfHandled(&$host) - { - return $host->status->current_state == 0 || - $host->status->problem_has_been_acknowledged || - $host->status->scheduled_downtime_depth; - } - - public function getNrOfUnhandledServices(&$host) - { - $ct = 0; - foreach ($host->services as &$service) { - if ($service->status->current_state > 0 - && $service->status->problem_has_been_acknowledged == 0 - && $service->status->scheduled_downtime_depth == 0) { - $ct++; - } - } - return $ct; - } - - public function getLastComment(&$host) - { - if (!isset($host->comment) || empty($host->comment)) { - return null; - } - $comment = end($host->comment); - return $comment->comment_id; - } - /** - * @var array - */ - public static $mappedParameters = array( - "host_address" => "address", - "host_name" => "host_name", - "host" => "host_name", - "host_state" => "status.current_state", - "host_output" => "status.plugin_output", - "host_long_output" => "status.long_plugin_output", - "host_perfdata" => "status.performance_data", - "host_last_state_change" => "status.last_state_change", - "host_check_command" => "check_command", - "host_last_check" => "TO_DATE(status.last_check)", - "host_next_check" => "status.next_check", - "host_check_latency" => "status.check_latency", - "host_check_execution_time" => "status.check_execution_time", - "host_active_checks_enabled" => "status.active_checks_enabled", - "host_in_downtime" => "status.scheduled_downtime_depth", - "host_is_flapping" => "status.is_flapping", - "host_notifications_enabled"=> "status.notifications_enabled", - "host_state_type" => "status.state_type", - "host_icon_image" => "icon_image", - "host_action_url" => "action_url", - "host_notes_url" => "notes_url", - "host_acknowledged" => "status.problem_has_been_acknowledged" - // "state" => "current_state" - ); - - /** - * @param $item - * @return null - */ - public function getHost(&$item) - { - if (!isset($this->state["service"][$item->host_name])) { - return null; - } - if (!isset($this->state["host"][$item->host_name])) { - return null; - } - return $this->state["host"][$item->host_name]; - } - - /** - * @param IReader $reader - */ - public function __construct(IReader $reader) - { - $this->state = $reader->getState(); - } -} diff --git a/modules/monitoring/library/Monitoring/Backend/Statusdat/DataView/ServiceStatusView.php b/modules/monitoring/library/Monitoring/Backend/Statusdat/DataView/ServiceStatusView.php deleted file mode 100644 index de45a58bc..000000000 --- a/modules/monitoring/library/Monitoring/Backend/Statusdat/DataView/ServiceStatusView.php +++ /dev/null @@ -1,162 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Icinga\Module\Monitoring\Backend\Statusdat\DataView; - -use Icinga\Protocol\Statusdat\View\ObjectRemappingView; -use Icinga\Protocol\Statusdat\IReader; - -/** - * Class StatusdatHostView - * @package Icinga\Backend\Statusdat\DataView - */ -class ServiceStatusView extends ObjectRemappingView -{ - /** - * @var mixed - */ - private $state; - - /** - * @var array - */ - protected $handlerParameters = array( - "host" => "getHost", - "host_last_comment" => "getLastHostComment", - 'host_handled' => "checkIfHostHandled", - 'service_handled' => "checkIfHandled", - "service_last_comment" => "getLastComment" - ); - - public function checkIfHostHandled(&$service) - { - return $service->host->status->current_state == 0 || - $service->host->status->problem_has_been_acknowledged || - $service->host->status->scheduled_downtime_depth; - } - - public function checkIfHandled(&$service) - { - return $service->status->current_state == 0 || - $service->status->problem_has_been_acknowledged || - $service->status->scheduled_downtime_depth; - } - - public function getLastComment(&$service) - { - if (!isset($service->comment) || empty($service->comment)) { - return null; - } - $comment = end($service->comment); - return $comment->comment_id; - } - - public function getLastHostComment(&$service) - { - if (!isset($service->host->comment) || empty($service->host->comment)) { - return null; - } - $comment = end($service->host->comment); - return $comment->comment_id; - } - - /** - * @var array - */ - public static $mappedParameters = array( - "host_address" => "host.address", - "host_name" => "host.host_name", - "host" => "host.host_name", - "host_state" => "host.status.current_state", - "host_output" => "host.status.plugin_output", - "host_long_output" => "host.status.long_plugin_output", - "host_perfdata" => "host.status.performance_data", - "host_last_state_change" => "host.status.last_state_change", - "host_check_command" => "host.check_command", - "host_last_check" => "TO_DATE(host.status.last_check)", - "host_next_check" => "host.status.next_check", - "host_check_latency" => "host.status.check_latency", - "host_check_execution_time" => "host.status.check_execution_time", - "host_active_checks_enabled" => "host.status.active_checks_enabled", - "host_in_downtime" => "host.status.scheduled_downtime_depth", - "host_is_flapping" => "host.status.is_flapping", - "host_notifications_enabled" => "host.status.notifications_enabled", - "host_state_type" => "host.status.state_type", - "host_icon_image" => "host.icon_image", - "host_action_url" => "host.action_url", - "host_notes_url" => "host.notes_url", - "host_acknowledged" => "host.status.problem_has_been_acknowledged", - "service" => "service_description", - "service_display_name" => "service_description", - "service_description" => "service_description", - "service_state" => "status.current_state", - "service_icon_image" => "icon_image", - "service_output" => "status.plugin_output", - "service_long_output" => "status.long_plugin_output", - "service_perfdata" => "status.performance_data", - "service_last_state_change" => "status.last_state_change", - "service_check_command" => "check_command", - "service_last_check" => "TO_DATE(status.last_check)", - "service_next_check" => "status.next_check", - "service_check_latency" => "status.check_latency", - "service_check_execution_time" => "status.check_execution_time", - "service_active_checks_enabled" => "status.active_checks_enabled", - "service_in_downtime" => "status.scheduled_downtime_depth", - "service_is_flapping" => "status.is_flapping", - "service_notifications_enabled" => "status.notifications_enabled", - "service_state_type" => "status.state_type", - "service_icon_image" => "icon_image", - "service_action_url" => "action_url", - "service_notes_url" => "notes_url", - "service_acknowledged" => "status.problem_has_been_acknowledged", - // "state" => "current_state" - ); - - /** - * @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]; - } - - /** - * @param IReader $reader - */ - public function __construct(IReader $reader) - { - $this->state = $reader->getState(); - } -} diff --git a/modules/monitoring/library/Monitoring/Backend/Statusdat/DataView/StatusdatServiceView.php b/modules/monitoring/library/Monitoring/Backend/Statusdat/DataView/StatusdatServiceView.php deleted file mode 100644 index edf427724..000000000 --- a/modules/monitoring/library/Monitoring/Backend/Statusdat/DataView/StatusdatServiceView.php +++ /dev/null @@ -1,122 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Icinga\Module\Monitoring\Backend\Statusdat\DataView; - -use Icinga\Protocol\Statusdat\View\ObjectRemappingView; -use \Icinga\Protocol\Statusdat\IReader; - -class StatusdatServiceView extends ObjectRemappingView -{ - /** - * @var mixed - */ - private $state; - - /** - * @var array - */ - protected $handlerParameters = array( - "host" => "getHost", - "downtimes_with_info" => "getDowntimes" - ); - - /** - * @var array - */ - public static $mappedParameters = array( - "host_address" => "parenthost.address", - "host_name" => "host_name", - "active_checks_enabled" => "status.active_checks_enabled", - "passive_checks_enabled" => "status.passive_checks_enabled", - "service_state" => "status.current_state", - "service_perfdata" => "status.performance_data", - "service_last_state_change" => "status.last_state_change", - "service_output" => "status.plugin_output", - "service_long_output" => "status.long_plugin_output", - "service_check_command" => "check_command", - "service_last_check" => "status.last_check", - "service_next_check" => "status.next_check", - "service_check_latency" => "status.check_latency", - "service_check_execution_time" => "status.check_execution_time", - "service_acknowledged" => "status.problem_has_been_acknowledged", - "service_comments" => "comment" - - ); - - /** - * @param \Icinga\Backend\DataView\The $item - * @param \Icinga\Backend\DataView\The $field - * @return \Icinga\Backend\DataView\The|string - */ - public function get(&$item, $field) - { - if (!isset($item->parenthost) && isset($this->state["host"])) { - $item->parenthost = $this->state["host"]; - } - - return parent::get($item, $field); - } - - /** - * @param \Icinga\Backend\DataView\The $item - * @param \Icinga\Backend\DataView\The $field - * @return bool - */ - public function exists(&$item, $field) - { - if (!isset($item->parenthost)) { - $item->parenthost = $this->state["host"]; - } - - return parent::exists($item, $field); - } - - /** - * @param $item - * @return null - */ - public function getHost(&$item) - { - if (!isset($this->state["host"][$item->host_name])) { - return null; - } - if (!isset($this->state["host"][$item->host_name])) { - return null; - } - return $this->state["host"][$item->host_name]; - } - - /** - * @param IReader $reader - */ - public function __construct(IReader $reader) - { - $this->state = & $reader->getState(); - } -} diff --git a/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/CommentQuery.php b/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/CommentQuery.php new file mode 100644 index 000000000..06c7ce1ff --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/CommentQuery.php @@ -0,0 +1,108 @@ + + * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 + * @author Icinga Development Team + */ +// {{{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()); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/ContactQuery.php b/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/ContactQuery.php new file mode 100644 index 000000000..f69b18452 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/ContactQuery.php @@ -0,0 +1,131 @@ + '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()); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/ContactgroupQuery.php b/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/ContactgroupQuery.php new file mode 100644 index 000000000..0f9f7806e --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/ContactgroupQuery.php @@ -0,0 +1,59 @@ + '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()); + + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/DowntimeQuery.php b/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/DowntimeQuery.php new file mode 100644 index 000000000..b0e15be26 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/DowntimeQuery.php @@ -0,0 +1,91 @@ + + * @author Icinga Development Team + */ +// {{{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' => 'internal_downtime_id', + 'host' => 'host_name', + 'host_name' => 'host_name', + 'service_host_name' => 'host_name', + 'service_description' => 'service_description', + ); + + public static $handlerParameters = array( + 'object_type' => 'getObjectType', + 'downtime_start' => 'getDowntimeStart', + 'downtime_is_flexible' => 'getFlexibleFlag' + ); + + public static $fieldTypes = array( + 'downtime_end' => self::TIMESTAMP, + 'downtime_trigger_time' => self::TIMESTAMP, + 'downtime_start' => self::TIMESTAMP + ); + + + 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()); + } +} diff --git a/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/GroupsummaryQuery.php b/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/GroupsummaryQuery.php old mode 100755 new mode 100644 index bf53e9853..98f3e5d50 --- a/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/GroupsummaryQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/GroupsummaryQuery.php @@ -1,203 +1,246 @@ - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - */ -// {{{ICINGA_LICENSE_HEADER}}} namespace Icinga\Module\Monitoring\Backend\Statusdat\Query; -abstract class GroupsummaryQuery extends Query +class GroupsummaryQuery extends StatusdatQuery { - /** - * @var mixed - */ - protected $reader; - - /** - * @var string - */ - protected $groupType = "servicegroup"; - - /** - * @var string - */ - protected $base = "services"; - - /** - * @var array - */ - protected $available_columns = array( - 'ok' => 'SUM(CASE WHEN state = 0 THEN 1 ELSE 0 END)', - 'critical' => 'SUM(CASE WHEN state = 2 AND downtime = 0 AND ack = 0 THEN 1 ELSE 0 END)', - 'critical_dt' => 'SUM(CASE WHEN state = 2 AND downtime = 1 THEN 1 ELSE 0 END)', - 'critical_ack' => 'SUM(CASE WHEN state = 2 AND downtime = 0 AND ack = 1 THEN 1 ELSE 0 END)', - 'unknown' => 'SUM(CASE WHEN state = 3 AND downtime = 0 AND ack = 0 THEN 1 ELSE 0 END)', - 'unknown_dt' => 'SUM(CASE WHEN state = 3 AND downtime = 1 THEN 1 ELSE 0 END)', - 'unknown_ack' => 'SUM(CASE WHEN state = 3 AND downtime = 0 AND ack = 1 THEN 1 ELSE 0 END)', - 'warning' => 'SUM(CASE WHEN state = 1 AND downtime = 0 AND ack = 0 THEN 1 ELSE 0 END)', - 'warning_dt' => 'SUM(CASE WHEN state = 1 AND downtime = 1 THEN 1 ELSE 0 END)', - 'warning_ack' => 'SUM(CASE WHEN state = 1 AND downtime = 0 AND ack = 1 THEN 1 ELSE 0 END)', + public static $mappedParameters = array( + 'hostgroup_name' => 'hostgroup_name', + 'servicegroup_name' => 'servicegroup_name' ); - /** - * @var array - */ - protected $orderColumns = array( - 'state' => array( - 'ASC' => array( - 'ok ASC', - 'warning_dt ASC', - 'warning_ack ASC', - 'warning ASC', - 'unknown_dt ASC', - 'unknown_ack ASC', - 'unknown ASC', - 'critical_dt ASC', - 'critical_ack ASC', - 'critical ASC', - ), - 'DESC' => array( - 'critical DESC', - 'critical_ack DESC', - 'critical_dt DESC', - 'unknown DESC', - 'unknown_ack DESC', - 'unknown_dt DESC', - 'warning DESC', - 'warning_ack DESC', - 'warning_dt DESC', - 'ok DESC', - ), - 'default' => 'DESC' - ) + public static $handlerParameters = array( + 'cnt_hosts_up' => 'getHostUpSum', + 'cnt_hosts_unreachable' => 'getHostUnreachableSum', + 'cnt_hosts_unreachable_unhandled' => 'getHostUnreachableUnhandledSum', + 'cnt_hosts_down' => 'getHostDownSum', + 'cnt_hosts_down_unhandled' => 'getHostDownUnhandledSum', + 'cnt_hosts_pending' => 'getHostPendingSum', + 'cnt_services_ok' => 'getServiceOkSum', + 'cnt_services_unknown' => 'getServiceUnknownSum', + 'cnt_services_unknown_unhandled' => 'getServiceUnknownUnhandledSum', + 'cnt_services_critical' => 'getServiceCriticalSum', + 'cnt_services_critical_unhandled' => 'getServiceCriticalUnhandledSum', + 'cnt_services_warning' => 'getServiceWarningSum', + 'cnt_services_warning_unhandled' => 'getServiceWarningUnhandledSum', + 'cnt_services_pending' => 'getServicePendingSum', + ); - /** - * @param $obj - * @return string - */ - private function getStateType(&$obj) + private function getMembers(&$obj, $hint = null) { - if ($obj->status->current_state == 0) { - return "ok"; + if (!isset($obj->service) && !isset($obj->host)) { + return null; } - $typeBase = ""; - if ($obj->status->current_state == 1) { - $typeBase = 'warning'; - } else { - if ($obj->status->current_state == 2) { - $typeBase = 'critical'; + $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 ($obj->status->current_state == 3) { - $typeBase = 'unknown'; + if ($criteriaFn($member->$type)) { + $ids[$name] = true; } } } - if ($obj->status->problem_has_been_acknowledged) { - return $typeBase . "_ack"; - - } else { - if (isset($obj->status->downtime)) { - return $typeBase . "_dt"; - } - } - return $typeBase; + return count(array_keys($ids)); } - /** - * @param $indices - * @return array - */ - public function groupByProblemType(&$indices) + public function getHostUpSum(&$obj) { - $typename = $this->groupType . "_name"; - $result = array(); - foreach ($indices as $type => $subIndices) { - - foreach ($subIndices as $objName) { - - $obj = $this->reader->getObjectByName($type, $objName); - $statetype = $this->getStateType($obj); - foreach ($obj->group as $group) { - if (!isset($result[$group])) { - $result[$group] = (object)array( - $typename => $group, - 'ok' => 0, - 'critical' => 0, - 'critical_dt' => 0, - 'critical_ack' => 0, - 'unknown' => 0, - 'unknown_dt' => 0, - 'unknown_ack' => 0, - 'warning' => 0, - 'warning_dt' => 0, - 'warning_ack' => 0 - ); - } - $result[$group]->$statetype++; - } - } - } - - return array_values($result); + return $this->getMembersByCriteria($obj, 'host', 'host_name', function($member) { + return ($member->status->current_state == 0 + && $member->status->has_been_checked); + }); } - /** - * @var \Icinga\Protocol\Statusdat\Query - * @return mixed|void - */ - public function init() + public function getHostUnreachableSum(&$obj) { - $this->reader = $this->ds->getReader(); - $this->query = $this->reader->select()->from($this->base, array())->groupByFunction( - "groupByProblemType", - $this - )->where("COUNT{group} > 0"); - + 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 + ) + ); + }); } - /** - * @param The $column - * @param null $value - * @return $this|Query - */ - public function where($column, $value = null) + public function getHostUnreachableUnhandledSum(&$obj) { - if ($column === 'problems') { - if ($value === 'true') { - //$this->where( - // "COUNT{downtime} == 0 AND status.problem_has_been_acknowledged == 0 AND status.current_state > 0" - // ); - } - } elseif ($column === 'search') { - if ($value) { - $this->where($this->name_alias . ' LIKE ?', '%' . $value . '%'); - } - } else { - parent::where($column, $value); + 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_name', $this->getColumns())) { + return 'servicegroups'; } - return $this; + return "hostgroups"; + } + + public function selectBase() + { + $this->select()->from($this->getTarget(), array()); } } diff --git a/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/HostgroupQuery.php b/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/HostgroupQuery.php new file mode 100755 index 000000000..8bb3f1af7 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/HostgroupQuery.php @@ -0,0 +1,49 @@ + + * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 + * @author Icinga Development Team + */ +// {{{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()); + } +} \ No newline at end of file diff --git a/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/HostlistQuery.php b/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/HostlistQuery.php index ada926f9b..cd44b5170 100755 --- a/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/HostlistQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/HostlistQuery.php @@ -35,7 +35,7 @@ use Icinga\Exception; * Class HostListQuery * @package Icinga\Backend\Statusdat */ -class HostListQuery extends Query +class HostListQuery extends StatusdatQuery { /** * @var \Icinga\Protocol\Statusdat\Query @@ -50,9 +50,8 @@ class HostListQuery extends Query /** * @return mixed|void */ - public function init() + public function selectBase() { - $this->reader = $this->backend->getReader(); - $this->query = $this->reader->select()->from("hosts", array()); + $this->select()->from("hosts", array()); } } diff --git a/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/Query.php b/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/Query.php deleted file mode 100644 index a104a5641..000000000 --- a/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/Query.php +++ /dev/null @@ -1,327 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Icinga\Module\Monitoring\Backend\Statusdat\Query; - -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\BaseQuery; -use Icinga\Protocol\Statusdat\View\MonitoringObjectList as MList; -use Icinga\Protocol\Statusdat\Query as StatusdatQuery; -use Icinga\Filter\Filterable; - -/** - * Class Query - * @package Icinga\Backend\Statusdat - */ -abstract class Query extends BaseQuery implements Filterable -{ - /** - * @var null - */ - private $cursor = null; - - /** - * @var string - */ - private $viewClass = '\Icinga\Module\Monitoring\Backend\Statusdat\DataView\StatusdatServiceView'; - private $baseQuery = null; - - public function setBaseQuery(StatusdatQuery $query) - { - $this->baseQuery = $query; - } - - public function setResultViewClass($viewClass) - { - $this->viewClass = '\Icinga\Module\Monitoring\Backend\Statusdat\DataView\\'.$viewClass; - } - - /** - * Calls the apply%Filtername%Filter() method for the given filter, or simply calls - * where(), if the method is not available. - * - * @see \Icinga\Backend\Query For the parent definition - * - * @param array $filters An array of "filtername"=>"value" definitions - * - * @return Query Returns the query object to allow fluent calls - */ - public function applyFilters(array $filters = array()) - { - foreach ($filters as $filter => $value) { - $filter[0] = strtoupper($filter[0]); - $filterMethod = "apply" . $filter . "Filter"; - if (method_exists($this, $filterMethod)) { - $this->$filterMethod($filter, $value); - } else { - $this->where($filter, $value); - } - } - return $this; - } - - /** - * Applies a filter to only show open problems, or non problems, depending whether value is true or false - * - * @param $type ignored - * @param $value Whether problems should be shown (1) or non problems (0) - */ - public function applyProblemsFilter($type, $value) - { - if ($value) { // Status.dat only contains active downtimes - $value = array(1, 0); - $this->where("(status.current_state >= ? and COUNT{status.downtime} = ? )", $value); - } else { - $value = array(0, 1); - $this->where("(status.current_state < 1 or COUNT{status.downtime} > ? )", $value); - } - } - - /** - * Generic object search by host name, service description and plugin output - * - * @param $type ignored - * @param $value The string to search for - */ - public function applySearchFilter($type, $value) - { - $text = "%$value%"; - $val = array($text, $text, $text); - - $this->baseQuery->where("(host_name LIKE ? OR service_description LIKE ? OR status.plugin_output LIKE ?)", $val); - - } - - /** - * Applies a hostgroup filter on this object - * - * @param $type ignored - * @param $value The hostgroup to filter for - */ - public function applyHostgroupsFilter($type, $value) - { - $filter = array($value); - $this->baseQuery->where("host.group IN ?", $filter); - } - - /** - * Applies a servicegroup filter on this object - * - * @param $type ignored - * @param $value The servicegroup to filter for - */ - public function applyServicegroupsFilter($type, $value) - { - $filter = array($value); - $this->baseQuery->where("group IN ?", $filter); - } - - /** - * Filters by handled problems or unhandled - * - * @todo: Add downtime - * @param $type - * @param $value Whether to search for unhandled (0) or handled (1) - */ - public function applyHandledFilter($type, $value) - { - $val = array($value, $value); - $this->baseQuery->where("(status.problem_has_been_acknowledged = ? )", $val); - } - - /** - * @param $type - * @param $value - */ - public function applyHostnameFilter($type, $value) - { - if (!is_array($value)) { - $value = array($value); - } - $this->baseQuery->where("host_name LIKE ?", $value); - } - - /** - * @param $type - * @param $value - */ - public function applyStateFilter($type, $value) - { - $this->baseQuery->where("status.current_state = $value"); - } - - /** - * @param $type - * @param $value - */ - public function applyHoststateFilter($type, $value) - { - $this->baseQuery->where("host.status.current_state = $value"); - } - - /** - * @param $type - * @param $value - */ - public function applyServiceDescriptionFilter($type, $value) - { - if (!is_array($value)) { - $value = array($value); - } - $this->baseQuery->where("service_description LIKE ?", $value); - } - - /** - * Limits this query and offsets it - * @param null|integer $count The maximum element count to display - * @param null|integer $offset The offset to start counting - * @return Query This object, for fluent interface - */ - public function limit($count = null, $offset = null) - { - $this->baseQuery->limit($count, $offset); - return $this; - } - - /** - * 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) - { - - if ($column) { - $class = $this->viewClass; - $this->baseQuery->order($class::$mappedParameters[$column], strtolower($dir)); - } - return $this; - } - - /** - * Applies a filter on this query by calling the statusdat where() function - * - * @param $column The (statusdat!) column to filter in "field operator ?" - * format. (@example status.current_state > ?) - * @param mixed $value The value to filter for - * @return Query Returns this query,for fluent interface - */ - public function where($column, $value = null) - { - if (!is_array($value)) { - $value = array($value); - } - $this->baseQuery->where($column, $value); - return $this; - } - - /** - * @return MList|mixed|null - */ - public function fetchAll() - { - $view = $this->viewClass; - if (!$this->cursor) { - $result = $this->baseQuery->getResult(); - $this->cursor = new MList($result, new $view($this->reader)); - } - return $this->cursor; - } - - /** - * @return mixed - */ - public function fetchRow() - { - return next($this->fetchAll()); - } - - /** - * @return mixed|void - */ - public function fetchPairs() - { - - } - - /** - * @return mixed - */ - public function fetchOne() - { - return next($this->fetchAll()); - } - - /** - * @return int|mixed - */ - public function count() - { - return count($this->baseQuery->getResult()); - } - - public function isValidFilterTarget($field) - { - // TODO: Implement isValidFilterTarget() method. - } - - public function getMappedField($field) - { - // TODO: Implement getMappedField() method. - } - - public function applyFilter() - { - // TODO: Implement applyFilter() method. - } - - /** - * Parse a backend specific filter expression and return a Query\Node object - * - * @param $expression The expression to parse - * @param $parameters Optional parameters for the expression - * @return Node A query node or null if it's an invalid expression - */ - protected function parseFilterExpression($expression, $parameters = null) - { - // TODO: Implement parseFilterExpression() method. - } - - - - - -} - diff --git a/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/ServicegroupQuery.php b/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/ServicegroupQuery.php new file mode 100755 index 000000000..b08550f6a --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/ServicegroupQuery.php @@ -0,0 +1,52 @@ + + * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 + * @author Icinga Development Team + */ +// {{{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()); + } +} \ No newline at end of file diff --git a/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/ServicelistQuery.php b/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/ServicelistQuery.php index 6b6da7dd0..85d45cb78 100755 --- a/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/ServicelistQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/ServicelistQuery.php @@ -35,7 +35,7 @@ use Icinga\Exception; * Class ServicelistQuery * @package Icinga\Backend\Statusdat */ -class ServicelistQuery extends Query +class ServicelistQuery extends StatusdatQuery { /** * @var \Icinga\Protocol\Statusdat\Query @@ -47,9 +47,8 @@ class ServicelistQuery extends Query */ protected $view = 'Icinga\Backend\Statusdat\DataView\StatusdatServiceView'; - public function init() + public function selectBase() { - $this->reader = $this->backend->getReader(); - $this->query = $this->reader->select()->from("services", array()); + $this->select()->from("services", array()); } } diff --git a/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/StatusQuery.php b/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/StatusQuery.php index 51b4dfca0..e1141c7fa 100644 --- a/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/StatusQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/StatusQuery.php @@ -10,27 +10,344 @@ namespace Icinga\Module\Monitoring\Backend\Statusdat\Query; use Icinga\Protocol\Statusdat; +use Icinga\Protocol\Statusdat\IReader; use Icinga\Exception; -class StatusQuery extends Query +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_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_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', + 'hostgroups' => 'host.group', + 'servicegroups' => '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_severity' => 'getSeverityForHost', + 'host_in_downtime' => 'isInDowntimeForHost', + 'host_problem' => 'isProblemForHost', + 'host_attempt' => 'getAttemptStringForHost', + 'service_state' => 'getState', + 'service_hard_state' => 'getHardState', + 'service_handled' => 'isHandled', + '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; + } + + public function isInDowntime(&$obj) + { + return $obj->status->scheduled_downtime_depth > 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 || + $host->status->scheduled_downtime_depth; + } + + 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)) + foreach ($this->getColumns() as $column) { + if (preg_match("/^service/",$column)) { return "service"; + } } + return "host"; } - public function init() - { - $target = $this->getTarget(); - $this->reader = $this->ds; - $this->setResultViewClass(ucfirst($target)."StatusView"); - $this->setBaseQuery($this->reader->select()->from($target."s", array())); + 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 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); + } + + } diff --git a/library/Icinga/Protocol/Statusdat/View/ObjectRemappingView.php b/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/StatusdatQuery.php old mode 100755 new mode 100644 similarity index 56% rename from library/Icinga/Protocol/Statusdat/View/ObjectRemappingView.php rename to modules/monitoring/library/Monitoring/Backend/Statusdat/Query/StatusdatQuery.php index 911a36e17..4e6ba295c --- a/library/Icinga/Protocol/Statusdat/View/ObjectRemappingView.php +++ b/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/StatusdatQuery.php @@ -26,49 +26,95 @@ */ // {{{ICINGA_LICENSE_HEADER}}} -namespace Icinga\Protocol\Statusdat\View; +namespace Icinga\Module\Monitoring\Backend\Statusdat\Query; + +use Icinga\Application\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\BaseQuery; +use Icinga\Protocol\Statusdat\Query as Query; +use Icinga\Protocol\Statusdat\View\AccessorStrategy; +use Icinga\Filter\Filterable; /** - * Class ObjectRemappingView - * - * Dataview that maps generic field names to storage specific fields or requests them via handlers. - * - * When accessing objects, every storage api returns them with other names. You can't simply say - * $object->service_state, because this field is, e.g. under status.current_state in the status.dat - * view, while IDO uses servicestate->current_state. - * - * This view is intended for normalizing these changes, so a request of service_state returns the - * right field for the backend. When implementing it, you have to fill the mappedParameters and/or - * the handlerParameters array. While mappedParameters simply translate logic field names to - * storage specific ones, handlerParameters determins functions that handle data retrieval for - * the specific fields. - * + * Class Query + * @package Icinga\Backend\Statusdat */ - -class ObjectRemappingView implements AccessorStrategy +abstract class StatusdatQuery extends Query implements Filterable, AccessorStrategy { + const TIMESTAMP = 'timestamp'; /** - * When implementing your own Mapper, this contains the static mapping rules. - * @see Icinga\Module\Monitoring\Backend\Statusdat\DataView\StatusdatServiceView for an example + * 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" ); - /** - * When implementing your own Mapper, this contains the handler for specific fields and allows you to lazy load - * different fields if necessary. The methods are strings that will be mapped to methods of this class - * - * @see Icinga\Backend\Statusdat\DataView\StatusdatServiceView for an example - * - * @var array - */ - protected $handlerParameters = array(); + /** * @@ -81,19 +127,17 @@ class ObjectRemappingView implements AccessorStrategy */ public function get(&$item, $field) { - + $result = null; if (isset($item->$field)) { - return $item->$field; - } - if (isset(static::$mappedParameters[$field])) { - return $this->getMappedParameter($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); } - if (isset($this->handlerParameters[$field])) { - $hdl = $this->handlerParameters[$field]; - return $this->$hdl($item); - } - throw new \InvalidArgumentException("Field $field does not exist for status.dat services"); + return $result; } private function applyPropertyFunction($function, $value) @@ -119,6 +163,7 @@ class ObjectRemappingView implements AccessorStrategy { $matches = array(); $fieldDef = static::$mappedParameters[$field]; + $function = false; if (preg_match_all('/(?P\w+)\((?P.*)\)/', $fieldDef, $matches)) { $function = $matches["FUNCTION"][0]; @@ -128,11 +173,23 @@ class ObjectRemappingView implements AccessorStrategy $res = $item; foreach ($mapped as $map) { - if (!isset($res->$map)) { - return ""; + 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; } - $res = $res->$map; } + if ($function) { return $this->applyPropertyFunction($function, $res); } @@ -146,7 +203,7 @@ class ObjectRemappingView implements AccessorStrategy * @param The $field * @return The|string */ - public function getNormalizedFieldName($field) + public function getMappedField($field) { if (isset(static::$mappedParameters[$field])) { return static::$mappedParameters[$field]; @@ -166,7 +223,20 @@ class ObjectRemappingView implements AccessorStrategy { return (isset($item->$field) || isset(static::$mappedParameters[$field]) - || isset($this->handlerParameters[$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; + } + } + diff --git a/modules/monitoring/library/Monitoring/Controller.php b/modules/monitoring/library/Monitoring/Controller.php index 9958a3819..255913562 100644 --- a/modules/monitoring/library/Monitoring/Controller.php +++ b/modules/monitoring/library/Monitoring/Controller.php @@ -37,6 +37,7 @@ class Controller extends ActionController 'service_acknowledged', 'service_handled', 'service_output', + 'service_attempt', 'service_last_state_change', 'service_icon_image', 'service_long_output', diff --git a/modules/monitoring/library/Monitoring/DataView/DataView.php b/modules/monitoring/library/Monitoring/DataView/DataView.php index aad28053b..e07f97886 100644 --- a/modules/monitoring/library/Monitoring/DataView/DataView.php +++ b/modules/monitoring/library/Monitoring/DataView/DataView.php @@ -71,7 +71,6 @@ abstract class DataView implements Filterable */ public static function fromRequest($request, array $columns = null) { - $view = new static(Backend::createBackend($request->getParam('backend')), $columns); $parser = new UrlViewFilter($view); $view->getQuery()->setFilter($parser->fromRequest($request)); @@ -108,6 +107,7 @@ abstract class DataView implements Filterable $view->getQuery()->where($key, $value); } } + $order = isset($params['order']) ? $params['order'] : null; if ($order !== null) { if (strtolower($order) === 'desc') { @@ -154,6 +154,7 @@ abstract class DataView implements Filterable public function sort($column = null, $order = null) { $sortRules = $this->getSortRules(); + if ($column === null) { $sortColumns = reset($sortRules); if (!isset($sortColumns['columns'])) { diff --git a/modules/monitoring/library/Monitoring/DataView/HostStatus.php b/modules/monitoring/library/Monitoring/DataView/HostStatus.php index 5f87a7101..d359e7694 100644 --- a/modules/monitoring/library/Monitoring/DataView/HostStatus.php +++ b/modules/monitoring/library/Monitoring/DataView/HostStatus.php @@ -85,8 +85,7 @@ class HostStatus extends DataView ), 'host_address' => array( 'columns' => array( - 'host_ipv4', - 'service_description' + 'host_ipv4' ), 'order' => self::SORT_ASC ), diff --git a/modules/monitoring/library/Monitoring/DataView/ServiceStatus.php b/modules/monitoring/library/Monitoring/DataView/ServiceStatus.php index d5cd32adf..0a42434ac 100644 --- a/modules/monitoring/library/Monitoring/DataView/ServiceStatus.php +++ b/modules/monitoring/library/Monitoring/DataView/ServiceStatus.php @@ -41,6 +41,7 @@ class ServiceStatus extends DataView 'service_last_comment', 'service_last_check', 'service_next_check', + 'service_attempt', 'service_last_notification', 'service_check_command', 'host_icon_image', diff --git a/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/HostgroupsummaryQuery.php b/modules/monitoring/library/Monitoring/Exception/UnsupportedBackendException.php old mode 100755 new mode 100644 similarity index 77% rename from modules/monitoring/library/Monitoring/Backend/Statusdat/Query/HostgroupsummaryQuery.php rename to modules/monitoring/library/Monitoring/Exception/UnsupportedBackendException.php index e21881128..b5a1fb1fa --- a/modules/monitoring/library/Monitoring/Backend/Statusdat/Query/HostgroupsummaryQuery.php +++ b/modules/monitoring/library/Monitoring/Exception/UnsupportedBackendException.php @@ -26,21 +26,10 @@ */ // {{{ICINGA_LICENSE_HEADER}}} -namespace Icinga\Module\Monitoring\Backend\Statusdat\Query; -/** - * Class HostgroupsummaryQuery - * @package Icinga\Backend\Statusdat - */ -class HostgroupsummaryQuery extends GroupsummaryQuery +namespace Icinga\Module\Monitoring\Exception; +use \Exception; + +class UnsupportedBackendException extends Exception { - /** - * @var string - */ - protected $groupType = "hostgroup"; - - /** - * @var string - */ - protected $base = "hosts"; -} +} \ No newline at end of file diff --git a/modules/monitoring/library/Monitoring/Object/AbstractObject.php b/modules/monitoring/library/Monitoring/Object/AbstractObject.php index cf6c70dab..1b8d755c6 100644 --- a/modules/monitoring/library/Monitoring/Object/AbstractObject.php +++ b/modules/monitoring/library/Monitoring/Object/AbstractObject.php @@ -32,17 +32,13 @@ abstract class AbstractObject public $customvars = array(); public $events = array(); + private $properties = array(); private $request = null; public function __construct(Request $request) { $this->request = $request; - $properties = $this->getProperties(); - if ($properties) { - foreach ($properties as $key => $value) { - $this->$key = $value; - } - } + $this->properties = $this->getProperties(); } abstract protected function getProperties(); @@ -81,6 +77,7 @@ abstract class AbstractObject 'hostgroup_alias' ) )->getQuery()->fetchPairs(); + return $this; } @@ -147,6 +144,12 @@ abstract class AbstractObject public function __get($param) { + + if (isset($this->properties->$param)) { + return $this->properties->$param; + } elseif (isset($this->$param)) { + return $this->$param; + } if (substr($param, 0, strlen($this->prefix)) === $this->prefix) { return false; } @@ -159,8 +162,6 @@ abstract class AbstractObject return $this->request; } - abstract public function populate(); - public static function fromRequest(Request $request) { if ($request->has('service') && $request->has('host')) { @@ -169,4 +170,6 @@ abstract class AbstractObject return new Host($request); } } + + abstract public function populate(); } diff --git a/modules/monitoring/library/Monitoring/Object/Host.php b/modules/monitoring/library/Monitoring/Object/Host.php index ab812bed1..4e7a5a133 100644 --- a/modules/monitoring/library/Monitoring/Object/Host.php +++ b/modules/monitoring/library/Monitoring/Object/Host.php @@ -10,7 +10,7 @@ class Host extends AbstractObject public $type = self::TYPE_HOST; public $prefix = 'host_'; - private $view = null; + private $view = null; public function populate() diff --git a/modules/monitoring/test/php/application/controllers/ListControllerHostTest.php b/modules/monitoring/test/php/application/controllers/ListControllerHostTest.php index db1e4f361..18e529beb 100644 --- a/modules/monitoring/test/php/application/controllers/ListControllerHostTest.php +++ b/modules/monitoring/test/php/application/controllers/ListControllerHostTest.php @@ -44,12 +44,14 @@ class ListControllerHostMySQLTest extends MonitoringControllerTest $firstHostFlags = ObjectFlags::PASSIVE_ONLY(); $firstHostFlags->acknowledged = 1; $firstHostFlags->in_downtime = 1; + $firstHostFlags->has_been_checked = 1; $firstHostFlags->notifications = 0; $firstHostFlags->flapping = 1; $firstHostFlags->time = $checkTime; $fixture->addHost('host1', 1, $firstHostFlags, array( "address" => "10.92.1.5", + "has_been_checked" => 1, "icon_image" => "myIcon.png", "notes_url" => "note1.html", "action_url" => "action.html"))-> @@ -90,7 +92,6 @@ class ListControllerHostMySQLTest extends MonitoringControllerTest $persistedLastCheck = explode("+", $hostToTest->host_last_check); $persistedLastCheck = $persistedLastCheck[0]; $this->assertEquals("10.92.1.5", $hostToTest->host_address, "Testing for correct host address field (backend ".$backend.")"); - $this->assertEquals(1, $hostToTest->host_state, "Testing for status being DOWN (backend ".$backend.")"); // commented out due to failing tests when delay is too long // $this->assertEquals(date("Y-m-d H:i:s", intval($checkTime)), $persistedLastCheck, "Testing for correct last check time format (backend ".$backend.")"); //$this->assertEquals($checkTime, $hostToTest->host_last_state_change, "Testing for correct last state change (backend ".$backend.")"); diff --git a/modules/monitoring/test/php/library/Backend/Statusdat/ServicegroupsummaryQueryTest.php b/modules/monitoring/test/php/library/Backend/Statusdat/ServicegroupsummaryQueryTest.php deleted file mode 100644 index 547a4480d..000000000 --- a/modules/monitoring/test/php/library/Backend/Statusdat/ServicegroupsummaryQueryTest.php +++ /dev/null @@ -1,178 +0,0 @@ -reader = $reader; - } - - public function getReader() { - return $this->reader; - } -} - -class ServicegroupsummaryqueryTest extends \PHPUnit_Framework_TestCase -{ - public function testGroupByProblemType() - { - $backendConfig = new Zend_Config( - array() - ); - $backend = new BackendMock(); - $backend->setReader($this->getTestDataset()); - $q = new ServicegroupsummaryQuery($backend); - $indices = array( - "service" => array( - "hosta;service1", "hosta;service2", "hosta;service3", - "hostb;service1", "hostb;service2", "hostb;service3", "hostb;service4" - ) - ); - $this->assertEquals(array( - (object) array( - "servicegroup_name" => "sv1", - 'ok' => 1, - 'critical' => 1, - 'critical_dt' => 0, - 'critical_ack' => 1, - 'unknown' => 0, - 'unknown_dt' => 0, - 'unknown_ack' => 0, - 'warning' => 0, - 'warning_dt' => 1, - 'warning_ack' => 2 - ), - (object) array( - "servicegroup_name" => "sv2", - 'ok' => 0, - 'critical' => 0, - 'critical_dt' => 0, - 'critical_ack' => 1, - 'unknown' => 0, - 'unknown_dt' => 0, - 'unknown_ack' => 0, - 'warning' => 1, - 'warning_dt' => 0, - 'warning_ack' => 2 - ) - ),$q->groupByProblemType($indices)); - } - - private function getTestDataset() - { - return new ReaderMock(array( - "host" => array( - "hosta" => (object) array( - "host_name" => "hosta", - "numeric_val" => 0, - "services" => array(0, 1, 2) - ), - "hostb" => (object) array( - "host_name" => "hostb", - "numeric_val" => 0, - "services" => array(3, 4, 5) - ) - ), - "service" => array( - "hosta;service1" => (object) array( - "host_name" => "hosta", - "service_description" => "service1", - "group" => array( - "sv1" - ), - "status" => (object) array( - "current_state" => 0, - "problem_has_been_acknowledged" => 0 - - ) - ), - "hosta;service2" => (object) array( - "host_name" => "hosta", - "service_description" => "service2", - "group" => array( - "sv1" - ), - "status" => (object) array( - "current_state" => 1, - "downtime" => array("..."), - "problem_has_been_acknowledged" => 0 - ) - ), - "hosta;service3" => (object) array( - "host_name" => "hosta", - "service_description" => "service3", - "group" => array( - "sv1" - ), - "status" => (object) array( - "current_state" => 2, - "problem_has_been_acknowledged" => 0 - ) - ), - "hostb;service1" => (object) array( - "host_name" => "hostb", - "service_description" => "service1", - "group" => array( - "sv2" - ), - "status" => (object) array( - "current_state" => 1, - "problem_has_been_acknowledged" => 0 - ) - ), - "hostb;service2" => (object) array( - "host_name" => "hostb", - "service_description" => "service2", - "group" => array( - "sv2","sv1" - ), - "status" => (object) array( - "current_state" => 2, - "problem_has_been_acknowledged" => 1 - ) - ), - "hostb;service3" => (object) array( - "host_name" => "hostb", - "service_description" => "service3", - "group" => array( - "sv2","sv1" - ), - "status" => (object) array( - "current_state" => 1, - "problem_has_been_acknowledged" => 1 - ) - ), - "hostb;service4" => (object) array( - "host_name" => "hostb", - "service_description" => "service4", - "group" => array( - "sv2","sv1" - ), - "status" => (object) array( - "current_state" => 1, - "problem_has_been_acknowledged" => 1 - ) - ) - ) - )); - } -} diff --git a/modules/monitoring/test/php/testlib/MonitoringControllerTest.php b/modules/monitoring/test/php/testlib/MonitoringControllerTest.php index 83821d36d..2b8b993fa 100644 --- a/modules/monitoring/test/php/testlib/MonitoringControllerTest.php +++ b/modules/monitoring/test/php/testlib/MonitoringControllerTest.php @@ -110,7 +110,7 @@ abstract class MonitoringControllerTest extends Zend_Test_PHPUnit_ControllerTest 'statusdat-unittest' => array( 'type' => 'statusdat', 'status_file' => '/tmp/teststatus.dat', - 'objects_file' => '/tmp/testobjects.cache', + 'object_file' => '/tmp/testobjects.cache', 'no_cache' => true ), 'ido-mysql-unittest' => array( @@ -203,11 +203,9 @@ abstract class MonitoringControllerTest extends Zend_Test_PHPUnit_ControllerTest */ private function requireStatusDatQueries() { - require_once(realpath($this->moduleDir.'/library/Monitoring/Backend/Statusdat/Query/Query.php')); + require_once(realpath($this->moduleDir.'/library/Monitoring/Backend/Statusdat/Query/StatusdatQuery.php')); $this->requireFolder('library/Monitoring/Backend/Statusdat'); - $this->requireFolder('library/Monitoring/Backend/Statusdat/Criteria'); $this->requireFolder('library/Monitoring/Backend/Statusdat/Query'); - $this->requireFolder('library/Monitoring/Backend/Statusdat/DataView'); } /** @@ -300,7 +298,7 @@ abstract class MonitoringControllerTest extends Zend_Test_PHPUnit_ControllerTest array( 'type' => 'statusdat', 'status_file' => '/tmp/teststatus.dat', - 'objects_file' => '/tmp/testobjects.cache', + 'object_file' => '/tmp/testobjects.cache', 'no_cache' => true ) ); diff --git a/modules/monitoring/test/php/testlib/datasource/strategies/StatusdatInsertionStrategy.php b/modules/monitoring/test/php/testlib/datasource/strategies/StatusdatInsertionStrategy.php index 7479a7c11..99f124777 100644 --- a/modules/monitoring/test/php/testlib/datasource/strategies/StatusdatInsertionStrategy.php +++ b/modules/monitoring/test/php/testlib/datasource/strategies/StatusdatInsertionStrategy.php @@ -65,7 +65,7 @@ class StatusdatInsertionStrategy implements InsertionStrategy { public function setConnection($ressource) { $this->statusDatFile = $ressource['status_file']; - $this->objectsCacheFile = $ressource['objects_file']; + $this->objectsCacheFile = $ressource['object_file']; } /** diff --git a/modules/monitoring/test/php/testlib/datasource/strategies/StatusdatSetupStrategy.php b/modules/monitoring/test/php/testlib/datasource/strategies/StatusdatSetupStrategy.php index 085a36330..c4367a579 100644 --- a/modules/monitoring/test/php/testlib/datasource/strategies/StatusdatSetupStrategy.php +++ b/modules/monitoring/test/php/testlib/datasource/strategies/StatusdatSetupStrategy.php @@ -65,13 +65,13 @@ class StatusdatSetupStrategy implements SetupStrategy { if ($resource == null) { $resource = array( "status_file" => "/tmp/teststatus.dat", - "objects_file" => "/tmp/testobjects.cache" + "object_file" => "/tmp/testobjects.cache" ); } $this->requireStatusDat(); $this->teardown($resource); touch($resource["status_file"]); - touch($resource["objects_file"]); + touch($resource["object_file"]); return $resource; } @@ -88,14 +88,14 @@ class StatusdatSetupStrategy implements SetupStrategy { if ($resource == null) { $resource = array( "status_file" => "/tmp/teststatus.dat", - "objects_file" => "/tmp/testobjects.cache" + "object_file" => "/tmp/testobjects.cache" ); } if (file_exists($resource["status_file"])) { unlink($resource["status_file"]); } - if (file_exists($resource["objects_file"])) { - unlink($resource["objects_file"]); + if (file_exists($resource["object_file"])) { + unlink($resource["object_file"]); } } } diff --git a/public/js/icinga/components/mainDetailGrid.js b/public/js/icinga/components/mainDetailGrid.js index 0884bc0aa..b2e53a5dc 100644 --- a/public/js/icinga/components/mainDetailGrid.js +++ b/public/js/icinga/components/mainDetailGrid.js @@ -309,8 +309,6 @@ function(Container, $, logger, URI, tpl, urlMgr, Selectable, TableMultiSelection contentNode = determineContentTable(); this.initRowSelection(); this.registerControls(); - this.registerHistoryChanges(); - }; this.construct(gridDomNode); diff --git a/test/php/library/Icinga/Protocol/Statusdat/Component/StatusdatComponentTest.php b/test/php/library/Icinga/Protocol/Statusdat/Component/StatusdatComponentTest.php index 4859f7625..4c56f3881 100755 --- a/test/php/library/Icinga/Protocol/Statusdat/Component/StatusdatComponentTest.php +++ b/test/php/library/Icinga/Protocol/Statusdat/Component/StatusdatComponentTest.php @@ -17,7 +17,7 @@ class StatusdatComponentTest extends \PHPUnit_Framework_TestCase StatusdatTestLoader::requireLibrary(); $reader = new SD\Reader(new \Zend_Config(array( "status_file" => dirname(__FILE__)."/status.dat", - "objects_file" => dirname(__FILE__)."/objects.cache" + "object_file" => dirname(__FILE__)."/objects.cache" )),null,true); return $reader; } @@ -26,7 +26,8 @@ class StatusdatComponentTest extends \PHPUnit_Framework_TestCase $r = $this->getReader(); $group = array(array('a1','b2')); $result = $r->select()->from("services")->where("group IN ?",$group)->getResult(); - $this->assertCount(2,$result); + + $this->assertCount(9, $result, 'Assert items to be returned in a servicegroup filter'); foreach($result as $obj) { $this->assertTrue(is_object($obj)); } @@ -36,7 +37,7 @@ class StatusdatComponentTest extends \PHPUnit_Framework_TestCase $r = $this->getReader(); $group = array(array('a1','b2')); $result = $r->select()->from("hosts")->where("services.group IN ?",$group)->getResult(); - $this->assertCount(2,$result); + $this->assertCount(3, $result); foreach($result as $obj) { $this->assertTrue(is_object($obj)); } @@ -46,7 +47,7 @@ class StatusdatComponentTest extends \PHPUnit_Framework_TestCase $r = $this->getReader(); $group = array(array('exc-hostb')); $result = $r->select()->from("hosts")->where("group IN ?",$group)->getResult(); - $this->assertCount(2,$result); + $this->assertCount(3, $result); foreach($result as $obj) { $this->assertTrue(is_object($obj)); } @@ -57,7 +58,7 @@ class StatusdatComponentTest extends \PHPUnit_Framework_TestCase $group = array(array('exc-hostb')); $result = $r->select()->from("services")->where("host.group IN ?",$group)->getResult(); - $this->assertCount(6,$result); + $this->assertCount(9, $result); foreach($result as $obj) { $this->assertTrue(is_object($obj)); } diff --git a/test/php/library/Icinga/Protocol/Statusdat/Query/GroupTest.php b/test/php/library/Icinga/Protocol/Statusdat/Query/GroupTest.php index 4bd59c580..f94f5ccd2 100755 --- a/test/php/library/Icinga/Protocol/Statusdat/Query/GroupTest.php +++ b/test/php/library/Icinga/Protocol/Statusdat/Query/GroupTest.php @@ -29,6 +29,19 @@ class QueryExpressionMock implements Statusdat\Query\IQueryPart { return array_intersect(array_values($idx), array_values($this->filter)); } + + /** + * Add additional information about the query this filter belongs to + * + * @param $query + * @return mixed + */ + public function setQuery($query) + { + // TODO: Implement setQuery() method. + } + + } class GroupTest extends \PHPUnit_Framework_TestCase diff --git a/test/php/library/Icinga/Protocol/Statusdat/QueryTest.php b/test/php/library/Icinga/Protocol/Statusdat/QueryTest.php index f0428bf39..fa283ea2c 100755 --- a/test/php/library/Icinga/Protocol/Statusdat/QueryTest.php +++ b/test/php/library/Icinga/Protocol/Statusdat/QueryTest.php @@ -21,20 +21,19 @@ class QueryTest extends \PHPUnit_Framework_TestCase { $readerMock = $this->getServiceTestReader(); $query = new Statusdat\Query($readerMock); - - $result = $query->from("services")->getResult(); $objects = $readerMock->getObjects(); - $this->assertCount(count($objects["service"]), $result); + $result = $query->select()->from("services")->getResult(); + $this->assertCount(count($objects["service"]), $result); } public function testSimpleHostSelect() { $readerMock = $this->getServiceTestReader(); $query = new Statusdat\Query($readerMock); + $objects = $readerMock->getObjects(); $result = $query->from("hosts")->getResult(); - $objects = $readerMock->getObjects(); $this->assertCount(count($objects["host"]), $result); } @@ -83,69 +82,15 @@ class QueryTest extends \PHPUnit_Framework_TestCase $query = new Statusdat\Query($readerMock); $result = $query->from("services")->order('numeric_val ASC')->groupByColumns("numeric_val")->getResult(); $this->assertCount(3,$result); - $lastIdx = ~PHP_INT_MAX; foreach($result as $sstatus) { $this->assertTrue(isset($sstatus->count)); $this->assertTrue(isset($sstatus->columns)); - $this->assertEquals(2,$sstatus->count); - $this->assertGreaterThanOrEqual($lastIdx,$sstatus->columns->numeric_val); - $lastIdx = $sstatus->columns->numeric_val; + $this->assertEquals(2, $sstatus->count); } } - public function testOrderSingleColumnASC() - { - $readerMock = $this->getServiceTestReader(); - $objects = $readerMock->getObjects(); - $query = new Statusdat\Query($readerMock); - $result = $query->from("services")->order('numeric_val ASC')->getResult(); - $lastIdx = ~PHP_INT_MAX; - foreach($result as $sstatus) { - $this->assertGreaterThanOrEqual($lastIdx,$sstatus->numeric_val); - $lastIdx = $sstatus->numeric_val; - } - } - - public function testOrderSingleColumnDESC() - { - $readerMock = $this->getServiceTestReader(); - $objects = $readerMock->getObjects(); - $query = new Statusdat\Query($readerMock); - $result = $query->from("services")->order('numeric_val DESC')->getResult(); - $lastIdx = PHP_INT_MAX; - foreach($result as $sstatus) { - $this->assertLessThanOrEqual($lastIdx,$sstatus->numeric_val); - $lastIdx = $sstatus->numeric_val; - } - } - - /** - * Integration test for query and Expression/Group objects. - * This is not a unit test, but checks if the 'where' filter really works - */ - public function testQueryIntegration() { - - $readerMock = $this->getServiceTestReader(); - $objects = $readerMock->getObjects(); - $query = new Statusdat\Query($readerMock); - $result = $query->from("services")->where('numeric_val = ?',array(1))->getResult(); - foreach($result as $testresult) { - $this->assertEquals($testresult->numeric_val,1); - } - $query = new Statusdat\Query($readerMock); - $result = $query->from("services")->where('numeric_val < ? OR numeric_val = ?',array(2,3))->getResult(); - foreach($result as $testresult) { - $this->assertNotEquals($testresult->numeric_val,2); - } - $query = new Statusdat\Query($readerMock); - $result = $query->from("services")->where('numeric_val < ? OR numeric_val = ?',array(2,3))->where("numeric_val = ?",array(1))->getResult(); - foreach($result as $testresult) { - $this->assertEquals($testresult->numeric_val,1); - } - } - private function getServiceTestReader() { $readerMock = new ReaderMock(array( diff --git a/test/php/library/Icinga/Protocol/Statusdat/ReaderMock.php b/test/php/library/Icinga/Protocol/Statusdat/ReaderMock.php index 998cdaed6..32c842fa9 100755 --- a/test/php/library/Icinga/Protocol/Statusdat/ReaderMock.php +++ b/test/php/library/Icinga/Protocol/Statusdat/ReaderMock.php @@ -17,6 +17,12 @@ class ReaderMock implements IReader, DatasourceInterface public function getState() { + return $this->objects; + } + + public function getInternalState() + { + return array( "objects" => $this->objects, "indices" => $this->indices diff --git a/test/php/library/Icinga/Protocol/Statusdat/ReaderTest.php b/test/php/library/Icinga/Protocol/Statusdat/ReaderTest.php index 489b5ca89..ca055e312 100755 --- a/test/php/library/Icinga/Protocol/Statusdat/ReaderTest.php +++ b/test/php/library/Icinga/Protocol/Statusdat/ReaderTest.php @@ -9,36 +9,47 @@ use Icinga\Protocol\Statusdat\Reader as Reader; StatusdatTestLoader::requireLibrary(); if (!defined('APPLICATION_PATH')) { - define("APPLICATION_PATH","./"); // TODO: test boostrap + define("APPLICATION_PATH", "./"); // TODO: test boostrap } /** -* -* Test class for Reader -* Created Wed, 16 Jan 2013 15:15:16 +0000 -* -**/ -class ConfigMock { - function __construct($data) { - foreach($data as $key=>$val) + * + * Test class for Reader + * Created Wed, 16 Jan 2013 15:15:16 +0000 + * + **/ +class ConfigMock +{ + function __construct($data) + { + foreach ($data as $key => $val) { $this->$key = $val; + } } - function get($attr) { + + function get($attr) + { return $this->$attr; } } -class ParserMock { +class ParserMock +{ public $runtime = array(); public $objects = array(); - public function parseObjectsFile() { + + public function parseObjectsFile() + { return $this->objects; } - public function parseRuntimeState() { + + public function parseRuntimeState() + { return $this->runtime; } - public function getRuntimeState() { + public function getRuntimeState() + { return $this->runtime; } } @@ -52,37 +63,42 @@ class ReaderTest extends \PHPUnit_Framework_TestCase } } - public function testFileCaching() { + public function testFileCaching() + { if (!file_exists('./tmp')) { mkdir('./tmp'); } $parser = new ParserMock(); - $parser->runtime = array("host"=>array( - "test" => (object) array( - "host_name" => "test" + $parser->runtime = array( + "host" => array( + "test" => (object)array( + "host_name" => "test" + ) ) - )); - $object_file = tempnam("./dir","object"); - $status_file = tempnam("./dir","status"); + ); + $object_file = tempnam("./dir", "object"); + $status_file = tempnam("./dir", "status"); $reader = new Reader(new ConfigMock(array( "cache_path" => "/tmp", - "objects_file" => $object_file, + "object_file" => $object_file, "status_file" => $status_file - )),$parser); + )), $parser); unlink($object_file); unlink($status_file); - $this->assertTrue(file_exists("/tmp/zend_cache---objects".md5($object_file))); - $this->assertTrue(file_exists("/tmp/zend_cache---state".md5($object_file))); + $this->assertTrue(file_exists("/tmp/zend_cache---object" . md5($object_file))); + $this->assertTrue(file_exists("/tmp/zend_cache---state" . md5($object_file))); system("rm /tmp/zend_cache*"); } - public function testEmptyFileException() { + + public function testEmptyFileException() + { $this->setExpectedException("Icinga\Exception\ConfigurationError"); $parser = new ParserMock(); $reader = new Reader(new ConfigMock(array( "cache_path" => "/tmp", - "objects_file" => "", + "object_file" => "", "status_file" => "", - )),$parser); + )), $parser); } } diff --git a/test/php/library/Icinga/Protocol/Statusdat/StatusdatTestLoader.php b/test/php/library/Icinga/Protocol/Statusdat/StatusdatTestLoader.php index 5f1975bdc..9244640d9 100644 --- a/test/php/library/Icinga/Protocol/Statusdat/StatusdatTestLoader.php +++ b/test/php/library/Icinga/Protocol/Statusdat/StatusdatTestLoader.php @@ -1,9 +1,11 @@ resourceConfig = new Zend_Config( array( 'status_file' => $statusdatFile, - 'objects_file' => $cacheFile, + 'object_file' => $cacheFile, 'type' => 'statusdat' ) ); diff --git a/test/php/library/Icinga/Web/Paginator/ScrollingStyle/SlidingWithBorderTest.php b/test/php/library/Icinga/Web/Paginator/ScrollingStyle/SlidingWithBorderTest.php index 78a08eafb..a46208939 100755 --- a/test/php/library/Icinga/Web/Paginator/ScrollingStyle/SlidingWithBorderTest.php +++ b/test/php/library/Icinga/Web/Paginator/ScrollingStyle/SlidingWithBorderTest.php @@ -21,11 +21,9 @@ require_once 'library/Icinga/Protocol/Statusdat/StatusdatTestLoader.php'; StatusdatTestLoader::requireLibrary(); -require_once '../../modules/monitoring/library/Monitoring/Backend/Statusdat/Criteria/Order.php'; require_once '../../modules/monitoring/library/Monitoring/Backend.php'; -require_once '../../modules/monitoring/library/Monitoring/Backend/Statusdat/Query/Query.php'; +require_once '../../modules/monitoring/library/Monitoring/Backend/Statusdat/Query/StatusdatQuery.php'; require_once '../../modules/monitoring/library/Monitoring/Backend/Statusdat/Query/StatusQuery.php'; -require_once '../../modules/monitoring/library/Monitoring/Backend/Statusdat/DataView/HostStatusView.php'; require_once '../../library/Icinga/Web/Paginator/ScrollingStyle/SlidingWithBorder.php'; class TestPaginatorAdapter implements Zend_Paginator_Adapter_Interface @@ -103,7 +101,7 @@ class SlidingwithborderTest extends \PHPUnit_Framework_TestCase $this->resourceConfig = new Zend_Config( array( 'status_file' => $statusdatFile, - 'objects_file' => $cacheFile, + 'object_file' => $cacheFile, 'type' => 'statusdat' ) );