refactor: implement centralized cache key management and add utility traits for vCenter SSH operations.
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Jobs\VirtualMachine;
|
||||
|
||||
use App\Http\Facade\SignRSA;
|
||||
use App\Models\vCenter;
|
||||
use App\Services\VmProvisionService;
|
||||
use App\Services\VsphereHostSshService;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* ChangeVmPasswordJob
|
||||
*
|
||||
* Customer-initiated VM guest OS password change.
|
||||
*
|
||||
* Flow:
|
||||
* [1] Load vCenter credentials
|
||||
* [2] SSH → jumphost → changePwdLinux.ps1 / changePwdWindows.ps1
|
||||
* [3] Parse SUCCESS / ERROR from output
|
||||
* [4] On SUCCESS → persist encrypted new password to DB
|
||||
* [5] On FAIL → retry (up to $tries times)
|
||||
*/
|
||||
class ChangeVmPasswordJob implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public int $tries = 3;
|
||||
public int $timeout = 180;
|
||||
public int $backoff = 30;
|
||||
|
||||
public function __construct(
|
||||
public readonly int $moduleVmwareId,
|
||||
public readonly string $vmId,
|
||||
public readonly string $osFamily,
|
||||
public readonly string $newPassword,
|
||||
public readonly string $currentGuestPassword,
|
||||
) {}
|
||||
|
||||
public function handle(VmProvisionService $provision, VsphereHostSshService $ssh): void
|
||||
{
|
||||
Log::info('ChangeVmPasswordJob: starting', [
|
||||
'module_vmware_id' => $this->moduleVmwareId,
|
||||
'vm_id' => $this->vmId,
|
||||
'os_family' => $this->osFamily,
|
||||
]);
|
||||
|
||||
$vcenter = vCenter::first();
|
||||
if (!$vcenter) {
|
||||
throw new \RuntimeException('No vCenter record found in module_vcenter');
|
||||
}
|
||||
|
||||
$output = $ssh->changePasswordCustomer(
|
||||
vmId: $this->vmId,
|
||||
newPassword: $this->newPassword,
|
||||
currentGuestPassword: $this->currentGuestPassword,
|
||||
osFamily: $this->osFamily,
|
||||
vcenterHost: $vcenter->host,
|
||||
vcenterUser: $vcenter->user,
|
||||
vcenterPassword: SignRSA::DecryptFunc($vcenter->password),
|
||||
);
|
||||
|
||||
$this->assertSuccess($output);
|
||||
|
||||
// Persist encrypted password to DB
|
||||
$provision->updatePassword($this->moduleVmwareId, $this->newPassword);
|
||||
|
||||
Log::info('ChangeVmPasswordJob: password changed successfully', [
|
||||
'module_vmware_id' => $this->moduleVmwareId,
|
||||
'vm_id' => $this->vmId,
|
||||
]);
|
||||
}
|
||||
|
||||
public function failed(\Throwable $e): void
|
||||
{
|
||||
Log::error('ChangeVmPasswordJob: all retries exhausted', [
|
||||
'module_vmware_id' => $this->moduleVmwareId,
|
||||
'vm_id' => $this->vmId,
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
}
|
||||
|
||||
private function assertSuccess(string $output): void
|
||||
{
|
||||
if (str_contains(strtoupper(trim($output)), 'SUCCESS')) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new \RuntimeException(
|
||||
"Password change script failed for VM {$this->vmId}. Output: " . trim($output)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -75,7 +75,7 @@ class WaitStatusVirtualMachine implements ShouldQueue
|
||||
|
||||
// Action Completed
|
||||
// 1. Clear Cache again (to ensure next fetch gets new state)
|
||||
\Illuminate\Support\Facades\Cache::forget('vm_info_' . $this->vmware_id);
|
||||
\Illuminate\Support\Facades\Cache::forget(\App\Support\Cache\CacheKey::build('vm', 'info', ['id' => $this->vmware_id]));
|
||||
|
||||
// 2. Update DB Status and Dispatch Event
|
||||
$product = \App\Models\ModuleVmware::where('vmware_id', $this->vmware_id)->first();
|
||||
|
||||
@@ -57,7 +57,7 @@ class RebootVmJob implements ShouldQueue
|
||||
Log::info("RebootVmJob: Command sent successfully for VM {$product->vmware_id}");
|
||||
|
||||
// Clear VM info cache
|
||||
\Illuminate\Support\Facades\Cache::forget('vm_info_' . $product->vmware_id);
|
||||
\Illuminate\Support\Facades\Cache::forget(\App\Support\Cache\CacheKey::build('vm', 'info', ['id' => $product->vmware_id]));
|
||||
|
||||
// Dispatch Event to Frontend
|
||||
\App\Events\VirtualMachineStatusChanged::dispatch(
|
||||
|
||||
@@ -59,7 +59,7 @@ class StartVmJob implements ShouldQueue
|
||||
Log::info("StartVmJob: Command sent successfully for VM {$product->vmware_id}");
|
||||
|
||||
// Clear VM info cache
|
||||
\Illuminate\Support\Facades\Cache::forget('vm_info_' . $product->vmware_id);
|
||||
\Illuminate\Support\Facades\Cache::forget(\App\Support\Cache\CacheKey::build('vm', 'info', ['id' => $product->vmware_id]));
|
||||
|
||||
// Dispatch Event to Frontend
|
||||
\App\Events\VirtualMachineStatusChanged::dispatch(
|
||||
|
||||
@@ -57,7 +57,7 @@ class StopVmJob implements ShouldQueue
|
||||
|
||||
if (is_array($result) && isset($result['error']) && $result['error'] === false) {
|
||||
// Clear VM info cache
|
||||
\Illuminate\Support\Facades\Cache::forget('vm_info_' . $product->vmware_id);
|
||||
\Illuminate\Support\Facades\Cache::forget(\App\Support\Cache\CacheKey::build('vm', 'info', ['id' => $product->vmware_id]));
|
||||
|
||||
// Dispatch Event to Frontend
|
||||
\App\Events\VirtualMachineStatusChanged::dispatch(
|
||||
|
||||
@@ -126,7 +126,7 @@ class UpdateVMInfoJob implements ShouldQueue
|
||||
];
|
||||
|
||||
// Cache the result for 5 minutes
|
||||
$cacheKey = "vm_info_{$this->vmId}";
|
||||
$cacheKey = \App\Support\Cache\CacheKey::build('vm', 'info', ['id' => $this->vmId]);
|
||||
Cache::put($cacheKey, $vmInfo, 300);
|
||||
|
||||
Log::info('VM info updated successfully', ['vm_id' => $this->vmId]);
|
||||
|
||||
Reference in New Issue
Block a user