feat: Implement IP assignment and verification for VM guests; add related PowerShell scripts

This commit is contained in:
pbao9
2026-04-18 08:51:02 +07:00
parent f4145088e1
commit 8aef607e1f
8 changed files with 777 additions and 59 deletions
@@ -2,21 +2,16 @@
namespace App\Jobs\VirtualMachine\Create;
use App\Http\Facade\SignRSA;
use App\Http\Services\Telegram;
use App\Http\Services\vCenter;
use App\Jobs\Mail\Customer\VMCreationFailedJob;
use App\Jobs\Mail\SendInformationVirtualMachine;
use App\Jobs\VirtualMachine\Provision\ChangePasswordViaVsphereJob;
use App\Services\VmProvisionService;
use App\Models\OrderItem;
use App\Models\Os;
use App\Models\ModuleVmware;
use App\Models\ModuleIpAddress;
use App\Models\IpPool;
use App\Models\Log as CustomerLog;
use App\Models\Service;
use App\Models\Setting;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
@@ -222,31 +217,19 @@ class CreateVirtualMachineJob implements ShouldQueue
// VM started — SSH vào vSphere host để đổi mật khẩu qua PS1 script
try {
$customer = $this->item->order->customer;
$customer = $this->item->order->customer;
$serverName = $this->item->server_name ?? 'VM-' . $vmId;
$networkId = $product->ipAddress?->module_network_id ?? 1;
$availableIP = $this->getAvailableIPFromPool($networkId);
$moduleIpAddress = ModuleIpAddress::create([
'vm_name' => $serverName,
'module_host_id' => $host->id,
'module_network_id' => $networkId,
'ip' => $availableIP,
'gateway' => $product->ipAddress?->gateway ?? '0.0.0.0',
'netmask' => $product->ipAddress?->netmask ?? '255.255.255.0',
'dns' => $product->ipAddress?->dns ?? '8.8.8.8',
'status' => 1 // 1 = Assigned
]);
$months = (int) ($this->item->months ?? 0);
$months = (int) ($this->item->months ?? 0);
$firstPayment = (int) $this->item->price * ($months ?: 1);
$nextDueDate = $months > 0 ? now()->addMonths($months)->timestamp : null;
$nextDueDate = $months > 0 ? now()->addMonths($months)->timestamp : null;
// Create ModuleVmware without IP — AssignIpToGuestJob will
// pick, assign, and verify the real IP later, then write it to DB.
$moduleVmware = ModuleVmware::create([
'name' => $serverName,
'module_ip_address' => $moduleIpAddress->id,
'ip' => $availableIP,
'module_ip_address' => null, // set by AssignIpToGuestJob
'ip' => null, // set by AssignIpToGuestJob
'port' => $vmPort,
'order_id' => $this->item->order->id,
'first_payment' => $firstPayment,
@@ -267,7 +250,9 @@ class CreateVirtualMachineJob implements ShouldQueue
// Sync services table
$this->syncServiceRecord($moduleVmware);
// SSH → vSphere host → PS1 → change password → send email
// Step 1 of guest provisioning: change template password.
// On success ChangePasswordViaVsphereJob dispatches AssignIpToGuestJob,
// which handles IP selection, assignment, verification, and email.
ChangePasswordViaVsphereJob::dispatch(
$moduleVmware->id,
$vmId,
@@ -398,35 +383,6 @@ class CreateVirtualMachineJob implements ShouldQueue
}
}
private function getAvailableIPFromPool(int $networkId): string
{
// Lấy tất cả IPs đã được assign trong network này
$assignedIPs = ModuleIpAddress::where('module_network_id', $networkId)
->pluck('ip')
->toArray();
// Lấy ngẫu nhiên 1 IP từ pool chưa được assign
$available = IpPool::where('module_network_id', $networkId)
->when(!empty($assignedIPs), fn ($q) => $q->whereNotIn('ip_address', $assignedIPs))
->inRandomOrder()
->first();
if (!$available) {
Log::warning('getAvailableIPFromPool: không còn IP trống trong pool', [
'network_id' => $networkId,
'assigned_count' => count($assignedIPs),
]);
return '0.0.0.0';
}
Log::info('getAvailableIPFromPool: IP được chọn', [
'network_id' => $networkId,
'ip' => $available->ip_address,
]);
return $available->ip_address;
}
/**
* Start VM directly using vCenter API
*/