2015-04-24 15:57:01 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace Icinga\Module\Director\Objects;
|
|
|
|
|
2015-06-11 19:18:47 +02:00
|
|
|
use Icinga\Module\Director\CustomVariable\CustomVariables;
|
2015-04-24 15:57:01 +02:00
|
|
|
use Icinga\Module\Director\Data\Db\DbObject;
|
2015-06-16 17:58:47 +02:00
|
|
|
use Icinga\Module\Director\IcingaConfig\IcingaConfigRenderer;
|
2015-06-11 22:44:17 +02:00
|
|
|
use Icinga\Module\Director\IcingaConfig\IcingaConfigHelper as c;
|
2015-06-08 14:37:33 +02:00
|
|
|
use Icinga\Exception\ProgrammingError;
|
|
|
|
use Exception;
|
2015-04-24 15:57:01 +02:00
|
|
|
|
2015-06-16 17:58:47 +02:00
|
|
|
abstract class IcingaObject extends DbObject implements IcingaConfigRenderer
|
2015-04-24 15:57:01 +02:00
|
|
|
{
|
2015-07-02 14:31:35 +02:00
|
|
|
protected $keyName = 'object_name';
|
2015-04-24 15:57:01 +02:00
|
|
|
|
|
|
|
protected $autoincKeyName = 'id';
|
|
|
|
|
2015-06-08 13:02:09 +02:00
|
|
|
protected $supportsCustomVars = false;
|
|
|
|
|
2015-06-16 17:58:47 +02:00
|
|
|
protected $supportsGroups = false;
|
|
|
|
|
2015-07-01 15:15:49 +02:00
|
|
|
protected $supportsRanges = false;
|
|
|
|
|
2015-06-26 10:39:30 +02:00
|
|
|
protected $supportsImports = false;
|
|
|
|
|
2015-06-08 14:37:33 +02:00
|
|
|
private $type;
|
|
|
|
|
2015-06-11 19:46:36 +02:00
|
|
|
private $vars;
|
|
|
|
|
2015-06-16 17:58:47 +02:00
|
|
|
private $groups;
|
|
|
|
|
2015-06-26 10:39:30 +02:00
|
|
|
private $imports;
|
|
|
|
|
2015-07-02 14:51:59 +02:00
|
|
|
private $importedObjects;
|
|
|
|
|
2015-07-01 15:15:49 +02:00
|
|
|
private $ranges;
|
|
|
|
|
2015-06-08 13:02:09 +02:00
|
|
|
public function supportsCustomVars()
|
|
|
|
{
|
|
|
|
return $this->supportsCustomVars;
|
|
|
|
}
|
|
|
|
|
2015-06-16 17:58:47 +02:00
|
|
|
public function supportsGroups()
|
|
|
|
{
|
|
|
|
return $this->supportsGroups;
|
|
|
|
}
|
|
|
|
|
2015-07-01 15:15:49 +02:00
|
|
|
public function supportsRanges()
|
|
|
|
{
|
|
|
|
return $this->supportsRanges;
|
|
|
|
}
|
|
|
|
|
2015-06-26 10:39:30 +02:00
|
|
|
public function supportsImports()
|
|
|
|
{
|
|
|
|
return $this->supportsImports;
|
|
|
|
}
|
|
|
|
|
2015-06-24 10:13:06 +02:00
|
|
|
public function hasBeenModified()
|
|
|
|
{
|
|
|
|
if ($this->supportsCustomVars() && $this->vars !== null && $this->vars()->hasBeenModified()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-06-24 11:25:22 +02:00
|
|
|
if ($this->supportsGroups() && $this->groups !== null && $this->groups()->hasBeenModified()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-06-26 10:39:30 +02:00
|
|
|
if ($this->supportsImports() && $this->imports !== null && $this->imports()->hasBeenModified()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-07-01 15:15:49 +02:00
|
|
|
if ($this->supportsRanges() && $this->ranges !== null && $this->ranges()->hasBeenModified()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-06-24 10:13:06 +02:00
|
|
|
return parent::hasBeenModified();
|
|
|
|
}
|
|
|
|
|
2015-06-16 17:58:47 +02:00
|
|
|
public function groups()
|
|
|
|
{
|
|
|
|
$this->assertGroupsSupport();
|
|
|
|
if ($this->groups === null) {
|
|
|
|
if ($this->hasBeenLoadedFromDb()) {
|
|
|
|
$this->groups = IcingaObjectGroups::loadForStoredObject($this);
|
|
|
|
} else {
|
|
|
|
$this->groups = new IcingaObjectGroups($this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->groups;
|
|
|
|
}
|
|
|
|
|
2015-07-01 15:15:49 +02:00
|
|
|
public function ranges()
|
|
|
|
{
|
|
|
|
$this->assertRangesSupport();
|
|
|
|
if ($this->ranges === null) {
|
|
|
|
if ($this->hasBeenLoadedFromDb()) {
|
|
|
|
$this->ranges = IcingaTimePeriodRanges::loadForStoredObject($this);
|
|
|
|
} else {
|
|
|
|
$this->ranges = new IcingaTimePeriodRanges($this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->ranges;
|
|
|
|
}
|
|
|
|
|
2015-06-26 10:39:30 +02:00
|
|
|
public function imports()
|
|
|
|
{
|
|
|
|
$this->assertImportsSupport();
|
|
|
|
if ($this->imports === null) {
|
|
|
|
if ($this->hasBeenLoadedFromDb()) {
|
|
|
|
$this->imports = IcingaObjectImports::loadForStoredObject($this);
|
|
|
|
} else {
|
|
|
|
$this->imports = new IcingaObjectImports($this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->imports;
|
|
|
|
}
|
|
|
|
|
2015-07-02 14:51:59 +02:00
|
|
|
// TODO: what happens if imports change at runtime?
|
|
|
|
public function importedObjects()
|
|
|
|
{
|
|
|
|
$this->assertImportsSupport();
|
|
|
|
if ($this->importedObjects === null) {
|
|
|
|
$this->importedObjects = array();
|
|
|
|
foreach ($this->imports()->listImportNames() as $import) {
|
|
|
|
$this->importedObjects[$import] = self::load($import, $this->connection);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->importedObjects;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getResolvedProperties()
|
|
|
|
{
|
|
|
|
$res = $this->resolveProperties();
|
|
|
|
return $res['_MERGED_'];
|
|
|
|
}
|
|
|
|
|
|
|
|
public function resolveProperties()
|
|
|
|
{
|
|
|
|
$props = array();
|
|
|
|
$props['_MERGED_'] = (object) array();
|
|
|
|
$objects = $this->importedObjects();
|
|
|
|
|
|
|
|
$objects[$this->object_name] = $this;
|
|
|
|
$blacklist = array('id', 'object_type', 'object_name');
|
|
|
|
foreach ($objects as $name => $object) {
|
|
|
|
$props[$name] = (object) array();
|
|
|
|
if ($name === $this->object_name) {
|
|
|
|
$pprops = $object->getProperties();
|
|
|
|
} else {
|
|
|
|
$pprops = $object->getResolvedProperties();
|
|
|
|
}
|
|
|
|
foreach ($pprops as $key => $value) {
|
|
|
|
if (in_array($key, $blacklist)) continue;
|
|
|
|
if ($value !== null) {
|
|
|
|
$props[$name]->$key = $value;
|
|
|
|
$props['_MERGED_']->$key = $value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $props;
|
|
|
|
}
|
|
|
|
|
2015-06-11 19:18:47 +02:00
|
|
|
protected function assertCustomVarsSupport()
|
|
|
|
{
|
|
|
|
if (! $this->supportsCustomVars()) {
|
|
|
|
throw new ProgrammingError(
|
|
|
|
'Objects of type "%s" have no custom vars',
|
|
|
|
$this->getType()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2015-06-16 17:58:47 +02:00
|
|
|
protected function assertGroupsSupport()
|
|
|
|
{
|
|
|
|
if (! $this->supportsGroups()) {
|
|
|
|
throw new ProgrammingError(
|
|
|
|
'Objects of type "%s" have no groups',
|
|
|
|
$this->getType()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2015-07-01 15:15:49 +02:00
|
|
|
protected function assertRangesSupport()
|
|
|
|
{
|
|
|
|
if (! $this->supportsRanges()) {
|
|
|
|
throw new ProgrammingError(
|
|
|
|
'Objects of type "%s" have no ranges',
|
|
|
|
$this->getType()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2015-06-26 10:39:30 +02:00
|
|
|
protected function assertImportsSupport()
|
|
|
|
{
|
|
|
|
if (! $this->supportsImports()) {
|
|
|
|
throw new ProgrammingError(
|
|
|
|
'Objects of type "%s" have no imports',
|
|
|
|
$this->getType()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2015-06-11 19:18:47 +02:00
|
|
|
public function vars()
|
|
|
|
{
|
|
|
|
$this->assertCustomVarsSupport();
|
|
|
|
if ($this->vars === null) {
|
2015-06-15 16:35:18 +02:00
|
|
|
if ($this->hasBeenLoadedFromDb()) {
|
|
|
|
$this->vars = CustomVariables::loadForStoredObject($this);
|
|
|
|
} else {
|
|
|
|
$this->vars = new CustomVariables();
|
|
|
|
}
|
2015-06-11 19:18:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return $this->vars;
|
|
|
|
}
|
|
|
|
|
2015-06-15 16:35:18 +02:00
|
|
|
public function getVarsTableName()
|
|
|
|
{
|
|
|
|
return $this->getTableName() . '_var';
|
|
|
|
}
|
|
|
|
|
2015-06-16 17:58:47 +02:00
|
|
|
public function getShortTableName()
|
2015-06-15 16:35:18 +02:00
|
|
|
{
|
|
|
|
// strlen('icinga_') = 7
|
2015-06-16 17:58:47 +02:00
|
|
|
return substr($this->getTableName(), 7);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getVarsIdColumn()
|
|
|
|
{
|
|
|
|
return $this->getShortTableName() . '_id';
|
2015-06-15 16:35:18 +02:00
|
|
|
}
|
|
|
|
|
2015-06-08 13:02:09 +02:00
|
|
|
public function isTemplate()
|
|
|
|
{
|
2015-06-08 14:37:33 +02:00
|
|
|
return $this->hasProperty('object_type')
|
2015-06-08 13:02:09 +02:00
|
|
|
&& $this->object_type === 'template';
|
|
|
|
}
|
|
|
|
|
|
|
|
public function isApplyRule()
|
|
|
|
{
|
2015-06-08 14:37:33 +02:00
|
|
|
return $this->hasProperty('object_type')
|
2015-06-08 13:02:09 +02:00
|
|
|
&& $this->object_type === 'apply';
|
|
|
|
}
|
|
|
|
|
2015-04-24 15:57:01 +02:00
|
|
|
public function onInsert()
|
|
|
|
{
|
2015-07-01 15:15:49 +02:00
|
|
|
$this->storeCustomVars()->storeGroups()->storeImports()->storeRanges();
|
2015-04-24 15:57:01 +02:00
|
|
|
DirectorActivityLog::logCreation($this, $this->connection);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function onUpdate()
|
|
|
|
{
|
2015-07-01 15:15:49 +02:00
|
|
|
$this->storeCustomVars()->storeGroups()->storeImports()->storeRanges();
|
2015-04-24 15:57:01 +02:00
|
|
|
DirectorActivityLog::logModification($this, $this->connection);
|
|
|
|
}
|
|
|
|
|
2015-06-24 10:13:06 +02:00
|
|
|
protected function storeCustomVars()
|
|
|
|
{
|
|
|
|
if ($this->supportsCustomVars()) {
|
2015-06-24 11:25:22 +02:00
|
|
|
$this->vars !== null && $this->vars()->storeToDb($this);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function storeGroups()
|
|
|
|
{
|
|
|
|
if ($this->supportsGroups()) {
|
|
|
|
$this->groups !== null && $this->groups()->store();
|
2015-06-24 10:13:06 +02:00
|
|
|
}
|
|
|
|
|
2015-06-26 15:55:16 +02:00
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2015-07-01 15:15:49 +02:00
|
|
|
protected function storeRanges()
|
|
|
|
{
|
|
|
|
if ($this->supportsRanges()) {
|
|
|
|
$this->ranges !== null && $this->ranges()->store();
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2015-06-26 15:55:16 +02:00
|
|
|
protected function storeImports()
|
|
|
|
{
|
|
|
|
if ($this->supportsImports()) {
|
|
|
|
$this->imports !== null && $this->imports()->store();
|
|
|
|
}
|
|
|
|
|
2015-06-24 10:13:06 +02:00
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2015-04-24 15:57:01 +02:00
|
|
|
public function onDelete()
|
|
|
|
{
|
|
|
|
DirectorActivityLog::logRemoval($this, $this->connection);
|
|
|
|
}
|
2015-06-08 14:37:33 +02:00
|
|
|
|
|
|
|
protected function renderImports()
|
|
|
|
{
|
|
|
|
// TODO: parent_host ORDERed by weigth...
|
2015-06-26 10:39:30 +02:00
|
|
|
if ($this->supportsImports()) {
|
|
|
|
return $this->imports()->toConfigString();
|
|
|
|
} else {
|
|
|
|
return '';
|
|
|
|
}
|
2015-06-08 14:37:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
protected function renderProperties()
|
|
|
|
{
|
|
|
|
$out = '';
|
|
|
|
$blacklist = array(
|
|
|
|
'id',
|
|
|
|
'object_name',
|
|
|
|
'object_type',
|
|
|
|
);
|
|
|
|
|
|
|
|
foreach ($this->properties as $key => $value) {
|
|
|
|
|
|
|
|
if ($value === null) continue;
|
|
|
|
if (in_array($key, $blacklist)) continue;
|
|
|
|
|
|
|
|
$method = 'render' . ucfirst($key);
|
|
|
|
if (method_exists($this, $method)) {
|
|
|
|
$out .= $this->$method($value);
|
|
|
|
} else {
|
2015-06-11 23:02:43 +02:00
|
|
|
$out .= c::renderKeyValue($key, c::renderString($value));
|
2015-06-08 14:37:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $out;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function renderBooleanProperty($key)
|
|
|
|
{
|
2015-06-11 23:02:43 +02:00
|
|
|
return c::renderKeyValue($key, c::renderBoolean($this->$key));
|
2015-06-08 14:37:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
protected function renderSuffix()
|
|
|
|
{
|
2015-06-11 22:49:06 +02:00
|
|
|
return "}\n\n";
|
2015-06-08 14:37:33 +02:00
|
|
|
}
|
|
|
|
|
2015-06-10 15:40:45 +02:00
|
|
|
/**
|
|
|
|
* @return string
|
|
|
|
*/
|
2015-06-08 14:37:33 +02:00
|
|
|
protected function renderCustomVars()
|
|
|
|
{
|
|
|
|
if ($this->supportsCustomVars()) {
|
2015-06-15 14:23:15 +02:00
|
|
|
return $this->vars()->toConfigString();
|
|
|
|
} else {
|
|
|
|
return '';
|
2015-06-08 14:37:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-16 17:58:47 +02:00
|
|
|
/**
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
protected function renderGroups()
|
|
|
|
{
|
|
|
|
if ($this->supportsGroups()) {
|
|
|
|
return $this->groups()->toConfigString();
|
|
|
|
} else {
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-01 15:15:49 +02:00
|
|
|
/**
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
protected function renderRanges()
|
|
|
|
{
|
|
|
|
if ($this->supportsRanges()) {
|
|
|
|
return $this->ranges()->toConfigString();
|
|
|
|
} else {
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-08 14:37:33 +02:00
|
|
|
protected function renderCommandProperty($commandId, $propertyName = 'check_command')
|
|
|
|
{
|
2015-06-11 07:44:22 +02:00
|
|
|
return c::renderKeyValue(
|
2015-06-08 14:37:33 +02:00
|
|
|
$propertyName,
|
2015-06-11 23:02:43 +02:00
|
|
|
c::renderString($this->connection->getCommandName($commandId))
|
2015-06-08 14:37:33 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function renderZoneProperty($zoneId, $propertyName = 'zone')
|
|
|
|
{
|
2015-06-11 07:44:22 +02:00
|
|
|
return c::renderKeyValue(
|
2015-06-08 14:37:33 +02:00
|
|
|
$propertyName,
|
2015-06-11 23:02:43 +02:00
|
|
|
c::renderString($this->connection->getZoneName($zoneId))
|
2015-06-08 14:37:33 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function renderZone_id()
|
|
|
|
{
|
|
|
|
return $this->renderZoneProperty($this->zone_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function renderObjectHeader()
|
|
|
|
{
|
|
|
|
return sprintf(
|
|
|
|
"%s %s %s {\n",
|
|
|
|
$this->getObjectTypeName(),
|
|
|
|
$this->getType(),
|
2015-06-11 07:44:22 +02:00
|
|
|
c::renderString($this->getObjectName())
|
2015-06-08 14:37:33 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function toConfigString()
|
|
|
|
{
|
|
|
|
return implode(array(
|
|
|
|
$this->renderObjectHeader(),
|
|
|
|
$this->renderImports(),
|
|
|
|
$this->renderProperties(),
|
2015-07-01 15:15:49 +02:00
|
|
|
$this->renderRanges(),
|
2015-06-16 17:58:47 +02:00
|
|
|
$this->renderGroups(),
|
2015-06-08 14:37:33 +02:00
|
|
|
$this->renderCustomVars(),
|
|
|
|
$this->renderSuffix()
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2015-06-30 11:19:31 +02:00
|
|
|
public function isGroup()
|
|
|
|
{
|
|
|
|
return substr($this->getType(), -5) === 'Group';
|
|
|
|
}
|
|
|
|
|
2015-06-08 14:37:33 +02:00
|
|
|
protected function getType()
|
|
|
|
{
|
|
|
|
if ($this->type === null) {
|
|
|
|
$parts = explode('\\', get_class($this));
|
|
|
|
// 6 = strlen('Icinga');
|
|
|
|
$this->type = substr(end($parts), 6);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->type;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function getObjectTypeName()
|
|
|
|
{
|
|
|
|
if ($this->isTemplate()) {
|
|
|
|
return 'template';
|
|
|
|
} elseif ($this->isApplyRule()) {
|
|
|
|
return 'apply';
|
|
|
|
} else {
|
|
|
|
return 'object';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function getObjectName()
|
|
|
|
{
|
|
|
|
if ($this->hasProperty('object_name')) {
|
|
|
|
return $this->object_name;
|
|
|
|
} else {
|
|
|
|
// TODO: replace with an exception once finished
|
|
|
|
return 'ERROR: NO NAME';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function __toString()
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
return $this->toConfigString();
|
|
|
|
} catch (Exception $e) {
|
|
|
|
trigger_error($e);
|
|
|
|
$previousHandler = set_exception_handler(function () {});
|
|
|
|
restore_error_handler();
|
2015-06-15 16:36:51 +02:00
|
|
|
if ($previousHandler !== null) {
|
|
|
|
call_user_func($previousHandler, $e);
|
|
|
|
die();
|
|
|
|
} else {
|
|
|
|
die($e->getMessage());
|
|
|
|
}
|
2015-06-08 14:37:33 +02:00
|
|
|
}
|
|
|
|
}
|
2015-04-24 15:57:01 +02:00
|
|
|
}
|