130 lines
3.9 KiB
PHP
130 lines
3.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Jobs\VirtualMachine\Rebuild;
|
|
|
|
use App\Models\ModuleVmware;
|
|
use App\Models\ReinstallLog;
|
|
use App\Models\Service;
|
|
use App\Services\VirtualMachine\Rebuild\VmRebuildCloneService;
|
|
use App\Services\VirtualMachine\Rebuild\VmRebuildService;
|
|
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;
|
|
use Throwable;
|
|
|
|
/**
|
|
* RebuildVirtualMachineJob
|
|
*
|
|
* First step of the isolated rebuild pipeline.
|
|
*
|
|
* [1] Build RebuildContext from current DB state (idempotent reload).
|
|
* [2] Power off old VM (best-effort).
|
|
* [3] Clone new VM from chosen OS template.
|
|
* [4] Power on new VM + wait for VMware Tools.
|
|
* [5] Dispatch RebuildAssignIpJob with the new vSphere vm_id.
|
|
*
|
|
* On failure: old VM remains active, no DB references are swapped, no IP
|
|
* change, no deletion. ReinstallLog is marked failed; service is reverted
|
|
* to 'active' for visibility.
|
|
*/
|
|
final class RebuildVirtualMachineJob implements ShouldQueue
|
|
{
|
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
|
|
|
public int $tries = 1;
|
|
public int $timeout = 900;
|
|
|
|
public function __construct(
|
|
public readonly int $moduleVmwareId,
|
|
public readonly int $newOsId,
|
|
public readonly int $reinstallLogId,
|
|
) {
|
|
}
|
|
|
|
public function handle(
|
|
VmRebuildService $rebuildService,
|
|
VmRebuildCloneService $cloneService,
|
|
): void {
|
|
Log::info('RebuildVirtualMachineJob: start', [
|
|
'module_vmware_id' => $this->moduleVmwareId,
|
|
'new_os_id' => $this->newOsId,
|
|
'reinstall_log_id' => $this->reinstallLogId,
|
|
]);
|
|
|
|
try {
|
|
$ctx = $rebuildService->buildContext($this->moduleVmwareId, $this->newOsId);
|
|
|
|
$this->markServiceStatus($ctx->serviceId, 'rebuilding');
|
|
|
|
$cloneService->powerOffOldVm($ctx);
|
|
|
|
$newVmId = $cloneService->clone($ctx);
|
|
$ctx = $ctx->withNewVmId($newVmId);
|
|
|
|
$cloneService->powerOnAndWaitTools($ctx);
|
|
|
|
$this->markLog([
|
|
'status' => ReinstallLog::STATUS_IN_PROGRESS,
|
|
'new_vmware_id' => $newVmId,
|
|
'started_at' => now(),
|
|
]);
|
|
|
|
RebuildAssignIpJob::dispatch(
|
|
$this->moduleVmwareId,
|
|
$this->newOsId,
|
|
$newVmId,
|
|
$this->reinstallLogId,
|
|
)->onQueue('default');
|
|
|
|
Log::info('RebuildVirtualMachineJob: completed, IP job dispatched', [
|
|
'module_vmware_id' => $this->moduleVmwareId,
|
|
'new_vm_id' => $newVmId,
|
|
]);
|
|
} catch (Throwable $e) {
|
|
$this->onFailure($e);
|
|
throw $e;
|
|
}
|
|
}
|
|
|
|
public function failed(Throwable $e): void
|
|
{
|
|
$this->onFailure($e);
|
|
}
|
|
|
|
private function onFailure(Throwable $e): void
|
|
{
|
|
Log::error('RebuildVirtualMachineJob: failed — old VM preserved', [
|
|
'module_vmware_id' => $this->moduleVmwareId,
|
|
'error' => $e->getMessage(),
|
|
]);
|
|
|
|
ModuleVmware::where('id', $this->moduleVmwareId)->update(['status' => 1]);
|
|
$service = Service::where('vm_id', $this->moduleVmwareId)->first();
|
|
if ($service) {
|
|
$service->update(['status' => 'active']);
|
|
}
|
|
|
|
$this->markLog([
|
|
'status' => ReinstallLog::STATUS_FAILED,
|
|
'error_message' => $e->getMessage(),
|
|
]);
|
|
}
|
|
|
|
private function markServiceStatus(?int $serviceId, string $status): void
|
|
{
|
|
if ($serviceId) {
|
|
Service::where('id', $serviceId)->update(['status' => $status]);
|
|
}
|
|
}
|
|
|
|
private function markLog(array $attrs): void
|
|
{
|
|
ReinstallLog::where('id', $this->reinstallLogId)->update($attrs + ['updated_at' => now()]);
|
|
}
|
|
}
|