This commit is contained in:
baodev0
2026-06-22 08:43:32 +07:00
parent 3243473843
commit 0c436153c6
22 changed files with 1389 additions and 95 deletions
@@ -9,6 +9,7 @@ use App\Jobs\VirtualMachine\Provision\AssignIpToGuestJob;
use App\Models\OrderItem;
use App\Services\VirtualMachine\VmAddonResolver;
use App\Services\VirtualMachine\VmInfrastructureResolver;
use App\Services\VirtualMachine\VmIpReservationService;
use App\Services\VirtualMachine\VmModuleService;
use App\Services\VirtualMachine\VmNotificationService;
use App\Services\VirtualMachine\VmPowerService;
@@ -50,7 +51,11 @@ class CreateVirtualMachineJob implements ShouldQueue
VmServiceSyncService $serviceSync,
VmNotificationService $notification,
VmVcenterErrorTranslator $errorTranslator,
VmIpReservationService $ipReservation,
): bool {
$reservation = null;
$ipPoolId = null;
try {
$vmLogger->step('Create VM job started', [
'order_item_id' => $this->item->id,
@@ -66,6 +71,39 @@ class CreateVirtualMachineJob implements ShouldQueue
$infra = $infraResolver->resolve($this->item, $product);
$addonData = $addonResolver->resolve($this->item);
// Reserve IP BEFORE clone so VM name on vCenter, ModuleVmware.name
// and services.server_name all carry the format {ip}_{server_name}.
// Network comes from the active chain (active host → active network);
// product->ipAddress is no longer consulted for network selection.
if (!$infra->network) {
throw new RuntimeException("Active host id={$infra->host->id} chưa có network active.");
}
$networkId = $infra->network->id;
$dns = $product->ipAddress->dns ?? '8.8.8.8';
$picked = $ipReservation->reserve($networkId, $infra->host->id, $dns);
if (!$picked) {
throw new RuntimeException(
"Không còn IP free trong pool (network_id={$networkId}) để tạo VM."
);
}
$reservation = $picked['reservation'];
$ipPoolId = $picked['ip_pool_id'];
$reservedIp = $reservation->ip;
$originalName = $this->item->server_name ?? ('VM-' . $this->item->id);
$combinedName = "{$reservedIp}_{$originalName}";
$this->item->server_name = $combinedName;
$vmLogger->step('IP reserved for VM', [
'order_item_id' => $this->item->id,
'ip' => $reservedIp,
'ip_pool_id' => $ipPoolId,
'server_name' => $combinedName,
]);
if (!$vCenter->loginServer($infra->vcenter)) {
throw new RuntimeException("Login vào vCenter thất bại với host: {$infra->vcenter->host}");
}
@@ -142,6 +180,8 @@ class CreateVirtualMachineJob implements ShouldQueue
(string) $vmId,
$infra->isWindows ? VmProvisionService::OS_WINDOWS : VmProvisionService::OS_LINUX,
VmProvisionService::TEMPLATE_PASSWORD,
$reservation->id,
$ipPoolId,
)->onQueue('default');
$vmLogger->success('AssignIpToGuestJob dispatched', [
@@ -160,6 +200,10 @@ class CreateVirtualMachineJob implements ShouldQueue
return true;
} catch (Throwable $e) {
if ($reservation) {
$ipReservation->release($reservation, $ipPoolId);
}
$vmLogger->exception('Create VM job failed', $e, [
'order_item_id' => $this->item->id,
'is_retry' => $this->isRetry,