diff options
Diffstat (limited to '')
69 files changed, 5804 insertions, 0 deletions
diff --git a/library/Icingadb/Model/AcknowledgementHistory.php b/library/Icingadb/Model/AcknowledgementHistory.php new file mode 100644 index 0000000..549d2ff --- /dev/null +++ b/library/Icingadb/Model/AcknowledgementHistory.php @@ -0,0 +1,102 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use Icinga\Module\Icingadb\Model\Behavior\BoolCast; +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behavior\MillisecondTimestamp; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +/** + * Model for table `acknowledgement_history` + * + * Please note that using this model will fetch history entries for decommissioned services. To avoid this, the query + * needs a `acknowledgement_history.service_id IS NULL OR acknowledgement_history_service.id IS NOT NULL` where. + */ +class AcknowledgementHistory extends Model +{ + public function getTableName() + { + return 'acknowledgement_history'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'environment_id', + 'endpoint_id', + 'object_type', + 'host_id', + 'service_id', + 'set_time', + 'clear_time', + 'author', + 'cleared_by', + 'comment', + 'expire_time', + 'is_sticky', + 'is_persistent' + ]; + } + + public function getColumnDefinitions() + { + return [ + 'environment_id' => t('Environment Id'), + 'endpoint_id' => t('Endpoint Id'), + 'object_type' => t('Object Type'), + 'host_id' => t('Host Id'), + 'service_id' => t('Service Id'), + 'set_time' => t('Acknowledgement Set Time'), + 'clear_time' => t('Acknowledgement Clear Time'), + 'author' => t('Acknowledgement Author'), + 'cleared_by' => t('Acknowledgement Cleared By'), + 'comment' => t('Acknowledgement Comment'), + 'expire_time' => t('Acknowledgement Expire Time'), + 'is_sticky' => t('Acknowledgement Is Sticky'), + 'is_persistent' => t('Acknowledgement Is Persistent') + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new BoolCast([ + 'is_sticky', + 'is_persistent' + ])); + + $behaviors->add(new MillisecondTimestamp([ + 'set_time', + 'clear_time', + 'expire_time' + ])); + + $behaviors->add(new Binary([ + 'id', + 'environment_id', + 'endpoint_id', + 'host_id', + 'service_id', + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('endpoint', Endpoint::class); + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('history', History::class) + ->setCandidateKey('id') + ->setForeignKey('acknowledgement_history_id'); + $relations->belongsTo('host', Host::class); + $relations->belongsTo('service', Service::class)->setJoinType('LEFT'); + } +} diff --git a/library/Icingadb/Model/ActionUrl.php b/library/Icingadb/Model/ActionUrl.php new file mode 100644 index 0000000..e0b092e --- /dev/null +++ b/library/Icingadb/Model/ActionUrl.php @@ -0,0 +1,62 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use Icinga\Module\Icingadb\Model\Behavior\ActionAndNoteUrl; +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class ActionUrl extends Model +{ + public function getTableName() + { + return 'action_url'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'action_url', + 'environment_id' + ]; + } + + public function getColumnDefinitions() + { + return [ + 'action_url' => t('Action Url'), + 'environment_id' => t('Environment Id') + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new ActionAndNoteUrl(['action_url'])); + + $behaviors->add(new Binary([ + 'id', + 'environment_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + + $relations->hasMany('host', Host::class) + ->setCandidateKey('id') + ->setForeignKey('action_url_id'); + $relations->hasMany('service', Service::class) + ->setCandidateKey('id') + ->setForeignKey('action_url_id'); + } +} diff --git a/library/Icingadb/Model/Behavior/ActionAndNoteUrl.php b/library/Icingadb/Model/Behavior/ActionAndNoteUrl.php new file mode 100644 index 0000000..e8f6799 --- /dev/null +++ b/library/Icingadb/Model/Behavior/ActionAndNoteUrl.php @@ -0,0 +1,52 @@ +<?php + +/* Icinga DB Web | (c) 2021 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model\Behavior; + +use ipl\Orm\Contract\PropertyBehavior; + +class ActionAndNoteUrl extends PropertyBehavior +{ + public function fromDb($value, $key, $_) + { + if (empty($value)) { + return []; + } + + $links = []; + if (strpos($value, "' ") === false) { + $links[] = $value; + } else { + foreach (explode("' ", $value) as $url) { + $url = strpos($url, "'") === 0 ? substr($url, 1) : $url; + $url = strpos($url, "'") === strlen($url) - 1 ? substr($url, 0, strlen($url) - 1) : $url; + $links[] = $url; + } + } + + return $links; + } + + public function toDb($value, $key, $_) + { + if (empty($value) || ! is_array($value)) { + return $value; + } + + if (count($value) === 1) { + return $value[0]; + } + + $links = ''; + foreach ($value as $url) { + if (! empty($links)) { + $links .= ' '; + } + + $links .= "'$url'"; + } + + return $links; + } +} diff --git a/library/Icingadb/Model/Behavior/Bitmask.php b/library/Icingadb/Model/Behavior/Bitmask.php new file mode 100644 index 0000000..f8d91f6 --- /dev/null +++ b/library/Icingadb/Model/Behavior/Bitmask.php @@ -0,0 +1,83 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model\Behavior; + +use ipl\Orm\Contract\PropertyBehavior; +use ipl\Orm\Contract\RewriteFilterBehavior; +use ipl\Stdlib\Filter\Condition; + +/** + * Class Bitmask + * + * @method void __construct(array $properties) Pass property names as keys and their bitmap ([value => bit]) as value + */ +class Bitmask extends PropertyBehavior implements RewriteFilterBehavior +{ + public function fromDb($bits, $key, $context) + { + $values = []; + foreach ($context as $value => $bit) { + if ($bits & $bit) { + $values[] = $value; + } + } + + return $values; + } + + public function toDb($value, $key, $context) + { + if (! is_array($value)) { + if (is_int($value) || ctype_digit($value)) { + return $value; + } + + return isset($context[$value]) ? $context[$value] : -1; + } + + $bits = []; + $allBits = 0; + foreach ($value as $v) { + if (isset($context[$v])) { + $bits[] = $context[$v]; + $allBits |= $context[$v]; + } elseif (is_int($v) || ctype_digit($v)) { + $bits[] = $v; + $allBits |= $v; + } + } + + $bits[] = $allBits; + return $bits; + } + + public function rewriteCondition(Condition $condition, $relation = null) + { + $column = $condition->metaData()->get('columnName'); + if (! isset($this->properties[$column])) { + return; + } + + $values = $condition->getValue(); + if (! is_array($values)) { + if (is_int($values) || ctype_digit($values)) { + return; + } + + $values = [$values]; + } + + $bits = 0; + foreach ($values as $value) { + if (isset($this->properties[$column][$value])) { + $bits |= $this->properties[$column][$value]; + } elseif (is_int($value) || ctype_digit($value)) { + $bits |= $value; + } + } + + $condition->setColumn(sprintf('%s & %s', $condition->getColumn(), $bits)); + } +} diff --git a/library/Icingadb/Model/Behavior/BoolCast.php b/library/Icingadb/Model/Behavior/BoolCast.php new file mode 100644 index 0000000..8ab01ae --- /dev/null +++ b/library/Icingadb/Model/Behavior/BoolCast.php @@ -0,0 +1,31 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model\Behavior; + +use ipl\Orm\Contract\PropertyBehavior; + +class BoolCast extends PropertyBehavior +{ + public function fromDb($value, $key, $_) + { + switch ((string) $value) { + case 'y': + return true; + case 'n': + return false; + default: + return $value; + } + } + + public function toDb($value, $key, $_) + { + if (is_string($value)) { + return $value; + } + + return $value ? 'y' : 'n'; + } +} diff --git a/library/Icingadb/Model/Behavior/FlattenedObjectVars.php b/library/Icingadb/Model/Behavior/FlattenedObjectVars.php new file mode 100644 index 0000000..b1c308a --- /dev/null +++ b/library/Icingadb/Model/Behavior/FlattenedObjectVars.php @@ -0,0 +1,77 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model\Behavior; + +use Icinga\Module\Icingadb\Common\Auth; +use Icinga\Module\Icingadb\Model\CustomvarFlat; +use ipl\Orm\AliasedExpression; +use ipl\Orm\ColumnDefinition; +use ipl\Orm\Contract\QueryAwareBehavior; +use ipl\Orm\Contract\RewriteColumnBehavior; +use ipl\Orm\Query; +use ipl\Stdlib\Filter; + +class FlattenedObjectVars implements RewriteColumnBehavior, QueryAwareBehavior +{ + use Auth; + + /** @var Query */ + protected $query; + + public function setQuery(Query $query) + { + $this->query = $query; + + return $this; + } + + public function rewriteCondition(Filter\Condition $condition, $relation = null) + { + $column = $condition->metaData()->get('columnName'); + if ($column !== null) { + $relation = substr($relation, 0, -5) . 'customvar_flat.'; + $nameFilter = Filter::like($relation . 'flatname', $column); + $class = get_class($condition); + $valueFilter = new $class($relation . 'flatvalue', $condition->getValue()); + + return Filter::all($nameFilter, $valueFilter); + } + } + + public function rewriteColumn($column, $relation = null) + { + $subQuery = $this->query->createSubQuery(new CustomvarFlat(), $relation) + ->limit(1) + ->columns('flatvalue') + ->filter(Filter::equal('flatname', $column)); + + $this->applyRestrictions($subQuery); + + $alias = $this->query->getDb()->quoteIdentifier([str_replace('.', '_', $relation) . "_$column"]); + + list($select, $values) = $this->query->getDb()->getQueryBuilder()->assembleSelect($subQuery->assembleSelect()); + return new AliasedExpression($alias, "($select)", null, ...$values); + } + + public function rewriteColumnDefinition(ColumnDefinition $def, string $relation): void + { + $parts = explode('.', substr($relation, 0, -5)); + $objectType = array_pop($parts); + + $name = $def->getName(); + if (substr($name, -3) === '[*]') { + // The suggestions also hide this from the label, so should this + $name = substr($name, 0, -3); + } + + // Programmatically translated since the full definition is available in class ObjectSuggestions + $def->setLabel(sprintf(t(ucfirst($objectType) . ' %s', '..<customvar-name>'), $name)); + } + + public function isSelectableColumn(string $name): bool + { + return true; + } +} diff --git a/library/Icingadb/Model/Behavior/ReRoute.php b/library/Icingadb/Model/Behavior/ReRoute.php new file mode 100644 index 0000000..d054f00 --- /dev/null +++ b/library/Icingadb/Model/Behavior/ReRoute.php @@ -0,0 +1,83 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model\Behavior; + +use ipl\Orm\Contract\RewriteFilterBehavior; +use ipl\Orm\Contract\RewritePathBehavior; +use ipl\Stdlib\Filter; + +class ReRoute implements RewriteFilterBehavior, RewritePathBehavior +{ + protected $routes; + + /** + * Tables with mixed object type entries for which servicegroup filters need to be resolved in multiple steps + * + * @var string[] + */ + const MIXED_TYPE_RELATIONS = ['downtime', 'comment', 'history', 'notification_history']; + + public function __construct(array $routes) + { + $this->routes = $routes; + } + + public function getRoutes(): array + { + return $this->routes; + } + + public function rewriteCondition(Filter\Condition $condition, $relation = null) + { + $remainingPath = $condition->metaData()->get('columnName', ''); + if (strpos($remainingPath, '.') === false) { + return; + } + + if (($path = $this->rewritePath($remainingPath, $relation)) !== null) { + $class = get_class($condition); + $filter = new $class($relation . $path, $condition->getValue()); + if ($condition->metaData()->has('forceOptimization')) { + $filter->metaData()->set( + 'forceOptimization', + $condition->metaData()->get('forceOptimization') + ); + } + + if ( + in_array(substr($relation, 0, -1), self::MIXED_TYPE_RELATIONS) + && substr($remainingPath, 0, 13) === 'servicegroup.' + ) { + $applyAll = Filter::all(); + $applyAll->add(Filter::equal($relation . 'object_type', 'host')); + + $orgFilter = clone $filter; + $orgFilter->setColumn($relation . 'host.' . $path); + + $applyAll->add($orgFilter); + + $filter = Filter::any($filter, $applyAll); + } + + return $filter; + } + } + + public function rewritePath(string $path, ?string $relation = null): ?string + { + $dot = strpos($path, '.'); + if ($dot !== false) { + $routeName = substr($path, 0, $dot); + } else { + $routeName = $path; + } + + if (isset($this->routes[$routeName])) { + return $this->routes[$routeName] . ($dot !== false ? substr($path, $dot) : ''); + } + + return null; + } +} diff --git a/library/Icingadb/Model/Checkcommand.php b/library/Icingadb/Model/Checkcommand.php new file mode 100644 index 0000000..400a24b --- /dev/null +++ b/library/Icingadb/Model/Checkcommand.php @@ -0,0 +1,86 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use Icinga\Module\Icingadb\Model\Behavior\ReRoute; +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class Checkcommand extends Model +{ + public function getTableName() + { + return 'checkcommand'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'zone_id', + 'environment_id', + 'name_checksum', + 'properties_checksum', + 'name', + 'name_ci', + 'command', + 'timeout' + ]; + } + + public function getColumnDefinitions() + { + return [ + 'zone_id' => t('Zone Id'), + 'environment_id' => t('Environment Id'), + 'name_checksum' => t('Checkcommand Name Checksum'), + 'properties_checksum' => t('Checkcommand Properties Checksum'), + 'name' => t('Checkcommand Name'), + 'name_ci' => t('Checkcommand Name (CI)'), + 'command' => t('Checkcommand'), + 'timeout' => t('Checkcommand Timeout') + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new ReRoute([ + 'hostgroup' => 'host.hostgroup', + 'servicegroup' => 'service.servicegroup' + ])); + + $behaviors->add(new Binary([ + 'id', + 'zone_id', + 'environment_id', + 'name_checksum', + 'properties_checksum' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('zone', Zone::class); + + $relations->belongsToMany('customvar', Customvar::class) + ->through(CheckcommandCustomvar::class); + $relations->belongsToMany('customvar_flat', CustomvarFlat::class) + ->through(CheckcommandCustomvar::class); + $relations->belongsToMany('vars', Vars::class) + ->through(CheckcommandCustomvar::class); + + $relations->hasMany('argument', CheckcommandArgument::class); + $relations->hasMany('envvar', CheckcommandEnvvar::class); + $relations->hasMany('host', Host::class); + $relations->hasMany('service', Service::class); + } +} diff --git a/library/Icingadb/Model/CheckcommandArgument.php b/library/Icingadb/Model/CheckcommandArgument.php new file mode 100644 index 0000000..3fb4ad5 --- /dev/null +++ b/library/Icingadb/Model/CheckcommandArgument.php @@ -0,0 +1,75 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class CheckcommandArgument extends Model +{ + public function getTableName() + { + return 'checkcommand_argument'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'checkcommand_id', + 'argument_key', + 'environment_id', + 'properties_checksum', + 'argument_value', + 'argument_order', + 'description', + 'argument_key_override', + 'repeat_key', + 'required', + 'set_if', + 'skip_key' + ]; + } + + public function getColumnDefinitions() + { + return [ + 'checkcommand_id' => t('Checkcommand Id'), + 'argument_key' => t('Checkcommand Argument Name'), + 'environment_id' => t('Environment Id'), + 'properties_checksum' => t('Checkcommand Argument Properties Checksum'), + 'argument_value' => t('Checkcommand Argument Value'), + 'argument_order' => t('Checkcommand Argument Position'), + 'description' => t('Checkcommand Argument Description'), + 'argument_key_override' => t('Checkcommand Argument Actual Name'), + 'repeat_key' => t('Checkcommand Argument Repeated'), + 'required' => t('Checkcommand Argument Required'), + 'set_if' => t('Checkcommand Argument Condition'), + 'skip_key' => t('Checkcommand Argument Without Name') + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new Binary([ + 'id', + 'checkcommand_id', + 'environment_id', + 'properties_checksum' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('checkcommand', Checkcommand::class); + } +} diff --git a/library/Icingadb/Model/CheckcommandCustomvar.php b/library/Icingadb/Model/CheckcommandCustomvar.php new file mode 100644 index 0000000..0a834b5 --- /dev/null +++ b/library/Icingadb/Model/CheckcommandCustomvar.php @@ -0,0 +1,52 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class CheckcommandCustomvar extends Model +{ + public function getTableName() + { + return 'checkcommand_customvar'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'checkcommand_id', + 'customvar_id', + 'environment_id' + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new Binary([ + 'id', + 'checkcommand_id', + 'customvar_id', + 'environment_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('checkcommand', Checkcommand::class); + $relations->belongsTo('customvar', Customvar::class); + $relations->belongsTo('customvar_flat', CustomvarFlat::class) + ->setCandidateKey('customvar_id') + ->setForeignKey('customvar_id'); + } +} diff --git a/library/Icingadb/Model/CheckcommandEnvvar.php b/library/Icingadb/Model/CheckcommandEnvvar.php new file mode 100644 index 0000000..517a45f --- /dev/null +++ b/library/Icingadb/Model/CheckcommandEnvvar.php @@ -0,0 +1,61 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class CheckcommandEnvvar extends Model +{ + public function getTableName() + { + return 'checkcommand_envvar'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'checkcommand_id', + 'envvar_key', + 'environment_id', + 'properties_checksum', + 'envvar_value' + ]; + } + + public function getColumnDefinitions() + { + return [ + 'checkcommand_id' => t('Checkcommand Id'), + 'envvar_key' => t('Checkcommand Envvar Name'), + 'environment_id' => t('Environment Id'), + 'properties_checksum' => t('Checkcommand Properties Checksum'), + 'envvar_value' => t('Checkcommand Envvar Value') + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new Binary([ + 'id', + 'checkcommand_id', + 'environment_id', + 'properties_checksum' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('checkcommand', Checkcommand::class); + } +} diff --git a/library/Icingadb/Model/Comment.php b/library/Icingadb/Model/Comment.php new file mode 100644 index 0000000..bcdd5e0 --- /dev/null +++ b/library/Icingadb/Model/Comment.php @@ -0,0 +1,114 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use Icinga\Module\Icingadb\Model\Behavior\BoolCast; +use Icinga\Module\Icingadb\Model\Behavior\ReRoute; +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behavior\MillisecondTimestamp; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class Comment extends Model +{ + public function getTableName() + { + return 'comment'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'environment_id', + 'object_type', + 'host_id', + 'service_id', + 'name_checksum', + 'properties_checksum', + 'name', + 'author', + 'text', + 'entry_type', + 'entry_time', + 'is_persistent', + 'is_sticky', + 'expire_time', + 'zone_id' + ]; + } + + public function getColumnDefinitions() + { + return [ + 'environment_id' => t('Environment Id'), + 'object_type' => t('Object Type'), + 'host_id' => t('Host Id'), + 'service_id' => t('Service Id'), + 'name_checksum' => t('Comment Name Checksum'), + 'properties_checksum' => t('Comment Properties Checksum'), + 'name' => t('Comment Name'), + 'author' => t('Comment Author'), + 'text' => t('Comment Text'), + 'entry_type' => t('Comment Type'), + 'entry_time' => t('Comment Entry Time'), + 'is_persistent' => t('Comment Is Persistent'), + 'is_sticky' => t('Comment Is Sticky'), + 'expire_time' => t('Comment Expire Time'), + 'zone_id' => t('Zone Id') + ]; + } + + public function getSearchColumns() + { + return ['text']; + } + + public function getDefaultSort() + { + return 'comment.entry_time desc'; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new BoolCast([ + 'is_persistent', + 'is_sticky' + ])); + + $behaviors->add(new MillisecondTimestamp([ + 'entry_time', + 'expire_time' + ])); + + $behaviors->add(new Binary([ + 'id', + 'environment_id', + 'host_id', + 'service_id', + 'name_checksum', + 'properties_checksum', + 'zone_id' + ])); + + $behaviors->add(new ReRoute([ + 'hostgroup' => 'host.hostgroup', + 'servicegroup' => 'service.servicegroup' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('host', Host::class)->setJoinType('LEFT'); + $relations->belongsTo('service', Service::class)->setJoinType('LEFT'); + $relations->belongsTo('zone', Zone::class); + } +} diff --git a/library/Icingadb/Model/CommentHistory.php b/library/Icingadb/Model/CommentHistory.php new file mode 100644 index 0000000..5f03e68 --- /dev/null +++ b/library/Icingadb/Model/CommentHistory.php @@ -0,0 +1,107 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use Icinga\Module\Icingadb\Model\Behavior\BoolCast; +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behavior\MillisecondTimestamp; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +/** + * Model for table `comment_history` + * + * Please note that using this model will fetch history entries for decommissioned services. To avoid this, + * the query needs a `comment_history.service_id IS NULL OR comment_history_service.id IS NOT NULL` where. + */ +class CommentHistory extends Model +{ + public function getTableName() + { + return 'comment_history'; + } + + public function getKeyName() + { + return 'comment_id'; + } + + public function getColumns() + { + return [ + 'environment_id', + 'endpoint_id', + 'object_type', + 'host_id', + 'service_id', + 'entry_time', + 'author', + 'removed_by', + 'comment', + 'entry_type', + 'is_persistent', + 'is_sticky', + 'expire_time', + 'remove_time', + 'has_been_removed' + ]; + } + + public function getColumnDefinitions() + { + return [ + 'environment_id' => t('Environment Id'), + 'endpoint_id' => t('Endpoint Id'), + 'object_type' => t('Object Type'), + 'host_id' => t('Host Id'), + 'service_id' => t('Service Id'), + 'entry_time' => t('Comment Entry Time'), + 'author' => t('Comment Author'), + 'removed_by' => t('Comment Removed By'), + 'comment' => t('Comment Text'), + 'entry_type' => t('Comment Entry Type'), + 'is_persistent' => t('Comment Is Persistent'), + 'is_sticky' => t('Comment Is Sticky'), + 'expire_time' => t('Comment Expire Time'), + 'remove_time' => t('Comment Remove Time'), + 'has_been_removed' => t('Comment Has Been Removed') + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new BoolCast([ + 'is_persistent', + 'is_sticky', + 'has_been_removed' + ])); + + $behaviors->add(new MillisecondTimestamp([ + 'entry_time', + 'expire_time', + 'remove_time' + ])); + + $behaviors->add(new Binary([ + 'comment_id', + 'environment_id', + 'endpoint_id', + 'host_id', + 'service_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('endpoint', Endpoint::class); + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('history', History::class) + ->setCandidateKey('comment_id') + ->setForeignKey('comment_history_id'); + $relations->belongsTo('host', Host::class); + $relations->belongsTo('service', Service::class)->setJoinType('LEFT'); + } +} diff --git a/library/Icingadb/Model/Customvar.php b/library/Icingadb/Model/Customvar.php new file mode 100644 index 0000000..e043229 --- /dev/null +++ b/library/Icingadb/Model/Customvar.php @@ -0,0 +1,72 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class Customvar extends Model +{ + public function getTableName() + { + return 'customvar'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'environment_id', + 'name_checksum', + 'name', + 'value' + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new Binary([ + 'id', + 'environment_id', + 'name_checksum' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + + $relations->belongsToMany('checkcommand', Checkcommand::class) + ->through(CheckcommandCustomvar::class); + $relations->belongsToMany('eventcommand', Eventcommand::class) + ->through(EventcommandCustomvar::class); + $relations->belongsToMany('host', Host::class) + ->through(HostCustomvar::class); + $relations->belongsToMany('hostgroup', Hostgroup::class) + ->through(HostgroupCustomvar::class); + $relations->belongsToMany('notification', Notification::class) + ->through(NotificationCustomvar::class); + $relations->belongsToMany('notificationcommand', Notificationcommand::class) + ->through(NotificationcommandCustomvar::class); + $relations->belongsToMany('service', Service::class) + ->through(ServiceCustomvar::class); + $relations->belongsToMany('servicegroup', Servicegroup::class) + ->through(ServicegroupCustomvar::class); + $relations->belongsToMany('timeperiod', Timeperiod::class) + ->through(TimeperiodCustomvar::class); + $relations->belongsToMany('user', User::class) + ->through(UserCustomvar::class); + $relations->belongsToMany('usergroup', Usergroup::class) + ->through(UsergroupCustomvar::class); + + $relations->hasMany('customvar_flat', CustomvarFlat::class); + } +} diff --git a/library/Icingadb/Model/CustomvarFlat.php b/library/Icingadb/Model/CustomvarFlat.php new file mode 100644 index 0000000..99d8aca --- /dev/null +++ b/library/Icingadb/Model/CustomvarFlat.php @@ -0,0 +1,167 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Query; +use ipl\Orm\Relations; +use Traversable; + +class CustomvarFlat extends Model +{ + public function getTableName() + { + return 'customvar_flat'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'environment_id', + 'customvar_id', + 'flatname_checksum', + 'flatname', + 'flatvalue' + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new Binary([ + 'id', + 'environment_id', + 'customvar_id', + 'flatname_checksum' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('customvar', Customvar::class); + + $relations->belongsToMany('checkcommand', Checkcommand::class) + ->through(CheckcommandCustomvar::class) + ->setCandidateKey('customvar_id'); + $relations->belongsToMany('eventcommand', Eventcommand::class) + ->through(EventcommandCustomvar::class) + ->setCandidateKey('customvar_id'); + $relations->belongsToMany('host', Host::class) + ->through(HostCustomvar::class) + ->setCandidateKey('customvar_id'); + $relations->belongsToMany('hostgroup', Hostgroup::class) + ->through(HostgroupCustomvar::class) + ->setCandidateKey('customvar_id'); + $relations->belongsToMany('notification', Notification::class) + ->through(NotificationCustomvar::class) + ->setCandidateKey('customvar_id'); + $relations->belongsToMany('notificationcommand', Notificationcommand::class) + ->through(NotificationcommandCustomvar::class) + ->setCandidateKey('customvar_id'); + $relations->belongsToMany('service', Service::class) + ->through(ServiceCustomvar::class) + ->setCandidateKey('customvar_id'); + $relations->belongsToMany('servicegroup', Servicegroup::class) + ->through(ServicegroupCustomvar::class) + ->setCandidateKey('customvar_id'); + $relations->belongsToMany('timeperiod', Timeperiod::class) + ->through(TimeperiodCustomvar::class) + ->setCandidateKey('customvar_id'); + $relations->belongsToMany('user', User::class) + ->through(UserCustomvar::class) + ->setCandidateKey('customvar_id'); + $relations->belongsToMany('usergroup', Usergroup::class) + ->through(UsergroupCustomvar::class) + ->setCandidateKey('customvar_id'); + } + + /** + * Restore flattened custom variables to their previous structure + * + * @param Traversable $flattenedVars + * + * @return array + */ + public function unFlattenVars(Traversable $flattenedVars): array + { + $registerValue = function (&$data, $source, $path, $value) use (&$registerValue) { + $step = array_shift($path); + + $isIndex = (bool) preg_match('/^\[(\d+)]$/', $step, $m); + if ($isIndex) { + $step = $m[1]; + } + + if ($source !== null) { + while (! isset($source[$step])) { + if ($isIndex) { + $step = sprintf('[%d]', $step); + $isIndex = false; + } else { + if (empty($path)) { + break; + } + + $step = implode('.', [$step, array_shift($path)]); + } + } + } + + if (! empty($path)) { + if (! isset($data[$step])) { + $data[$step] = []; + } + + $registerValue($data[$step], $source[$step] ?? null, $path, $value); + } else { + // Since empty custom vars of type dictionaries and arrays have null values in customvar_flat table, + // we won't be able to render them as such. Therefore, we have to use the value of the `customvar` + // table if it's not null, otherwise the current value, which is a "null" string. + $data[$step] = $value === null && ($source[$step] ?? null) === [] ? $source[$step] : $value; + } + }; + + if ($flattenedVars instanceof Query) { + $flattenedVars->withColumns(['customvar.name', 'customvar.value']); + } + + $vars = []; + foreach ($flattenedVars as $var) { + if (isset($var->customvar->name)) { + $var->customvar->value = json_decode($var->customvar->value, true); + + $realName = $var->customvar->name; + $source = [$realName => $var->customvar->value]; + + $sourcePath = ltrim(substr($var->flatname, strlen($realName)), '.'); + $path = array_merge( + [$realName], + $sourcePath + ? preg_split('/(?<=\w|])\.|(?<!^|\.)(?=\[)/', $sourcePath) + : [] + ); + } else { + $path = explode('.', $var->flatname); + $source = null; + } + + $registerValue($vars, $source, $path, $var->flatvalue); + + if (isset($var->customvar->name)) { + $var->customvar->name = null; + $var->customvar->value = null; + } + } + + return $vars; + } +} diff --git a/library/Icingadb/Model/Downtime.php b/library/Icingadb/Model/Downtime.php new file mode 100644 index 0000000..7f600e9 --- /dev/null +++ b/library/Icingadb/Model/Downtime.php @@ -0,0 +1,144 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use Icinga\Module\Icingadb\Model\Behavior\BoolCast; +use Icinga\Module\Icingadb\Model\Behavior\ReRoute; +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behavior\MillisecondTimestamp; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class Downtime extends Model +{ + public function getTableName() + { + return 'downtime'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'environment_id', + 'triggered_by_id', + 'parent_id', + 'object_type', + 'host_id', + 'service_id', + 'name_checksum', + 'properties_checksum', + 'name', + 'author', + 'comment', + 'entry_time', + 'scheduled_start_time', + 'scheduled_end_time', + 'scheduled_duration', + 'is_flexible', + 'flexible_duration', + 'is_in_effect', + 'start_time', + 'end_time', + 'duration', + 'scheduled_by', + 'zone_id' + ]; + } + + public function getColumnDefinitions() + { + return [ + 'environment_id' => t('Environment Id'), + 'triggered_by_id' => t('Triggered By Downtime Id'), + 'parent_id' => t('Parent Downtime Id'), + 'object_type' => t('Object Type'), + 'host_id' => t('Host Id'), + 'service_id' => t('Service Id'), + 'name_checksum' => t('Downtime Name Checksum'), + 'properties_checksum' => t('Downtime Properties Checksum'), + 'name' => t('Downtime Name'), + 'author' => t('Downtime Author'), + 'comment' => t('Downtime Comment'), + 'entry_time' => t('Downtime Entry Time'), + 'scheduled_start_time' => t('Downtime Scheduled Start'), + 'scheduled_end_time' => t('Downtime Scheduled End'), + 'scheduled_duration' => t('Downtime Scheduled Duration'), + 'is_flexible' => t('Downtime Is Flexible'), + 'flexible_duration' => t('Downtime Flexible Duration'), + 'is_in_effect' => t('Downtime Is In Effect'), + 'start_time' => t('Downtime Actual Start'), + 'end_time' => t('Downtime Actual End'), + 'duration' => t('Downtime Duration'), + 'scheduled_by' => t('Scheduled By Downtime'), + 'zone_id' => t('Zone Id') + ]; + } + + public function getSearchColumns() + { + return ['comment']; + } + + public function getDefaultSort() + { + return ['downtime.is_in_effect desc', 'downtime.start_time desc']; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new BoolCast([ + 'is_flexible', + 'is_in_effect' + ])); + + $behaviors->add(new MillisecondTimestamp([ + 'entry_time', + 'scheduled_start_time', + 'scheduled_end_time', + 'start_time', + 'end_time' + ])); + + $behaviors->add(new Binary([ + 'id', + 'environment_id', + 'triggered_by_id', + 'parent_id', + 'host_id', + 'service_id', + 'name_checksum', + 'properties_checksum', + 'zone_id' + ])); + + // As long as the rewriteCondition() expects only Filter\Condition as a first argument + // We have to add this reroute behavior after the binary because the filter condition might + // be transformed into a filter chain! + $behaviors->add(new ReRoute([ + 'hostgroup' => 'host.hostgroup', + 'servicegroup' => 'service.servicegroup' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('triggered_by', self::class) + ->setCandidateKey('triggered_by_id') + ->setJoinType('LEFT'); + $relations->belongsTo('parent', self::class) + ->setCandidateKey('parent_id') + ->setJoinType('LEFT'); + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('host', Host::class)->setJoinType('LEFT'); + $relations->belongsTo('service', Service::class)->setJoinType('LEFT'); + $relations->belongsTo('zone', Zone::class); + } +} diff --git a/library/Icingadb/Model/DowntimeHistory.php b/library/Icingadb/Model/DowntimeHistory.php new file mode 100644 index 0000000..7ba992f --- /dev/null +++ b/library/Icingadb/Model/DowntimeHistory.php @@ -0,0 +1,128 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use Icinga\Module\Icingadb\Model\Behavior\BoolCast; +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behavior\MillisecondTimestamp; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +/** + * Model for table `downtime_history` + * + * Please note that using this model will fetch history entries for decommissioned services. To avoid this, + * the query needs a `downtime_history.service_id IS NULL OR downtime_history_service.id IS NOT NULL` where. + */ +class DowntimeHistory extends Model +{ + public function getTableName() + { + return 'downtime_history'; + } + + public function getKeyName() + { + return 'downtime_id'; + } + + public function getColumns() + { + return [ + 'environment_id', + 'endpoint_id', + 'triggered_by_id', + 'parent_id', + 'object_type', + 'host_id', + 'service_id', + 'entry_time', + 'author', + 'cancelled_by', + 'comment', + 'is_flexible', + 'flexible_duration', + 'scheduled_start_time', + 'scheduled_end_time', + 'start_time', + 'end_time', + 'has_been_cancelled', + 'trigger_time', + 'cancel_time' + ]; + } + + public function getColumnDefinitions() + { + return [ + 'environment_id' => t('Environment Id'), + 'endpoint_id' => t('Endpoint Id'), + 'triggered_by_id' => t('Triggered By Downtime Id'), + 'parent_id' => t('Parent Downtime Id'), + 'object_type' => t('Object Type'), + 'host_id' => t('Host Id'), + 'service_id' => t('Service Id'), + 'entry_time' => t('Downtime Entry Time'), + 'author' => t('Downtime Author'), + 'cancelled_by' => t('Downtime Cancelled By'), + 'comment' => t('Downtime Comment'), + 'is_flexible' => t('Downtime Is Flexible'), + 'flexible_duration' => t('Downtime Flexible Duration'), + 'scheduled_start_time' => t('Downtime Scheduled Start'), + 'scheduled_end_time' => t('Downtime Scheduled End'), + 'start_time' => t('Downtime Actual Start'), + 'end_time' => t('Downtime Actual End'), + 'has_been_cancelled' => t('Downtime Has Been Cancelled'), + 'trigger_time' => t('Downtime Trigger Time'), + 'cancel_time' => t('Downtime Cancel Time') + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new BoolCast([ + 'is_flexible', + 'has_been_cancelled' + ])); + + $behaviors->add(new MillisecondTimestamp([ + 'entry_time', + 'scheduled_start_time', + 'scheduled_end_time', + 'start_time', + 'end_time', + 'trigger_time', + 'cancel_time' + ])); + + $behaviors->add(new Binary([ + 'downtime_id', + 'environment_id', + 'endpoint_id', + 'triggered_by_id', + 'parent_id', + 'host_id', + 'service_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('triggered_by', self::class) + ->setCandidateKey('triggered_by_id') + ->setJoinType('LEFT'); + $relations->belongsTo('parent', self::class) + ->setCandidateKey('parent_id') + ->setJoinType('LEFT'); + $relations->belongsTo('endpoint', Endpoint::class); + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('history', History::class) + ->setCandidateKey('downtime_id') + ->setForeignKey('downtime_history_id'); + $relations->belongsTo('host', Host::class)->setJoinType('LEFT'); + $relations->belongsTo('service', Service::class)->setJoinType('LEFT'); + } +} diff --git a/library/Icingadb/Model/Endpoint.php b/library/Icingadb/Model/Endpoint.php new file mode 100644 index 0000000..257001b --- /dev/null +++ b/library/Icingadb/Model/Endpoint.php @@ -0,0 +1,69 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class Endpoint extends Model +{ + public function getTableName() + { + return 'endpoint'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'environment_id', + 'name_checksum', + 'properties_checksum', + 'name', + 'name_ci', + 'zone_id' + ]; + } + + public function getColumnDefinitions() + { + return [ + 'environment_id' => t('Environment Id'), + 'name_checksum' => t('Endpoint Name Checksum'), + 'properties_checksum' => t('Endpoint Properties Checksum'), + 'name' => t('Endpoint Name'), + 'name_ci' => t('Endpoint Name (CI)'), + 'zone_id' => t('Zone Id') + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new Binary([ + 'id', + 'environment_id', + 'name_checksum', + 'properties_checksum', + 'zone_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('zone', Zone::class); + + $relations->hasMany('host', Host::class) + ->setForeignKey('command_endpoint_id'); + $relations->hasMany('service', Service::class) + ->setForeignKey('command_endpoint_id'); + } +} diff --git a/library/Icingadb/Model/Environment.php b/library/Icingadb/Model/Environment.php new file mode 100644 index 0000000..919ca1c --- /dev/null +++ b/library/Icingadb/Model/Environment.php @@ -0,0 +1,105 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class Environment extends Model +{ + public function getTableName() + { + return 'environment'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'name' + ]; + } + + public function getColumnDefinitions() + { + return [ + 'name' => t('Environment Name') + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new Binary([ + 'id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->hasMany('acknowledgement_history', AcknowledgementHistory::class); + $relations->hasMany('action_url', ActionUrl::class); + $relations->hasMany('checkcommand', Checkcommand::class); + $relations->hasMany('checkcommand_argument', CheckcommandArgument::class); + $relations->hasMany('checkcommand_customvar', CheckcommandCustomvar::class); + $relations->hasMany('checkcommand_envvar', CheckcommandEnvvar::class); + $relations->hasMany('comment', Comment::class); + $relations->hasMany('comment_history', CommentHistory::class); + $relations->hasMany('customvar', Customvar::class); + $relations->hasMany('customvar_flat', CustomvarFlat::class); + $relations->hasMany('downtime', Downtime::class); + $relations->hasMany('downtime_history', DowntimeHistory::class); + $relations->hasMany('endpoint', Endpoint::class); + $relations->hasMany('eventcommand', Eventcommand::class); + $relations->hasMany('eventcommand_argument', EventcommandArgument::class); + $relations->hasMany('eventcommand_customvar', EventcommandCustomvar::class); + $relations->hasMany('eventcommand_envvar', EventcommandEnvvar::class); + $relations->hasMany('flapping_history', FlappingHistory::class); + $relations->hasMany('history', History::class); + $relations->hasMany('host', Host::class); + $relations->hasMany('host_customvar', HostCustomvar::class); + $relations->hasMany('host_state', HostState::class); + $relations->hasMany('hostgroup', Hostgroup::class); + $relations->hasMany('hostgroup_customvar', HostgroupCustomvar::class); + $relations->hasMany('hostgroup_member', HostgroupMember::class); + $relations->hasMany('instance', Instance::class); + $relations->hasMany('icon_image', IconImage::class); + $relations->hasMany('notes_url', NotesUrl::class); + $relations->hasMany('notification', Notification::class); + $relations->hasMany('notification_customvar', NotificationCustomvar::class); + $relations->hasMany('notification_history', NotificationHistory::class); + //$relations->hasMany('notification_recipient', NotificationRecipient::class); + $relations->hasMany('notification_user', NotificationUser::class); + $relations->hasMany('notification_usergroup', NotificationUsergroup::class); + $relations->hasMany('notificationcommand', Notificationcommand::class); + $relations->hasMany('notificationcommand_argument', NotificationcommandArgument::class); + $relations->hasMany('notificationcommand_customvar', NotificationcommandCustomvar::class); + $relations->hasMany('notificationcommand_envvar', NotificationcommandEnvvar::class); + $relations->hasMany('service', Service::class); + $relations->hasMany('service_customvar', ServiceCustomvar::class); + $relations->hasMany('service_state', ServiceState::class); + $relations->hasMany('servicegroup', Servicegroup::class); + $relations->hasMany('servicegroup_customvar', ServicegroupCustomvar::class); + $relations->hasMany('servicegroup_member', ServicegroupMember::class); + $relations->hasMany('state_history', StateHistory::class); + $relations->hasMany('timeperiod', Timeperiod::class); + $relations->hasMany('timeperiod_customvar', TimeperiodCustomvar::class); + $relations->hasMany('timeperiod_override_exclude', TimeperiodOverrideExclude::class); + $relations->hasMany('timeperiod_override_include', TimeperiodOverrideInclude::class); + $relations->hasMany('timeperiod_range', TimeperiodRange::class); + $relations->hasMany('user', User::class); + $relations->hasMany('user_customvar', UserCustomvar::class); + //$relations->hasMany('user_notification_history', UserNotificationHistory::class); + $relations->hasMany('usergroup', Usergroup::class); + $relations->hasMany('usergroup_customvar', UsergroupCustomvar::class); + $relations->hasMany('usergroup_member', UsergroupMember::class); + $relations->hasMany('zone', Zone::class); + } +} diff --git a/library/Icingadb/Model/Eventcommand.php b/library/Icingadb/Model/Eventcommand.php new file mode 100644 index 0000000..ad18e22 --- /dev/null +++ b/library/Icingadb/Model/Eventcommand.php @@ -0,0 +1,86 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use Icinga\Module\Icingadb\Model\Behavior\ReRoute; +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class Eventcommand extends Model +{ + public function getTableName() + { + return 'eventcommand'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'zone_id', + 'environment_id', + 'name_checksum', + 'properties_checksum', + 'name', + 'name_ci', + 'command', + 'timeout' + ]; + } + + public function getColumnDefinitions() + { + return [ + 'zone_id' => t('Zone Id'), + 'environment_id' => t('Environment Id'), + 'name_checksum' => t('Eventcommand Name Checksum'), + 'properties_checksum' => t('Eventcommand Properties Checksum'), + 'name' => t('Eventcommand Name'), + 'name_ci' => t('Eventcommand Name (CI)'), + 'command' => t('Eventcommand'), + 'timeout' => t('Eventcommand Timeout') + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new ReRoute([ + 'hostgroup' => 'host.hostgroup', + 'servicegroup' => 'service.servicegroup' + ])); + + $behaviors->add(new Binary([ + 'id', + 'zone_id', + 'environment_id', + 'name_checksum', + 'properties_checksum' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('zone', Zone::class); + + $relations->belongsToMany('customvar', Customvar::class) + ->through(EventcommandCustomvar::class); + $relations->belongsToMany('customvar_flat', CustomvarFlat::class) + ->through(EventcommandCustomvar::class); + $relations->belongsToMany('vars', Vars::class) + ->through(EventcommandCustomvar::class); + + $relations->hasMany('argument', EventcommandArgument::class); + $relations->hasMany('envvar', EventcommandEnvvar::class); + $relations->hasMany('host', Host::class); + $relations->hasMany('service', Service::class); + } +} diff --git a/library/Icingadb/Model/EventcommandArgument.php b/library/Icingadb/Model/EventcommandArgument.php new file mode 100644 index 0000000..485e5d3 --- /dev/null +++ b/library/Icingadb/Model/EventcommandArgument.php @@ -0,0 +1,75 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class EventcommandArgument extends Model +{ + public function getTableName() + { + return 'eventcommand_argument'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'eventcommand_id', + 'argument_key', + 'environment_id', + 'properties_checksum', + 'argument_value', + 'argument_order', + 'description', + 'argument_key_override', + 'repeat_key', + 'required', + 'set_if', + 'skip_key' + ]; + } + + public function getColumnDefinitions() + { + return [ + 'eventcommand_id' => t('Eventcommand Id'), + 'argument_key' => t('Eventcommand Argument Name'), + 'environment_id' => t('Environment Id'), + 'properties_checksum' => t('Eventcommand Argument Properties Checksum'), + 'argument_value' => t('Eventcommand Argument Value'), + 'argument_order' => t('Eventcommand Argument Position'), + 'description' => t('Eventcommand Argument Description'), + 'argument_key_override' => t('Eventcommand Argument Actual Name'), + 'repeat_key' => t('Eventcommand Argument Repeated'), + 'required' => t('Eventcommand Argument Required'), + 'set_if' => t('Eventcommand Argument Condition'), + 'skip_key' => t('Eventcommand Argument Without Name') + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new Binary([ + 'id', + 'eventcommand_id', + 'environment_id', + 'properties_checksum' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('eventcommand', Eventcommand::class); + } +} diff --git a/library/Icingadb/Model/EventcommandCustomvar.php b/library/Icingadb/Model/EventcommandCustomvar.php new file mode 100644 index 0000000..3d1fa48 --- /dev/null +++ b/library/Icingadb/Model/EventcommandCustomvar.php @@ -0,0 +1,52 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class EventcommandCustomvar extends Model +{ + public function getTableName() + { + return 'eventcommand_customvar'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'eventcommand_id', + 'customvar_id', + 'environment_id' + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new Binary([ + 'id', + 'eventcommand_id', + 'customvar_id', + 'environment_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('eventcommand', Eventcommand::class); + $relations->belongsTo('customvar', Customvar::class); + $relations->belongsTo('customvar_flat', CustomvarFlat::class) + ->setCandidateKey('customvar_id') + ->setForeignKey('customvar_id'); + } +} diff --git a/library/Icingadb/Model/EventcommandEnvvar.php b/library/Icingadb/Model/EventcommandEnvvar.php new file mode 100644 index 0000000..3883bef --- /dev/null +++ b/library/Icingadb/Model/EventcommandEnvvar.php @@ -0,0 +1,61 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class EventcommandEnvvar extends Model +{ + public function getTableName() + { + return 'eventcommand_envvar'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'eventcommand_id', + 'envvar_key', + 'environment_id', + 'properties_checksum', + 'envvar_value' + ]; + } + + public function getColumnDefinitions() + { + return [ + 'eventcommand_id' => t('Eventcommand Id'), + 'envvar_key' => t('Eventcommand Envvar Name'), + 'environment_id' => t('Environment Id'), + 'properties_checksum' => t('Eventcommand Envvar Properties Checksum'), + 'envvar_value' => t('Eventcommand Envvar Value') + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new Binary([ + 'id', + 'eventcommand_id', + 'environment_id', + 'properties_checksum' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('eventcommand', Eventcommand::class); + } +} diff --git a/library/Icingadb/Model/FlappingHistory.php b/library/Icingadb/Model/FlappingHistory.php new file mode 100644 index 0000000..69711eb --- /dev/null +++ b/library/Icingadb/Model/FlappingHistory.php @@ -0,0 +1,91 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behavior\MillisecondTimestamp; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +/** + * Model for table `flapping_history` + * + * Please note that using this model will fetch history entries for decommissioned services. To avoid this, + * the query needs a `flapping_history.service_id IS NULL OR flapping_history_service.id IS NOT NULL` where. + */ +class FlappingHistory extends Model +{ + public function getTableName() + { + return 'flapping_history'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'environment_id', + 'endpoint_id', + 'object_type', + 'host_id', + 'service_id', + 'start_time', + 'end_time', + 'percent_state_change_start', + 'percent_state_change_end', + 'flapping_threshold_low', + 'flapping_threshold_high' + ]; + } + + public function getColumnDefinitions() + { + return [ + 'environment_id' => t('Environment Id'), + 'endpoint_id' => t('Endpoint Id'), + 'object_type' => t('Object Type'), + 'host_id' => t('Host Id'), + 'service_id' => t('Service Id'), + 'start_time' => t('Flapping Start Time'), + 'end_time' => t('Flapping End Time'), + 'percent_state_change_start' => t('Flapping Percent State Change Start'), + 'percent_state_change_end' => t('Flapping Percent State Change End'), + 'flapping_threshold_low' => t('Flapping Threshold Low'), + 'flapping_threshold_high' => t('Flapping Threshold High') + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new MillisecondTimestamp([ + 'start_time', + 'end_time' + ])); + + $behaviors->add(new Binary([ + 'id', + 'environment_id', + 'endpoint_id', + 'host_id', + 'service_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('endpoint', Endpoint::class); + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('history', History::class) + ->setCandidateKey('id') + ->setForeignKey('flapping_history_id'); + $relations->belongsTo('host', Host::class); + $relations->belongsTo('service', Service::class)->setJoinType('LEFT'); + } +} diff --git a/library/Icingadb/Model/History.php b/library/Icingadb/Model/History.php new file mode 100644 index 0000000..a34b3bd --- /dev/null +++ b/library/Icingadb/Model/History.php @@ -0,0 +1,127 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use Icinga\Module\Icingadb\Model\Behavior\ReRoute; +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behavior\MillisecondTimestamp; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +/** + * Model for table `history` + * + * Please note that using this model will fetch history entries for decommissioned services. To avoid + * this, the query needs a `history.service_id IS NULL OR history_service.id IS NOT NULL` where. + */ +class History extends Model +{ + public function getTableName() + { + return 'history'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'environment_id', + 'endpoint_id', + 'object_type', + 'host_id', + 'service_id', + 'comment_history_id', + 'downtime_history_id', + 'flapping_history_id', + 'notification_history_id', + 'acknowledgement_history_id', + 'state_history_id', + 'event_type', + 'event_time' + ]; + } + + public function getColumnDefinitions() + { + return [ + 'environment_id' => t('Environment Id'), + 'endpoint_id' => t('Endpoint Id'), + 'object_type' => t('Object Type'), + 'host_id' => t('Host Id'), + 'service_id' => t('Service Id'), + 'event_type' => t('Event Type'), + 'event_time' => t('Event Time') + ]; + } + + public function getDefaultSort() + { + return 'history.event_time desc, history.event_type desc'; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new MillisecondTimestamp([ + 'event_time' + ])); + + $behaviors->add(new Binary([ + 'id', + 'environment_id', + 'endpoint_id', + 'host_id', + 'service_id', + 'comment_history_id', + 'downtime_history_id', + 'flapping_history_id', + 'notification_history_id', + 'acknowledgement_history_id', + 'state_history_id' + ])); + + $behaviors->add(new ReRoute([ + 'hostgroup' => 'host.hostgroup', + 'servicegroup' => 'service.servicegroup' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('endpoint', Endpoint::class); + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('host', Host::class); + $relations->belongsTo('service', Service::class)->setJoinType('LEFT'); + + $relations->hasOne('comment', CommentHistory::class) + ->setCandidateKey('comment_history_id') + ->setForeignKey('comment_id') + ->setJoinType('LEFT'); + $relations->hasOne('downtime', DowntimeHistory::class) + ->setCandidateKey('downtime_history_id') + ->setForeignKey('downtime_id') + ->setJoinType('LEFT'); + $relations->hasOne('flapping', FlappingHistory::class) + ->setCandidateKey('flapping_history_id') + ->setForeignKey('id') + ->setJoinType('LEFT'); + $relations->hasOne('notification', NotificationHistory::class) + ->setCandidateKey('notification_history_id') + ->setForeignKey('id') + ->setJoinType('LEFT'); + $relations->hasOne('acknowledgement', AcknowledgementHistory::class) + ->setCandidateKey('acknowledgement_history_id') + ->setForeignKey('id') + ->setJoinType('LEFT'); + $relations->hasOne('state', StateHistory::class) + ->setCandidateKey('state_history_id') + ->setForeignKey('id') + ->setJoinType('LEFT'); + } +} diff --git a/library/Icingadb/Model/Host.php b/library/Icingadb/Model/Host.php new file mode 100644 index 0000000..e1296c8 --- /dev/null +++ b/library/Icingadb/Model/Host.php @@ -0,0 +1,234 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use Icinga\Module\Icingadb\Common\Auth; +use Icinga\Module\Icingadb\Model\Behavior\BoolCast; +use Icinga\Module\Icingadb\Model\Behavior\ReRoute; +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Defaults; +use ipl\Orm\Model; +use ipl\Orm\Relations; +use ipl\Orm\ResultSet; + +/** + * Host model. + */ +class Host extends Model +{ + use Auth; + + public function getTableName() + { + return 'host'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'environment_id', + 'name_checksum', + 'properties_checksum', + 'name', + 'name_ci', + 'display_name', + 'address', + 'address6', + 'address_bin', + 'address6_bin', + 'checkcommand_name', + 'checkcommand_id', + 'max_check_attempts', + 'check_timeperiod_name', + 'check_timeperiod_id', + 'check_timeout', + 'check_interval', + 'check_retry_interval', + 'active_checks_enabled', + 'passive_checks_enabled', + 'event_handler_enabled', + 'notifications_enabled', + 'flapping_enabled', + 'flapping_threshold_low', + 'flapping_threshold_high', + 'perfdata_enabled', + 'eventcommand_name', + 'eventcommand_id', + 'is_volatile', + 'action_url_id', + 'notes_url_id', + 'notes', + 'icon_image_id', + 'icon_image_alt', + 'zone_name', + 'zone_id', + 'command_endpoint_name', + 'command_endpoint_id' + ]; + } + + public function getColumnDefinitions() + { + return [ + 'environment_id' => t('Environment Id'), + 'name_checksum' => t('Host Name Checksum'), + 'properties_checksum' => t('Host Properties Checksum'), + 'name' => t('Host Name'), + 'name_ci' => t('Host Name (CI)'), + 'display_name' => t('Host Display Name'), + 'address' => t('Host Address (IPv4)'), + 'address6' => t('Host Address (IPv6)'), + 'address_bin' => t('Host Address (IPv4, Binary)'), + 'address6_bin' => t('Host Address (IPv6, Binary)'), + 'checkcommand_name' => t('Checkcommand Name'), + 'checkcommand_id' => t('Checkcommand Id'), + 'max_check_attempts' => t('Host Max Check Attempts'), + 'check_timeperiod_name' => t('Check Timeperiod Name'), + 'check_timeperiod_id' => t('Check Timeperiod Id'), + 'check_timeout' => t('Host Check Timeout'), + 'check_interval' => t('Host Check Interval'), + 'check_retry_interval' => t('Host Check Retry Inverval'), + 'active_checks_enabled' => t('Host Active Checks Enabled'), + 'passive_checks_enabled' => t('Host Passive Checks Enabled'), + 'event_handler_enabled' => t('Host Event Handler Enabled'), + 'notifications_enabled' => t('Host Notifications Enabled'), + 'flapping_enabled' => t('Host Flapping Enabled'), + 'flapping_threshold_low' => t('Host Flapping Threshold Low'), + 'flapping_threshold_high' => t('Host Flapping Threshold High'), + 'perfdata_enabled' => t('Host Performance Data Enabled'), + 'eventcommand_name' => t('Eventcommand Name'), + 'eventcommand_id' => t('Eventcommand Id'), + 'is_volatile' => t('Host Is Volatile'), + 'action_url_id' => t('Action Url Id'), + 'notes_url_id' => t('Notes Url Id'), + 'notes' => t('Host Notes'), + 'icon_image_id' => t('Icon Image Id'), + 'icon_image_alt' => t('Icon Image Alt'), + 'zone_name' => t('Zone Name'), + 'zone_id' => t('Zone Id'), + 'command_endpoint_name' => t('Endpoint Name'), + 'command_endpoint_id' => t('Endpoint Id') + ]; + } + + public function getSearchColumns() + { + return ['name_ci', 'display_name']; + } + + public function getDefaultSort() + { + return 'host.display_name'; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new BoolCast([ + 'active_checks_enabled', + 'passive_checks_enabled', + 'event_handler_enabled', + 'notifications_enabled', + 'flapping_enabled', + 'is_volatile' + ])); + + $behaviors->add(new ReRoute([ + 'servicegroup' => 'service.servicegroup', + 'user' => 'notification.user', + 'usergroup' => 'notification.usergroup' + ])); + + $behaviors->add(new Binary([ + 'id', + 'environment_id', + 'name_checksum', + 'properties_checksum', + 'address_bin', + 'address6_bin', + 'checkcommand_id', + 'check_timeperiod_id', + 'eventcommand_id', + 'action_url_id', + 'notes_url_id', + 'icon_image_id', + 'zone_id', + 'command_endpoint_id' + ])); + } + + public function createDefaults(Defaults $defaults) + { + $defaults->add('vars', function (self $subject) { + if (! $subject->customvar_flat instanceof ResultSet) { + $this->applyRestrictions($subject->customvar_flat); + } + + $vars = []; + foreach ($subject->customvar_flat as $customVar) { + $vars[$customVar->flatname] = $customVar->flatvalue; + } + + return $vars; + }); + + $defaults->add('customvars', function (self $subject) { + if (! $subject->customvar instanceof ResultSet) { + $this->applyRestrictions($subject->customvar); + } + + $vars = []; + foreach ($subject->customvar as $customVar) { + $vars[$customVar->name] = json_decode($customVar->value, true); + } + + return $vars; + }); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('eventcommand', Eventcommand::class); + $relations->belongsTo('checkcommand', Checkcommand::class); + $relations->belongsTo('timeperiod', Timeperiod::class) + ->setCandidateKey('check_timeperiod_id') + ->setJoinType('LEFT'); + $relations->belongsTo('action_url', ActionUrl::class) + ->setCandidateKey('action_url_id') + ->setForeignKey('id'); + $relations->belongsTo('notes_url', NotesUrl::class) + ->setCandidateKey('notes_url_id') + ->setForeignKey('id'); + $relations->belongsTo('icon_image', IconImage::class) + ->setCandidateKey('icon_image_id') + ->setJoinType('LEFT'); + $relations->belongsTo('zone', Zone::class); + $relations->belongsTo('endpoint', Endpoint::class) + ->setCandidateKey('command_endpoint_id'); + + $relations->belongsToMany('customvar', Customvar::class) + ->through(HostCustomvar::class); + $relations->belongsToMany('customvar_flat', CustomvarFlat::class) + ->through(HostCustomvar::class); + $relations->belongsToMany('vars', Vars::class) + ->through(HostCustomvar::class); + $relations->belongsToMany('hostgroup', Hostgroup::class) + ->through(HostgroupMember::class); + + $relations->hasOne('state', HostState::class)->setJoinType('LEFT'); + $relations->hasMany('comment', Comment::class)->setJoinType('LEFT'); + $relations->hasMany('downtime', Downtime::class)->setJoinType('LEFT'); + $relations->hasMany('history', History::class); + $relations->hasMany('notification', Notification::class)->setJoinType('LEFT'); + $relations->hasMany('notification_history', NotificationHistory::class); + $relations->hasMany('service', Service::class)->setJoinType('LEFT'); + } +} diff --git a/library/Icingadb/Model/HostCustomvar.php b/library/Icingadb/Model/HostCustomvar.php new file mode 100644 index 0000000..9f7df26 --- /dev/null +++ b/library/Icingadb/Model/HostCustomvar.php @@ -0,0 +1,52 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class HostCustomvar extends Model +{ + public function getTableName() + { + return 'host_customvar'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'host_id', + 'customvar_id', + 'environment_id' + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new Binary([ + 'id', + 'host_id', + 'customvar_id', + 'environment_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('host', Host::class); + $relations->belongsTo('customvar', Customvar::class); + $relations->belongsTo('customvar_flat', CustomvarFlat::class) + ->setForeignKey('customvar_id') + ->setCandidateKey('customvar_id'); + } +} diff --git a/library/Icingadb/Model/HostState.php b/library/Icingadb/Model/HostState.php new file mode 100644 index 0000000..efa2752 --- /dev/null +++ b/library/Icingadb/Model/HostState.php @@ -0,0 +1,81 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use Icinga\Module\Icingadb\Common\HostStates; +use ipl\Orm\Relations; + +/** + * Host state model. + */ +class HostState extends State +{ + public function getTableName() + { + return 'host_state'; + } + + public function getKeyName() + { + return 'host_id'; + } + + public function getColumnDefinitions() + { + return [ + 'environment_id' => t('Environment Id'), + 'state_type' => t('Host State Type'), + 'soft_state' => t('Host Soft State'), + 'hard_state' => t('Host Hard State'), + 'previous_soft_state' => t('Host Previous Soft State'), + 'previous_hard_state' => t('Host Previous Hard State'), + 'check_attempt' => t('Host Check Attempt No.'), + 'severity' => t('Host State Severity'), + 'output' => t('Host Output'), + 'long_output' => t('Host Long Output'), + 'performance_data' => t('Host Performance Data'), + 'normalized_performance_data' => t('Host Normalized Performance Data'), + 'check_commandline' => t('Host Check Commandline'), + 'is_problem' => t('Host Has Problem'), + 'is_handled' => t('Host Is Handled'), + 'is_reachable' => t('Host Is Reachable'), + 'is_flapping' => t('Host Is Flapping'), + 'is_overdue' => t('Host Check Is Overdue'), + 'is_acknowledged' => t('Host Is Acknowledged'), + 'acknowledgement_comment_id' => t('Acknowledgement Comment Id'), + 'in_downtime' => t('Host In Downtime'), + 'execution_time' => t('Host Check Execution Time'), + 'latency' => t('Host Check Latency'), + 'check_timeout' => t('Host Check Timeout'), + 'check_source' => t('Host Check Source'), + 'last_update' => t('Host Last Update'), + 'last_state_change' => t('Host Last State Change'), + 'next_check' => t('Host Next Check'), + 'next_update' => t('Host Next Update') + ]; + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('host', Host::class); + $relations->hasOne('last_comment', LastHostComment::class) + ->setCandidateKey('last_comment_id') + ->setForeignKey('id') + ->setJoinType('LEFT'); + } + + + public function getStateText(): string + { + return HostStates::text($this->soft_state); + } + + + public function getStateTextTranslated(): string + { + return HostStates::text($this->soft_state); + } +} diff --git a/library/Icingadb/Model/Hostgroup.php b/library/Icingadb/Model/Hostgroup.php new file mode 100644 index 0000000..97930fa --- /dev/null +++ b/library/Icingadb/Model/Hostgroup.php @@ -0,0 +1,92 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use Icinga\Module\Icingadb\Model\Behavior\ReRoute; +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class Hostgroup extends Model +{ + public function getTableName() + { + return 'hostgroup'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'environment_id', + 'name_checksum', + 'properties_checksum', + 'name', + 'name_ci', + 'display_name', + 'zone_id' + ]; + } + + public function getColumnDefinitions() + { + return [ + 'environment_id' => t('Environment Id'), + 'name_checksum' => t('Hostgroup Name Checksum'), + 'properties_checksum' => t('Hostgroup Properties Checksum'), + 'name' => t('Hostgroup Name'), + 'name_ci' => t('Hostgroup Name (CI)'), + 'display_name' => t('Hostgroup Display Name'), + 'zone_id' => t('Zone Id') + ]; + } + + public function getSearchColumns() + { + return ['name_ci', 'display_name']; + } + + public function getDefaultSort() + { + return 'display_name'; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new ReRoute([ + 'servicegroup' => 'service.servicegroup' + ])); + + $behaviors->add(new Binary([ + 'id', + 'environment_id', + 'name_checksum', + 'properties_checksum', + 'zone_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('zone', Zone::class); + + $relations->belongsToMany('customvar', Customvar::class) + ->through(HostgroupCustomvar::class); + $relations->belongsToMany('customvar_flat', CustomvarFlat::class) + ->through(HostgroupCustomvar::class); + $relations->belongsToMany('vars', Vars::class) + ->through(HostgroupCustomvar::class); + $relations->belongsToMany('host', Host::class) + ->through(HostgroupMember::class); + $relations->belongsToMany('service', Service::class) + ->through(HostgroupMember::class); + } +} diff --git a/library/Icingadb/Model/HostgroupCustomvar.php b/library/Icingadb/Model/HostgroupCustomvar.php new file mode 100644 index 0000000..41272d1 --- /dev/null +++ b/library/Icingadb/Model/HostgroupCustomvar.php @@ -0,0 +1,52 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class HostgroupCustomvar extends Model +{ + public function getTableName() + { + return 'hostgroup_customvar'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'hostgroup_id', + 'customvar_id', + 'environment_id' + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new Binary([ + 'id', + 'hostgroup_id', + 'customvar_id', + 'environment_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('hostgroup', Hostgroup::class); + $relations->belongsTo('customvar', Customvar::class); + $relations->belongsTo('customvar_flat', CustomvarFlat::class) + ->setCandidateKey('customvar_id') + ->setForeignKey('customvar_id'); + } +} diff --git a/library/Icingadb/Model/HostgroupMember.php b/library/Icingadb/Model/HostgroupMember.php new file mode 100644 index 0000000..3660e71 --- /dev/null +++ b/library/Icingadb/Model/HostgroupMember.php @@ -0,0 +1,53 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class HostgroupMember extends Model +{ + public function getTableName() + { + return 'hostgroup_member'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'host_id', + 'hostgroup_id', + 'environment_id' + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new Binary([ + 'id', + 'host_id', + 'hostgroup_id', + 'environment_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('hostgroup', Hostgroup::class); + $relations->belongsTo('host', Host::class); + + $relations->hasMany('service', Service::class) + ->setForeignKey('host_id') + ->setCandidateKey('host_id'); + } +} diff --git a/library/Icingadb/Model/Hostgroupsummary.php b/library/Icingadb/Model/Hostgroupsummary.php new file mode 100644 index 0000000..a9295bb --- /dev/null +++ b/library/Icingadb/Model/Hostgroupsummary.php @@ -0,0 +1,213 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Relations; +use ipl\Orm\UnionModel; +use ipl\Sql\Adapter\Pgsql; +use ipl\Sql\Connection; +use ipl\Sql\Expression; +use ipl\Sql\Select; + +class Hostgroupsummary extends UnionModel +{ + public static function on(Connection $db) + { + $q = parent::on($db); + + $q->on($q::ON_SELECT_ASSEMBLED, function (Select $select) use ($q) { + $model = $q->getModel(); + + $groupBy = $q->getResolver()->qualifyColumnsAndAliases((array) $model->getKeyName(), $model, false); + + // For PostgreSQL, ALL non-aggregate SELECT columns must appear in the GROUP BY clause: + if ($q->getDb()->getAdapter() instanceof Pgsql) { + /** + * Ignore Expressions, i.e. aggregate functions {@see getColumns()}, + * which do not need to be added to the GROUP BY. + */ + $candidates = array_filter($select->getColumns(), 'is_string'); + // Remove already considered columns for the GROUP BY, i.e. the primary key. + $candidates = array_diff_assoc($candidates, $groupBy); + $groupBy = array_merge($groupBy, $candidates); + } + + $select->groupBy($groupBy); + }); + + return $q; + } + + public function getTableName() + { + return 'hostgroup'; + } + + public function getKeyName() + { + return ['id' => 'hostgroup_id']; + } + + public function getColumns() + { + return [ + 'display_name' => 'hostgroup_display_name', + 'hosts_down_handled' => new Expression( + 'SUM(CASE WHEN host_state = 1' + . ' AND (host_handled = \'y\' OR host_reachable = \'n\') THEN 1 ELSE 0 END)' + ), + 'hosts_down_unhandled' => new Expression( + 'SUM(CASE WHEN host_state = 1' + . ' AND host_handled = \'n\' AND host_reachable = \'y\' THEN 1 ELSE 0 END)' + ), + 'hosts_pending' => new Expression( + 'SUM(CASE WHEN host_state = 99 THEN 1 ELSE 0 END)' + ), + 'hosts_total' => new Expression( + 'SUM(CASE WHEN host_id IS NOT NULL THEN 1 ELSE 0 END)' + ), + 'hosts_up' => new Expression( + 'SUM(CASE WHEN host_state = 0 THEN 1 ELSE 0 END)' + ), + 'hosts_severity' => new Expression('MAX(host_severity)'), + 'name' => 'hostgroup_name', + 'services_critical_handled' => new Expression( + 'SUM(CASE WHEN service_state = 2' + . ' AND (service_handled = \'y\' OR service_reachable = \'n\') THEN 1 ELSE 0 END)' + ), + 'services_critical_unhandled' => new Expression( + 'SUM(CASE WHEN service_state = 2' + . ' AND service_handled = \'n\' AND service_reachable = \'y\' THEN 1 ELSE 0 END)' + ), + 'services_ok' => new Expression( + 'SUM(CASE WHEN service_state = 0 THEN 1 ELSE 0 END)' + ), + 'services_pending' => new Expression( + 'SUM(CASE WHEN service_state = 99 THEN 1 ELSE 0 END)' + ), + 'services_total' => new Expression( + 'SUM(CASE WHEN service_id IS NOT NULL THEN 1 ELSE 0 END)' + ), + 'services_unknown_handled' => new Expression( + 'SUM(CASE WHEN service_state = 3' + . ' AND (service_handled = \'y\' OR service_reachable = \'n\') THEN 1 ELSE 0 END)' + ), + 'services_unknown_unhandled' => new Expression( + 'SUM(CASE WHEN service_state = 3' + . ' AND service_handled = \'n\' AND service_reachable = \'y\' THEN 1 ELSE 0 END)' + ), + 'services_warning_handled' => new Expression( + 'SUM(CASE WHEN service_state = 1' + . ' AND (service_handled = \'y\' OR service_reachable = \'n\') THEN 1 ELSE 0 END)' + ), + 'services_warning_unhandled' => new Expression( + 'SUM(CASE WHEN service_state = 1' + . ' AND service_handled = \'n\' AND service_reachable = \'y\' THEN 1 ELSE 0 END)' + ) + ]; + } + + public function getSearchColumns() + { + return ['display_name']; + } + + public function getDefaultSort() + { + return 'display_name'; + } + + public function getUnions() + { + $unions = [ + [ + Host::class, + [ + 'hostgroup', + 'state' + ], + [ + 'hostgroup_id' => 'hostgroup.id', + 'hostgroup_name' => 'hostgroup.name', + 'hostgroup_display_name' => 'hostgroup.display_name', + 'host_id' => 'host.id', + 'host_state' => 'state.soft_state', + 'host_handled' => 'state.is_handled', + 'host_reachable' => 'state.is_reachable', + 'host_severity' => 'state.severity', + 'service_id' => new Expression('NULL'), + 'service_state' => new Expression('NULL'), + 'service_handled' => new Expression('NULL'), + 'service_reachable' => new Expression('NULL') + ] + ], + [ + Service::class, + [ + 'hostgroup', + 'state' + ], + [ + 'hostgroup_id' => 'hostgroup.id', + 'hostgroup_name' => 'hostgroup.name', + 'hostgroup_display_name' => 'hostgroup.display_name', + 'host_id' => new Expression('NULL'), + 'host_state' => new Expression('NULL'), + 'host_handled' => new Expression('NULL'), + 'host_reachable' => new Expression('NULL'), + 'host_severity' => new Expression('0'), + 'service_id' => 'service.id', + 'service_state' => 'state.soft_state', + 'service_handled' => 'state.is_handled', + 'service_reachable' => 'state.is_reachable' + ] + ], + [ + Hostgroup::class, + [], + [ + 'hostgroup_id' => 'hostgroup.id', + 'hostgroup_name' => 'hostgroup.name', + 'hostgroup_display_name' => 'hostgroup.display_name', + 'host_id' => new Expression('NULL'), + 'host_state' => new Expression('NULL'), + 'host_handled' => new Expression('NULL'), + 'host_reachable' => new Expression('NULL'), + 'host_severity' => new Expression('0'), + 'service_id' => new Expression('NULL'), + 'service_state' => new Expression('NULL'), + 'service_handled' => new Expression('NULL'), + 'service_reachable' => new Expression('NULL') + ] + ] + ]; + + return $unions; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new Binary([ + 'id' + ])); + + // This is because there is no better way + (new Hostgroup())->createBehaviors($behaviors); + } + + public function createRelations(Relations $relations) + { + // This is because there is no better way + (new Hostgroup())->createRelations($relations); + } + + public function getColumnDefinitions() + { + // This is because there is no better way + return (new Hostgroup())->getColumnDefinitions(); + } +} diff --git a/library/Icingadb/Model/HoststateSummary.php b/library/Icingadb/Model/HoststateSummary.php new file mode 100644 index 0000000..93268f3 --- /dev/null +++ b/library/Icingadb/Model/HoststateSummary.php @@ -0,0 +1,78 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Sql\Connection; +use ipl\Sql\Expression; + +class HoststateSummary extends Host +{ + public function getSummaryColumns() + { + return [ + 'hosts_acknowledged' => new Expression( + 'SUM(CASE WHEN host_state.is_acknowledged = \'y\' THEN 1 ELSE 0 END)' + ), + 'hosts_active_checks_enabled' => new Expression( + 'SUM(CASE WHEN host.active_checks_enabled = \'y\' THEN 1 ELSE 0 END)' + ), + 'hosts_passive_checks_enabled' => new Expression( + 'SUM(CASE WHEN host.passive_checks_enabled = \'y\' THEN 1 ELSE 0 END)' + ), + 'hosts_down_handled' => new Expression( + 'SUM(CASE WHEN host_state.soft_state = 1' + . ' AND (host_state.is_handled = \'y\' OR host_state.is_reachable = \'n\') THEN 1 ELSE 0 END)' + ), + 'hosts_down_unhandled' => new Expression( + 'SUM(CASE WHEN host_state.soft_state = 1' + . ' AND host_state.is_handled = \'n\' AND host_state.is_reachable = \'y\' THEN 1 ELSE 0 END)' + ), + 'hosts_event_handler_enabled' => new Expression( + 'SUM(CASE WHEN host.event_handler_enabled = \'y\' THEN 1 ELSE 0 END)' + ), + 'hosts_flapping_enabled' => new Expression( + 'SUM(CASE WHEN host.flapping_enabled = \'y\' THEN 1 ELSE 0 END)' + ), + 'hosts_notifications_enabled' => new Expression( + 'SUM(CASE WHEN host.notifications_enabled = \'y\' THEN 1 ELSE 0 END)' + ), + 'hosts_pending' => new Expression( + 'SUM(CASE WHEN host_state.soft_state = 99 THEN 1 ELSE 0 END)' + ), + 'hosts_problems_unacknowledged' => new Expression( + 'SUM(CASE WHEN host_state.is_problem = \'y\'' + . ' AND host_state.is_acknowledged = \'n\' THEN 1 ELSE 0 END)' + ), + 'hosts_total' => new Expression( + 'SUM(CASE WHEN host.id IS NOT NULL THEN 1 ELSE 0 END)' + ), + 'hosts_up' => new Expression( + 'SUM(CASE WHEN host_state.soft_state = 0 THEN 1 ELSE 0 END)' + ) + ]; + } + + public static function on(Connection $db) + { + $q = parent::on($db); + $q->utilize('state'); + + /** @var static $m */ + $m = $q->getModel(); + $q->columns($m->getSummaryColumns()); + + return $q; + } + + public function getColumns() + { + return array_merge(parent::getColumns(), $this->getSummaryColumns()); + } + + public function getDefaultSort() + { + return null; + } +} diff --git a/library/Icingadb/Model/IconImage.php b/library/Icingadb/Model/IconImage.php new file mode 100644 index 0000000..212234a --- /dev/null +++ b/library/Icingadb/Model/IconImage.php @@ -0,0 +1,55 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class IconImage extends Model +{ + public function getTableName() + { + return 'icon_image'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'icon_image', + 'environment_id' + ]; + } + + public function getColumnDefinitions() + { + return [ + 'icon_image' => t('Icon Image'), + 'environment_id' => t('Environment Id') + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new Binary([ + 'id', + 'environment_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + + $relations->hasMany('host', Host::class); + $relations->hasMany('service', Service::class); + } +} diff --git a/library/Icingadb/Model/Instance.php b/library/Icingadb/Model/Instance.php new file mode 100644 index 0000000..73db565 --- /dev/null +++ b/library/Icingadb/Model/Instance.php @@ -0,0 +1,78 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use Icinga\Module\Icingadb\Model\Behavior\BoolCast; +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behavior\MillisecondTimestamp; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class Instance extends Model +{ + public function getTableName() + { + return 'icingadb_instance'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'environment_id', + 'endpoint_id', + 'heartbeat', + 'responsible', + 'icinga2_active_host_checks_enabled', + 'icinga2_active_service_checks_enabled', + 'icinga2_event_handlers_enabled', + 'icinga2_flap_detection_enabled', + 'icinga2_notifications_enabled', + 'icinga2_performance_data_enabled', + 'icinga2_start_time', + 'icinga2_version' + ]; + } + + public function getDefaultSort() + { + return ['responsible desc', 'heartbeat desc']; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new MillisecondTimestamp([ + 'heartbeat', + 'icinga2_start_time' + ])); + + $behaviors->add(new BoolCast([ + 'responsible', + 'icinga2_active_host_checks_enabled', + 'icinga2_active_service_checks_enabled', + 'icinga2_event_handlers_enabled', + 'icinga2_flap_detection_enabled', + 'icinga2_notifications_enabled', + 'icinga2_performance_data_enabled' + ])); + + $behaviors->add(new Binary([ + 'id', + 'environment_id', + 'endpoint_id', + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('endpoint', Endpoint::class)->setJoinType('LEFT'); + } +} diff --git a/library/Icingadb/Model/LastHostComment.php b/library/Icingadb/Model/LastHostComment.php new file mode 100644 index 0000000..621b204 --- /dev/null +++ b/library/Icingadb/Model/LastHostComment.php @@ -0,0 +1,19 @@ +<?php + +/* Icinga DB Web | (c) 2023 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Relations; + +class LastHostComment extends Comment +{ + public function createRelations(Relations $relations): void + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('zone', Zone::class); + $relations->belongsTo('state', HostState::class) + ->setForeignKey('last_comment_id') + ->setCandidateKey('id'); + } +} diff --git a/library/Icingadb/Model/LastServiceComment.php b/library/Icingadb/Model/LastServiceComment.php new file mode 100644 index 0000000..4d44f11 --- /dev/null +++ b/library/Icingadb/Model/LastServiceComment.php @@ -0,0 +1,19 @@ +<?php + +/* Icinga DB Web | (c) 2023 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Relations; + +class LastServiceComment extends Comment +{ + public function createRelations(Relations $relations): void + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('zone', Zone::class); + $relations->belongsTo('state', ServiceState::class) + ->setForeignKey('last_comment_id') + ->setCandidateKey('id'); + } +} diff --git a/library/Icingadb/Model/NotesUrl.php b/library/Icingadb/Model/NotesUrl.php new file mode 100644 index 0000000..5865c52 --- /dev/null +++ b/library/Icingadb/Model/NotesUrl.php @@ -0,0 +1,62 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use Icinga\Module\Icingadb\Model\Behavior\ActionAndNoteUrl; +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class NotesUrl extends Model +{ + public function getTableName() + { + return 'notes_url'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'notes_url', + 'environment_id' + ]; + } + + public function getColumnDefinitions() + { + return [ + 'notes_url' => t('Notes Url'), + 'environment_id' => t('Environment Id') + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new ActionAndNoteUrl(['notes_url'])); + + $behaviors->add(new Binary([ + 'id', + 'environment_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + + $relations->hasMany('host', Host::class) + ->setCandidateKey('id') + ->setForeignKey('notes_url_id'); + $relations->hasMany('service', Service::class) + ->setCandidateKey('id') + ->setForeignKey('notes_url_id'); + } +} diff --git a/library/Icingadb/Model/Notification.php b/library/Icingadb/Model/Notification.php new file mode 100644 index 0000000..8d42301 --- /dev/null +++ b/library/Icingadb/Model/Notification.php @@ -0,0 +1,130 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use Icinga\Module\Icingadb\Model\Behavior\Bitmask; +use Icinga\Module\Icingadb\Model\Behavior\ReRoute; +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class Notification extends Model +{ + public function getTableName() + { + return 'notification'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'environment_id', + 'name_checksum', + 'properties_checksum', + 'name', + 'name_ci', + 'host_id', + 'service_id', + 'notificationcommand_id', + 'times_begin', + 'times_end', + 'notification_interval', + 'timeperiod_id', + 'states', + 'types', + 'zone_id' + ]; + } + + public function getColumnDefinitions() + { + return [ + 'environment_id' => t('Environment Id'), + 'name_checksum' => t('Notification Name Checksum'), + 'properties_checksum' => t('Notification Properties Checksum'), + 'name' => t('Notification Name'), + 'name_ci' => t('Notification Name (CI)'), + 'host_id' => t('Host Id'), + 'service_id' => t('Service Id'), + 'notificationcommand_id' => t('Notificationcommand Id'), + 'times_begin' => t('Notification Escalate After'), + 'times_end' => t('Notification Escalate Until'), + 'notification_interval' => t('Notification Interval'), + 'timeperiod_id' => t('Timeperiod Id'), + 'states' => t('Notification State Filter'), + 'types' => t('Notification Type Filter'), + 'zone_id' => t('Zone Id') + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new ReRoute([ + 'hostgroup' => 'host.hostgroup', + 'servicegroup' => 'service.servicegroup' + ])); + + $behaviors->add(new Bitmask([ + 'states' => [ + 'ok' => 1, + 'warning' => 2, + 'critical' => 4, + 'unknown' => 8, + 'up' => 16, + 'down' => 32 + ], + 'types' => [ + 'downtime_start' => 1, + 'downtime_end' => 2, + 'downtime_removed' => 4, + 'custom' => 8, + 'ack' => 16, + 'problem' => 32, + 'recovery' => 64, + 'flapping_start' => 128, + 'flapping_end' => 256 + ] + ])); + + $behaviors->add(new Binary([ + 'id', + 'environment_id', + 'name_checksum', + 'properties_checksum', + 'host_id', + 'service_id', + 'notificationcommand_id', + 'timeperiod_id', + 'zone_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('host', Host::class); + $relations->belongsTo('service', Service::class); + $relations->belongsTo('notificationcommand', Notificationcommand::class); + $relations->belongsTo('timeperiod', Timeperiod::class); + $relations->belongsTo('zone', Zone::class); + + $relations->belongsToMany('customvar', Customvar::class) + ->through(NotificationCustomvar::class); + $relations->belongsToMany('customvar_flat', CustomvarFlat::class) + ->through(NotificationCustomvar::class); + $relations->belongsToMany('vars', Vars::class) + ->through(NotificationCustomvar::class); + $relations->belongsToMany('user', User::class) + ->through('notification_recipient'); + $relations->belongsToMany('usergroup', Usergroup::class) + ->through('notification_recipient'); + } +} diff --git a/library/Icingadb/Model/NotificationCustomvar.php b/library/Icingadb/Model/NotificationCustomvar.php new file mode 100644 index 0000000..620ae5c --- /dev/null +++ b/library/Icingadb/Model/NotificationCustomvar.php @@ -0,0 +1,52 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class NotificationCustomvar extends Model +{ + public function getTableName() + { + return 'notification_customvar'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'notification_id', + 'customvar_id', + 'environment_id' + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new Binary([ + 'id', + 'notification_id', + 'customvar_id', + 'environment_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('notification', Notification::class); + $relations->belongsTo('customvar', Customvar::class); + $relations->belongsTo('customvar_flat', CustomvarFlat::class) + ->setCandidateKey('customvar_id') + ->setForeignKey('customvar_id'); + } +} diff --git a/library/Icingadb/Model/NotificationHistory.php b/library/Icingadb/Model/NotificationHistory.php new file mode 100644 index 0000000..c635dbb --- /dev/null +++ b/library/Icingadb/Model/NotificationHistory.php @@ -0,0 +1,115 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use Icinga\Module\Icingadb\Model\Behavior\ReRoute; +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behavior\MillisecondTimestamp; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +/** + * Model for table `notification_history` + * + * Please note that using this model will fetch history entries for decommissioned services. To avoid this, the + * query needs a `notification_history.service_id IS NULL OR notification_history_service.id IS NOT NULL` where. + */ +class NotificationHistory extends Model +{ + public function getTableName() + { + return 'notification_history'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'environment_id', + 'endpoint_id', + 'object_type', + 'host_id', + 'service_id', + 'notification_id', + 'type', + 'send_time', + 'state', + 'previous_hard_state', + 'author', + 'text', + 'users_notified' + ]; + } + + public function getColumnDefinitions() + { + return [ + 'id' => t('History Id'), + 'environment_id' => t('Environment Id'), + 'endpoint_id' => t('Endpoint Id'), + 'object_type' => t('Object Type'), + 'host_id' => t('Host Id'), + 'service_id' => t('Service Id'), + 'notification_id' => t('Notification Id'), + 'type' => t('Notification Type'), + 'send_time' => t('Notification Sent On'), + 'state' => t('Hard State'), + 'previous_hard_state' => t('Previous Hard State'), + 'author' => t('Notification Author'), + 'text' => t('Notification Text'), + 'users_notified' => t('Users Notified') + ]; + } + + public function getSearchColumns() + { + return ['text']; + } + + public function getDefaultSort() + { + return 'notification_history.send_time desc'; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new MillisecondTimestamp([ + 'send_time' + ])); + + $behaviors->add(new Binary([ + 'id', + 'environment_id', + 'endpoint_id', + 'host_id', + 'service_id', + 'notification_id' + ])); + + $behaviors->add(new ReRoute([ + 'hostgroup' => 'host.hostgroup', + 'servicegroup' => 'service.servicegroup' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('history', History::class) + ->setCandidateKey('id') + ->setForeignKey('notification_history_id'); + $relations->belongsTo('host', Host::class); + $relations->belongsTo('service', Service::class)->setJoinType('LEFT'); + $relations->belongsTo('notification', Notification::class)->setJoinType('LEFT'); + + $relations->belongsToMany('user', User::class) + ->through('user_notification_history'); + } +} diff --git a/library/Icingadb/Model/NotificationUser.php b/library/Icingadb/Model/NotificationUser.php new file mode 100644 index 0000000..ab23ad4 --- /dev/null +++ b/library/Icingadb/Model/NotificationUser.php @@ -0,0 +1,49 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class NotificationUser extends Model +{ + public function getTableName() + { + return 'notification_user'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'notification_id', + 'user_id', + 'environment_id' + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new Binary([ + 'id', + 'notification_id', + 'user_id', + 'environment_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('notification', Notification::class); + $relations->belongsTo('user', User::class); + } +} diff --git a/library/Icingadb/Model/NotificationUsergroup.php b/library/Icingadb/Model/NotificationUsergroup.php new file mode 100644 index 0000000..bd60fae --- /dev/null +++ b/library/Icingadb/Model/NotificationUsergroup.php @@ -0,0 +1,49 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class NotificationUsergroup extends Model +{ + public function getTableName() + { + return 'notification_usergroup'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'notification_id', + 'usergroup_id', + 'environment_id' + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new Binary([ + 'id', + 'notification_id', + 'usergroup_id', + 'environment_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('notification', Notification::class); + $relations->belongsTo('usergroup', Usergroup::class); + } +} diff --git a/library/Icingadb/Model/Notificationcommand.php b/library/Icingadb/Model/Notificationcommand.php new file mode 100644 index 0000000..6ee2a21 --- /dev/null +++ b/library/Icingadb/Model/Notificationcommand.php @@ -0,0 +1,87 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use Icinga\Module\Icingadb\Model\Behavior\ReRoute; +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class Notificationcommand extends Model +{ + public function getTableName() + { + return 'notificationcommand'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'zone_id', + 'environment_id', + 'name_checksum', + 'properties_checksum', + 'name', + 'name_ci', + 'command', + 'timeout' + ]; + } + + public function getColumnDefinitions() + { + return [ + 'zone_id' => t('Zone Id'), + 'environment_id' => t('Environment Id'), + 'name_checksum' => t('Notificationcommand Name Checksum'), + 'properties_checksum' => t('Notificationcommand Properties Checksum'), + 'name' => t('Notificationcommand Name'), + 'name_ci' => t('Notificationcommand Name (CI)'), + 'command' => t('Notificationcommand'), + 'timeout' => t('Notificationcommand Timeout') + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new ReRoute([ + 'host' => 'notification.host', + 'hostgroup' => 'notification.host.hostgroup', + 'service' => 'notification.service', + 'servicegroup' => 'notification.service.servicegroup' + ])); + + $behaviors->add(new Binary([ + 'id', + 'zone_id', + 'environment_id', + 'name_checksum', + 'properties_checksum' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('zone', Zone::class); + + $relations->belongsToMany('customvar', Customvar::class) + ->through(NotificationcommandCustomvar::class); + $relations->belongsToMany('customvar_flat', CustomvarFlat::class) + ->through(NotificationcommandCustomvar::class); + $relations->belongsToMany('vars', Vars::class) + ->through(NotificationcommandCustomvar::class); + + $relations->hasMany('notification', Notification::class); + $relations->hasMany('argument', NotificationcommandArgument::class); + $relations->hasMany('envvar', NotificationcommandEnvvar::class); + } +} diff --git a/library/Icingadb/Model/NotificationcommandArgument.php b/library/Icingadb/Model/NotificationcommandArgument.php new file mode 100644 index 0000000..e855022 --- /dev/null +++ b/library/Icingadb/Model/NotificationcommandArgument.php @@ -0,0 +1,75 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class NotificationcommandArgument extends Model +{ + public function getTableName() + { + return 'notificationcommand_argument'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'notificationcommand_id', + 'argument_key', + 'environment_id', + 'properties_checksum', + 'argument_value', + 'argument_order', + 'description', + 'argument_key_override', + 'repeat_key', + 'required', + 'set_if', + 'skip_key' + ]; + } + + public function getColumnDefinitions() + { + return [ + 'notificationcommand_id' => t('Notificationcommand Id'), + 'argument_key' => t('Notificationcommand Argument Name'), + 'environment_id' => t('Environment Id'), + 'properties_checksum' => t('Notificationcommand Argument Properties Checksum'), + 'argument_value' => t('Notificationcommand Argument Value'), + 'argument_order' => t('Notificationcommand Argument Position'), + 'description' => t('Notificationcommand Argument Description'), + 'argument_key_override' => t('Notificationcommand Argument Actual Name'), + 'repeat_key' => t('Notificationcommand Argument Repeated'), + 'required' => t('Notificationcommand Argument Required'), + 'set_if' => t('Notificationcommand Argument Condition'), + 'skip_key' => t('Notificationcommand Argument Without Name') + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new Binary([ + 'id', + 'notificationcommand_id', + 'environment_id', + 'properties_checksum' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('notificationcommand', Notificationcommand::class); + } +} diff --git a/library/Icingadb/Model/NotificationcommandCustomvar.php b/library/Icingadb/Model/NotificationcommandCustomvar.php new file mode 100644 index 0000000..bd103f7 --- /dev/null +++ b/library/Icingadb/Model/NotificationcommandCustomvar.php @@ -0,0 +1,52 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class NotificationcommandCustomvar extends Model +{ + public function getTableName() + { + return 'notificationcommand_customvar'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'notificationcommand_id', + 'customvar_id', + 'environment_id' + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new Binary([ + 'id', + 'notificationcommand_id', + 'customvar_id', + 'environment_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('notificationcommand', Notificationcommand::class); + $relations->belongsTo('customvar', Customvar::class); + $relations->belongsTo('customvar_flat', CustomvarFlat::class) + ->setCandidateKey('customvar_id') + ->setForeignKey('customvar_id'); + } +} diff --git a/library/Icingadb/Model/NotificationcommandEnvvar.php b/library/Icingadb/Model/NotificationcommandEnvvar.php new file mode 100644 index 0000000..09f77b0 --- /dev/null +++ b/library/Icingadb/Model/NotificationcommandEnvvar.php @@ -0,0 +1,61 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class NotificationcommandEnvvar extends Model +{ + public function getTableName() + { + return 'notificationcommand_envvar'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'notificationcommand_id', + 'envvar_key', + 'environment_id', + 'properties_checksum', + 'envvar_value' + ]; + } + + public function getColumnDefinitions() + { + return [ + 'notificationcommand_id' => t('Notificationcommand Id'), + 'envvar_key' => t('Notificationcommand Envvar Key'), + 'environment_id' => t('Environment Id'), + 'properties_checksum' => t('Notificationcommand Envvar Properties Checksum'), + 'envvar_value' => t('Notificationcommand Envvar Value') + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new Binary([ + 'id', + 'notificationcommand_id', + 'environment_id', + 'properties_checksum', + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('notificationcommand', Notificationcommand::class); + } +} diff --git a/library/Icingadb/Model/Service.php b/library/Icingadb/Model/Service.php new file mode 100644 index 0000000..c57b6ba --- /dev/null +++ b/library/Icingadb/Model/Service.php @@ -0,0 +1,225 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use Icinga\Module\Icingadb\Common\Auth; +use Icinga\Module\Icingadb\Model\Behavior\BoolCast; +use Icinga\Module\Icingadb\Model\Behavior\ReRoute; +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Defaults; +use ipl\Orm\Model; +use ipl\Orm\Relations; +use ipl\Orm\ResultSet; + +class Service extends Model +{ + use Auth; + + public function getTableName() + { + return 'service'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'environment_id', + 'name_checksum', + 'properties_checksum', + 'host_id', + 'name', + 'name_ci', + 'display_name', + 'checkcommand_name', + 'checkcommand_id', + 'max_check_attempts', + 'check_timeperiod_name', + 'check_timeperiod_id', + 'check_timeout', + 'check_interval', + 'check_retry_interval', + 'active_checks_enabled', + 'passive_checks_enabled', + 'event_handler_enabled', + 'notifications_enabled', + 'flapping_enabled', + 'flapping_threshold_low', + 'flapping_threshold_high', + 'perfdata_enabled', + 'eventcommand_name', + 'eventcommand_id', + 'is_volatile', + 'action_url_id', + 'notes_url_id', + 'notes', + 'icon_image_id', + 'icon_image_alt', + 'zone_name', + 'zone_id', + 'command_endpoint_name', + 'command_endpoint_id' + ]; + } + + public function getColumnDefinitions() + { + return [ + 'environment_id' => t('Environment Id'), + 'name_checksum' => t('Service Name Checksum'), + 'properties_checksum' => t('Service Properties Checksum'), + 'host_id' => t('Host Id'), + 'name' => t('Service Name'), + 'name_ci' => t('Service Name (CI)'), + 'display_name' => t('Service Display Name'), + 'checkcommand_name' => t('Checkcommand Name'), + 'checkcommand_id' => t('Checkcommand Id'), + 'max_check_attempts' => t('Service Max Check Attempts'), + 'check_timeperiod_name' => t('Check Timeperiod Name'), + 'check_timeperiod_id' => t('Check Timeperiod Id'), + 'check_timeout' => t('Service Check Timeout'), + 'check_interval' => t('Service Check Interval'), + 'check_retry_interval' => t('Service Check Retry Inverval'), + 'active_checks_enabled' => t('Service Active Checks Enabled'), + 'passive_checks_enabled' => t('Service Passive Checks Enabled'), + 'event_handler_enabled' => t('Service Event Handler Enabled'), + 'notifications_enabled' => t('Service Notifications Enabled'), + 'flapping_enabled' => t('Service Flapping Enabled'), + 'flapping_threshold_low' => t('Service Flapping Threshold Low'), + 'flapping_threshold_high' => t('Service Flapping Threshold High'), + 'perfdata_enabled' => t('Service Performance Data Enabled'), + 'eventcommand_name' => t('Eventcommand Name'), + 'eventcommand_id' => t('Eventcommand Id'), + 'is_volatile' => t('Service Is Volatile'), + 'action_url_id' => t('Action Url Id'), + 'notes_url_id' => t('Notes Url Id'), + 'notes' => t('Service Notes'), + 'icon_image_id' => t('Icon Image Id'), + 'icon_image_alt' => t('Icon Image Alt'), + 'zone_name' => t('Zone Name'), + 'zone_id' => t('Zone Id'), + 'command_endpoint_name' => t('Endpoint Name'), + 'command_endpoint_id' => t('Endpoint Id') + ]; + } + + public function getSearchColumns() + { + return ['name_ci', 'display_name']; + } + + public function getDefaultSort() + { + return 'service.display_name'; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new BoolCast([ + 'active_checks_enabled', + 'passive_checks_enabled', + 'event_handler_enabled', + 'notifications_enabled', + 'flapping_enabled', + 'is_volatile' + ])); + + $behaviors->add(new ReRoute([ + 'user' => 'notification.user', + 'usergroup' => 'notification.usergroup' + ])); + + $behaviors->add(new Binary([ + 'id', + 'environment_id', + 'name_checksum', + 'properties_checksum', + 'host_id', + 'checkcommand_id', + 'check_timeperiod_id', + 'eventcommand_id', + 'action_url_id', + 'notes_url_id', + 'icon_image_id', + 'zone_id', + 'command_endpoint_id' + ])); + } + + public function createDefaults(Defaults $defaults) + { + $defaults->add('vars', function (self $subject) { + if (! $subject->customvar_flat instanceof ResultSet) { + $this->applyRestrictions($subject->customvar_flat); + } + + $vars = []; + foreach ($subject->customvar_flat as $customVar) { + $vars[$customVar->flatname] = $customVar->flatvalue; + } + + return $vars; + }); + + $defaults->add('customvars', function (self $subject) { + if (! $subject->customvar instanceof ResultSet) { + $this->applyRestrictions($subject->customvar); + } + + $vars = []; + foreach ($subject->customvar as $customVar) { + $vars[$customVar->name] = json_decode($customVar->value, true); + } + + return $vars; + }); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('host', Host::class)->setJoinType('LEFT'); + $relations->belongsTo('checkcommand', Checkcommand::class); + $relations->belongsTo('timeperiod', Timeperiod::class) + ->setCandidateKey('check_timeperiod_id') + ->setJoinType('LEFT'); + $relations->belongsTo('eventcommand', Eventcommand::class); + $relations->belongsTo('action_url', ActionUrl::class) + ->setCandidateKey('action_url_id') + ->setForeignKey('id'); + $relations->belongsTo('notes_url', NotesUrl::class) + ->setCandidateKey('notes_url_id') + ->setForeignKey('id'); + $relations->belongsTo('icon_image', IconImage::class) + ->setCandidateKey('icon_image_id') + ->setJoinType('LEFT'); + $relations->belongsTo('zone', Zone::class); + $relations->belongsTo('endpoint', Endpoint::class) + ->setCandidateKey('command_endpoint_id'); + + $relations->belongsToMany('customvar', Customvar::class) + ->through(ServiceCustomvar::class); + $relations->belongsToMany('customvar_flat', CustomvarFlat::class) + ->through(ServiceCustomvar::class); + $relations->belongsToMany('vars', Vars::class) + ->through(ServiceCustomvar::class); + $relations->belongsToMany('servicegroup', Servicegroup::class) + ->through(ServicegroupMember::class); + $relations->belongsToMany('hostgroup', Hostgroup::class) + ->through(HostgroupMember::class); + + $relations->hasOne('state', ServiceState::class)->setJoinType('LEFT'); + $relations->hasMany('comment', Comment::class)->setJoinType('LEFT'); + $relations->hasMany('downtime', Downtime::class)->setJoinType('LEFT'); + $relations->hasMany('history', History::class); + $relations->hasMany('notification', Notification::class)->setJoinType('LEFT'); + $relations->hasMany('notification_history', NotificationHistory::class); + } +} diff --git a/library/Icingadb/Model/ServiceCustomvar.php b/library/Icingadb/Model/ServiceCustomvar.php new file mode 100644 index 0000000..07ee84c --- /dev/null +++ b/library/Icingadb/Model/ServiceCustomvar.php @@ -0,0 +1,52 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class ServiceCustomvar extends Model +{ + public function getTableName() + { + return 'service_customvar'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'service_id', + 'customvar_id', + 'environment_id' + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new Binary([ + 'id', + 'service_id', + 'customvar_id', + 'environment_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('service', Service::class); + $relations->belongsTo('customvar', Customvar::class); + $relations->belongsTo('customvar_flat', CustomvarFlat::class) + ->setForeignKey('customvar_id') + ->setCandidateKey('customvar_id'); + } +} diff --git a/library/Icingadb/Model/ServiceState.php b/library/Icingadb/Model/ServiceState.php new file mode 100644 index 0000000..c5daa08 --- /dev/null +++ b/library/Icingadb/Model/ServiceState.php @@ -0,0 +1,76 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use Icinga\Module\Icingadb\Common\ServiceStates; +use ipl\Orm\Relations; + +class ServiceState extends State +{ + public function getTableName() + { + return 'service_state'; + } + + public function getKeyName() + { + return 'service_id'; + } + + public function getColumnDefinitions() + { + return [ + 'environment_id' => t('Environment Id'), + 'state_type' => t('Service State Type'), + 'soft_state' => t('Service Soft State'), + 'hard_state' => t('Service Hard State'), + 'previous_soft_state' => t('Service Previous Soft State'), + 'previous_hard_state' => t('Service Previous Hard State'), + 'check_attempt' => t('Service Check Attempt No.'), + 'severity' => t('Service State Severity'), + 'output' => t('Service Output'), + 'long_output' => t('Service Long Output'), + 'performance_data' => t('Service Performance Data'), + 'normalized_performance_data' => t('Service Normalized Performance Data'), + 'check_commandline' => t('Service Check Commandline'), + 'is_problem' => t('Service Has Problem'), + 'is_handled' => t('Service Is Handled'), + 'is_reachable' => t('Service Is Reachable'), + 'is_flapping' => t('Service Is Flapping'), + 'is_overdue' => t('Service Check Is Overdue'), + 'is_acknowledged' => t('Service Is Acknowledged'), + 'acknowledgement_comment_id' => t('Acknowledgement Comment Id'), + 'in_downtime' => t('Service In Downtime'), + 'execution_time' => t('Service Check Execution Time'), + 'latency' => t('Service Check Latency'), + 'check_timeout' => t('Service Check Timeout'), + 'check_source' => t('Service Check Source'), + 'last_update' => t('Service Last Update'), + 'last_state_change' => t('Service Last State Change'), + 'next_check' => t('Service Next Check'), + 'next_update' => t('Service Next Update') + ]; + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('service', Service::class); + $relations->hasOne('last_comment', LastServiceComment::class) + ->setCandidateKey('last_comment_id') + ->setForeignKey('id') + ->setJoinType('LEFT'); + } + + public function getStateText(): string + { + return ServiceStates::text($this->soft_state); + } + + public function getStateTextTranslated(): string + { + return ServiceStates::text($this->soft_state); + } +} diff --git a/library/Icingadb/Model/Servicegroup.php b/library/Icingadb/Model/Servicegroup.php new file mode 100644 index 0000000..0da92fb --- /dev/null +++ b/library/Icingadb/Model/Servicegroup.php @@ -0,0 +1,91 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use Icinga\Module\Icingadb\Model\Behavior\ReRoute; +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class Servicegroup extends Model +{ + public function getTableName() + { + return 'servicegroup'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'environment_id', + 'name_checksum', + 'properties_checksum', + 'name', + 'name_ci', + 'display_name', + 'zone_id' + ]; + } + + public function getColumnDefinitions() + { + return [ + 'environment_id' => t('Environment Id'), + 'name_checksum' => t('Servicegroup Name Checksum'), + 'properties_checksum' => t('Servicegroup Properties Checksum'), + 'name' => t('Servicegroup Name'), + 'name_ci' => t('Servicegroup Name (CI)'), + 'display_name' => t('Servicegroup Display Name'), + 'zone_id' => t('Zone Id') + ]; + } + + public function getSearchColumns() + { + return ['name_ci', 'display_name']; + } + + public function getDefaultSort() + { + return 'display_name'; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new ReRoute([ + 'host' => 'service.host', + 'hostgroup' => 'service.hostgroup' + ])); + + $behaviors->add(new Binary([ + 'id', + 'environment_id', + 'name_checksum', + 'properties_checksum', + 'zone_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('zone', Zone::class); + + $relations->belongsToMany('customvar', Customvar::class) + ->through(ServicegroupCustomvar::class); + $relations->belongsToMany('customvar_flat', CustomvarFlat::class) + ->through(ServicegroupCustomvar::class); + $relations->belongsToMany('vars', Vars::class) + ->through(ServicegroupCustomvar::class); + $relations->belongsToMany('service', Service::class) + ->through(ServicegroupMember::class); + } +} diff --git a/library/Icingadb/Model/ServicegroupCustomvar.php b/library/Icingadb/Model/ServicegroupCustomvar.php new file mode 100644 index 0000000..23e536b --- /dev/null +++ b/library/Icingadb/Model/ServicegroupCustomvar.php @@ -0,0 +1,52 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class ServicegroupCustomvar extends Model +{ + public function getTableName() + { + return 'servicegroup_customvar'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'servicegroup_id', + 'customvar_id', + 'environment_id' + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new Binary([ + 'id', + 'servicegroup_id', + 'customvar_id', + 'environment_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('servicegroup', Servicegroup::class); + $relations->belongsTo('customvar', Customvar::class); + $relations->belongsTo('customvar_flat', CustomvarFlat::class) + ->setCandidateKey('customvar_id') + ->setForeignKey('customvar_id'); + } +} diff --git a/library/Icingadb/Model/ServicegroupMember.php b/library/Icingadb/Model/ServicegroupMember.php new file mode 100644 index 0000000..5da537a --- /dev/null +++ b/library/Icingadb/Model/ServicegroupMember.php @@ -0,0 +1,49 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class ServicegroupMember extends Model +{ + public function getTableName() + { + return 'servicegroup_member'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'service_id', + 'servicegroup_id', + 'environment_id' + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new Binary([ + 'id', + 'service_id', + 'servicegroup_id', + 'environment_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('servicegroup', Servicegroup::class); + $relations->belongsTo('service', Service::class); + } +} diff --git a/library/Icingadb/Model/ServicegroupSummary.php b/library/Icingadb/Model/ServicegroupSummary.php new file mode 100644 index 0000000..89a0953 --- /dev/null +++ b/library/Icingadb/Model/ServicegroupSummary.php @@ -0,0 +1,167 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Relations; +use ipl\Orm\UnionModel; +use ipl\Sql\Adapter\Pgsql; +use ipl\Sql\Connection; +use ipl\Sql\Expression; +use ipl\Sql\Select; + +class ServicegroupSummary extends UnionModel +{ + public static function on(Connection $db) + { + $q = parent::on($db); + + $q->on($q::ON_SELECT_ASSEMBLED, function (Select $select) use ($q) { + $model = $q->getModel(); + + $groupBy = $q->getResolver()->qualifyColumnsAndAliases((array) $model->getKeyName(), $model, false); + + // For PostgreSQL, ALL non-aggregate SELECT columns must appear in the GROUP BY clause: + if ($q->getDb()->getAdapter() instanceof Pgsql) { + /** + * Ignore Expressions, i.e. aggregate functions {@see getColumns()}, + * which do not need to be added to the GROUP BY. + */ + $candidates = array_filter($select->getColumns(), 'is_string'); + // Remove already considered columns for the GROUP BY, i.e. the primary key. + $candidates = array_diff_assoc($candidates, $groupBy); + $groupBy = array_merge($groupBy, $candidates); + } + + $select->groupBy($groupBy); + }); + + return $q; + } + + public function getTableName() + { + return 'servicegroup'; + } + + public function getKeyName() + { + return ['id' => 'servicegroup_id']; + } + + public function getColumns() + { + return [ + 'display_name' => 'servicegroup_display_name', + 'name' => 'servicegroup_name', + 'services_critical_handled' => new Expression( + 'SUM(CASE WHEN service_state = 2' + . ' AND (service_handled = \'y\' OR service_reachable = \'n\') THEN 1 ELSE 0 END)' + ), + 'services_critical_unhandled' => new Expression( + 'SUM(CASE WHEN service_state = 2' + . ' AND service_handled = \'n\' AND service_reachable = \'y\' THEN 1 ELSE 0 END)' + ), + 'services_ok' => new Expression( + 'SUM(CASE WHEN service_state = 0 THEN 1 ELSE 0 END)' + ), + 'services_pending' => new Expression( + 'SUM(CASE WHEN service_state = 99 THEN 1 ELSE 0 END)' + ), + 'services_total' => new Expression( + 'SUM(CASE WHEN service_id IS NOT NULL THEN 1 ELSE 0 END)' + ), + 'services_unknown_handled' => new Expression( + 'SUM(CASE WHEN service_state = 3' + . ' AND (service_handled = \'y\' OR service_reachable = \'n\') THEN 1 ELSE 0 END)' + ), + 'services_unknown_unhandled' => new Expression( + 'SUM(CASE WHEN service_state = 3' + . ' AND service_handled = \'n\' AND service_reachable = \'y\' THEN 1 ELSE 0 END)' + ), + 'services_warning_handled' => new Expression( + 'SUM(CASE WHEN service_state = 1' + . ' AND (service_handled = \'y\' OR service_reachable = \'n\') THEN 1 ELSE 0 END)' + ), + 'services_warning_unhandled' => new Expression( + 'SUM(CASE WHEN service_state = 1' + . ' AND service_handled = \'n\' AND service_reachable = \'y\' THEN 1 ELSE 0 END)' + ), + 'services_severity' => new Expression('MAX(service_severity)') + ]; + } + + public function getSearchColumns() + { + return ['display_name']; + } + + public function getDefaultSort() + { + return 'display_name'; + } + + public function getUnions() + { + $unions = [ + [ + Service::class, + [ + 'servicegroup', + 'state' + ], + [ + 'servicegroup_id' => 'servicegroup.id', + 'servicegroup_name' => 'servicegroup.name', + 'servicegroup_display_name' => 'servicegroup.display_name', + 'service_id' => 'service.id', + 'service_state' => 'state.soft_state', + 'service_handled' => 'state.is_handled', + 'service_reachable' => 'state.is_reachable', + 'service_severity' => 'state.severity' + ] + ], + [ + Servicegroup::class, + [], + [ + 'servicegroup_id' => 'servicegroup.id', + 'servicegroup_name' => 'servicegroup.name', + 'servicegroup_display_name' => 'servicegroup.display_name', + 'service_id' => new Expression('NULL'), + 'service_state' => new Expression('NULL'), + 'service_handled' => new Expression('NULL'), + 'service_reachable' => new Expression('NULL'), + 'service_severity' => new Expression('0') + ] + ] + ]; + + return $unions; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new Binary([ + 'id' + ])); + + // This is because there is no better way + (new Servicegroup())->createBehaviors($behaviors); + } + + public function createRelations(Relations $relations) + { + // This is because there is no better way + (new Servicegroup())->createRelations($relations); + } + + public function getColumnDefinitions() + { + // This is because there is no better way + return (new Servicegroup())->getColumnDefinitions(); + } +} diff --git a/library/Icingadb/Model/ServicestateSummary.php b/library/Icingadb/Model/ServicestateSummary.php new file mode 100644 index 0000000..b1364f7 --- /dev/null +++ b/library/Icingadb/Model/ServicestateSummary.php @@ -0,0 +1,99 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Sql\Connection; +use ipl\Sql\Expression; + +class ServicestateSummary extends Service +{ + public function getSummaryColumns() + { + return [ + 'services_acknowledged' => new Expression( + 'SUM(CASE WHEN service_state.is_acknowledged = \'y\' THEN 1 ELSE 0 END)' + ), + 'services_active_checks_enabled' => new Expression( + 'SUM(CASE WHEN service.active_checks_enabled = \'y\' THEN 1 ELSE 0 END)' + ), + 'services_passive_checks_enabled' => new Expression( + 'SUM(CASE WHEN service.passive_checks_enabled = \'y\' THEN 1 ELSE 0 END)' + ), + 'services_critical_handled' => new Expression( + 'SUM(CASE WHEN service_state.soft_state = 2' + . ' AND (service_state.is_handled = \'y\' OR service_state.is_reachable = \'n\') THEN 1 ELSE 0 END)' + ), + 'services_critical_unhandled' => new Expression( + 'SUM(CASE WHEN service_state.soft_state = 2' + . ' AND service_state.is_handled = \'n\' AND service_state.is_reachable = \'y\' THEN 1 ELSE 0 END)' + ), + 'services_event_handler_enabled' => new Expression( + 'SUM(CASE WHEN service.event_handler_enabled = \'y\' THEN 1 ELSE 0 END)' + ), + 'services_flapping_enabled' => new Expression( + 'SUM(CASE WHEN service.flapping_enabled = \'y\' THEN 1 ELSE 0 END)' + ), + 'services_notifications_enabled' => new Expression( + 'SUM(CASE WHEN service.notifications_enabled = \'y\' THEN 1 ELSE 0 END)' + ), + 'services_ok' => new Expression( + 'SUM(CASE WHEN service_state.soft_state = 0 THEN 1 ELSE 0 END)' + ), + 'services_pending' => new Expression( + 'SUM(CASE WHEN service_state.soft_state = 99 THEN 1 ELSE 0 END)' + ), + 'services_problems_unacknowledged' => new Expression( + 'SUM(CASE WHEN service_state.is_problem = \'y\'' + . ' AND service_state.is_acknowledged = \'n\' THEN 1 ELSE 0 END)' + ), + 'services_total' => new Expression( + 'SUM(CASE WHEN service.id IS NOT NULL THEN 1 ELSE 0 END)' + ), + 'services_unknown_handled' => new Expression( + 'SUM(CASE WHEN service_state.soft_state = 3' + . ' AND (service_state.is_handled = \'y\' OR service_state.is_reachable = \'n\') THEN 1 ELSE 0 END)' + ), + 'services_unknown_unhandled' => new Expression( + 'SUM(CASE WHEN service_state.soft_state = 3' + . ' AND service_state.is_handled = \'n\' AND service_state.is_reachable = \'y\' THEN 1 ELSE 0 END)' + ), + 'services_warning_handled' => new Expression( + 'SUM(CASE WHEN service_state.soft_state = 1' + . ' AND (service_state.is_handled = \'y\' OR service_state.is_reachable = \'n\') THEN 1 ELSE 0 END)' + ), + 'services_warning_unhandled' => new Expression( + 'SUM(CASE WHEN service_state.soft_state = 1' + . ' AND service_state.is_handled = \'n\' AND service_state.is_reachable = \'y\' THEN 1 ELSE 0 END)' + ) + ]; + } + + public static function on(Connection $db) + { + $q = parent::on($db); + $q->utilize('state'); + + /** @var static $m */ + $m = $q->getModel(); + $q->columns($m->getSummaryColumns()); + + return $q; + } + + public function getColumns() + { + return array_merge(parent::getColumns(), $this->getSummaryColumns()); + } + + public function getDefaultSort() + { + return null; + } + + public function getSearchColumns() + { + return ['name_ci', 'host.name_ci']; + } +} diff --git a/library/Icingadb/Model/State.php b/library/Icingadb/Model/State.php new file mode 100644 index 0000000..2d242a8 --- /dev/null +++ b/library/Icingadb/Model/State.php @@ -0,0 +1,177 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use DateTime; +use Icinga\Module\Icingadb\Common\Icons; +use Icinga\Module\Icingadb\Model\Behavior\BoolCast; +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behavior\MillisecondTimestamp; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Web\Widget\Icon; + +/** + * Base class for the {@link HostState} and {@link ServiceState} models providing common columns. + * + * @property string $environment_id The environment id + * @property string $state_type The state type (hard or soft) + * @property int $soft_state The current soft state code (0 = OK, 1 = WARNING, 2 = CRITICAL, 3 = UNKNOWN) + * @property int $hard_state The current hard state code (0 = OK, 1 = WARNING, 2 = CRITICAL, 3 = UNKNOWN) + * @property int $previous_soft_state The previous soft state code (0 = OK, 1 = WARNING, 2 = CRITICAL, 3 = UNKNOWN) + * @property int $previous_hard_state The previous hard state code (0 = OK, 1 = WARNING, 2 = CRITICAL, 3 = UNKNOWN) + * @property int $check_attempt The check attempt count + * @property int $severity The calculated severity + * @property ?string $output The check output + * @property ?string $long_output The long check output + * @property ?string $performance_data The performance data + * @property ?string $normalized_performance_data The normalized performance data (converted ms to s, GiB to byte etc.) + * @property ?string $check_commandline The executed check command + * @property bool $is_problem Whether in non-OK state + * @property bool $is_handled Whether the state is handled + * @property bool $is_reachable Whether the node is reachable + * @property bool $is_flapping Whether the state is flapping + * @property bool $is_overdue Whether the check is overdue + * @property bool|string $is_acknowledged Whether the state is acknowledged (bool), can also be `sticky` (string) + * @property ?string $acknowledgement_comment_id The id of acknowledgement comment + * @property ?string $last_comment_id The id of last comment + * @property bool $in_downtime Whether the node is in downtime + * @property ?int $execution_time The check execution time + * @property ?int $latency The check latency + * @property ?int $check_timeout The check timeout + * @property ?string $check_source The name of the node that executes the check + * @property ?string $scheduling_source The name of the node that schedules the check + * @property ?DateTime $last_update The time when the node was last updated + * @property ?DateTime $last_state_change The time when the node last got a status change + * @property ?DateTime $next_check The time when the node will execute the next check + * @property ?DateTime $next_update The time when the next check of the node is expected to end + */ +abstract class State extends Model +{ + /** + * Get the state as the textual representation + * + * @return string + */ + abstract public function getStateText(): string; + + /** + * Get the state as the translated textual representation + * + * @return string + */ + abstract public function getStateTextTranslated(): string; + + public function getColumns() + { + return [ + 'environment_id', + 'state_type', + 'soft_state', + 'hard_state', + 'previous_soft_state', + 'previous_hard_state', + 'check_attempt', + 'severity', + 'output', + 'long_output', + 'performance_data', + 'normalized_performance_data', + 'check_commandline', + 'is_problem', + 'is_handled', + 'is_reachable', + 'is_flapping', + 'is_overdue', + 'is_acknowledged', + 'acknowledgement_comment_id', + 'last_comment_id', + 'in_downtime', + 'execution_time', + 'latency', + 'check_timeout', + 'check_source', + 'scheduling_source', + 'last_update', + 'last_state_change', + 'next_check', + 'next_update' + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new BoolCast([ + 'is_problem', + 'is_handled', + 'is_reachable', + 'is_flapping', + 'is_overdue', + 'is_acknowledged', + 'in_downtime' + ])); + + $behaviors->add(new MillisecondTimestamp([ + 'last_update', + 'last_state_change', + 'next_check', + 'next_update' + ])); + + $behaviors->add(new Binary([ + $this->getKeyName(), + 'environment_id', + 'acknowledgement_comment_id', + 'last_comment_id' + ])); + } + + /** + * Get the state icon + * + * @return Icon|null + */ + public function getIcon(): ?Icon + { + $icon = null; + switch (true) { + case $this->is_acknowledged: + $icon = new Icon(Icons::IS_ACKNOWLEDGED); + + break; + case $this->in_downtime: + $icon = new Icon( + Icons::IN_DOWNTIME, + ['title' => sprintf( + '%s (%s)', + strtoupper($this->getStateTextTranslated()), + $this->is_handled ? t('handled by Downtime') : t('in Downtime') + )] + ); + + break; + case $this->is_flapping: + $icon = new Icon(Icons::IS_FLAPPING); + + break; + case ! $this->is_reachable: + $icon = new Icon(Icons::HOST_DOWN, [ + 'title' => sprintf( + '%s (%s)', + strtoupper($this->getStateTextTranslated()), + t('is unreachable') + ) + ]); + + break; + case $this->is_handled: + $icon = new Icon(Icons::HOST_DOWN); + + break; + } + + return $icon; + } +} diff --git a/library/Icingadb/Model/StateHistory.php b/library/Icingadb/Model/StateHistory.php new file mode 100644 index 0000000..9d80cb2 --- /dev/null +++ b/library/Icingadb/Model/StateHistory.php @@ -0,0 +1,101 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behavior\MillisecondTimestamp; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +/** + * Model for table `state_history` + * + * Please note that using this model will fetch history entries for decommissioned services. To avoid this, + * the query needs a `state_history.service_id IS NULL OR state_history_service.id IS NOT NULL` where. + */ +class StateHistory extends Model +{ + public function getTableName() + { + return 'state_history'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'environment_id', + 'endpoint_id', + 'object_type', + 'host_id', + 'service_id', + 'event_time', + 'state_type', + 'soft_state', + 'hard_state', + 'check_attempt', + 'previous_soft_state', + 'previous_hard_state', + 'output', + 'long_output', + 'max_check_attempts', + 'check_source', + 'scheduling_source' + ]; + } + + public function getColumnDefinitions() + { + return [ + 'environment_id' => t('Environment Id'), + 'endpoint_id' => t('Endpoint Id'), + 'object_type' => t('Object Type'), + 'host_id' => t('Host Id'), + 'service_id' => t('Service Id'), + 'event_time' => t('Event Time'), + 'state_type' => t('Event State Type'), + 'soft_state' => t('Event Soft State'), + 'hard_state' => t('Event Hard State'), + 'check_attempt' => t('Event Check Attempt No.'), + 'previous_soft_state' => t('Event Previous Soft State'), + 'previous_hard_state' => t('Event Previous Hard State'), + 'output' => t('Event Output'), + 'long_output' => t('Event Long Output'), + 'max_check_attempts' => t('Event Max Check Attempts'), + 'check_source' => t('Event Check Source') + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new MillisecondTimestamp([ + 'event_time' + ])); + + $behaviors->add(new Binary([ + 'id', + 'environment_id', + 'endpoint_id', + 'host_id', + 'service_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('endpoint', Endpoint::class); + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('history', History::class) + ->setCandidateKey('id') + ->setForeignKey('state_history_id'); + $relations->belongsTo('host', Host::class); + $relations->belongsTo('service', Service::class)->setJoinType('LEFT'); + } +} diff --git a/library/Icingadb/Model/Timeperiod.php b/library/Icingadb/Model/Timeperiod.php new file mode 100644 index 0000000..26dd722 --- /dev/null +++ b/library/Icingadb/Model/Timeperiod.php @@ -0,0 +1,91 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use Icinga\Module\Icingadb\Model\Behavior\ReRoute; +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class Timeperiod extends Model +{ + public function getTableName() + { + return 'timeperiod'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'environment_id', + 'name_checksum', + 'properties_checksum', + 'name', + 'name_ci', + 'display_name', + 'prefer_includes', + 'zone_id' + ]; + } + + public function getColumnDefinitions() + { + return [ + 'environment_id' => t('Environment Id'), + 'name_checksum' => t('Timeperiod Name Checksum'), + 'properties_checksum' => t('Timeperiod Properties Checksum'), + 'name' => t('Timeperiod Name'), + 'name_ci' => t('Timeperiod Name (CI)'), + 'display_name' => t('Timeperiod Display Name'), + 'prefer_includes' => t('Timeperiod Prefer Includes'), + 'zone_id' => t('Zone Id') + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new ReRoute([ + 'hostgroup' => 'host.hostgroup', + 'servicegroup' => 'service.servicegroup' + ])); + + $behaviors->add(new Binary([ + 'id', + 'environment_id', + 'name_checksum', + 'properties_checksum', + 'zone_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('zone', Zone::class); + + $relations->belongsToMany('customvar', Customvar::class) + ->through(TimeperiodCustomvar::class); + $relations->belongsToMany('customvar_flat', CustomvarFlat::class) + ->through(TimeperiodCustomvar::class); + $relations->belongsToMany('vars', Vars::class) + ->through(TimeperiodCustomvar::class); + + // TODO: Decide how to establish the override relations + + $relations->hasMany('range', TimeperiodRange::class); + $relations->hasMany('host', Host::class) + ->setForeignKey('check_timeperiod_id'); + $relations->hasMany('Notification', Notification::class); + $relations->hasMany('service', Service::class) + ->setForeignKey('check_timeperiod_id'); + $relations->hasMany('user', User::class); + } +} diff --git a/library/Icingadb/Model/TimeperiodCustomvar.php b/library/Icingadb/Model/TimeperiodCustomvar.php new file mode 100644 index 0000000..614a312 --- /dev/null +++ b/library/Icingadb/Model/TimeperiodCustomvar.php @@ -0,0 +1,52 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class TimeperiodCustomvar extends Model +{ + public function getTableName() + { + return 'timeperiod_customvar'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'timeperiod_id', + 'customvar_id', + 'environment_id' + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new Binary([ + 'id', + 'timeperiod_id', + 'customvar_id', + 'environment_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('timeperiod', Timeperiod::class); + $relations->belongsTo('customvar', Customvar::class); + $relations->belongsTo('customvar_flat', CustomvarFlat::class) + ->setCandidateKey('customvar_id') + ->setForeignKey('customvar_id'); + } +} diff --git a/library/Icingadb/Model/TimeperiodOverrideExclude.php b/library/Icingadb/Model/TimeperiodOverrideExclude.php new file mode 100644 index 0000000..c33df77 --- /dev/null +++ b/library/Icingadb/Model/TimeperiodOverrideExclude.php @@ -0,0 +1,51 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class TimeperiodOverrideExclude extends Model +{ + public function getTableName() + { + return 'timeperiod_override_exclude'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'timeperiod_id', + 'override_id', + 'environment_id' + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new Binary([ + 'id', + 'timeperiod_id', + 'override_id', + 'environment_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('timeperiod', Timeperiod::class); + // TODO: `timeperiod` cannot be used again, find a better name + $relations->belongsTo('timeperiod', Timeperiod::class) + ->setCandidateKey('override_id'); + } +} diff --git a/library/Icingadb/Model/TimeperiodOverrideInclude.php b/library/Icingadb/Model/TimeperiodOverrideInclude.php new file mode 100644 index 0000000..5418596 --- /dev/null +++ b/library/Icingadb/Model/TimeperiodOverrideInclude.php @@ -0,0 +1,51 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class TimeperiodOverrideInclude extends Model +{ + public function getTableName() + { + return 'timeperiod_override_include'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'timeperiod_id', + 'override_id', + 'environment_id' + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new Binary([ + 'id', + 'timeperiod_id', + 'override_id', + 'environment_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('timeperiod', Timeperiod::class); + // TODO: `timeperiod` cannot be used again, find a better name + $relations->belongsTo('timeperiod', Timeperiod::class) + ->setCandidateKey('override_id'); + } +} diff --git a/library/Icingadb/Model/TimeperiodRange.php b/library/Icingadb/Model/TimeperiodRange.php new file mode 100644 index 0000000..62e87f8 --- /dev/null +++ b/library/Icingadb/Model/TimeperiodRange.php @@ -0,0 +1,58 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class TimeperiodRange extends Model +{ + public function getTableName() + { + return 'timeperiod_range'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'timeperiod_id', + 'range_key', + 'environment_id', + 'range_value' + ]; + } + + public function getColumnDefinitions() + { + return [ + 'timeperiod_id' => t('Timeperiod Id'), + 'range_key' => t('Timeperiod Range Date(s)/Day'), + 'environment_id' => t('Environment Id'), + 'range_value' => t('Timeperiod Range Time') + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new Binary([ + 'id', + 'timeperiod_id', + 'environment_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('timeperiod', Timeperiod::class); + } +} diff --git a/library/Icingadb/Model/User.php b/library/Icingadb/Model/User.php new file mode 100644 index 0000000..91d0d71 --- /dev/null +++ b/library/Icingadb/Model/User.php @@ -0,0 +1,134 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use Icinga\Module\Icingadb\Model\Behavior\Bitmask; +use Icinga\Module\Icingadb\Model\Behavior\ReRoute; +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class User extends Model +{ + public function getTableName() + { + return 'user'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'environment_id', + 'name_checksum', + 'properties_checksum', + 'name', + 'name_ci', + 'display_name', + 'email', + 'pager', + 'notifications_enabled', + 'timeperiod_id', + 'states', + 'types', + 'zone_id' + ]; + } + + public function getColumnDefinitions() + { + return [ + 'environment_id' => t('Environment Id'), + 'name_checksum' => t('User Name Checksum'), + 'properties_checksum' => t('User Properties Checksum'), + 'name' => t('User Name'), + 'name_ci' => t('User Name (CI)'), + 'display_name' => t('User Display Name'), + 'email' => t('User Email'), + 'pager' => t('User Pager'), + 'notifications_enabled' => t('User Receives Notifications'), + 'timeperiod_id' => t('Timeperiod Id'), + 'states' => t('Notification State Filter'), + 'types' => t('Notification Type Filter'), + 'zone_id' => t('Zone Id') + ]; + } + + public function getSearchColumns() + { + return ['name_ci', 'display_name']; + } + + public function getDefaultSort() + { + return 'user.display_name'; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new ReRoute([ + 'host' => 'notification.host', + 'service' => 'notification.service', + 'hostgroup' => 'notification.host.hostgroup', + 'servicegroup' => 'notification.service.servicegroup' + ])); + + $behaviors->add(new Bitmask([ + 'states' => [ + 'ok' => 1, + 'warning' => 2, + 'critical' => 4, + 'unknown' => 8, + 'up' => 16, + 'down' => 32 + ], + 'types' => [ + 'downtime_start' => 1, + 'downtime_end' => 2, + 'downtime_removed' => 4, + 'custom' => 8, + 'ack' => 16, + 'problem' => 32, + 'recovery' => 64, + 'flapping_start' => 128, + 'flapping_end' => 256 + ] + ])); + + $behaviors->add(new Binary([ + 'id', + 'environment_id', + 'name_checksum', + 'properties_checksum', + 'timeperiod_id', + 'zone_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('timeperiod', Timeperiod::class); + $relations->belongsTo('zone', Zone::class); + + $relations->belongsToMany('customvar', Customvar::class) + ->through(UserCustomvar::class); + $relations->belongsToMany('customvar_flat', CustomvarFlat::class) + ->through(UserCustomvar::class); + $relations->belongsToMany('vars', Vars::class) + ->through(UserCustomvar::class); + $relations->belongsToMany('notification', Notification::class) + ->through('notification_recipient'); + $relations->belongsToMany('notification_history', NotificationHistory::class) + ->through('user_notification_history'); + $relations->belongsToMany('usergroup', Usergroup::class) + ->through(UsergroupMember::class); + } +} diff --git a/library/Icingadb/Model/UserCustomvar.php b/library/Icingadb/Model/UserCustomvar.php new file mode 100644 index 0000000..a702b68 --- /dev/null +++ b/library/Icingadb/Model/UserCustomvar.php @@ -0,0 +1,52 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class UserCustomvar extends Model +{ + public function getTableName() + { + return 'user_customvar'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'user_id', + 'customvar_id', + 'environment_id' + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new Binary([ + 'id', + 'user_id', + 'customvar_id', + 'environment_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('user', User::class); + $relations->belongsTo('customvar', Customvar::class); + $relations->belongsTo('customvar_flat', CustomvarFlat::class) + ->setCandidateKey('customvar_id') + ->setForeignKey('customvar_id'); + } +} diff --git a/library/Icingadb/Model/Usergroup.php b/library/Icingadb/Model/Usergroup.php new file mode 100644 index 0000000..34b0647 --- /dev/null +++ b/library/Icingadb/Model/Usergroup.php @@ -0,0 +1,95 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use Icinga\Module\Icingadb\Model\Behavior\ReRoute; +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class Usergroup extends Model +{ + public function getTableName() + { + return 'usergroup'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'environment_id', + 'name_checksum', + 'properties_checksum', + 'name', + 'name_ci', + 'display_name', + 'zone_id' + ]; + } + + public function getColumnDefinitions() + { + return [ + 'environment_id' => t('Environment Id'), + 'name_checksum' => t('Usergroup Name Checksum'), + 'properties_checksum' => t('Usergroup Properties Checksum'), + 'name' => t('Usergroup Name'), + 'name_ci' => t('Usergroup Name (CI)'), + 'display_name' => t('Usergroup Display Name'), + 'zone_id' => t('Zone Id') + ]; + } + + public function getSearchColumns() + { + return ['name_ci', 'display_name']; + } + + public function getDefaultSort() + { + return 'usergroup.display_name'; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new ReRoute([ + 'host' => 'notification.host', + 'service' => 'notification.service', + 'hostgroup' => 'notification.host.hostgroup', + 'servicegroup' => 'notification.service.servicegroup' + ])); + + $behaviors->add(new Binary([ + 'id', + 'environment_id', + 'name_checksum', + 'properties_checksum', + 'zone_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('zone', Zone::class); + + $relations->belongsToMany('customvar', Customvar::class) + ->through(UsergroupCustomvar::class); + $relations->belongsToMany('customvar_flat', CustomvarFlat::class) + ->through(UsergroupCustomvar::class); + $relations->belongsToMany('vars', Vars::class) + ->through(UsergroupCustomvar::class); + $relations->belongsToMany('user', User::class) + ->through(UsergroupMember::class); + $relations->belongsToMany('notification', Notification::class) + ->through('notification_recipient'); + } +} diff --git a/library/Icingadb/Model/UsergroupCustomvar.php b/library/Icingadb/Model/UsergroupCustomvar.php new file mode 100644 index 0000000..ab97273 --- /dev/null +++ b/library/Icingadb/Model/UsergroupCustomvar.php @@ -0,0 +1,52 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class UsergroupCustomvar extends Model +{ + public function getTableName() + { + return 'usergroup_customvar'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'usergroup_id', + 'customvar_id', + 'environment_id' + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new Binary([ + 'id', + 'usergroup_id', + 'customvar_id', + 'environment_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('usergroup', Usergroup::class); + $relations->belongsTo('customvar', Customvar::class); + $relations->belongsTo('customvar_flat', CustomvarFlat::class) + ->setCandidateKey('customvar_id') + ->setForeignKey('customvar_id'); + } +} diff --git a/library/Icingadb/Model/UsergroupMember.php b/library/Icingadb/Model/UsergroupMember.php new file mode 100644 index 0000000..7c61d67 --- /dev/null +++ b/library/Icingadb/Model/UsergroupMember.php @@ -0,0 +1,49 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class UsergroupMember extends Model +{ + public function getTableName() + { + return 'usergroup_member'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'user_id', + 'usergroup_id', + 'environment_id' + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new Binary([ + 'id', + 'user_id', + 'usergroup_id', + 'environment_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + $relations->belongsTo('usergroup', Usergroup::class); + $relations->belongsTo('user', User::class); + } +} diff --git a/library/Icingadb/Model/Vars.php b/library/Icingadb/Model/Vars.php new file mode 100644 index 0000000..304d526 --- /dev/null +++ b/library/Icingadb/Model/Vars.php @@ -0,0 +1,28 @@ +<?php + +/* Icinga DB Web | (c) 2022 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use Icinga\Module\Icingadb\Model\Behavior\FlattenedObjectVars; +use ipl\Orm\Behaviors; +use ipl\Sql\Connection; + +class Vars extends CustomvarFlat +{ + /** + * @internal Don't use. This model acts only as relation target and is not supposed to be directly used as query + * target. Use {@see CustomvarFlat} instead. + */ + public static function on(Connection $_) + { + throw new \LogicException('Documentation says: DO NOT USE. Can\'t you read?'); + } + + public function createBehaviors(Behaviors $behaviors) + { + parent::createBehaviors($behaviors); + + $behaviors->add(new FlattenedObjectVars()); + } +} diff --git a/library/Icingadb/Model/Zone.php b/library/Icingadb/Model/Zone.php new file mode 100644 index 0000000..aaf3bbf --- /dev/null +++ b/library/Icingadb/Model/Zone.php @@ -0,0 +1,82 @@ +<?php + +/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Model; + +use ipl\Orm\Behavior\Binary; +use ipl\Orm\Behaviors; +use ipl\Orm\Model; +use ipl\Orm\Relations; + +class Zone extends Model +{ + public function getTableName() + { + return 'zone'; + } + + public function getKeyName() + { + return 'id'; + } + + public function getColumns() + { + return [ + 'environment_id', + 'name_checksum', + 'properties_checksum', + 'name', + 'name_ci', + 'is_global', + 'parent_id', + 'depth' + ]; + } + + public function getColumnDefinitions() + { + return [ + 'environment_id' => t('Environment Id'), + 'name_checksum' => t('Zone Name Checksum'), + 'properties_checksum' => t('Zone Properties Checksum'), + 'name' => t('Zone Name'), + 'name_ci' => t('Zone Name (CI)'), + 'is_global' => t('Zone Is Global'), + 'parent_id' => t('Parent Zone Id'), + 'depth' => t('Zone Depth') + ]; + } + + public function createBehaviors(Behaviors $behaviors) + { + $behaviors->add(new Binary([ + 'id', + 'environment_id', + 'name_checksum', + 'properties_checksum', + 'parent_id' + ])); + } + + public function createRelations(Relations $relations) + { + $relations->belongsTo('environment', Environment::class); + + $relations->hasMany('comment', Comment::class); + $relations->hasMany('downtime', Downtime::class); + $relations->hasMany('endpoint', Endpoint::class); + $relations->hasMany('eventcommand', Eventcommand::class); + $relations->hasMany('host', Host::class); + $relations->hasMany('hostgroup', Hostgroup::class); + $relations->hasMany('notification', Notification::class); + $relations->hasMany('service', Service::class); + $relations->hasMany('servicegroup', Servicegroup::class); + $relations->hasMany('timeperiod', Timeperiod::class); + $relations->hasMany('user', User::class); + $relations->hasMany('usergroup', Usergroup::class); + + // TODO: Decide how to establish recursive relations + } +} |