Add VM rebuild pipeline with isolated job chain and admin log API
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
<?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()]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user