attempts(); Log::info('WaitVmReadyJob: polling', [ 'vm_id' => $this->vmId, 'attempt' => $attempt, 'os_family' => $this->osFamily, ]); // ── 1. Login to vCenter ─────────────────────────────────────────────── $vcenter = \App\Models\vCenter::find($this->vcenterId); if (!$vcenter) { Log::error('WaitVmReadyJob: vCenter model not found', ['vcenter_id' => $this->vcenterId]); $this->fail(new \RuntimeException("vCenter id={$this->vcenterId} not found")); return; } try { $provision->loginVCenter($vcenter, $vCenterService); } catch (\Throwable $e) { Log::warning('WaitVmReadyJob: vCenter login failed, will retry', [ 'vm_id' => $this->vmId, 'error' => $e->getMessage(), ]); $this->releaseOrFail(15, $attempt); return; } // ── 2. Check VMware Tools + guest IP ───────────────────────────────── // Invoke-VMScript requires VMware Tools to be running inside the guest. $guest = $provision->getVmGuestInfo($vCenterService, $this->vmId); Log::info('WaitVmReadyJob: guest info', [ 'vm_id' => $this->vmId, 'attempt' => $attempt, 'tools_running' => $guest['tools_running'], 'ip_address' => $guest['ip_address'], ]); if (!$guest['tools_running'] || $guest['ip_address'] === null) { Log::info('WaitVmReadyJob: VMware Tools not ready yet', ['vm_id' => $this->vmId]); $this->releaseOrFail(15, $attempt); return; } $guestIp = $guest['ip_address']; // ── 3. VM ready — dispatch password-change job ──────────────────────── Log::info('WaitVmReadyJob: VMware Tools ready, dispatching ChangePasswordViaVsphereJob', [ 'vm_id' => $this->vmId, 'guest_ip' => $guestIp, ]); ChangePasswordViaVsphereJob::dispatch( $this->moduleVmwareId, $this->vmId, $this->osFamily, ); } // ------------------------------------------------------------------------- public function failed(\Throwable $e): void { Log::error('WaitVmReadyJob: exceeded max attempts, marking VM failed', [ 'vm_id' => $this->vmId, 'module_vmware_id' => $this->moduleVmwareId, 'error' => $e->getMessage(), ]); \App\Models\ModuleVmware::where('id', $this->moduleVmwareId) ->update(['status' => 0]); } // ------------------------------------------------------------------------- private function releaseOrFail(int $delaySeconds, int $attempt): void { if ($attempt >= $this->tries) { $this->fail(new \RuntimeException( "VM {$this->vmId} not ready after {$this->tries} attempts (~10 min)", )); return; } $this->release($delaySeconds); } }