Sync: tune membership resolver

Also fixes error on host creation

refs #832
This commit is contained in:
Thomas Gelf 2017-03-14 14:21:15 +01:00
parent 3cb38596c0
commit 5ae7997f9d
5 changed files with 138 additions and 15 deletions

View File

@ -6,6 +6,9 @@ use Exception;
use Icinga\Data\Filter\Filter; use Icinga\Data\Filter\Filter;
use Icinga\Module\Director\Db; use Icinga\Module\Director\Db;
use Icinga\Module\Director\Db\Cache\PrefetchCache; use Icinga\Module\Director\Db\Cache\PrefetchCache;
use Icinga\Module\Director\Objects\HostGroupMembershipResolver;
use Icinga\Module\Director\Objects\IcingaHost;
use Icinga\Module\Director\Objects\IcingaHostGroup;
use Icinga\Module\Director\Objects\IcingaObject; use Icinga\Module\Director\Objects\IcingaObject;
use Icinga\Module\Director\Objects\ImportSource; use Icinga\Module\Director\Objects\ImportSource;
use Icinga\Module\Director\Objects\IcingaService; use Icinga\Module\Director\Objects\IcingaService;
@ -79,6 +82,9 @@ class Sync
/** @var Filter[] */ /** @var Filter[] */
protected $columnFilters = array(); protected $columnFilters = array();
/** @var HostGroupMembershipResolver|bool */
protected $hostGropMembershipResolver;
/** /**
* Constructor. No direct initialization allowed right now. Please use one * Constructor. No direct initialization allowed right now. Please use one
* of the available static factory methods * of the available static factory methods
@ -480,6 +486,53 @@ class Sync
return $newObjects; return $newObjects;
} }
protected function deferResolvers()
{
if (in_array($this->rule->get('object_type'), array('host', 'hostgroup'))) {
$resolver = new HostGroupMembershipResolver($this->db);
$resolver->defer()->setUseTransactions(false);
}
return $this;
}
protected function setResolver(IcingaObject $object)
{
if ($resolver = $this->getHostGropMembershipResolver()) {
/** @var IcingaHost|IcingaHostGroup $object */
$object->setHostGroupMembershipResolver($resolver);
}
return $this;
}
protected function notifyResolvers()
{
if ($resolver = $this->getHostGropMembershipResolver()) {
$resolver->defer();
}
return $this;
}
protected function getHostGropMembershipResolver()
{
if ($this->hostGropMembershipResolver === null) {
if (in_array(
$this->rule->get('object_type'),
array('host', 'hostgroup')
)) {
$this->hostGropMembershipResolver = new HostGroupMembershipResolver(
$this->db
);
} else {
$this->hostGropMembershipResolver = false;
}
}
return $this->hostGropMembershipResolver;
}
/** /**
* Evaluates a SyncRule and returns a list of modified objects * Evaluates a SyncRule and returns a list of modified objects
* *
@ -501,7 +554,8 @@ class Sync
->prepareRelatedImportSources() ->prepareRelatedImportSources()
->prepareSourceColumns() ->prepareSourceColumns()
->loadExistingObjects() ->loadExistingObjects()
->fetchImportedData(); ->fetchImportedData()
->deferResolvers();
// TODO: directly work on existing objects, remember imported keys, then purge // TODO: directly work on existing objects, remember imported keys, then purge
$newObjects = $this->prepareNewObjects(); $newObjects = $this->prepareNewObjects();
@ -579,6 +633,7 @@ class Sync
$modified = 0; $modified = 0;
$deleted = 0; $deleted = 0;
foreach ($objects as $object) { foreach ($objects as $object) {
$this->setResolver($object);
if ($object->shouldBeRemoved()) { if ($object->shouldBeRemoved()) {
$object->delete($db); $object->delete($db);
$deleted++; $deleted++;

View File

@ -32,12 +32,16 @@ class HostGroupMembershipResolver
/** @var IcingaHost[] */ /** @var IcingaHost[] */
protected $hosts; protected $hosts;
/** @var IcingaHostGroup */ /** @var IcingaHostGroup[] */
protected $hostgroups = array(); protected $hostgroups = array();
protected $table = 'icinga_hostgroup_host_resolved'; protected $table = 'icinga_hostgroup_host_resolved';
protected static $deferred; /** @var bool */
protected $deferred = false;
/** @var bool */
protected $useTransactions = false;
public function __construct(Db $connection) public function __construct(Db $connection)
{ {
@ -59,7 +63,7 @@ class HostGroupMembershipResolver
*/ */
public function refreshDb($force = false) public function refreshDb($force = false)
{ {
if ($force || ! static::$deferred) { if ($force || ! $this->isDeferred()) {
Benchmark::measure('Going to refresh all hostgroup mappings'); Benchmark::measure('Going to refresh all hostgroup mappings');
$this->fetchStoredMappings(); $this->fetchStoredMappings();
Benchmark::measure('Got stored HG mappings, rechecking all hosts'); Benchmark::measure('Got stored HG mappings, rechecking all hosts');
@ -72,14 +76,32 @@ class HostGroupMembershipResolver
return $this; return $this;
} }
public static function defer($defer = true) /**
* @param bool $defer
* @return $this
*/
public function defer($defer = true)
{ {
static::$deferred = $defer; $this->deferred = $defer;
return $this;
} }
public static function isDeferred() /**
* @param $use
* @return $this
*/
public function setUseTransactions($use)
{ {
return static::$deferred; $this->useTransactions = $use;
return $this;
}
/**
* @return bool
*/
public function isDeferred()
{
return $this->deferred;
} }
/** /**
@ -205,7 +227,7 @@ class HostGroupMembershipResolver
} }
$db = $this->db; $db = $this->db;
$db->beginTransaction(); $this->beginTransaction();
foreach ($diff as $row) { foreach ($diff as $row) {
$db->insert( $db->insert(
$this->table, $this->table,
@ -213,7 +235,7 @@ class HostGroupMembershipResolver
); );
} }
$db->commit(); $this->commit();
Benchmark::measure( Benchmark::measure(
sprintf( sprintf(
'Stored %d new resolved hostgroup memberships', 'Stored %d new resolved hostgroup memberships',
@ -231,7 +253,7 @@ class HostGroupMembershipResolver
} }
$db = $this->db; $db = $this->db;
$db->beginTransaction(); $this->beginTransaction();
foreach ($diff as $row) { foreach ($diff as $row) {
$db->delete( $db->delete(
$this->table, $this->table,
@ -243,7 +265,7 @@ class HostGroupMembershipResolver
); );
} }
$db->commit(); $this->commit();
Benchmark::measure( Benchmark::measure(
sprintf( sprintf(
'Removed %d outdated hostgroup memberships', 'Removed %d outdated hostgroup memberships',
@ -306,6 +328,12 @@ class HostGroupMembershipResolver
$this->existingMappings = $mappings; $this->existingMappings = $mappings;
} }
/**
* @param ZfSelect $query
* @param string $column
* @param IcingaObject[] $objects
* @return ZfSelect
*/
protected function addMembershipWhere(ZfSelect $query, $column, & $objects) protected function addMembershipWhere(ZfSelect $query, $column, & $objects)
{ {
if (empty($objects)) { if (empty($objects)) {
@ -379,6 +407,30 @@ class HostGroupMembershipResolver
return $this->db->fetchPairs($query); return $this->db->fetchPairs($query);
} }
/**
* @return $this
*/
protected function beginTransaction()
{
if ($this->useTransactions) {
$this->db->beginTransaction();
}
return $this;
}
/**
* @return $this
*/
protected function commit()
{
if ($this->useTransactions) {
$this->db->commit();
}
return $this;
}
/** /**
* @return IcingaHost[] * @return IcingaHost[]
*/ */
@ -393,7 +445,7 @@ class HostGroupMembershipResolver
protected function assertBeenLoadedFromDb(IcingaObject $object) protected function assertBeenLoadedFromDb(IcingaObject $object)
{ {
if (! $object->hasBeenLoadedFromDb()) { if (! ctype_digit($object->get('id'))) {
throw new ProgrammingError( throw new ProgrammingError(
'Hostgroup resolver does not support unstored objects' 'Hostgroup resolver does not support unstored objects'
); );

View File

@ -315,6 +315,12 @@ class IcingaHost extends IcingaObject
return $this->hostgroupMembershipResolver; return $this->hostgroupMembershipResolver;
} }
public function setHostGroupMembershipResolver(HostGroupMembershipResolver $resolver)
{
$this->hostgroupMembershipResolver = $resolver;
return $this;
}
protected function getServiceOverrivesVarname() protected function getServiceOverrivesVarname()
{ {
return $this->connection->settings()->override_services_varname; return $this->connection->settings()->override_services_varname;

View File

@ -39,6 +39,12 @@ class IcingaHostGroup extends IcingaObjectGroup
return $this->hostgroupMembershipResolver; return $this->hostgroupMembershipResolver;
} }
public function setHostGroupMembershipResolver(HostGroupMembershipResolver $resolver)
{
$this->hostgroupMembershipResolver = $resolver;
return $this;
}
protected function notifyResolvers() protected function notifyResolvers()
{ {
$resolver = $this->getHostGroupMembershipResolver(); $resolver = $this->getHostGroupMembershipResolver();

View File

@ -1278,8 +1278,7 @@ abstract class IcingaObject extends DbObject implements IcingaConfigRenderer
->storeImports() ->storeImports()
->storeRanges() ->storeRanges()
->storeRelatedSets() ->storeRelatedSets()
->storeArguments() ->storeArguments();
->notifyResolvers();
} }
protected function beforeStore() protected function beforeStore()
@ -1299,6 +1298,11 @@ abstract class IcingaObject extends DbObject implements IcingaConfigRenderer
$this->storeRelatedObjects(); $this->storeRelatedObjects();
} }
public function onStore()
{
$this->notifyResolvers();
}
/** /**
* @return self * @return self
*/ */