|
209 | 209 | import com.cloud.exception.ResourceUnavailableException; |
210 | 210 | import com.cloud.exception.StorageAccessException; |
211 | 211 | import com.cloud.exception.StorageUnavailableException; |
| 212 | +import com.cloud.ha.HaWorkVO; |
212 | 213 | import com.cloud.ha.HighAvailabilityManager; |
213 | 214 | import com.cloud.ha.HighAvailabilityManager.WorkType; |
| 215 | +import com.cloud.ha.dao.HighAvailabilityDao; |
214 | 216 | import com.cloud.host.Host; |
215 | 217 | import com.cloud.host.HostVO; |
216 | 218 | import com.cloud.host.Status; |
@@ -361,6 +363,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac |
361 | 363 | @Inject |
362 | 364 | private HighAvailabilityManager _haMgr; |
363 | 365 | @Inject |
| 366 | + private HighAvailabilityDao _haDao; |
| 367 | + @Inject |
364 | 368 | private HostPodDao _podDao; |
365 | 369 | @Inject |
366 | 370 | private DataCenterDao _dcDao; |
@@ -5395,9 +5399,43 @@ private void handlePowerOffReportWithNoPendingJobsOnVM(final VMInstanceVO vm) { |
5395 | 5399 | && HaVmRestartHostUp.value() |
5396 | 5400 | && vm.getHypervisorType() != HypervisorType.VMware |
5397 | 5401 | && vm.getHypervisorType() != HypervisorType.Hyperv) { |
5398 | | - logger.info("Detected out-of-band stop of a HA enabled VM {}, will schedule restart.", vm); |
| 5402 | + logger.info("Detected out-of-band stop of HA enabled VM {}, transitioning to Stopped and scheduling HA restart (investigate=false).", vm); |
5399 | 5403 | if (!_haMgr.hasPendingHaWork(vm.getId())) { |
5400 | | - _haMgr.scheduleRestart(vm, true); |
| 5404 | + // The power state report already confirmed the VM is off |
| 5405 | + // (e.g. OOM-killed QEMU process). We cannot use _haMgr.scheduleRestart() because it |
| 5406 | + // calls advanceStop(), which submits a VM work job and blocks waiting for completion. |
| 5407 | + // This code runs on the AgentManager-Handler thread, and the VM job queue does not |
| 5408 | + // dispatch jobs from this context — causing an indefinite block that leaves the VM |
| 5409 | + // stuck in Running. Instead we release resources, transition to Stopped, and insert |
| 5410 | + // an HA work item directly into op_ha_work (Step.Scheduled) for the HA worker to pick up. |
| 5411 | + final VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); |
| 5412 | + releaseVmResources(profile, true); |
| 5413 | + |
| 5414 | + // Save lastHostId before transition (stateTransitTo sets hostId=null) |
| 5415 | + final Long lastHostId = vm.getHostId(); |
| 5416 | + try { |
| 5417 | + stateTransitTo(vm, VirtualMachine.Event.FollowAgentPowerOffReport, null); |
| 5418 | + } catch (final NoTransitionException e) { |
| 5419 | + logger.warn("Failed to transition VM {} to Stopped state: {}", vm, e.getMessage()); |
| 5420 | + return; |
| 5421 | + } |
| 5422 | + |
| 5423 | + _alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_SYNC, vm.getDataCenterId(), vm.getPodIdToDeployIn(), |
| 5424 | + VM_SYNC_ALERT_SUBJECT, String.format("VM %s(%s) stopped out-of-band (OOM-killed or crashed). HA restart scheduled.", |
| 5425 | + vm.getHostName(), vm.getInstanceName())); |
| 5426 | + |
| 5427 | + // Insert HA work item directly — bypasses advanceStop/job queue entirely |
| 5428 | + final VMInstanceVO refreshedVm = _vmDao.findByUuid(vm.getUuid()); |
| 5429 | + final Long haHostId = lastHostId != null ? lastHostId : refreshedVm.getLastHostId(); |
| 5430 | + if (haHostId == null || haHostId == 0L) { |
| 5431 | + logger.warn("Cannot schedule HA for VM {} — no valid host_id available (would violate FK constraint).", vm); |
| 5432 | + } else { |
| 5433 | + final HaWorkVO work = new HaWorkVO(refreshedVm.getId(), refreshedVm.getType(), |
| 5434 | + WorkType.HA, HighAvailabilityManager.Step.Scheduled, haHostId, |
| 5435 | + refreshedVm.getState(), 0, refreshedVm.getUpdated(), null); |
| 5436 | + _haDao.persist(work); |
| 5437 | + logger.info("Scheduled VM for HA: {}", refreshedVm); |
| 5438 | + } |
5401 | 5439 | } else { |
5402 | 5440 | logger.info("VM {} already has a pending HA task working on it.", vm); |
5403 | 5441 | } |
|
0 commit comments