Files
portal-api/app/Jobs/VirtualMachine/ChangeVmPasswordJob.php
T

100 lines
3.1 KiB
PHP

<?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)
);
}
}