getHostObject(); $auth = $this->Auth(); $backend = $this->backend(); if ($this->isServiceAction() && $backend->canModifyService($host->getObjectName(), $this->getParam('service')) ) { return; } if ($this->isServicesReadOnlyAction() && $auth->hasPermission($this->getServicesReadOnlyPermission())) { return; } if ($auth->hasPermission(Permission::HOSTS)) { // faster return; } if ($backend->canModifyHost($host->getObjectName())) { return; } $this->assertPermission(Permission::HOSTS); // complain about default hosts permission } protected function isServicesReadOnlyAction() { return in_array($this->getRequest()->getActionName(), [ 'servicesro', 'findservice', 'invalidservice', ]); } protected function isServiceAction() { return in_array($this->getRequest()->getActionName(), [ 'servicesro', 'findservice', 'invalidservice', 'servicesetservice', 'appliedservice', 'inheritedservice', ]); } /** * @return HostgroupRestriction */ protected function getHostgroupRestriction() { return new HostgroupRestriction($this->db(), $this->Auth()); } public function editAction() { parent::editAction(); $this->addOptionalMonitoringLink(); } public function serviceAction() { $host = $this->getHostObject(); $this->addServicesHeader(); $this->addTitle($this->translate('Add Service to %s'), $host->getObjectName()); $this->content()->add( IcingaAddServiceForm::load() ->setBranch($this->getBranch()) ->setHost($host) ->setDb($this->db()) ->handleRequest() ); } public function servicesetAction() { $host = $this->getHostObject(); $this->addServicesHeader(); $this->addTitle($this->translate('Add Service Set to %s'), $host->getObjectName()); $this->content()->add( IcingaServiceSetForm::load() ->setBranch($this->getBranch()) ->setHost($host) ->setDb($this->db()) ->handleRequest() ); } protected function addServicesHeader() { $host = $this->getHostObject(); $hostname = $host->getObjectName(); $this->tabs()->activate('services'); $this->actions()->add(Link::create( $this->translate('Add service'), 'director/host/service', ['name' => $hostname], ['class' => 'icon-plus'] ))->add(Link::create( $this->translate('Add service set'), 'director/host/serviceset', ['name' => $hostname], ['class' => 'icon-plus'] )); } public function findserviceAction() { $auth = $this->Auth(); $host = $this->getHostObject(); $hostName = $host->getObjectName(); $serviceName = $this->params->get('service'); $info = ServiceFinder::find($host, $serviceName); $backend = $this->backend(); if ($info && $auth->hasPermission(Permission::HOSTS)) { $redirectUrl = $info->getUrl(); } elseif ($info && (($backend instanceof Monitoring && $auth->hasPermission(Permission::MONITORING_HOSTS)) || ($backend instanceof IcingadbBackend && $auth->hasPermission(Permission::ICINGADB_HOSTS)) ) && $backend->canModifyService($hostName, $serviceName) ) { $redirectUrl = $info->getUrl(); } elseif ($auth->hasPermission($this->getServicesReadOnlyPermission())) { $redirectUrl = Url::fromPath('director/host/servicesro', [ 'name' => $hostName, 'service' => $serviceName ]); } else { $redirectUrl = Url::fromPath('director/host/invalidservice', [ 'name' => $hostName, 'service' => $serviceName, ]); } $this->redirectNow($redirectUrl); } /** * @throws \Icinga\Exception\NotFoundError */ public function invalidserviceAction() { if (! $this->showInfoForNonDirectorService()) { $this->content()->add(Hint::error(sprintf( $this->translate('No such service: %s'), $this->params->get('service') ))); } $this->servicesAction(); } protected function showInfoForNonDirectorService() { try { $api = $this->getApiIfAvailable(); if ($api) { $name = $this->params->get('name') . '!' . $this->params->get('service'); $info = $api->getObject($name, 'Services'); if (isset($info->attrs->source_location)) { $source = $info->attrs->source_location; $this->content()->add(Hint::info(Html::sprintf( 'The configuration for this object has not been rendered by' . ' Icinga Director. You can find it on line %s in %s.', Html::tag('strong', null, $source->first_line), Html::tag('strong', null, $source->path) ))); } } return true; } catch (Exception $e) { return false; } } /** * @throws \Icinga\Exception\NotFoundError */ public function servicesAction() { $this->addServicesHeader(); $host = $this->getHostObject(); $this->addTitle($this->translate('Services: %s'), $host->getObjectName()); $branch = $this->getBranch(); $hostHasBeenCreatedInBranch = $branch->isBranch() && $host->get('id'); $content = $this->content(); $table = (new ObjectsTableService($this->db(), $this->Auth())) ->setHost($host) ->setBranch($branch) ->setTitle($this->translate('Individual Service objects')) ->removeQueryLimit(); if (count($table)) { $content->add($table); } /** @var IcingaHost[] $parents */ $parents = IcingaTemplateRepository::instanceByObject($this->object) ->getTemplatesFor($this->object, true); foreach ($parents as $parent) { $table = (new ObjectsTableService($this->db(), $this->Auth())) ->setBranch($branch) ->setHost($parent) ->setInheritedBy($host) ->removeQueryLimit(); if (count($table)) { $content->add( $table->setTitle(sprintf( $this->translate('Inherited from %s'), $parent->getObjectName() )) ); } } if (! $hostHasBeenCreatedInBranch) { $this->addHostServiceSetTables($host); } foreach ($parents as $parent) { $this->addHostServiceSetTables($parent, $host); } $appliedSets = AppliedServiceSetLoader::fetchForHost($host); foreach ($appliedSets as $set) { $title = sprintf($this->translate('%s (Applied Service set)'), $set->getObjectName()); $content->add( IcingaServiceSetServiceTable::load($set) // ->setHost($host) ->setBranch($branch) ->setAffectedHost($host) ->setTitle($title) ->removeQueryLimit() ); } $table = IcingaHostAppliedServicesTable::load($host) ->setTitle($this->translate('Applied services')); if (count($table)) { $content->add($table); } } /** * Hint: this duplicates quite some logic from servicesAction. We might want * to clean this up, but as soon as we store fully resolved Services this * will be obsolete anyways * * @throws \Icinga\Exception\NotFoundError * @throws \Icinga\Security\SecurityException * @throws \Icinga\Exception\MissingParameterException */ public function servicesroAction() { $this->assertPermission($this->getServicesReadOnlyPermission()); $host = $this->getHostObject(); $service = $this->params->getRequired('service'); $db = $this->db(); $branch = $this->getBranch(); $this->controls()->setTabs(new Tabs()); $this->addSingleTab($this->translate('Configuration (read-only)')); $this->addTitle($this->translate('Services on %s'), $host->getObjectName()); $content = $this->content(); $table = (new ObjectsTableService($db, $this->Auth())) ->setHost($host) ->setBranch($branch) ->setReadonly() ->highlightService($service) ->setTitle($this->translate('Individual Service objects')); if (count($table)) { $content->add($table); } /** @var IcingaHost[] $parents */ $parents = IcingaTemplateRepository::instanceByObject($this->object) ->getTemplatesFor($this->object, true); foreach ($parents as $parent) { $table = (new ObjectsTableService($db, $this->Auth())) ->setReadonly() ->setBranch($branch) ->setHost($parent) ->highlightService($service) ->setInheritedBy($host); if (count($table)) { $content->add( $table->setTitle(sprintf( 'Inherited from %s', $parent->getObjectName() )) ); } } $this->addHostServiceSetTables($host); foreach ($parents as $parent) { $this->addHostServiceSetTables($parent, $host, $service); } $appliedSets = AppliedServiceSetLoader::fetchForHost($host); foreach ($appliedSets as $set) { $title = sprintf($this->translate('%s (Applied Service set)'), $set->getObjectName()); $content->add( IcingaServiceSetServiceTable::load($set) // ->setHost($host) ->setBranch($branch) ->setAffectedHost($host) ->setReadonly() ->highlightService($service) ->setTitle($title) ); } $table = IcingaHostAppliedServicesTable::load($host) ->setReadonly() ->highlightService($service) ->setTitle($this->translate('Applied services')); if (count($table)) { $content->add($table); } } /** * @param IcingaHost $host * @param IcingaHost|null $affectedHost */ protected function addHostServiceSetTables(IcingaHost $host, IcingaHost $affectedHost = null, $roService = null) { $db = $this->db(); if ($affectedHost === null) { $affectedHost = $host; } if ($host->get('id') === null) { return; } $query = $db->getDbAdapter()->select() ->from( array('ss' => 'icinga_service_set'), 'ss.*' )->join( array('hsi' => 'icinga_service_set_inheritance'), 'hsi.parent_service_set_id = ss.id', array() )->join( array('hs' => 'icinga_service_set'), 'hs.id = hsi.service_set_id', array() )->where('hs.host_id = ?', $host->get('id')); $sets = IcingaServiceSet::loadAll($db, $query, 'object_name'); /** @var IcingaServiceSet $set*/ foreach ($sets as $name => $set) { $title = sprintf($this->translate('%s (Service set)'), $name); $table = IcingaServiceSetServiceTable::load($set) ->setHost($host) ->setBranch($this->getBranch()) ->setAffectedHost($affectedHost) ->removeQueryLimit() ->setTitle($title); if ($roService) { $table->setReadonly()->highlightService($roService); } $this->content()->add($table); } } /** * @throws \Icinga\Exception\NotFoundError */ public function appliedserviceAction() { $db = $this->db(); $host = $this->getHostObject(); $serviceId = $this->params->get('service_id'); $parent = IcingaService::loadWithAutoIncId($serviceId, $db); $serviceName = $parent->getObjectName(); $service = IcingaService::create([ 'imports' => $parent, 'object_type' => 'apply', 'object_name' => $serviceName, 'host_id' => $host->get('id'), 'vars' => $host->getOverriddenServiceVars($serviceName), ], $db); $this->addTitle( $this->translate('Applied service: %s'), $serviceName ); $this->content()->add( IcingaServiceForm::load() ->setDb($db) ->setBranch($this->getBranch()) ->setHost($host) ->setApplyGenerated($parent) ->setObject($service) ->handleRequest() ); $this->commonForServices(); } /** * @throws \Icinga\Exception\NotFoundError */ public function inheritedserviceAction() { $db = $this->db(); $host = $this->getHostObject(); $serviceName = $this->params->get('service'); $from = IcingaHost::load($this->params->get('inheritedFrom'), $this->db()); $parent = IcingaService::load([ 'object_name' => $serviceName, 'host_id' => $from->get('id') ], $this->db()); // TODO: we want to eventually show the host template name, doesn't work // as template resolution would break. // $parent->object_name = $from->object_name; $service = IcingaService::create([ 'object_type' => 'apply', 'object_name' => $serviceName, 'host_id' => $host->get('id'), 'imports' => [$parent], 'vars' => $host->getOverriddenServiceVars($serviceName), ], $db); $this->addTitle($this->translate('Inherited service: %s'), $serviceName); $form = IcingaServiceForm::load() ->setDb($db) ->setBranch($this->getBranch()) ->setHost($host) ->setInheritedFrom($from->getObjectName()) ->setObject($service) ->handleRequest(); $this->content()->add($form); $this->commonForServices(); } /** * @throws \Icinga\Exception\NotFoundError */ public function removesetAction() { // TODO: clean this up, use POST $db = $this->db()->getDbAdapter(); $query = $db->select()->from( array('ss' => 'icinga_service_set'), array('id' => 'ss.id') )->join( array('si' => 'icinga_service_set_inheritance'), 'si.service_set_id = ss.id', array() )->where( 'si.parent_service_set_id = ?', $this->params->get('setId') )->where('ss.host_id = ?', $this->object->get('id')); IcingaServiceSet::loadWithAutoIncId($db->fetchOne($query), $this->db())->delete(); $this->redirectNow( Url::fromPath('director/host/services', array( 'name' => $this->object->getObjectName() )) ); } /** * @throws \Icinga\Exception\NotFoundError */ public function servicesetserviceAction() { $db = $this->db(); $host = $this->getHostObject(); $serviceName = $this->params->get('service'); $setParams = [ 'object_name' => $this->params->get('set'), 'host_id' => $host->get('id') ]; $setTemplate = IcingaServiceSet::load($this->params->get('set'), $db); if (IcingaServiceSet::exists($setParams, $db)) { $set = IcingaServiceSet::load($setParams, $db); } else { $set = $setTemplate; } $service = IcingaService::load([ 'object_name' => $serviceName, 'service_set_id' => $setTemplate->get('id') ], $this->db()); $service = IcingaService::create([ 'id' => $service->get('id'), 'object_type' => 'apply', 'object_name' => $serviceName, 'host_id' => $host->get('id'), 'imports' => $service->listImportNames(), 'vars' => $host->getOverriddenServiceVars($serviceName), ], $db); // $set->copyVarsToService($service); $this->addTitle( $this->translate('%s on %s (from set: %s)'), $serviceName, $host->getObjectName(), $set->getObjectName() ); $form = IcingaServiceForm::load() ->setDb($db) ->setBranch($this->getBranch()) ->setHost($host) ->setServiceSet($set) ->setObject($service) ->handleRequest(); $this->tabs()->activate('services'); $this->content()->add($form); $this->commonForServices(); } protected function commonForServices() { $host = $this->object; $this->actions()->add(Link::create( $this->translate('back'), 'director/host/services', ['name' => $host->getObjectName()], ['class' => 'icon-left-big'] )); $this->tabs()->activate('services'); } /** * @throws \Icinga\Exception\NotFoundError */ public function agentAction() { $selfService = new SelfService($this->getHostObject(), $this->api()); if ($os = $this->params->get('download')) { $selfService->handleLegacyAgentDownloads($os); return; } $selfService->renderTo($this); $this->tabs()->activate('agent'); } protected function addOptionalMonitoringLink() { $host = $this->object; try { $backend = $this->backend(); if ($host instanceof IcingaHost && $host->isObject() && $backend->hasHost($host->getObjectName()) ) { $this->actions()->add( Link::create( $this->translate('Show'), $backend->getHostUrl($host->getObjectName()), null, ['class' => 'icon-globe critical', 'data-base-target' => '_next'] ) ); // Intentionally placed here, show it only for deployed Hosts $this->addOptionalInspectLink(); } } catch (Exception $e) { // Silently ignore errors in the monitoring module } } protected function addOptionalInspectLink() { if (! $this->hasPermission(Permission::INSPECT)) { return; } $this->actions()->add(Link::create( $this->translate('Inspect'), 'director/inspect/object', [ 'type' => 'host', 'plural' => 'hosts', 'name' => $this->object->getObjectName() ], [ 'class' => 'icon-zoom-in', 'data-base-target' => '_next' ] )); } /** * @return ?IcingaHost */ protected function getHostObject() { if ($this->object !== null) { assert($this->object instanceof IcingaHost); } return $this->object; } /** * Get readOnly permission of the service for the current backend * * @return string permission */ protected function getServicesReadOnlyPermission(): string { return $this->backend() instanceof IcingadbBackend ? Permission::ICINGADB_SERVICES_RO : Permission::MONITORING_SERVICES_RO; } }