Housekeeping: Add helper to refresh memberships in database

This is usually only done when either object or group changes.
This commit is contained in:
Markus Frosch 2018-05-17 13:00:31 +02:00
parent e46a610b5f
commit 7bfe1e03e6
3 changed files with 155 additions and 0 deletions

View File

@ -5,6 +5,7 @@ namespace Icinga\Module\Director\Clicommands;
use Icinga\Exception\MissingParameterException;
use Icinga\Module\Director\Cli\Command;
use Icinga\Module\Director\Db\Housekeeping;
use Icinga\Module\Director\Db\MembershipHousekeeping;
class HousekeepingCommand extends Command
{
@ -62,6 +63,41 @@ class HousekeepingCommand extends Command
}
}
/**
* Check and repair membership cache
*
* Options:
* --type host Set the object type (Only host supported currently)
* --apply Actually update the database
*/
public function membershipsAction()
{
$type = $this->params->get('type', 'host');
$apply = $this->params->shift('apply');
/** @var MembershipHousekeeping $class */
$class = 'Icinga\\Module\\Director\\Db\\' . ucfirst($type) . 'MembershipHousekeeping';
/** @var MembershipHousekeeping $helper */
$helper = new $class($this->db());
printf("Checking %s memberships\n", $type);
list($new, $outdated) = $helper->check();
$newCount = count($new);
$outdatedCount = count($outdated);
$objects = $helper->getObjects();
$groups = $helper->getGroups();
printf("%d objects - %d groups\n", count($objects), count($groups));
printf("Found %d new and %d outdated mappings\n", $newCount, $outdatedCount);
if ($apply && ($newCount > 0 || $outdatedCount > 0)) {
$helper->update();
printf("Update complete.\n");
}
}
protected function housekeeping()
{
if ($this->housekeeping === null) {

View File

@ -0,0 +1,8 @@
<?php
namespace Icinga\Module\Director\Db;
class HostMembershipHousekeeping extends MembershipHousekeeping
{
protected $type = 'host';
}

View File

@ -0,0 +1,111 @@
<?php
namespace Icinga\Module\Director\Db;
use Icinga\Module\Director\Application\MemoryLimit;
use Icinga\Module\Director\Db;
use Icinga\Module\Director\Db\Cache\PrefetchCache;
use Icinga\Module\Director\Objects\GroupMembershipResolver;
use Icinga\Module\Director\Objects\IcingaObject;
use Icinga\Module\Director\Objects\IcingaObjectGroup;
abstract class MembershipHousekeeping
{
protected $type;
protected $groupType;
protected $connection;
/** @var GroupMembershipResolver */
protected $resolver;
/** @var IcingaObject[] */
protected $objects;
/** @var IcingaObjectGroup[] */
protected $groups;
protected $prepared = false;
public function __construct(Db $connection)
{
$this->connection = $connection;
if ($this->groupType === null) {
$this->groupType = $this->type . 'Group';
}
}
protected function prepare()
{
if ($this->prepared) {
return $this;
}
$this->prepareCache();
$this->resolver()->defer();
$this->objects = IcingaObject::loadAllByType($this->type, $this->connection);
$this->resolver()->addObjects($this->objects);
$this->groups = IcingaObject::loadAllByType($this->groupType, $this->connection);
$this->resolver()->addGroups($this->groups);
MemoryLimit::raiseTo('1024M');
$this->prepared = true;
return $this;
}
public function check()
{
$this->prepare();
$resolver = $this->resolver()->checkDb();
return array($resolver->getNewMappings(), $resolver->getOutdatedMappings());
}
public function update()
{
$this->prepare();
$this->resolver()->refreshDb(true);
}
protected function prepareCache()
{
PrefetchCache::initialize($this->connection);
IcingaObject::prefetchAllRelationsByType($this->type, $this->connection);
}
protected function resolver()
{
if ($this->resolver === null) {
/** @var GroupMembershipResolver $class */
$class = 'Icinga\\Module\\Director\\Objects\\' . ucfirst($this->type) . 'GroupMembershipResolver';
$this->resolver = new $class($this->connection);
}
return $this->resolver;
}
/**
* @return IcingaObject[]
*/
public function getObjects()
{
return $this->objects;
}
/**
* @return IcingaObjectGroup[]
*/
public function getGroups()
{
return $this->groups;
}
}