245 lines
9.1 KiB
PHP
245 lines
9.1 KiB
PHP
<?php
|
||
|
||
namespace App\Jobs\VirtualMachine\Create;
|
||
|
||
use App\Http\Services\Telegram;
|
||
use App\Http\Services\vCenter;
|
||
use App\Models\ModuleVmware;
|
||
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\Facades\Http;
|
||
|
||
class AssignIPJob implements ShouldQueue
|
||
{
|
||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||
|
||
public string $vmId;
|
||
public int $moduleVmwareId;
|
||
public string $availableIP;
|
||
|
||
/**
|
||
* Create a new job instance.
|
||
*/
|
||
public function __construct(string $vmId, int $moduleVmwareId, string $availableIP)
|
||
{
|
||
$this->vmId = $vmId;
|
||
$this->moduleVmwareId = $moduleVmwareId;
|
||
$this->availableIP = $availableIP;
|
||
}
|
||
|
||
/**
|
||
* Execute the job.
|
||
*/
|
||
public function handle(vCenter $vCenter, Telegram $telegram)
|
||
{
|
||
try {
|
||
Log::info('🔧 Bắt đầu AssignIPJob', [
|
||
'vm_id' => $this->vmId,
|
||
'module_vmware_id' => $this->moduleVmwareId,
|
||
'assigned_ip' => $this->availableIP
|
||
]);
|
||
|
||
// Lấy thông tin ModuleVmware
|
||
$moduleVmware = ModuleVmware::with(['ipAddress.host.datacenter.vCenter'])->find($this->moduleVmwareId);
|
||
|
||
if (!$moduleVmware || !$moduleVmware->ipAddress) {
|
||
Log::error('❌ Không tìm thấy ModuleVmware hoặc IP address', [
|
||
'vm_id' => $this->vmId,
|
||
'module_vmware_id' => $this->moduleVmwareId
|
||
]);
|
||
|
||
$telegram->SendErrorMessage([
|
||
'error' => 'ModuleVmware or IP address not found',
|
||
'vm_id' => $this->vmId,
|
||
'module_vmware_id' => $this->moduleVmwareId
|
||
], 'AssignIPJob - Data Not Found');
|
||
|
||
return;
|
||
}
|
||
|
||
// Login vào vCenter
|
||
$vcenter = $moduleVmware->ipAddress->host->datacenter->vCenter;
|
||
if (!$vCenter->loginServer($vcenter)) {
|
||
Log::error('❌ Không thể login vào vCenter cho AssignIP', [
|
||
'vm_id' => $this->vmId,
|
||
'vcenter_host' => $vcenter->host
|
||
]);
|
||
|
||
$telegram->SendErrorMessage([
|
||
'error' => 'Cannot login to vCenter',
|
||
'vm_id' => $this->vmId,
|
||
'vcenter_host' => $vcenter->host
|
||
], 'AssignIPJob - vCenter Login Failed');
|
||
|
||
return;
|
||
}
|
||
|
||
// Kiểm tra OS family và assign IP
|
||
$this->handleIPAssignment($vCenter, $this->vmId, $moduleVmware, $this->availableIP, $telegram);
|
||
|
||
} catch (\Throwable $e) {
|
||
Log::error('❌ Lỗi trong AssignIPJob: ' . $e->getMessage(), [
|
||
'vm_id' => $this->vmId,
|
||
'module_vmware_id' => $this->moduleVmwareId,
|
||
'error' => $e->getMessage(),
|
||
'trace' => $e->getTraceAsString()
|
||
]);
|
||
|
||
$telegram->SendErrorMessage([
|
||
'error' => $e->getMessage(),
|
||
'vm_id' => $this->vmId,
|
||
'module_vmware_id' => $this->moduleVmwareId,
|
||
'file' => $e->getFile(),
|
||
'line' => $e->getLine()
|
||
], 'AssignIPJob - Exception');
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Handle IP assignment based on OS family
|
||
*/
|
||
private function handleIPAssignment(vCenter $vCenter, string $vmId, ModuleVmware $moduleVmware, string $availableIP, Telegram $telegram): void
|
||
{
|
||
try {
|
||
// Kiểm tra OS family trước khi assign IP
|
||
$osFamily = $this->checkVMOSFamily($vCenter, $vmId);
|
||
|
||
if ($osFamily === 'WINDOWS') {
|
||
Log::info('✅ Phát hiện Windows VM, bắt đầu assign IP', [
|
||
'vm_id' => $vmId,
|
||
'os_family' => $osFamily,
|
||
'assigned_ip' => $availableIP
|
||
]);
|
||
|
||
// Assign IP cho Windows VM
|
||
$assignIPResult = $vCenter->assignIPWindows($moduleVmware, $vmId);
|
||
|
||
if (is_array($assignIPResult) && !$assignIPResult['error']) {
|
||
Log::info('✅ Assign IP Windows thành công', [
|
||
'vm_id' => $vmId,
|
||
'result' => $assignIPResult['data']
|
||
]);
|
||
|
||
$telegram->SendJobRunInfo(
|
||
'AssignIPWindows',
|
||
'success',
|
||
[
|
||
'vm_id' => $vmId,
|
||
'assigned_ip' => $availableIP,
|
||
'result' => $assignIPResult['data']
|
||
]
|
||
);
|
||
} else {
|
||
Log::warning('⚠️ Assign IP Windows thất bại', [
|
||
'vm_id' => $vmId,
|
||
'error' => $assignIPResult['data'] ?? 'Unknown error'
|
||
]);
|
||
|
||
$telegram->SendErrorMessage([
|
||
'error' => 'Assign IP Windows failed',
|
||
'vm_id' => $vmId,
|
||
'details' => $assignIPResult['data'] ?? 'Unknown error'
|
||
], 'AssignIPWindows - Failed');
|
||
}
|
||
} elseif ($osFamily === 'LINUX' || $osFamily === 'OTHER') {
|
||
Log::info('ℹ️ Phát hiện non-Windows VM, hệ thống đang nâng cấp', [
|
||
'vm_id' => $vmId,
|
||
'os_family' => $osFamily
|
||
]);
|
||
|
||
$telegram->SendJobRunInfo(
|
||
'AssignIP',
|
||
'upgrade',
|
||
[
|
||
'vm_id' => $vmId,
|
||
'os_family' => $osFamily,
|
||
'message' => 'Hệ thống đang nâng cấp để hỗ trợ IP assignment cho ' . $osFamily
|
||
]
|
||
);
|
||
} else {
|
||
Log::warning('⚠️ Không thể xác định OS family', [
|
||
'vm_id' => $vmId,
|
||
'os_family' => $osFamily
|
||
]);
|
||
|
||
$telegram->SendErrorMessage([
|
||
'error' => 'Cannot determine OS family',
|
||
'vm_id' => $vmId,
|
||
'os_family' => $osFamily
|
||
], 'AssignIP - Unknown OS');
|
||
}
|
||
} catch (\Exception $e) {
|
||
Log::error('❌ Lỗi khi handle IP assignment: ' . $e->getMessage(), [
|
||
'vm_id' => $vmId,
|
||
'error' => $e->getMessage()
|
||
]);
|
||
|
||
$telegram->SendErrorMessage([
|
||
'error' => 'IP Assignment handling failed',
|
||
'vm_id' => $vmId,
|
||
'details' => $e->getMessage()
|
||
], 'HandleIPAssignment - Exception');
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Check VM OS family using vCenter API
|
||
*/
|
||
private function checkVMOSFamily(vCenter $vCenter, string $vmId): string
|
||
{
|
||
try {
|
||
// Kiểm tra session còn valid không
|
||
$check = $vCenter->checkApiExits();
|
||
if (!$check) {
|
||
Log::warning('vCenter session expired, cannot check OS family');
|
||
return 'UNKNOWN';
|
||
}
|
||
|
||
// Gọi API để lấy guest identity
|
||
$response = Http::withoutVerifying()
|
||
->withHeaders([
|
||
'vmware-api-session-id' => $vCenter->token
|
||
])
|
||
->get("https://{$vCenter->apiUri}/rest/vcenter/vm/{$vmId}/guest/identity");
|
||
|
||
if ($response->successful()) {
|
||
$data = $response->json();
|
||
|
||
if (isset($data['value']['family'])) {
|
||
$family = strtoupper($data['value']['family']);
|
||
|
||
Log::info('✅ Phát hiện OS family', [
|
||
'vm_id' => $vmId,
|
||
'family' => $family,
|
||
'full_name' => $data['value']['full_name'] ?? 'Unknown'
|
||
]);
|
||
|
||
return $family;
|
||
} else {
|
||
Log::warning('⚠️ Không tìm thấy family trong response', [
|
||
'vm_id' => $vmId,
|
||
'response' => $data
|
||
]);
|
||
return 'UNKNOWN';
|
||
}
|
||
} else {
|
||
Log::warning('⚠️ API call thất bại khi check OS family', [
|
||
'vm_id' => $vmId,
|
||
'status' => $response->status(),
|
||
'response' => $response->body()
|
||
]);
|
||
return 'UNKNOWN';
|
||
}
|
||
} catch (\Exception $e) {
|
||
Log::error('❌ Exception khi check OS family: ' . $e->getMessage(), [
|
||
'vm_id' => $vmId,
|
||
'error' => $e->getMessage()
|
||
]);
|
||
return 'UNKNOWN';
|
||
}
|
||
}
|
||
}
|