Skip to content

Fix HA-enabled VMs stuck in Running after out-of-band stop (OOM-kill)#13

Open
poddm wants to merge 1 commit into
att:att/4.22.0.0from
poddm:mp/FLXCLD-2814
Open

Fix HA-enabled VMs stuck in Running after out-of-band stop (OOM-kill)#13
poddm wants to merge 1 commit into
att:att/4.22.0.0from
poddm:mp/FLXCLD-2814

Conversation

@poddm

@poddm poddm commented Jul 22, 2026

Copy link
Copy Markdown

Description

This PR fixes HA-enabled KVM VMs getting stuck in Running after an out-of-band stop (e.g. the QEMU process is OOM-killed while the host stays up).

Actual behaviour (before): On a power-off report, VirtualMachineManagerImpl.handlePowerOffReportWithNoPendingJobsOnVM() calls _haMgr.scheduleRestart(vm, true). That path:

  1. Invokes advanceStop(), which submits a VM work job and blocks on it. This handler runs on the AgentManager-Handler thread, and the VM job queue does not dispatch jobs from that context, so it blocks indefinitely.
  2. Relies on KVMInvestigator, which only checks whether the host is up — not the VM. Since the host is alive (only QEMU died), it concludes the VM is alive and exits without changing state. The VM stays Running forever and is never restarted.

Expected behaviour (after): In the HA branch, the blocking scheduleRestart() call is replaced with a direct, non-blocking path (the power-state report has already confirmed the VM is off):

  1. Release VM resources (DB-level NICs/volumes — no agent round-trip).
  2. Transition the VM to Stopped.
  3. Insert an HA work item directly into op_ha_work with Step.Scheduled (guarding against a null/zero host_id to avoid FK violations).

The HA worker thread then picks up the work item on its next poll and restarts the VM on an available host.

The fix is placed in VirtualMachineManagerImpl where the method is defined; the runtime bean ClusteredVirtualMachineManagerImpl inherits it. This replaces a prior extension-side override (ATTClusteredVirtualMachineManagerImpl, removed in a companion PR) that copied the entire private handler chain to change one branch.

Fixes: FLXCLD-2814

Types of changes

  • Breaking change (fix or feature that would cause existing functionality to change)
  • New feature (non-breaking change which adds functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • Enhancement (improves an existing feature and functionality)
  • Cleanup (Code refactoring and cleanup, that may add test cases)
  • Build/CI
  • Test (unit or integration test code)

Feature/Enhancement Scale or Bug Severity

Feature/Enhancement Scale

  • Major
  • Minor

Bug Severity

  • BLOCKER
  • Critical
  • Major
  • Minor
  • Trivial

Screenshots (if appropriate):

N/A

How Has This Been Tested?

Environment: KVM cluster on the management server with HA enabled (ha.enabled/force.ha and ha.vm.restart.hostup in effect).

  • OOM-killed an HA-enabled VM by kill -9 on the QEMU PID while leaving the host UP; confirmed the VM transitions Running → Stopped and is then restarted on an available host via an op_ha_work (Step.Scheduled) item.
  • Verified the AgentManager-Handler thread no longer blocks while processing the power-off report (no thread stall / no backlog of power-state reports).
  • Verified a non-HA VM stopped out-of-band still syncs to Stopped without triggering a restart.
  • Verified a VM that already has a pending HA task is not double-scheduled.
  • Verified host_id guard: when no valid last host is available, the work item is skipped (warning logged) rather than persisting a row that violates the op_ha_work FK constraint.

How did you try to break this feature and the system with this change?

  • Killed QEMU repeatedly to force multiple back-to-back power-off reports for the same VM, checking for duplicate HA work / double restarts.
  • Tested a VM whose host_id was already null at report time to exercise the FK-guard path.
  • Ran with a mix of HA and non-HA VMs, and across VMware/Hyperv-excluded hypervisor checks, to confirm only the intended KVM HA path is affected.
  • Confirmed the change compiles with no new errors (the qualified HighAvailabilityManager.Step avoids collision with the existing ItWorkVO.Step import).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant