- VmProvisionException/VmProvisionRefund xử lý lỗi cấp phát VM - QueueJobInspector + QueueMonitorController xem chi tiết job - Thêm service uuid cho ticket, thời lượng cho activity_logs - Migration chuẩn hoá RAM addon sang MB, trạng thái deleting cho snapshot Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
183 lines
5.5 KiB
PHP
183 lines
5.5 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Api\Service\Concerns;
|
|
|
|
use App\Actions\VM\PowerOffVMAction;
|
|
use App\Actions\VM\PowerOnVMAction;
|
|
use App\Http\Services\vCenter;
|
|
use App\Models\ModuleVmware;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\Request;
|
|
|
|
trait ManagesVmPower
|
|
{
|
|
/**
|
|
* POST /v1/system/vm-power-on
|
|
*
|
|
* Body: { "product": <ModuleVmware.id|vmware_id|service_uuid> }
|
|
*/
|
|
public function powerOn(Request $request, PowerOnVMAction $action): JsonResponse
|
|
{
|
|
$productId = $request->input('product');
|
|
if (!$productId) {
|
|
return response()->json(['success' => false, 'message' => 'Thiếu product id.'], 422);
|
|
}
|
|
|
|
$vm = $this->resolveVmById($productId, $request);
|
|
if ($vm instanceof JsonResponse) {
|
|
return $vm;
|
|
}
|
|
|
|
$lock = $this->acquireVmLock($vm);
|
|
if (!$lock) {
|
|
return $this->vmLocked();
|
|
}
|
|
|
|
$startedAt = now();
|
|
try {
|
|
$result = $action->execute($vm);
|
|
} finally {
|
|
$lock->release();
|
|
}
|
|
|
|
$this->activityLogger->log(
|
|
event: 'power_on',
|
|
logName: 'VM',
|
|
description: "Customer {$request->user()->email} bật VM: {$vm->name} (ID: {$vm->vmware_id})",
|
|
subject: $vm,
|
|
startedAt: $startedAt,
|
|
finishedAt: now(),
|
|
);
|
|
|
|
return $this->vmResponse($result, 'Đã gửi lệnh bật VM.');
|
|
}
|
|
|
|
/**
|
|
* POST /v1/system/vm-power-off
|
|
*
|
|
* Body: { "product": <ModuleVmware.id|vmware_id|service_uuid> }
|
|
*/
|
|
public function powerOff(Request $request, PowerOffVMAction $action): JsonResponse
|
|
{
|
|
$productId = $request->input('product');
|
|
if (!$productId) {
|
|
return response()->json(['success' => false, 'message' => 'Thiếu product id.'], 422);
|
|
}
|
|
|
|
$vm = $this->resolveVmById($productId, $request);
|
|
if ($vm instanceof JsonResponse) {
|
|
return $vm;
|
|
}
|
|
|
|
$lock = $this->acquireVmLock($vm);
|
|
if (!$lock) {
|
|
return $this->vmLocked();
|
|
}
|
|
|
|
$startedAt = now();
|
|
try {
|
|
$result = $action->execute($vm);
|
|
} finally {
|
|
$lock->release();
|
|
}
|
|
|
|
$this->activityLogger->log(
|
|
event: 'power_off',
|
|
logName: 'VM',
|
|
description: "Customer {$request->user()->email} tắt VM: {$vm->name} (ID: {$vm->vmware_id})",
|
|
subject: $vm,
|
|
startedAt: $startedAt,
|
|
finishedAt: now(),
|
|
);
|
|
|
|
return $this->vmResponse($result, 'Đã gửi lệnh tắt VM.');
|
|
}
|
|
|
|
public function restart(Request $request, vCenter $serviceVCenter): JsonResponse
|
|
{
|
|
$productId = $request->input('product');
|
|
if (!$productId) {
|
|
return response()->json(['error' => true, 'message' => 'Thiếu product id'], 422);
|
|
}
|
|
|
|
$vm = $this->resolveVmById($productId, $request);
|
|
if ($vm instanceof JsonResponse) {
|
|
return $vm;
|
|
}
|
|
|
|
$lock = $this->acquireVmLock($vm);
|
|
if (!$lock) {
|
|
return $this->vmLocked();
|
|
}
|
|
|
|
$startedAt = now();
|
|
try {
|
|
$result = $serviceVCenter->restartVM($vm, $vm->vmware_id);
|
|
} finally {
|
|
$lock->release();
|
|
}
|
|
|
|
if (is_string($result) || ($result['error'] ?? true)) {
|
|
return response()->json([
|
|
'error' => true,
|
|
'message' => is_string($result) ? $result : ($result['data'] ?? 'Không thể restart VM'),
|
|
], 400);
|
|
}
|
|
|
|
$this->activityLogger->log(
|
|
event: 'restart',
|
|
logName: 'VM',
|
|
description: "Customer {$request->user()->email} restart VM: {$vm->name} (ID: {$vm->vmware_id})",
|
|
subject: $vm,
|
|
startedAt: $startedAt,
|
|
finishedAt: now(),
|
|
);
|
|
|
|
return response()->json([
|
|
'error' => false,
|
|
'message' => 'Đang restart máy ảo vui lòng chờ!',
|
|
'data' => $result['data'] ?? 'success',
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* GET /v1/system/vm-power-state?product={id|uuid|vmware_id}
|
|
*
|
|
* Calls vSphere REST API directly: GET /rest/vcenter/vm/{vmware_id}/power
|
|
* Returns: { success: true, data: { state: "POWERED_ON"|"POWERED_OFF"|"SUSPENDED", clean_power_off: bool } }
|
|
*/
|
|
public function powerState(Request $request, vCenter $serviceVCenter): JsonResponse
|
|
{
|
|
$productId = $request->input('product');
|
|
if (!$productId) {
|
|
return response()->json(['success' => false, 'message' => 'Thiếu product id.'], 422);
|
|
}
|
|
|
|
$vm = $this->resolveVmById($productId, $request, requireActiveService: false);
|
|
if ($vm instanceof JsonResponse) {
|
|
return $vm;
|
|
}
|
|
|
|
$result = $serviceVCenter->getVmPowerState($vm, $vm->vmware_id);
|
|
|
|
if ($result === 'Login_Again') {
|
|
return response()->json(['success' => false, 'message' => 'Không thể đăng nhập vào vCenter.'], 400);
|
|
}
|
|
|
|
if (is_array($result) && ($result['error'] ?? true)) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => $result['data'] ?? 'Không thể lấy trạng thái VM.',
|
|
], 400);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'data' => [
|
|
'state' => $result['data']['state'] ?? null,
|
|
'clean_power_off' => $result['data']['clean_power_off'] ?? null,
|
|
],
|
|
]);
|
|
}
|
|
}
|