$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, ]); (new Telegram)->SendRebuildStepNotification($ctx->vmName, $ctx->ip, 'Clone VM mới', true); } catch (Throwable $e) { $this->onFailure($e); throw $e; } } public function failed(Throwable $e): void { $this->onFailure($e); } private function onFailure(Throwable $e): void { if ($this->failureHandled) { return; } $this->failureHandled = true; 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(), ]); $vm = ModuleVmware::with('customer')->find($this->moduleVmwareId); (new Telegram)->SendRebuildStepNotification( $vm->name ?? "VM #{$this->moduleVmwareId}", $vm->ip ?? '', 'Clone VM mới', false, $e->getMessage(), ); VmRebuildFailedJob::dispatch([ 'customer_email' => $vm?->customer?->email, 'customer_name' => $vm?->customer?->fullname, 'vm_name' => $vm->name ?? "VM #{$this->moduleVmwareId}", 'ip' => $vm->ip ?? '', 'module_vmware_id' => $this->moduleVmwareId, ]); } 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()]); } }