Files
portal-api/app/Jobs/VirtualMachine/Create/CreateVirtualMachineJob.php
T

176 lines
6.2 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
namespace App\Jobs\VirtualMachine\Create;
use App\Http\Services\vCenter;
use App\Jobs\VirtualMachine\Provision\AssignIpToGuestJob;
use App\Models\OrderItem;
use App\Services\VirtualMachine\VmAddonResolver;
use App\Services\VirtualMachine\VmInfrastructureResolver;
use App\Services\VirtualMachine\VmModuleService;
use App\Services\VirtualMachine\VmNotificationService;
use App\Services\VirtualMachine\VmPowerService;
use App\Services\VirtualMachine\VmProvisionLogger;
use App\Services\VirtualMachine\VmServiceSyncService;
use App\Services\VirtualMachine\VmVcenterErrorTranslator;
use App\Services\VmProvisionService;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use RuntimeException;
use Throwable;
class CreateVirtualMachineJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** VM clone can take 5–8 minutes */
public int $timeout = 600;
/** No auto-retry — VM errors need manual review */
public int $tries = 1;
public function __construct(
public OrderItem $item,
public bool $isRetry = false,
) {
}
public function handle(
vCenter $vCenter,
VmProvisionLogger $vmLogger,
VmInfrastructureResolver $infraResolver,
VmAddonResolver $addonResolver,
VmPowerService $powerService,
VmModuleService $moduleService,
VmServiceSyncService $serviceSync,
VmNotificationService $notification,
VmVcenterErrorTranslator $errorTranslator,
): bool {
try {
$vmLogger->step('Create VM job started', [
'order_item_id' => $this->item->id,
'is_retry' => $this->isRetry,
]);
$product = $this->item->getProductAttribute();
if (!$product) {
throw new RuntimeException("Không tìm thấy sản phẩm từ OrderItem #{$this->item->id}");
}
$infra = $infraResolver->resolve($this->item, $product);
$addonData = $addonResolver->resolve($this->item);
if (!$vCenter->loginServer($infra->vcenter)) {
throw new RuntimeException("Login vào vCenter thất bại với host: {$infra->vcenter->host}");
}
$vmLogger->step('VM clone started', [
'order_item_id' => $this->item->id,
'product_id' => $product->id,
'template' => $infra->template,
'host_id' => $infra->host->id,
'vcenter_id' => $infra->vcenter->id,
]);
$result = $vCenter->CreateVirtualMachine([
'item' => $this->item,
'host' => $infra->host,
'datacenter' => $infra->datacenter,
'vcenter' => $infra->vcenter,
'template' => $infra->template,
'addon' => $addonData,
]);
if (is_array($result) && ($result['error'] ?? false)) {
throw new RuntimeException(
$errorTranslator->translate($result, $this->item->server_name)
);
}
if ($result === 'Login_Again') {
throw new RuntimeException('Tạo máy ảo thất bại: cần đăng nhập lại vCenter.');
}
$vmId = is_array($result) ? ($result['data'] ?? null) : $result;
if (!$vmId || in_array($vmId, ['unknown', 'UNKNOWN'], true)) {
throw new RuntimeException('Không lấy được vm_id sau khi tạo máy ảo.');
}
$vmLogger->success('VM clone success', [
'order_item_id' => $this->item->id,
'vm_id' => $vmId,
]);
$vmLogger->step('VM start started', ['vm_id' => $vmId]);
$startResult = $powerService->start($vCenter, $vmId);
if (is_array($startResult) && ($startResult['error'] ?? false)) {
throw new RuntimeException(
'Start VM thất bại: ' . json_encode($startResult['data'] ?? null)
);
}
if ($startResult === 'Login_Again') {
throw new RuntimeException('Start VM thất bại: cần đăng nhập lại vCenter.');
}
$vmLogger->success('VM start success', ['vm_id' => $vmId]);
$moduleVmware = $moduleService->create($this->item, $infra, $vmId);
$vmLogger->success('ModuleVmware created', [
'module_vmware_id' => $moduleVmware->id,
'vm_id' => $vmId,
]);
$serviceSync->sync($moduleVmware, $this->item);
$vmLogger->success('Service synced', [
'module_vmware_id' => $moduleVmware->id,
'order_item_id' => $this->item->id,
]);
AssignIpToGuestJob::dispatch(
$moduleVmware->id,
(string) $vmId,
$infra->isWindows ? VmProvisionService::OS_WINDOWS : VmProvisionService::OS_LINUX,
VmProvisionService::TEMPLATE_PASSWORD,
)->onQueue('default');
$vmLogger->success('AssignIpToGuestJob dispatched', [
'module_vmware_id' => $moduleVmware->id,
'vm_id' => $vmId,
'os_family' => $infra->isWindows ? 'WINDOWS' : 'LINUX',
]);
$notification->success($this->item, $moduleVmware, (string) $vmId);
$vmLogger->success('Create VM job success', [
'order_item_id' => $this->item->id,
'module_vmware_id' => $moduleVmware->id,
'vm_id' => $vmId,
]);
return true;
} catch (Throwable $e) {
$vmLogger->exception('Create VM job failed', $e, [
'order_item_id' => $this->item->id,
'is_retry' => $this->isRetry,
]);
if (!$this->isRetry) {
$notification->failed($this->item, $e->getMessage());
}
return false;
}
}
}