diff --git a/doc/84-Changelog.md b/doc/84-Changelog.md index 470f7ad7..cf46d2ad 100644 --- a/doc/84-Changelog.md +++ b/doc/84-Changelog.md @@ -15,6 +15,11 @@ v1.8.0 (unreleased) * FIX: vCenter filter is now preserved across main table tabs (#516) +### Integrations +* FEATURE: Director Import Source now ships an object path array (#255) + +![Path Export](screenshot/84_changelog/v1.8.0/84-18-03_path_export.png) + ### REST API * Hosts, VirtualMachines and DataStores can now be exported via REST API (#511) diff --git a/doc/screenshot/84_changelog/v1.8.0/84-18-03_path_export.png b/doc/screenshot/84_changelog/v1.8.0/84-18-03_path_export.png new file mode 100644 index 00000000..42772fa6 Binary files /dev/null and b/doc/screenshot/84_changelog/v1.8.0/84-18-03_path_export.png differ diff --git a/library/Vspheredb/Db/BulkPathLookup.php b/library/Vspheredb/Db/BulkPathLookup.php new file mode 100644 index 00000000..d898d290 --- /dev/null +++ b/library/Vspheredb/Db/BulkPathLookup.php @@ -0,0 +1,59 @@ +db = $db; + $this->vCenterFilterUuids = $vCenterUuids; + } + + public function getParents(?string $objectParent): array + { + if ($this->nodes === null) { + $this->nodes = $this->fetchAllParents(); + } + $path = []; + $parentUuid = $objectParent; + while ($parentUuid !== null) { + if (! isset($this->nodes[$parentUuid])) { + throw new RuntimeException('Parent lookup failed: ' . Uuid::fromBytes($parentUuid)->toString()); + } + $node = $this->nodes[$parentUuid]; + $path[$parentUuid] = $node->object_name; + $parentUuid = $node->parent_uuid; + } + + return array_reverse($path, true); + } + + protected function fetchAllParents(): array + { + $db = $this->db->getDbAdapter(); + $query = $db->select()->from(['p' => 'object'], [ + 'uuid' => 'p.uuid', + 'parent_uuid' => 'p.parent_uuid', + 'object_name' => 'p.object_name' + ])->join(['o' => 'object'], 'o.parent_uuid = p.uuid', []); + QueryHelper::applyOptionalVCenterFilter($db, $query, 'o.vcenter_uuid', $this->vCenterFilterUuids); + $result = []; + foreach ($db->fetchAll($query) as $row) { + $result[$row->uuid] = $row; + } + return $result; + } +} diff --git a/library/Vspheredb/Db/QueryHelper.php b/library/Vspheredb/Db/QueryHelper.php new file mode 100644 index 00000000..29d55771 --- /dev/null +++ b/library/Vspheredb/Db/QueryHelper.php @@ -0,0 +1,25 @@ +where('1 = 0'); + return; + } + + if (count($vCenterFilterUuids) === 1) { + $query->where("$column = ?", DbUtil::quoteBinaryCompat(array_shift($vCenterFilterUuids), $db)); + } else { + $query->where("$column IN (?)", DbUtil::quoteBinaryCompat($vCenterFilterUuids, $db)); + } + } +} diff --git a/library/Vspheredb/ProvidedHook/Director/ImportSource.php b/library/Vspheredb/ProvidedHook/Director/ImportSource.php index 114461d2..e577829d 100644 --- a/library/Vspheredb/ProvidedHook/Director/ImportSource.php +++ b/library/Vspheredb/ProvidedHook/Director/ImportSource.php @@ -7,14 +7,15 @@ use Icinga\Module\Director\Hook\ImportSourceHook; use Icinga\Module\Director\Web\Form\QuickForm; use Icinga\Module\Vspheredb\Db; +use Icinga\Module\Vspheredb\Db\BulkPathLookup; use Icinga\Module\Vspheredb\Db\DbUtil; +use Icinga\Module\Vspheredb\Db\QueryHelper; use Icinga\Module\Vspheredb\DbObject\VCenter; use Icinga\Module\Vspheredb\Web\Table\TableWithParentFilter; use Icinga\Module\Vspheredb\Web\Table\TableWithVCenterFilter; use Ramsey\Uuid\Uuid; use Zend_Db_Adapter_Abstract as ZfDb; use function array_keys; -use function in_array; /** * Class ImportSource @@ -26,6 +27,7 @@ class ImportSource extends ImportSourceHook implements TableWithVCenterFilter, T protected $hostColumns = [ 'object_name' => 'o.object_name', 'uuid' => 'o.uuid', + 'parent_uuid' => 'o.parent_uuid', 'vcenter_name' => 'vc.name', 'sysinfo_vendor' => 'h.sysinfo_vendor', 'sysinfo_model' => 'h.sysinfo_model', @@ -43,6 +45,7 @@ class ImportSource extends ImportSourceHook implements TableWithVCenterFilter, T 'object_name' => 'o.object_name', 'moref' => 'o.moref', 'uuid' => 'o.uuid', + 'parent_uuid' => 'o.parent_uuid', 'vcenter_name' => 'vc.name', 'guest_ip_address' => 'vm.guest_ip_address', 'hardware_numcpu' => 'vm.hardware_numcpu', @@ -62,6 +65,7 @@ class ImportSource extends ImportSourceHook implements TableWithVCenterFilter, T 'object_name' => 'o.object_name', 'object_type' => 'o.object_type', 'uuid' => 'o.uuid', + 'parent_uuid' => 'o.parent_uuid', 'vcenter_name' => 'vc.name', 'effective_cpu_mhz' => 'cr.effective_cpu_mhz', 'effective_memory_size_mb' => 'cr.effective_memory_size_mb', @@ -77,6 +81,7 @@ class ImportSource extends ImportSourceHook implements TableWithVCenterFilter, T protected $datastoreColumns = [ 'object_name' => 'o.object_name', 'uuid' => 'o.uuid', + 'parent_uuid' => 'o.parent_uuid', 'vcenter_name' => 'vc.name', 'maintenance_mode' => 'ds.maintenance_mode', 'capacity' => 'ds.capacity', @@ -159,6 +164,7 @@ public function fetchData(): array { $connection = Db::newConfiguredInstance(); $db = $connection->getDbAdapter(); + $pathLookup = new BulkPathLookup($connection); $objectType = $this->getSetting('object_type'); switch ($objectType) { case 'host_system': @@ -176,7 +182,7 @@ public function fetchData(): array default: return []; } - $this->applyOptionalVCenterFilter($db, $query); + QueryHelper::applyOptionalVCenterFilter($db, $query, 'vc.instance_uuid', $this->vCenterFilterUuids); $this->applyOptionalParentFilter($query); $result = $db->fetchAll( $this->eventuallyFilterVCenter($this->joinVCenter($query)) @@ -187,6 +193,8 @@ public function fetchData(): array } foreach ($result as $row) { + $row->path = array_values($pathLookup->getParents($row->parent_uuid)); + unset($row->parent_uuid); static::convertDbRowToJsonData($row); } @@ -338,23 +346,4 @@ protected function applyOptionalParentFilter($query) $query->where('o.parent_uuid IN (?)', $this->parentFilterUuids); } - - protected function applyOptionalVCenterFilter(ZfDb $db, $query) - { - $uuids = $this->vCenterFilterUuids; - if ($uuids === null) { - return; - } - if (empty($uuids)) { - $query->where('1 = 0'); - return; - } - - $column = 'vc.instance_uuid'; - if (count($uuids) === 1) { - $query->where("$column = ?", DbUtil::quoteBinaryCompat(array_shift($uuids), $db)); - } else { - $query->where("$column IN (?)", DbUtil::quoteBinaryCompat($uuids, $db)); - } - } }