diff options
Diffstat (limited to '')
7 files changed, 659 insertions, 0 deletions
diff --git a/library/Director/DirectorObject/Lookup/AppliedServiceInfo.php b/library/Director/DirectorObject/Lookup/AppliedServiceInfo.php new file mode 100644 index 0000000..abda497 --- /dev/null +++ b/library/Director/DirectorObject/Lookup/AppliedServiceInfo.php @@ -0,0 +1,109 @@ +<?php + +namespace Icinga\Module\Director\DirectorObject\Lookup; + +use gipfl\IcingaWeb2\Url; +use Icinga\Data\Filter\Filter; +use Icinga\Module\Director\Db; +use Icinga\Module\Director\Objects\HostApplyMatches; +use Icinga\Module\Director\Objects\IcingaHost; +use Ramsey\Uuid\Uuid; +use Ramsey\Uuid\UuidInterface; + +/** + * A Service Apply Rule matching this Host, generating a Service with the given + * name + */ +class AppliedServiceInfo implements ServiceInfo +{ + /** @var string */ + protected $hostName; + + /** @var string */ + protected $serviceName; + + /** @var int */ + protected $serviceApplyRuleId; + + /** @var UuidInterface */ + protected $uuid; + + public function __construct($hostName, $serviceName, $serviceApplyRuleId, UuidInterface $uuid) + { + $this->hostName = $hostName; + $this->serviceName= $serviceName; + $this->serviceApplyRuleId = $serviceApplyRuleId; + $this->uuid = $uuid; + } + + public static function find(IcingaHost $host, $serviceName) + { + $matcher = HostApplyMatches::prepare($host); + $connection = $host->getConnection(); + foreach (static::fetchApplyRulesByServiceName($connection, $serviceName) as $rule) { + if ($matcher->matchesFilter($rule->filter)) { + return new static($host->getObjectName(), $serviceName, (int) $rule->id, $rule->uuid); + } + } + + return null; + } + + public function getHostName() + { + return $this->hostName; + } + + /** + * @return int + */ + public function getServiceApplyRuleId() + { + return $this->serviceApplyRuleId; + } + + public function getName() + { + return $this->serviceName; + } + + public function getUuid() + { + return $this->uuid; + } + + public function getUrl() + { + return Url::fromPath('director/host/appliedservice', [ + 'name' => $this->hostName, + 'service_id' => $this->serviceApplyRuleId, + ]); + } + + public function requiresOverrides() + { + return true; + } + + protected static function fetchApplyRulesByServiceName(Db $connection, $serviceName) + { + $db = $connection->getDbAdapter(); + $query = $db->select() + ->from(['s' => 'icinga_service'], [ + 'id' => 's.id', + 'uuid' => 's.uuid', + 'name' => 's.object_name', + 'assign_filter' => 's.assign_filter', + ]) + ->where('object_name = ?', $serviceName) + ->where('object_type = ? AND assign_filter IS NOT NULL', 'apply'); + + $allRules = $db->fetchAll($query); + foreach ($allRules as $rule) { + $rule->uuid = Uuid::fromBytes(Db\DbUtil::binaryResult($rule->uuid)); + $rule->filter = Filter::fromQueryString($rule->assign_filter); + } + + return $allRules; + } +} diff --git a/library/Director/DirectorObject/Lookup/AppliedServiceSetServiceInfo.php b/library/Director/DirectorObject/Lookup/AppliedServiceSetServiceInfo.php new file mode 100644 index 0000000..b5785d5 --- /dev/null +++ b/library/Director/DirectorObject/Lookup/AppliedServiceSetServiceInfo.php @@ -0,0 +1,127 @@ +<?php + +namespace Icinga\Module\Director\DirectorObject\Lookup; + +use gipfl\IcingaWeb2\Url; +use Icinga\Data\Filter\Filter; +use Icinga\Module\Director\Db; +use Icinga\Module\Director\Objects\HostApplyMatches; +use Icinga\Module\Director\Objects\IcingaHost; +use Ramsey\Uuid\Uuid; +use Ramsey\Uuid\UuidInterface; + +/** + * A Service that makes part of a Service Set Apply Rule matching this Host, + * generating a Service with the given name + */ +class AppliedServiceSetServiceInfo implements ServiceInfo +{ + /** @var string */ + protected $hostName; + + /** @var string */ + protected $serviceName; + + /** @var string */ + protected $serviceSetName; + + /** @var UuidInterface */ + protected $uuid; + + public function __construct($hostName, $serviceName, $serviceSetName, UuidInterface $uuid) + { + $this->hostName = $hostName; + $this->serviceName = $serviceName; + $this->serviceSetName = $serviceSetName; + $this->uuid = $uuid; + } + + public static function find(IcingaHost $host, $serviceName) + { + $matcher = HostApplyMatches::prepare($host); + $connection = $host->getConnection(); + foreach (static::fetchServiceSetApplyRulesByServiceName($connection, $host->get('id'), $serviceName) as $rule) { + if ($matcher->matchesFilter($rule->filter)) { + return new static( + $host->getObjectName(), + $serviceName, + $rule->service_set_name, + $rule->uuid + ); + } + } + + return null; + } + + public function getHostName() + { + return $this->hostName; + } + + public function getUuid() + { + return $this->uuid; + } + + /** + * @return string + */ + public function getServiceSetName() + { + return $this->serviceSetName; + } + + public function getName() + { + return $this->serviceName; + } + + public function getUrl() + { + return Url::fromPath('director/host/servicesetservice', [ + 'name' => $this->hostName, + 'service' => $this->serviceName, + 'set' => $this->serviceSetName, + ]); + } + + public function requiresOverrides() + { + return true; + } + + protected static function fetchServiceSetApplyRulesByServiceName(Db $connection, $hostId, $serviceName) + { + $db = $connection->getDbAdapter(); + $query = $db->select() + ->from(['s' => 'icinga_service'], [ + 'id' => 's.id', + 'uuid' => 'ss.uuid', + 'name' => 's.object_name', + 'assign_filter' => 'ss.assign_filter', + 'service_set_name' => 'ss.object_name', + ]) + ->join( + ['ss' => 'icinga_service_set'], + 's.service_set_id = ss.id', + [] + ) + ->where('s.object_name = ?', $serviceName) + ->where('ss.assign_filter IS NOT NULL') + ->where( // Ignore deactivated Services: + 'NOT EXISTS (SELECT 1 FROM icinga_host_service_blacklist hsb' + . ' WHERE hsb.host_id = ? AND hsb.service_id = s.id)', + (int) $hostId + ); + ; + + $allRules = $db->fetchAll($query); + foreach ($allRules as $rule) { + $rule->uuid = Uuid::fromBytes(Db\DbUtil::binaryResult($rule->uuid)); + $rule->filter = Filter::fromQueryString($rule->assign_filter); + } + + return $allRules; + } +} diff --git a/library/Director/DirectorObject/Lookup/InheritedServiceInfo.php b/library/Director/DirectorObject/Lookup/InheritedServiceInfo.php new file mode 100644 index 0000000..875d5fb --- /dev/null +++ b/library/Director/DirectorObject/Lookup/InheritedServiceInfo.php @@ -0,0 +1,94 @@ +<?php + +namespace Icinga\Module\Director\DirectorObject\Lookup; + +use gipfl\IcingaWeb2\Url; +use Icinga\Module\Director\Objects\IcingaHost; +use Icinga\Module\Director\Objects\IcingaService; +use Icinga\Module\Director\Repository\IcingaTemplateRepository; +use Ramsey\Uuid\UuidInterface; + +/** + * A Service attached to a parent Service Template. This is a shortcut for + * 'assign where "Template Name" in templates' + */ +class InheritedServiceInfo implements ServiceInfo +{ + /** @var string */ + protected $hostName; + + /** @var string */ + protected $hostTemplateName; + + /** @var string */ + protected $serviceName; + + /** @var UuidInterface */ + protected $uuid; + + public function __construct($hostName, $hostTemplateName, $serviceName, UuidInterface $uuid) + { + $this->hostName = $hostName; + $this->hostTemplateName = $hostTemplateName; + $this->serviceName= $serviceName; + $this->uuid = $uuid; + } + + public static function find(IcingaHost $host, $serviceName) + { + $db = $host->getConnection(); + foreach (IcingaTemplateRepository::instanceByObject($host)->getTemplatesFor($host, true) as $parent) { + $key = [ + 'host_id' => $parent->get('id'), + 'object_name' => $serviceName + ]; + if (IcingaService::exists($key, $db)) { + return new static( + $host->getObjectName(), + $parent->getObjectName(), + $serviceName, + IcingaService::load($key, $db)->getUniqueId() + ); + } + } + + return false; + } + + public function getHostName() + { + return $this->hostName; + } + + public function getUuid() + { + return $this->uuid; + } + + /** + * @return string + */ + public function getHostTemplateName() + { + return $this->hostTemplateName; + } + + public function getName() + { + return $this->serviceName; + } + + public function getUrl() + { + return Url::fromPath('director/host/inheritedservice', [ + 'name' => $this->hostName, + 'service' => $this->serviceName, + 'inheritedFrom' => $this->hostTemplateName + ]); + } + + public function requiresOverrides() + { + return true; + } +} diff --git a/library/Director/DirectorObject/Lookup/ServiceFinder.php b/library/Director/DirectorObject/Lookup/ServiceFinder.php new file mode 100644 index 0000000..fb8d74c --- /dev/null +++ b/library/Director/DirectorObject/Lookup/ServiceFinder.php @@ -0,0 +1,79 @@ +<?php + +namespace Icinga\Module\Director\DirectorObject\Lookup; + +use gipfl\IcingaWeb2\Url; +use Icinga\Authentication\Auth; +use Icinga\Module\Director\Objects\HostApplyMatches; +use Icinga\Module\Director\Objects\IcingaHost; +use RuntimeException; + +class ServiceFinder +{ + /** @var IcingaHost */ + protected $host; + + /** @var ?Auth */ + protected $auth; + + /** @var IcingaHost[] */ + protected $parents; + + /** @var HostApplyMatches */ + protected $applyMatcher; + + /** @var \Icinga\Module\Director\Db */ + protected $db; + + public function __construct(IcingaHost $host, Auth $auth = null) + { + $this->host = $host; + $this->auth = $auth; + $this->db = $host->getConnection(); + } + + public static function find(IcingaHost $host, $serviceName) + { + foreach ([ + SingleServiceInfo::class, + InheritedServiceInfo::class, + ServiceSetServiceInfo::class, + AppliedServiceInfo::class, + AppliedServiceSetServiceInfo::class, + ] as $class) { + /** @var ServiceInfo $class */ + if ($info = $class::find($host, $serviceName)) { + return $info; + } + } + + return false; + } + + /** + * @param $serviceName + * @return Url + */ + public function getRedirectionUrl($serviceName) + { + if ($this->auth === null) { + throw new RuntimeException('Auth is required for ServiceFinder when dealing when asking for URLs'); + } + if ($this->auth->hasPermission('director/host')) { + if ($info = $this::find($this->host, $serviceName)) { + return $info->getUrl(); + } + } + if ($this->auth->hasPermission('director/monitoring/services-ro')) { + return Url::fromPath('director/host/servicesro', [ + 'name' => $this->host->getObjectName(), + 'service' => $serviceName + ]); + } + + return Url::fromPath('director/host/invalidservice', [ + 'name' => $this->host->getObjectName(), + 'service' => $serviceName, + ]); + } +} diff --git a/library/Director/DirectorObject/Lookup/ServiceInfo.php b/library/Director/DirectorObject/Lookup/ServiceInfo.php new file mode 100644 index 0000000..3c8c51b --- /dev/null +++ b/library/Director/DirectorObject/Lookup/ServiceInfo.php @@ -0,0 +1,46 @@ +<?php + +namespace Icinga\Module\Director\DirectorObject\Lookup; + +use gipfl\IcingaWeb2\Url; +use Icinga\Module\Director\Objects\IcingaHost; +use Ramsey\Uuid\UuidInterface; + +interface ServiceInfo +{ + /** + * The final Service name + * + * @return string + */ + public function getName(); + + /** + * The host the final (rendered, processed) Service belongs to + * + * @return string + */ + public function getHostName(); + + /** + * @return Url + */ + public function getUrl(); + + /** + * @return UuidInterface + */ + public function getUuid(); + + /** + * @return bool + */ + public function requiresOverrides(); + + /** + * @param IcingaHost $host + * @param $serviceName + * @return ServiceInfo|false + */ + public static function find(IcingaHost $host, $serviceName); +} diff --git a/library/Director/DirectorObject/Lookup/ServiceSetServiceInfo.php b/library/Director/DirectorObject/Lookup/ServiceSetServiceInfo.php new file mode 100644 index 0000000..a980da8 --- /dev/null +++ b/library/Director/DirectorObject/Lookup/ServiceSetServiceInfo.php @@ -0,0 +1,121 @@ +<?php + +namespace Icinga\Module\Director\DirectorObject\Lookup; + +use gipfl\IcingaWeb2\Url; +use Icinga\Module\Director\Objects\IcingaHost; +use Icinga\Module\Director\Repository\IcingaTemplateRepository; +use Ramsey\Uuid\Uuid; +use Ramsey\Uuid\UuidInterface; + +/** + * A service belonging to a Service Set, attached either directly to the given + * Host or to one of it's inherited Host Templates + */ +class ServiceSetServiceInfo implements ServiceInfo +{ + /** @var string */ + protected $hostName; + + /** @var string */ + protected $serviceName; + + /** @var string */ + protected $serviceSetName; + + /** @var UuidInterface */ + protected $uuid; + + public function __construct($hostName, $serviceName, $serviceSetName, UuidInterface $uuid) + { + $this->hostName = $hostName; + $this->serviceName = $serviceName; + $this->serviceSetName = $serviceSetName; + $this->uuid = $uuid; + } + + public static function find(IcingaHost $host, $serviceName) + { + $ids = [$host->get('id')]; + + foreach (IcingaTemplateRepository::instanceByObject($host)->getTemplatesFor($host, true) as $parent) { + $ids[] = $parent->get('id'); + } + + $db = $host->getConnection()->getDbAdapter(); + $query = $db->select() + ->from( + ['s' => 'icinga_service'], + [ + 'service_set_name' => 'ss.object_name', + 'uuid' => 's.uuid', + ] + )->join( + ['ss' => 'icinga_service_set'], + 's.service_set_id = ss.id', + [] + )->join( + ['hsi' => 'icinga_service_set_inheritance'], + 'hsi.parent_service_set_id = ss.id', + [] + )->join( + ['hs' => 'icinga_service_set'], + 'hs.id = hsi.service_set_id', + [] + )->where('hs.host_id IN (?)', $ids) + ->where('s.object_name = ?', $serviceName) + ->where( // Ignore deactivated Services: + 'NOT EXISTS (SELECT 1 FROM icinga_host_service_blacklist hsb' + . ' WHERE hsb.host_id = ? AND hsb.service_id = s.id)', + (int) $host->get('id') + ); + + if ($row = $db->fetchRow($query)) { + return new static( + $host->getObjectName(), + $serviceName, + $row->service_set_name, + Uuid::fromBytes($row->uuid) + ); + } + + return null; + } + + public function getHostName() + { + return $this->hostName; + } + + public function getName() + { + return $this->serviceName; + } + + public function getUuid() + { + return $this->uuid; + } + + /** + * @return string + */ + public function getServiceSetName() + { + return $this->serviceSetName; + } + + public function getUrl() + { + return Url::fromPath('director/host/servicesetservice', [ + 'name' => $this->hostName, + 'service' => $this->serviceName, + 'set' => $this->serviceSetName, + ]); + } + + public function requiresOverrides() + { + return true; + } +} diff --git a/library/Director/DirectorObject/Lookup/SingleServiceInfo.php b/library/Director/DirectorObject/Lookup/SingleServiceInfo.php new file mode 100644 index 0000000..af54fc7 --- /dev/null +++ b/library/Director/DirectorObject/Lookup/SingleServiceInfo.php @@ -0,0 +1,83 @@ +<?php + +namespace Icinga\Module\Director\DirectorObject\Lookup; + +use gipfl\IcingaWeb2\Url; +use Icinga\Module\Director\Objects\IcingaHost; +use Icinga\Module\Director\Objects\IcingaService; +use Ramsey\Uuid\UuidInterface; + +/** + * A single service, directly attached to a Host Object. Overrides might + * still be used when use_var_overrides is true. + */ +class SingleServiceInfo implements ServiceInfo +{ + /** @var string */ + protected $hostName; + + /** @var string */ + protected $serviceName; + + /** @var bool */ + protected $useOverrides; + + /** @var UuidInterface */ + protected $uuid; + + public function __construct($hostName, $serviceName, UuidInterface $uuid, $useOverrides) + { + $this->hostName = $hostName; + $this->serviceName = $serviceName; + $this->useOverrides = $useOverrides; + $this->uuid = $uuid; + } + + public static function find(IcingaHost $host, $serviceName) + { + $keyParams = [ + 'host_id' => $host->get('id'), + 'object_name' => $serviceName + ]; + $connection = $host->getConnection(); + if (IcingaService::exists($keyParams, $connection)) { + $service = IcingaService::load($keyParams, $connection); + $useOverrides = $service->getResolvedVar('use_var_overrides') === 'y'; + + return new static($host->getObjectName(), $serviceName, $service->getUniqueId(), $useOverrides); + } + + return false; + } + + public function getHostName() + { + return $this->hostName; + } + + public function getName() + { + return $this->serviceName; + } + + /** + * @return UuidInterface + */ + public function getUuid() + { + return $this->uuid; + } + + public function getUrl() + { + return Url::fromPath('director/service/edit', [ + 'host' => $this->hostName, + 'name' => $this->serviceName, + ]); + } + + public function requiresOverrides() + { + return $this->useOverrides; + } +} |