update develop

This commit is contained in:
pbao9
2026-01-19 09:31:10 +07:00
parent 4f2fdbaaa5
commit b97676d557
8 changed files with 409 additions and 370 deletions
@@ -11,6 +11,7 @@ use App\Repositories\Invoice\InvoiceRepositoryInterface;
use App\Http\Services\vCenter;
use App\Jobs\VirtualMachine\Action\ChangeRemotePortJob;
use App\Models\ModuleSnapshot;
use App\Models\ModuleSnapshotLimit;
use App\Models\ModuleVmware;
use App\Models\Order;
use App\Models\Os;
@@ -59,7 +60,6 @@ class ServiceController extends Controller
$this->dispatchVMInfoUpdateJob($invoice);
}
$title = "Chi tiết dịch vụ #" . $invoice->id;
dd($vmInfo);
return view('frontend.service.show', [
'title' => $title,
'invoice' => $invoice,
@@ -354,194 +354,253 @@ class ServiceController extends Controller
return view('frontend.service.console', $data);
}
public function createSnapshots(SnapShotRequest $request, vCenter $serviceVCenter)
public function createSnapshots(SnapShotRequest $request)
{
try {
$user = customer();
if (!$user) {
return redirect()->back()->with('error', 'Chưa đăng nhập. Vui lòng đăng nhập để sử dụng tính năng này.');
return redirect()->back()->with('error', 'Chưa đăng nhập.');
}
$validator = $request->validated();
$productId = $validator['product_id'];
$userId = $user->id;
$data = $request->validated();
$productId = $data['product_id'];
$product = ModuleVmware::with('ipAddress.host.datacenter.vCenter')
->where('vmware_id', $productId)
->where('customer_id', $userId)
->where('customer_id', $user->id)
->first();
if (!$product) {
return redirect()->back()->with('error', "Không tìm thấy VPS #{$productId} hoặc bạn không có quyền truy cập");
}
if (!$product->ipAddress) {
return redirect()->back()->with('error', "VPS #{$productId} không có thông tin IP được cấu hình");
}
if (!$product->ipAddress->host) {
return redirect()->back()->with('error', "VPS #{$productId} không có thông tin Host được cấu hình");
}
if (!$product->ipAddress->host->datacenter) {
return redirect()->back()->with('error', "VPS #{$productId} không có thông tin Datacenter được cấu hình");
}
if (!$product->ipAddress->host->datacenter->vCenter) {
return redirect()->back()->with('error', "VPS #{$productId} không có thông tin vCenter được cấu hình");
return redirect()->back()->with('error', "Không tìm thấy VPS hoặc bạn không có quyền.");
}
if ($product->status != 1) {
return redirect()->back()->with('error', 'Chỉ có thể tạo snapshot cho máy ảo đang hoạt động');
return redirect()->back()->with('error', 'Chỉ tạo snapshot cho VM đang hoạt động.');
}
// Kiểm tra giới hạn snapshot
$snapshotLimit = \App\Models\ModuleSnapshotLimit::where('customer_id', $user->id)->first();
if ($snapshotLimit) {
$currentCount = ModuleSnapshot::where('customer_id', $user->id)
$limit = ModuleSnapshotLimit::where('customer_id', $user->id)->first();
if ($limit) {
$count = ModuleSnapshot::where('customer_id', $user->id)
->where('module_vmware_id', $product->id)
->count();
if ($currentCount >= $snapshotLimit->limit) {
return redirect()->back()->with('error', "Đã đạt giới hạn snapshot ({$snapshotLimit->limit}). Vui lòng xóa snapshot cũ.");
if ($count >= $limit->limit) {
return redirect()->back()->with(
'error',
"Đã đạt giới hạn snapshot ({$limit->limit})."
);
}
}
// Dispatch job để tạo snapshot trong background
\App\Jobs\VirtualMachine\Snapshot\CreateSnapshot::dispatch($product->id)
->delay(now()->addSeconds(5))
->onQueue('snapshots');
return redirect()->back()->with('success', 'Đã gửi yêu cầu tạo snapshot. Quá trình sẽ mất 3-5 phút, vui lòng chờ đợi.');
} catch (\Exception $e) {
Log::error('❌ Lỗi khi tạo snapshot', [
'product_id' => $request->product_id ?? 'not_provided',
'user_id' => $user->id ?? 'guest',
'error' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine()
$snapshot = ModuleSnapshot::create([
'name' => 'snapshot-' . now()->format('Ymd-His'),
'customer_id' => $user->id,
'module_vmware_id' => $product->id,
'status' => 'pending',
'created_by' => $user->id,
]);
return redirect()->back()->with('error', 'Lỗi hệ thống khi tạo snapshot: ' . $e->getMessage());
\App\Jobs\VirtualMachine\Snapshot\CreateSnapshot::dispatch(
$snapshot->id
)
->onQueue('snapshots')
->delay(now()->addSeconds(3));
return redirect()->back()->with(
'success',
'Đã gửi yêu cầu tạo snapshot. Hệ thống sẽ xử lý trong nền.'
);
} catch (\Throwable $e) {
Log::error('Lỗi khi tạo snapshot', [
'product_id' => $request->product_id ?? null,
'user_id' => $user->id ?? null,
'error' => $e->getMessage(),
]);
return redirect()->back()->with(
'error',
'Lỗi hệ thống khi tạo snapshot.'
);
}
}
/**
* Lấy danh sách snapshot với bảo mật và tối ưu hóa
*/
public function getSnapshots(Request $request, vCenter $serviceVCenter)
// public function getSnapshots(Request $request, vCenter $serviceVCenter)
// {
// try {
// // Kiểm tra authentication
// $user = customer();
// if (!$user) {
// return response()->json([
// 'error' => true,
// 'message' => __('Chưa đăng nhập. Vui lòng đăng nhập để sử dụng tính năng này.')
// ], 401);
// }
// // Validation với sanitization
// $validator = Validator::make($request->all(), [
// 'product_id' => 'required|string|max:255',
// ]);
// if ($validator->fails()) {
// return response()->json([
// 'error' => true,
// 'message' => __('Dữ liệu không hợp lệ'),
// 'errors' => $validator->errors()
// ], 422);
// }
// $productId = $this->sanitizeInput($request->product_id);
// $userId = $user->id;
// // Cache key cho snapshot data
// $cacheKey = "snapshots_{$userId}_{$productId}";
// $cacheDuration = 300; // 5 phút
// // Thử lấy từ cache trước
// if (Cache::has($cacheKey)) {
// $cachedData = Cache::get($cacheKey);
// if ($cachedData && !$this->isCacheExpired($cachedData)) {
// return response()->json([
// 'error' => false,
// 'message' => __('Lấy danh sách snapshot thành công'),
// 'data' => $cachedData,
// 'cached' => true
// ]);
// }
// }
// // Tìm VPS với eager loading tối ưu
// $product = $this->findVmwareProduct($productId, $userId);
// if (!$product) {
// return response()->json([
// 'error' => true,
// 'message' => __('Không tìm thấy VPS hoặc bạn không có quyền truy cập')
// ], 404);
// }
// // Kiểm tra cấu hình vCenter
// $vcenter = $this->validateVcenterConfiguration($product);
// if (!$vcenter) {
// return response()->json([
// 'error' => true,
// 'message' => __('Cấu hình vCenter không hợp lệ')
// ], 400);
// }
// // Lấy snapshot từ vCenter
// $snapshots = $this->fetchSnapshotsFromVCenter($serviceVCenter, $product, $vcenter);
// if ($snapshots === false) {
// return response()->json([
// 'error' => true,
// 'message' => __('Không thể kết nối đến vCenter')
// ], 500);
// }
// // Lấy thông tin bổ sung từ database
// $dbSnapshots = $this->getDatabaseSnapshots($userId, $product->id);
// // Merge và sanitize data
// $processedSnapshots = $this->processSnapshotsData($snapshots, $dbSnapshots);
// // Chuẩn bị response data
// $responseData = [
// 'snapshots' => $processedSnapshots,
// 'total_count' => count($processedSnapshots),
// 'vm_name' => $this->sanitizeOutput($product->name),
// 'vm_id' => $product->vmware_id,
// 'last_updated' => now()->format('Y-m-d H:i:s')
// ];
// // Cache kết quả
// Cache::put($cacheKey, $responseData, $cacheDuration);
// return response()->json([
// 'error' => false,
// 'message' => __('Lấy danh sách snapshot thành công'),
// 'data' => $responseData,
// 'cached' => false
// ]);
// } catch (\Exception $e) {
// Log::error('Lỗi khi lấy danh sách snapshot', [
// 'user_id' => $user->id ?? 'guest',
// 'product_id' => $request->product_id ?? 'not_provided',
// 'error' => $e->getMessage(),
// 'file' => $e->getFile(),
// 'line' => $e->getLine()
// ]);
// return response()->json([
// 'error' => true,
// 'message' => __('Có lỗi xảy ra khi lấy danh sách snapshot')
// ], 500);
// }
// }
public function getSnapshots(Request $request)
{
try {
// Kiểm tra authentication
$user = customer();
if (!$user) {
return response()->json([
'error' => true,
'message' => __('Chưa đăng nhập. Vui lòng đăng nhập để sử dụng tính năng này.')
], 401);
}
// Validation với sanitization
$validator = Validator::make($request->all(), [
'product_id' => 'required|string|max:255',
]);
if ($validator->fails()) {
return response()->json([
'error' => true,
'message' => __('Dữ liệu không hợp lệ'),
'errors' => $validator->errors()
], 422);
}
$productId = $this->sanitizeInput($request->product_id);
$userId = $user->id;
// Cache key cho snapshot data
$cacheKey = "snapshots_{$userId}_{$productId}";
$cacheDuration = 300; // 5 phút
// Thử lấy từ cache trước
if (Cache::has($cacheKey)) {
$cachedData = Cache::get($cacheKey);
if ($cachedData && !$this->isCacheExpired($cachedData)) {
return response()->json([
'error' => false,
'message' => __('Lấy danh sách snapshot thành công'),
'data' => $cachedData,
'cached' => true
]);
}
}
// Tìm VPS với eager loading tối ưu
$product = $this->findVmwareProduct($productId, $userId);
if (!$product) {
return response()->json([
'error' => true,
'message' => __('Không tìm thấy VPS hoặc bạn không có quyền truy cập')
], 404);
}
// Kiểm tra cấu hình vCenter
$vcenter = $this->validateVcenterConfiguration($product);
if (!$vcenter) {
return response()->json([
'error' => true,
'message' => __('Cấu hình vCenter không hợp lệ')
], 400);
}
// Lấy snapshot từ vCenter
$snapshots = $this->fetchSnapshotsFromVCenter($serviceVCenter, $product, $vcenter);
if ($snapshots === false) {
return response()->json([
'error' => true,
'message' => __('Không thể kết nối đến vCenter')
], 500);
}
// Lấy thông tin bổ sung từ database
$dbSnapshots = $this->getDatabaseSnapshots($userId, $product->id);
// Merge và sanitize data
$processedSnapshots = $this->processSnapshotsData($snapshots, $dbSnapshots);
// Chuẩn bị response data
$responseData = [
'snapshots' => $processedSnapshots,
'total_count' => count($processedSnapshots),
'vm_name' => $this->sanitizeOutput($product->name),
'vm_id' => $product->vmware_id,
'last_updated' => now()->format('Y-m-d H:i:s')
];
// Cache kết quả
Cache::put($cacheKey, $responseData, $cacheDuration);
return response()->json([
'error' => false,
'message' => __('Lấy danh sách snapshot thành công'),
'data' => $responseData,
'cached' => false
]);
} catch (\Exception $e) {
Log::error('Lỗi khi lấy danh sách snapshot', [
'user_id' => $user->id ?? 'guest',
'product_id' => $request->product_id ?? 'not_provided',
'error' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine()
]);
$user = customer();
if (!$user) {
return response()->json([
'error' => true,
'message' => __('Có lỗi xảy ra khi lấy danh sách snapshot')
], 500);
'message' => __('Chưa đăng nhập')
], 401);
}
$validator = Validator::make($request->all(), [
'product_id' => 'required|string|max:255',
]);
if ($validator->fails()) {
return response()->json([
'error' => true,
'message' => __('Dữ liệu không hợp lệ'),
'errors' => $validator->errors()
], 422);
}
$product = $this->findVmwareProduct(
$this->sanitizeInput($request->product_id),
$user->id
);
if (!$product) {
return response()->json([
'error' => true,
'message' => __('Không tìm thấy VPS')
], 404);
}
$snapshots = ModuleSnapshot::query()
->where('customer_id', $user->id)
->where('module_vmware_id', $product->id)
->orderByDesc('created_at')
->get([
'id',
'name',
'status',
'snapshot_ref',
'error_message',
'created_at',
]);
return response()->json([
'error' => false,
'message' => __('Lấy danh sách snapshot thành công'),
'data' => [
'vm_name' => e($product->name),
'vm_id' => $product->vmware_id,
'snapshots' => $snapshots,
'total_count' => $snapshots->count(),
'last_updated' => now()->format('Y-m-d H:i:s'),
]
]);
}
/**
* Reset VM password (Windows/Linux) via vCenter helpers
*/
@@ -956,7 +1015,7 @@ class ServiceController extends Controller
], 401);
}
$validator = \Validator::make($request->all(), [
$validator = Validator::make($request->all(), [
'product_id' => 'required|string|max:255',
]);
if ($validator->fails()) {
@@ -983,7 +1042,7 @@ class ServiceController extends Controller
$result = $vCenterService->StartVirtualMachine($product, $product->vmware_id);
if (is_array($result) && isset($result['error']) && $result['error'] === false) {
// Clear VM info cache after starting VM
\Cache::forget('vm_info_' . $product->vmware_id);
Cache::forget('vm_info_' . $product->vmware_id);
return response()->json([
'error' => false,
'message' => __('Yêu cầu khởi động máy ảo đã được gửi thành công.')
@@ -996,7 +1055,7 @@ class ServiceController extends Controller
], 500);
}
} catch (\Exception $e) {
\Log::error('Lỗi khi khởi động máy ảo', [
Log::error('Lỗi khi khởi động máy ảo', [
'user_id' => $user->id ?? 'guest',
'product_id' => $request->product_id ?? 'not_provided',
'error' => $e->getMessage(),
@@ -1050,7 +1109,6 @@ class ServiceController extends Controller
$result = $vCenterService->ShutdownGuestVirtualMachine($product, $product->vmware_id);
if (is_array($result) && isset($result['error']) && $result['error'] === false) {
// Clear VM info cache after stopping VM
Cache::forget('the_gioi_so_database_the_gioi_so_cache:vm_info_' . $product->vmware_id);
return response()->json([
'error' => false,
@@ -1064,7 +1122,7 @@ class ServiceController extends Controller
], 500);
}
} catch (\Exception $e) {
\Log::error('Lỗi khi tắt máy ảo', [
Log::error('Lỗi khi tắt máy ảo', [
'user_id' => $user->id ?? 'guest',
'product_id' => $request->product_id ?? 'not_provided',
'error' => $e->getMessage(),
@@ -1092,7 +1150,7 @@ class ServiceController extends Controller
], 401);
}
$validator = \Validator::make($request->all(), [
$validator = Validator::make($request->all(), [
'product_id' => 'required|string|max:255',
]);
if ($validator->fails()) {
@@ -1130,7 +1188,7 @@ class ServiceController extends Controller
], 500);
}
} catch (\Exception $e) {
\Log::error('Lỗi khi reboot VM', [
Log::error('Lỗi khi reboot VM', [
'user_id' => $user->id ?? 'guest',
'product_id' => $request->product_id ?? 'not_provided',
'error' => $e->getMessage(),
@@ -1148,12 +1206,6 @@ class ServiceController extends Controller
public function reinstallVM(Request $request, vCenter $vCenterService)
{
try {
// Debug: Log request data
Log::info('reinstallVM called', [
'request_data' => $request->all(),
'user_id' => customer()?->id ?? 'not_logged_in'
]);
$user = customer();
if (!$user) {
Log::warning('User not logged in for reinstallVM');
@@ -1178,18 +1230,7 @@ class ServiceController extends Controller
], 422);
}
// Debug: Log invoice lookup
Log::info('Looking for invoice', ['invoice_id' => $request->invoice_id]);
$invoice = Invoice::find($request->invoice_id);
// Debug: Log invoice result
Log::info('Invoice lookup result', [
'invoice_id' => $request->invoice_id,
'found' => $invoice ? 'yes' : 'no',
'invoice_data' => $invoice ? $invoice->toArray() : null
]);
if (!$invoice) {
return response()->json([
'error' => true,
@@ -1199,27 +1240,11 @@ class ServiceController extends Controller
// Debug: Log product lookup
$invoiceItem = $invoice->invoiceItem->first();
Log::info('Invoice item lookup', [
'invoice_item_found' => $invoiceItem ? 'yes' : 'no',
'invoice_item_data' => $invoiceItem ? $invoiceItem->toArray() : null
]);
$productId = $invoiceItem?->getProductAttribute()?->id;
Log::info('Product lookup', [
'product_id' => $productId,
'product_data' => $invoiceItem?->getProductAttribute()?->toArray() ?? null
]);
$vmware = $productId;
$osId = $request->os_id;
$userId = $user->id;
Log::info('VM lookup parameters', [
'vmware_id' => $vmware?->vmware_id ?? 'null',
'os_id' => $osId,
'user_id' => $userId
]);
// Tìm product và kiểm tra quyền sở hữu
$vm = ModuleVmware::where('vmware_id', $vmware->vmware_id)
->where('customer_id', $userId)
@@ -1254,42 +1279,14 @@ class ServiceController extends Controller
], 403);
}
// Debug: Log before vCenter call
Log::info('About to call vCenter DeleteVirtualMachine', [
'vmware_id' => $vm->vmware_id,
'os_id' => $osId
]);
// Gọi vCenter service để xóa VM
$result = $vCenterService->DeleteVirtualMachine($vm->vmware_id);
// Debug: Log vCenter result
Log::info('vCenter DeleteVirtualMachine result', [
'result' => $result,
'is_array' => is_array($result),
'has_error_key' => is_array($result) && isset($result['error']),
'error_value' => is_array($result) ? ($result['error'] ?? 'not_set') : 'not_array'
]);
if (is_array($result) && isset($result['error']) && $result['error'] === false) {
// Cập nhật OS trong database
$vm->update([
'os_id' => $osId
]);
// Clear VM info cache
Cache::forget('vm_info_' . $vm->vmware_id);
// Log hoạt động
Log::info('VM reinstall initiated', [
'user_id' => $userId,
'product_id' => $vm->id,
'old_os_id' => $vm->os_id,
'new_os_id' => $osId,
'os_name' => $os->version
]);
Log::info('Returning success response');
return response()->json([
'error' => false,
'message' => __('Yêu cầu cài lại máy ảo đã được gửi thành công. Quá trình sẽ mất 5-10 phút.')