diff --git a/application/clicommands/HousekeepingCommand.php b/application/clicommands/HousekeepingCommand.php index 58c673ae..20ea1635 100644 --- a/application/clicommands/HousekeepingCommand.php +++ b/application/clicommands/HousekeepingCommand.php @@ -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) { diff --git a/library/Director/Db/HostMembershipHousekeeping.php b/library/Director/Db/HostMembershipHousekeeping.php new file mode 100644 index 00000000..3a2de05d --- /dev/null +++ b/library/Director/Db/HostMembershipHousekeeping.php @@ -0,0 +1,8 @@ +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; + } +}