null, 'host_id' => null, 'object_name' => null, 'object_type' => null, 'description' => null, 'assign_filter' => null, ); protected $keyName = array('host_id', 'object_name'); protected $supportsImports = true; protected $supportsCustomVars = true; protected $supportsApplyRules = true; protected $supportedInLegacy = true; protected $relations = array( 'host' => 'IcingaHost', ); public function isDisabled() { return false; } public function supportsAssignments() { return true; } protected function setKey($key) { if (is_int($key)) { $this->id = $key; } elseif (is_string($key)) { $keyComponents = preg_split('~!~', $key); if (count($keyComponents) === 1) { $this->set('object_name', $keyComponents[0]); $this->set('object_type', 'template'); } else { throw new IcingaException('Can not parse key: %s', $key); } } else { return parent::setKey($key); } return $this; } /** * @return IcingaService[] */ public function getServiceObjects() { if ($this->get('host_id')) { $imports = $this->imports()->getObjects(); if (empty($imports)) { return array(); } return $this->getServiceObjectsForSet(array_shift($imports)); } else { return $this->getServiceObjectsForSet($this); } } protected function getServiceObjectsForSet(IcingaServiceSet $set) { if ($set->get('id') === null) { return array(); } $connection = $this->getConnection(); $db = $this->getDb(); $ids = $db->fetchCol( $db->select()->from('icinga_service', 'id') ->where('service_set_id = ?', $set->get('id')) ); $services = array(); foreach ($ids as $id) { $service = IcingaService::load(array( 'id' => $id, 'object_type' => 'template' ), $connection); $service->set('service_set', null); $services[$service->getObjectName()] = $service; } return $services; } public function renderToConfig(IcingaConfig $config) { if ($this->get('assign_filter') === null && $this->isTemplate()) { return; } if ($config->isLegacy()) { $this->renderToLegacyConfig($config); return; } $services = $this->getServiceObjects(); if (empty($services)) { return; } $file = $this->getConfigFileWithHeader($config); // Loop over all services belonging to this set // add our assign rules and then add the service to the config // eventually clone them beforehand to not get into trouble with caches // figure out whether we might need a zone property foreach ($services as $service) { if ($filter = $this->get('assign_filter')) { $service->set('object_type', 'apply'); $service->set('assign_filter', $filter); } elseif ($hostId = $this->get('host_id')) { $service->set('object_type', 'object'); $service->set('use_var_overrides', 'y'); $service->set('host_id', $this->get('host_id')); } else { // Service set template without assign filter or host continue; } $this->copyVarsToService($service); $file->addObject($service); } } protected function getConfigFileWithHeader(IcingaConfig $config) { $file = $config->configFile( 'zones.d/' . $this->getRenderingZone($config) . '/servicesets' ); $file->prepend($this->getConfigHeaderComment($config)); return $file; } protected function getConfigHeaderComment(IcingaConfig $config) { if ($config->isLegacy()) { if ($this->get('assign_filter')) { $comment = "## applied Service Set '%s'\n\n"; } else { $comment = "## Service Set '%s' on this host\n\n"; } } else { $comment = "/** Service Set '%s' **/\n\n"; } return sprintf($comment, $this->getObjectName()); } public function copyVarsToService(IcingaService $service) { $serviceVars = $service->vars(); foreach ($this->vars() as $k => $var) { $serviceVars->$k = $var; } return $this; } public function renderToLegacyConfig(IcingaConfig $config) { if ($this->get('assign_filter') === null && $this->isTemplate()) { return; } // evaluate my assign rules once, get related hosts // Loop over all services belonging to this set // generate every service with host_name host1,host2... -> not yet. And Zones? $conn = $this->getConnection(); // Delegating this to the service would look, but this way it's faster if ($filter = $this->get('assign_filter')) { $filter = Filter::fromQueryString($filter); $hosts = HostApplyMatches::forFilter($filter, $conn); foreach ($this->getServiceObjects() as $service) { $service->set('object_type', 'object'); $this->copyVarsToService($service); foreach ($hosts as $hostname) { $file = $this->legacyHostnameServicesFile($hostname, $config); $file->addContent($this->getConfigHeaderComment($config)); $service->set('host', $hostname); $file->addLegacyObject($service); } } } else { foreach ($this->getServiceObjects() as $service) { $service->set('object_type', 'object'); $service->set('host_id', $this->get('host_id')); foreach ($this->vars() as $k => $var) { $service->$k = $var; } $file = $this->legacyRelatedHostFile($service, $config); $file->addContent($this->getConfigHeaderComment($config)); $file->addLegacyObject($service); } } } protected function legacyHostnameServicesFile($hostname, IcingaConfig $config) { $host = IcingaHost::load($hostname, $this->getConnection()); return $config->configFile( 'director/' . $host->getRenderingZone($config) . '/servicesets', '.cfg' ); } protected function legacyRelatedHostFile(IcingaService $service, IcingaConfig $config) { return $config->configFile( 'director/' . $service->getRelated('host')->getRenderingZone($config) . '/servicesets', '.cfg' ); } public function getRenderingZone(IcingaConfig $config = null) { if ($this->get('host_id') === null) { return $this->connection->getDefaultGlobalZoneName(); } else { $host = $this->getRelatedObject('host', $this->get('host_id')); return $host->getRenderingZone($config); } } protected function beforeStore() { parent::beforeStore(); $name = $this->getObjectName(); // checking if template object_name is unique // TODO: Move to IcingaObject if (! $this->hasBeenLoadedFromDb() && $this->isTemplate() && static::exists($name, $this->connection)) { throw new DuplicateKeyException('%s template "%s" already existing in database!', $this->getType(), $name); } } }