Add username and password fields to VirtualMachines model and database migration; update related email templates to use config for frontend URL

This commit is contained in:
baodev0
2026-07-14 11:10:38 +07:00
parent 8e1252567e
commit f035730a44
8 changed files with 114 additions and 18 deletions
@@ -227,6 +227,8 @@ class VCenterController extends Controller
'uuid' => $vm->uuid,
'vm_id' => $vm->vm_id,
'ip' => $vm->ip,
'username' => $vm->username,
'password' => $vm->password,
'power_state' => $vm->power_state,
'folder' => $vm->folder,
'cpu' => $vm->cpu,
@@ -18,6 +18,7 @@ use App\Services\ActivityLogger;
use App\Services\VmProvisionService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
class VmController extends Controller
@@ -48,7 +49,16 @@ class VmController extends Controller
return $vm;
}
$result = $action->execute($vm);
$lock = $this->acquireVmLock($vm);
if (!$lock) {
return $this->vmLocked();
}
try {
$result = $action->execute($vm);
} finally {
$lock->release();
}
$this->activityLogger->log(
event: 'power_on',
@@ -81,7 +91,16 @@ class VmController extends Controller
return $vm;
}
$result = $action->execute($vm);
$lock = $this->acquireVmLock($vm);
if (!$lock) {
return $this->vmLocked();
}
try {
$result = $action->execute($vm);
} finally {
$lock->release();
}
$this->activityLogger->log(
event: 'power_off',
@@ -149,15 +168,24 @@ class VmController extends Controller
$dns = $validated['dns'] ?? '8.8.8.8';
$raw = $action->execute(
$vm,
$validated['ip_address'],
$gateway,
$osType,
$dns,
$validated['guest_user'],
$validated['guest_password']
);
$lock = $this->acquireVmLock($vm, 120);
if (!$lock) {
return $this->vmLocked();
}
try {
$raw = $action->execute(
$vm,
$validated['ip_address'],
$gateway,
$osType,
$dns,
$validated['guest_user'],
$validated['guest_password']
);
} finally {
$lock->release();
}
// Always log the raw PowerShell output for debugging
Log::channel('Custom')->info('[changeIp] raw output', [
@@ -244,7 +272,16 @@ class VmController extends Controller
return $vm;
}
$result = $action->execute($vm, (string) $validated['new_port']);
$lock = $this->acquireVmLock($vm);
if (!$lock) {
return $this->vmLocked();
}
try {
$result = $action->execute($vm, (string) $validated['new_port']);
} finally {
$lock->release();
}
// changeRDPPortWindows returns array on success/failure or string on login fail
if ($result === 'Login_Again' || $result === 'Login_Fail') {
@@ -334,7 +371,16 @@ class VmController extends Controller
return $vm;
}
$result = $serviceVCenter->restartVM($vm, $vm->vmware_id);
$lock = $this->acquireVmLock($vm);
if (!$lock) {
return $this->vmLocked();
}
try {
$result = $serviceVCenter->restartVM($vm, $vm->vmware_id);
} finally {
$lock->release();
}
if (is_string($result) || ($result['error'] ?? true)) {
return response()->json([
@@ -352,7 +398,7 @@ class VmController extends Controller
return response()->json([
'error' => false,
'message' => 'Đã gửi lệnh restart VM',
'message' => 'Đang restart máy ảo vui lòng chờ!',
'data' => $result['data'] ?? 'success',
]);
}
@@ -380,6 +426,12 @@ class VmController extends Controller
return $vm;
}
// ponytail: don't release — lock expires after 5 min while the async job runs
$lock = $this->acquireVmLock($vm, 300);
if (!$lock) {
return $this->vmLocked();
}
// Detect OS family from VM's os_id record
$os = $vm->os_id ? Os::with('osGroup')->find($vm->os_id) : null;
$osGroupName = strtolower($os?->osGroup?->name ?? '');
@@ -509,6 +561,21 @@ class VmController extends Controller
return $this->resolveVmById($id, $request);
}
/** Try to acquire a per-VM operation lock. Returns null if already locked. */
private function acquireVmLock(ModuleVmware $vm, int $ttl = 60): ?\Illuminate\Contracts\Cache\Lock
{
$lock = Cache::lock("vm_op:{$vm->id}", $ttl);
return $lock->get() ? $lock : null;
}
private function vmLocked(): JsonResponse
{
return response()->json([
'success' => false,
'message' => 'VM đang có thao tác đang xử lý, vui lòng chờ rồi thử lại.',
], 429);
}
/**
* Normalise the array|string return value from Power ON/OFF actions.
*/