This commit is contained in:
baodev0
2026-07-01 10:51:05 +07:00
parent 914e96138a
commit 3bb59feba3
43 changed files with 1680 additions and 28 deletions
@@ -46,6 +46,8 @@ class SyncVirtualMachine implements ShouldQueue
$vCenterCount = 0;
$vmTotalCount = 0;
$totalDeletedCount = 0;
foreach ($data as $item) {
Log::info("Processing vCenter: {$item->host}");
$this->vCenter->apiUri = $item->host;
@@ -65,24 +67,27 @@ class SyncVirtualMachine implements ShouldQueue
continue;
}
$syncedVmIds = [];
$fetchFailed = false;
$datacenters = ModuleDatacenter::where('vcenter_id', $item->id)->get();
if ($datacenters->count() > 0) {
foreach ($datacenters as $dc) {
// Get all hosts for this datacenter
$hosts = ModuleHost::where('module_datacenter_id', $dc->id)->get();
if ($hosts->count() > 0) {
foreach ($hosts as $host) {
Log::info("Fetching VMs for host: {$host->host_id} in datacenter: {$dc->name}");
$vms = $this->vCenter->getAllVirtualMachine($dc->datacenter_id, $host->host_id);
$vmCount = $this->processVMs($vms, $item, $dc->id, $host->id);
$vmCount = $this->processVMs($vms, $item, $dc->id, $host->id, $syncedVmIds, $fetchFailed);
$vmTotalCount += $vmCount;
}
} else {
// Fallback: Sync VMs by datacenter only
Log::info("No hosts found for datacenter {$dc->name}, fetching VMs by datacenter only");
$vms = $this->vCenter->getAllVirtualMachine($dc->datacenter_id);
$vmCount = $this->processVMs($vms, $item, $dc->id, null);
$vmCount = $this->processVMs($vms, $item, $dc->id, null, $syncedVmIds, $fetchFailed);
$vmTotalCount += $vmCount;
}
}
@@ -90,10 +95,20 @@ class SyncVirtualMachine implements ShouldQueue
// Fallback: Sync all VMs without datacenter context
Log::info("No datacenters found, fetching all VMs for {$item->host}");
$vms = $this->vCenter->getAllVirtualMachine();
$vmCount = $this->processVMs($vms, $item, null, null);
$vmCount = $this->processVMs($vms, $item, null, null, $syncedVmIds, $fetchFailed);
$vmTotalCount += $vmCount;
}
// Cleanup stale VMs in DB that no longer exist on vCenter.
// Only run when all fetches succeeded to avoid wiping data on transient failures.
if (!$fetchFailed) {
$datacenterIds = $datacenters->pluck('id')->all();
$deletedCount = $this->cleanupStaleVMs($datacenterIds, $syncedVmIds, $item);
$totalDeletedCount += $deletedCount;
} else {
Log::warning("Skip cleanup for vCenter {$item->host} because some VM fetches failed.");
}
$vCenterCount++; // Increment vCenter synced count
}
@@ -102,6 +117,7 @@ class SyncVirtualMachine implements ShouldQueue
'message' => 'Sync VMs completed successfully',
'synced_vcenter_count' => $vCenterCount,
'synced_vm_count' => $vmTotalCount,
'deleted_vm_count' => $totalDeletedCount,
]);
} catch (Throwable $e) {
@@ -117,7 +133,7 @@ class SyncVirtualMachine implements ShouldQueue
}
}
private function processVMs($vms, $vCenterItem, $datacenterId, $hostId)
private function processVMs($vms, $vCenterItem, $datacenterId, $hostId, array &$syncedVmIds, bool &$fetchFailed)
{
// If token expired, retry login (handled inside loop in previous logic, but simpler here if we just handle the array check)
if ($vms === 'Login_Again') {
@@ -139,6 +155,7 @@ class SyncVirtualMachine implements ShouldQueue
if (!is_array($vms)) {
Log::warning("Failed to fetch VMs or empty response. Response: " . json_encode($vms));
$fetchFailed = true;
return 0;
}
@@ -161,8 +178,48 @@ class SyncVirtualMachine implements ShouldQueue
$vmObj->last_synced_at = now();
$vmObj->save();
$syncedVmIds[] = $vmData['vm'];
$count++;
}
return $count;
}
/**
* Delete VMs in DB that belong to the given vCenter but no longer exist on vCenter.
*/
private function cleanupStaleVMs(array $datacenterIds, array $syncedVmIds, $vCenterItem): int
{
$syncedVmIds = array_values(array_unique($syncedVmIds));
if (!empty($datacenterIds)) {
$query = VirtualMachines::whereIn('datacenter_id', $datacenterIds);
} else {
// No datacenter context: fallback - chỉ xoá khi đã sync được ít nhất 1 VM
// để tránh xoá nhầm khi vCenter rỗng do lỗi.
if (empty($syncedVmIds)) {
Log::warning("Skip cleanup for {$vCenterItem->host}: no datacenters and no synced VMs.");
return 0;
}
$query = VirtualMachines::query();
}
if (!empty($syncedVmIds)) {
$query->whereNotIn('vm_id', $syncedVmIds);
}
$staleVms = $query->get(['id', 'vm_id', 'name']);
if ($staleVms->isEmpty()) {
return 0;
}
foreach ($staleVms as $stale) {
Log::info("Deleting stale VM removed from vCenter {$vCenterItem->host}: {$stale->name} ({$stale->vm_id})");
}
$deleted = VirtualMachines::whereIn('id', $staleVms->pluck('id')->all())->delete();
Log::info("Cleanup vCenter {$vCenterItem->host}: deleted {$deleted} stale VM(s).");
return (int) $deleted;
}
}