Files
portal-api/app/Jobs/VirtualMachine/Sync/SyncVirtualMachine.php
T

169 lines
6.3 KiB
PHP

<?php
namespace App\Jobs\VirtualMachine\Sync;
use App\Http\Services\Telegram;
use App\Http\Services\vCenter as ServiceVCenter;
use App\Models\ModuleDatacenter;
use App\Models\ModuleHost;
use App\Models\VirtualMachines;
use App\Models\vCenter;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Throwable;
class SyncVirtualMachine implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $vCenter;
protected $telegram;
/**
* Create a new job instance.
*/
public function __construct()
{
// Keep constructor empty or minimal to ensure lightweight serialization
}
/**
* Execute the job.
*/
public function handle()
{
$this->vCenter = new ServiceVCenter;
$this->telegram = new Telegram();
try {
$data = vCenter::select('id', 'host', 'user', 'password', 'token')->get();
$vCenterCount = 0;
$vmTotalCount = 0;
foreach ($data as $item) {
Log::info("Processing vCenter: {$item->host}");
$this->vCenter->apiUri = $item->host;
// Always login to get a fresh token
$token = $this->vCenter->loginServer($item);
if ($token) {
$item->token = $token;
$item->save();
$this->vCenter->token = $token;
} else {
$this->vCenter->token = null;
Log::error("Login failed for {$item->host}");
}
if (!$this->vCenter->token) {
continue;
}
$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);
$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);
$vmTotalCount += $vmCount;
}
}
} else {
// 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);
$vmTotalCount += $vmCount;
}
$vCenterCount++; // Increment vCenter synced count
}
// Notify success via Telegram
$this->telegram->SendJobRunInfo('SyncVirtualMachine', 'Success', [
'message' => 'Sync VMs completed successfully',
'synced_vcenter_count' => $vCenterCount,
'synced_vm_count' => $vmTotalCount,
]);
} catch (Throwable $e) {
Log::error("SyncVirtualMachine Job Failed: " . $e->getMessage());
// Gửi log lỗi qua Telegram
if (isset($this->telegram)) {
$this->telegram->SendJobRunInfo('SyncVirtualMachine', 'Failed', [
'error' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
]);
}
}
}
private function processVMs($vms, $vCenterItem, $datacenterId, $hostId)
{
// 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') {
Log::info("Token expired, retrying login for {$vCenterItem->host}");
$token = $this->vCenter->loginServer($vCenterItem);
if ($token) {
$vCenterItem->token = $token;
$vCenterItem->save();
$this->vCenter->token = $token;
// Retry fetch
$datacenter = $datacenterId ? ModuleDatacenter::find($datacenterId) : null;
$host = $hostId ? ModuleHost::find($hostId) : null;
$vms = $this->vCenter->getAllVirtualMachine(
$datacenter ? $datacenter->datacenter_id : '',
$host ? $host->host_id : ''
);
}
}
if (!is_array($vms)) {
Log::warning("Failed to fetch VMs or empty response. Response: " . json_encode($vms));
return 0;
}
Log::info("Fetched " . count($vms) . " VMs");
$count = 0;
foreach ($vms as $vmData) {
$vmObj = VirtualMachines::firstOrNew(['vm_id' => $vmData['vm']]);
if (!$vmObj->exists) {
$vmObj->uuid = Str::uuid();
}
$vmObj->name = $vmData['name'];
$vmObj->power_state = $vmData['power_state'];
$vmObj->cpu = $vmData['cpu_count'] ?? 0;
$vmObj->ram_mb = $vmData['memory_size_MiB'] ?? 0;
$vmObj->datacenter_id = $datacenterId;
$vmObj->host_id = $hostId;
$vmObj->folder = $vmData['folder'] ?? null;
$vmObj->last_synced_at = now();
$vmObj->save();
$count++;
}
return $count;
}
}