Refactor vCenter snapshot handling and VM operations
- Introduced a new method `resolveVCenterFromProduct` in `SnapshotService` to streamline vCenter resolution from product data. - Updated `CreateSnapshot`, `RemoveSnapshot`, and `RevertSnapshot` jobs to utilize the new vCenter resolution method. - Enhanced the `VmController` to support UUID-based service identification for VM operations. - Added new actions for changing VM IP and RDP port, encapsulating the logic for these operations. - Improved error handling and logging for VM operations, including detailed responses for API consumers. - Removed unnecessary relationships in model queries to optimize performance.
This commit is contained in:
+146
-48
@@ -5,6 +5,7 @@ use App\Http\Controllers\Api\Client\ClientController;
|
||||
use App\Http\Controllers\Api\Service\OrderController;
|
||||
use App\Http\Controllers\Api\Service\ProductCategoryController;
|
||||
use App\Http\Controllers\Api\Service\ServiceController;
|
||||
use App\Http\Controllers\Api\Service\VmController;
|
||||
use App\Http\Controllers\Api\Client\Service\ServiceController as ServiceClientController;
|
||||
use App\Http\Controllers\Api\Transaction\TransactionController;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
@@ -163,6 +164,14 @@ Route::prefix('v1')->as('api.')->group(function () {
|
||||
Route::get('v1/payment/vnpay/return', [TransactionController::class, 'returnCallback']);
|
||||
|
||||
Route::prefix('v1/system')->middleware(['api.auth'])->group(function () {
|
||||
// VM power & network operations
|
||||
Route::controller(VmController::class)->group(function () {
|
||||
Route::post('vm-power-on', 'powerOn') ->name('vm.power-on');
|
||||
Route::post('vm-power-off', 'powerOff') ->name('vm.power-off');
|
||||
Route::post('vm-change-ip', 'changeIp') ->name('vm.change-ip');
|
||||
Route::post('vm-change-port','changePort') ->name('vm.change-port');
|
||||
});
|
||||
|
||||
Route::get('get-ticket-console', function (\Illuminate\Http\Request $request, \App\Http\Services\vCenter $serviceVCenter) {
|
||||
$product_id = $request->get('product');
|
||||
if (!$product_id) {
|
||||
@@ -249,15 +258,36 @@ Route::prefix('v1/system')->middleware(['api.auth'])->group(function () {
|
||||
]);
|
||||
});
|
||||
|
||||
Route::post('vm-create-snapshot', function (\Illuminate\Http\Request $request, \App\Http\Services\vCenter $serviceVCenter) {
|
||||
Route::post('vm-create-snapshot', function (\Illuminate\Http\Request $request) {
|
||||
$customer = $request->user();
|
||||
$payload = $request->validate([
|
||||
'product' => ['required', 'integer'],
|
||||
'name' => ['nullable', 'string', 'max:191'],
|
||||
'product' => ['required'],
|
||||
'description' => ['nullable', 'string', 'max:1000'],
|
||||
]);
|
||||
|
||||
$product = \App\Models\ModuleVmware::with('ipAddress.host.datacenter.vCenter', 'vCenter')->find($payload['product']);
|
||||
// Kiểm tra nếu là UUID (Service UUID)
|
||||
$isUuid = preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i', $payload['product']);
|
||||
|
||||
if ($isUuid) {
|
||||
// Tìm qua Service UUID
|
||||
$service = \App\Models\Service::with('vmware.ipAddress.host.datacenter.vCenter', 'vmware.vCenter')
|
||||
->where('uuid', $payload['product'])
|
||||
->where('customer_id', $customer->id)
|
||||
->first();
|
||||
|
||||
if (!$service || !$service->vmware) {
|
||||
return response()->json(['error' => true, 'message' => 'Không tìm thấy VM'], 404);
|
||||
}
|
||||
$product = $service->vmware;
|
||||
} elseif (is_numeric($payload['product'])) {
|
||||
$product = \App\Models\ModuleVmware::with('ipAddress.host.datacenter.vCenter', 'vCenter')->find((int)$payload['product']);
|
||||
} else {
|
||||
$product = \App\Models\ModuleVmware::with('ipAddress.host.datacenter.vCenter', 'vCenter')
|
||||
->where('vmware_id', $payload['product'])
|
||||
->where('customer_id', $customer->id)
|
||||
->first();
|
||||
}
|
||||
|
||||
if (!$product) {
|
||||
return response()->json(['error' => true, 'message' => 'Không tìm thấy VM'], 404);
|
||||
}
|
||||
@@ -265,44 +295,68 @@ Route::prefix('v1/system')->middleware(['api.auth'])->group(function () {
|
||||
return response()->json(['error' => true, 'message' => 'Bạn không có quyền thao tác VM này'], 403);
|
||||
}
|
||||
|
||||
$result = $serviceVCenter->CreateSnapShot($product, $payload['name'] ?? null);
|
||||
if (is_string($result) || ($result['error'] ?? true)) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => is_string($result) ? $result : ($result['message'] ?? 'Không thể tạo snapshot'),
|
||||
], 400);
|
||||
}
|
||||
// Auto-generate snapshot name: {vm_name}-{date}-{count}
|
||||
$today = now()->format('d-m-Y');
|
||||
$existingCount = \App\Models\ModuleSnapshot::where('module_vmware_id', $product->id)
|
||||
->whereDate('created_at', today())
|
||||
->count();
|
||||
$snapshotName = sprintf('%s-%s-%d', $product->name, $today, $existingCount + 1);
|
||||
|
||||
$snapshotName = $result['data'] ?? ($payload['name'] ?? null);
|
||||
// Create snapshot record with pending status
|
||||
$snapshot = \App\Models\ModuleSnapshot::create([
|
||||
'name' => $snapshotName,
|
||||
'description' => $payload['description'] ?? null,
|
||||
'customer_id' => $customer->id,
|
||||
'module_vmware_id' => $product->id,
|
||||
'status' => 'success',
|
||||
'snapshot_ref' => $snapshotName,
|
||||
'status' => 'pending',
|
||||
'snapshot_ref' => null,
|
||||
]);
|
||||
|
||||
// Dispatch job to create snapshot
|
||||
\App\Jobs\VirtualMachine\Snapshot\CreateSnapshot::dispatch($snapshot->id);
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'message' => 'Đã tạo snapshot thành công',
|
||||
'message' => 'Đã gửi yêu cầu tạo snapshot vào hàng đợi',
|
||||
'data' => [
|
||||
'id' => $snapshot->id,
|
||||
'name' => $snapshot->name,
|
||||
'description' => $snapshot->description,
|
||||
'snapshot_ref' => $snapshot->snapshot_ref,
|
||||
'status' => 'pending',
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
Route::get('vm-snapshots', function (\Illuminate\Http\Request $request, \App\Http\Services\vCenter $serviceVCenter) {
|
||||
$customer = $request->user();
|
||||
$productId = (int)$request->query('product');
|
||||
if (!$productId) {
|
||||
$productParam = $request->query('product');
|
||||
if (!$productParam) {
|
||||
return response()->json(['error' => true, 'message' => 'Thiếu product id'], 422);
|
||||
}
|
||||
|
||||
$product = \App\Models\ModuleVmware::with('ipAddress.host.datacenter.vCenter', 'vCenter')->find($productId);
|
||||
// Kiểm tra nếu là UUID (Service UUID)
|
||||
$isUuid = preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i', $productParam);
|
||||
|
||||
if ($isUuid) {
|
||||
// Tìm qua Service UUID
|
||||
$service = \App\Models\Service::with('vmware.ipAddress.host.datacenter.vCenter', 'vmware.vCenter')
|
||||
->where('uuid', $productParam)
|
||||
->where('customer_id', $customer->id)
|
||||
->first();
|
||||
|
||||
if (!$service || !$service->vmware) {
|
||||
return response()->json(['error' => true, 'message' => 'Không tìm thấy VM'], 404);
|
||||
}
|
||||
$product = $service->vmware;
|
||||
} elseif (is_numeric($productParam)) {
|
||||
$product = \App\Models\ModuleVmware::with('ipAddress.host.datacenter.vCenter', 'vCenter')->find((int)$productParam);
|
||||
} else {
|
||||
$product = \App\Models\ModuleVmware::with('ipAddress.host.datacenter.vCenter', 'vCenter')
|
||||
->where('vmware_id', $productParam)
|
||||
->where('customer_id', $customer->id)
|
||||
->first();
|
||||
}
|
||||
|
||||
if (!$product) {
|
||||
return response()->json(['error' => true, 'message' => 'Không tìm thấy VM'], 404);
|
||||
}
|
||||
@@ -374,14 +428,35 @@ Route::prefix('v1/system')->middleware(['api.auth'])->group(function () {
|
||||
]);
|
||||
});
|
||||
|
||||
Route::post('vm-revert-snapshot', function (\Illuminate\Http\Request $request, \App\Http\Services\vCenter $serviceVCenter) {
|
||||
Route::post('vm-revert-snapshot', function (\Illuminate\Http\Request $request) {
|
||||
$customer = $request->user();
|
||||
$payload = $request->validate([
|
||||
'product' => ['required', 'integer'],
|
||||
'snapshot' => ['required', 'string'],
|
||||
'product' => ['required'],
|
||||
'snapshot_id' => ['required', 'numeric'],
|
||||
]);
|
||||
|
||||
$product = \App\Models\ModuleVmware::with('ipAddress.host.datacenter.vCenter', 'vCenter')->find($payload['product']);
|
||||
// Kiểm tra nếu là UUID (Service UUID)
|
||||
$isUuid = preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i', $payload['product']);
|
||||
|
||||
if ($isUuid) {
|
||||
// Tìm qua Service UUID
|
||||
$service = \App\Models\Service::with('vmware')
|
||||
->where('uuid', $payload['product'])
|
||||
->where('customer_id', $customer->id)
|
||||
->first();
|
||||
|
||||
if (!$service || !$service->vmware) {
|
||||
return response()->json(['error' => true, 'message' => 'Không tìm thấy VM'], 404);
|
||||
}
|
||||
$product = $service->vmware;
|
||||
} elseif (is_numeric($payload['product'])) {
|
||||
$product = \App\Models\ModuleVmware::find((int)$payload['product']);
|
||||
} else {
|
||||
$product = \App\Models\ModuleVmware::where('vmware_id', $payload['product'])
|
||||
->where('customer_id', $customer->id)
|
||||
->first();
|
||||
}
|
||||
|
||||
if (!$product) {
|
||||
return response()->json(['error' => true, 'message' => 'Không tìm thấy VM'], 404);
|
||||
}
|
||||
@@ -389,28 +464,54 @@ Route::prefix('v1/system')->middleware(['api.auth'])->group(function () {
|
||||
return response()->json(['error' => true, 'message' => 'Bạn không có quyền thao tác VM này'], 403);
|
||||
}
|
||||
|
||||
$result = $serviceVCenter->RevertSnapShot($product, $payload['snapshot']);
|
||||
if (is_string($result) || ($result['error'] ?? true)) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => is_string($result) ? $result : ($result['message'] ?? 'Không thể revert snapshot'),
|
||||
], 400);
|
||||
// Find snapshot
|
||||
$snapshot = \App\Models\ModuleSnapshot::where('id', $payload['snapshot_id'])
|
||||
->where('module_vmware_id', $product->id)
|
||||
->where('customer_id', $customer->id)
|
||||
->first();
|
||||
|
||||
if (!$snapshot) {
|
||||
return response()->json(['error' => true, 'message' => 'Không tìm thấy snapshot'], 404);
|
||||
}
|
||||
|
||||
// Dispatch job
|
||||
\App\Jobs\VirtualMachine\Snapshot\RevertSnapshot::dispatch($product->id, $snapshot->id);
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'message' => 'Đã gửi lệnh revert snapshot',
|
||||
'message' => 'Đã gửi yêu cầu revert snapshot vào hàng đợi',
|
||||
]);
|
||||
});
|
||||
|
||||
Route::post('vm-delete-snapshot', function (\Illuminate\Http\Request $request, \App\Http\Services\vCenter $serviceVCenter) {
|
||||
Route::post('vm-delete-snapshot', function (\Illuminate\Http\Request $request) {
|
||||
$customer = $request->user();
|
||||
$payload = $request->validate([
|
||||
'product' => ['required', 'integer'],
|
||||
'snapshot' => ['required', 'string'],
|
||||
'product' => ['required'],
|
||||
'snapshot_id' => ['required', 'numeric'],
|
||||
]);
|
||||
|
||||
$product = \App\Models\ModuleVmware::with('ipAddress.host.datacenter.vCenter', 'vCenter')->find($payload['product']);
|
||||
// Kiểm tra nếu là UUID (Service UUID)
|
||||
$isUuid = preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i', $payload['product']);
|
||||
|
||||
if ($isUuid) {
|
||||
// Tìm qua Service UUID
|
||||
$service = \App\Models\Service::with('vmware')
|
||||
->where('uuid', $payload['product'])
|
||||
->where('customer_id', $customer->id)
|
||||
->first();
|
||||
|
||||
if (!$service || !$service->vmware) {
|
||||
return response()->json(['error' => true, 'message' => 'Không tìm thấy VM'], 404);
|
||||
}
|
||||
$product = $service->vmware;
|
||||
} elseif (is_numeric($payload['product'])) {
|
||||
$product = \App\Models\ModuleVmware::find((int)$payload['product']);
|
||||
} else {
|
||||
$product = \App\Models\ModuleVmware::where('vmware_id', $payload['product'])
|
||||
->where('customer_id', $customer->id)
|
||||
->first();
|
||||
}
|
||||
|
||||
if (!$product) {
|
||||
return response()->json(['error' => true, 'message' => 'Không tìm thấy VM'], 404);
|
||||
}
|
||||
@@ -418,25 +519,22 @@ Route::prefix('v1/system')->middleware(['api.auth'])->group(function () {
|
||||
return response()->json(['error' => true, 'message' => 'Bạn không có quyền thao tác VM này'], 403);
|
||||
}
|
||||
|
||||
$result = $serviceVCenter->RemoveSnapShot($product, $payload['snapshot']);
|
||||
if (is_string($result) || ($result['error'] ?? true)) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => is_string($result) ? $result : ($result['message'] ?? 'Không thể xoá snapshot'),
|
||||
], 400);
|
||||
}
|
||||
|
||||
\App\Models\ModuleSnapshot::query()
|
||||
// Find snapshot
|
||||
$snapshot = \App\Models\ModuleSnapshot::where('id', $payload['snapshot_id'])
|
||||
->where('module_vmware_id', $product->id)
|
||||
->where('customer_id', $customer->id)
|
||||
->where(function ($q) use ($payload) {
|
||||
$q->where('snapshot_ref', $payload['snapshot'])->orWhere('name', $payload['snapshot']);
|
||||
})
|
||||
->delete();
|
||||
->first();
|
||||
|
||||
if (!$snapshot) {
|
||||
return response()->json(['error' => true, 'message' => 'Không tìm thấy snapshot'], 404);
|
||||
}
|
||||
|
||||
// Dispatch job
|
||||
\App\Jobs\VirtualMachine\Snapshot\RemoveSnapshot::dispatch($product->id, $snapshot->id);
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'message' => 'Đã xoá snapshot thành công',
|
||||
'message' => 'Đã gửi yêu cầu xóa snapshot vào hàng đợi',
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user