diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 85ec06d..ccffc4a 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -58,9 +58,11 @@ jobs: exit 1 fi - composer install --optimize-autoloader --no-interaction --no-dev + composer install - php artisan migrate --force + composer dump-autoload + + php artisan migrate php artisan config:clear php artisan optimize diff --git a/app/Services/VirtualMachine/VmIpReservationService.php b/app/Services/VirtualMachine/VmIpReservationService.php index c44c6c4..1924a04 100644 --- a/app/Services/VirtualMachine/VmIpReservationService.php +++ b/app/Services/VirtualMachine/VmIpReservationService.php @@ -24,18 +24,18 @@ class VmIpReservationService public function reserve(int $networkId, int $hostId, string $dns): ?array { return DB::transaction(function () use ($networkId, $hostId, $dns) { - // ponytail: exclude only IPs with an actual VM assigned, not stale __pending__ reservations - $usedIps = ModuleIpAddress::where('module_network_id', $networkId) - ->where('vm_name', '!=', '__pending__') + // Exclude IPs that have any active reservation (real VM or pending). + // Also accept status='reserved' in ip_pools so stale reservations + // (ip_pool row stuck as 'reserved' with no matching module_ip_addresses row) + // are recoverable without manual DB cleanup. + $allUsedIps = ModuleIpAddress::where('module_network_id', $networkId) ->lockForUpdate() ->pluck('ip') ->toArray(); $ipPool = IpPool::where('module_network_id', $networkId) - ->where('status', 'free') - ->whereNotNull('gateway') - ->where('gateway', '!=', '') - ->whereNotIn('ip_address', $usedIps) + ->whereIn('status', ['free', 'reserved']) + ->whereNotIn('ip_address', $allUsedIps) ->lockForUpdate() ->inRandomOrder() ->first(); diff --git a/database/migrations/2026_07_13_000002_fix_ip_pools_gateway_and_remove_gateway_ip.php b/database/migrations/2026_07_13_000002_fix_ip_pools_gateway_and_remove_gateway_ip.php new file mode 100644 index 0000000..c67a6fc --- /dev/null +++ b/database/migrations/2026_07_13_000002_fix_ip_pools_gateway_and_remove_gateway_ip.php @@ -0,0 +1,29 @@ +where('module_network_id', 1) + ->where('ip_address', '103.90.224.1') + ->delete(); + + // Backfill gateway cho toàn bộ pool network_id=1 + DB::table('ip_pools') + ->where('module_network_id', 1) + ->whereNull('gateway') + ->update(['gateway' => '103.90.224.1']); + } + + public function down(): void + { + DB::table('ip_pools') + ->where('module_network_id', 1) + ->update(['gateway' => null]); + } +}; diff --git a/resources/views/emails/customer/vm-creation-failed.blade.php b/resources/views/emails/customer/vm-creation-failed.blade.php index 6d6239f..d1418c3 100644 --- a/resources/views/emails/customer/vm-creation-failed.blade.php +++ b/resources/views/emails/customer/vm-creation-failed.blade.php @@ -1,74 +1,184 @@ - - -
- - -Đơn hàng #{{ $orderNum ?? 'N/A' }} - Cần xử lý
-
- Xin chào {{ $customerName ?? 'Quý khách' }},
- Rất tiếc, hệ thống gặp sự cố khi khởi tạo máy chủ ảo cho đơn hàng của bạn. Đội ngũ kỹ thuật của chúng tôi đã được thông báo và sẽ xử lý sớm nhất có thể.
-
| Mã đơn hàng | #{{ $orderNum ?? 'N/A' }} |
| Sản phẩm | {{ $productName ?? 'N/A' }} |
+
|
+