diff --git a/server/src/main/java/com/cloud/ha/HighAvailabilityManagerImpl.java b/server/src/main/java/com/cloud/ha/HighAvailabilityManagerImpl.java index e3f67420a2ab..bd63d595f844 100644 --- a/server/src/main/java/com/cloud/ha/HighAvailabilityManagerImpl.java +++ b/server/src/main/java/com/cloud/ha/HighAvailabilityManagerImpl.java @@ -433,6 +433,11 @@ public boolean scheduleMigration(final VMInstanceVO vm) { @Override public void scheduleRestart(VMInstanceVO vm, boolean investigate, ReasonType reasonType) { + if (VirtualMachine.State.Error.equals(vm.getState())) { + logger.info("Skipping HA restart for VM {} because it is in Error state", vm); + return; + } + if (!VmHaEnabled.valueIn(vm.getDataCenterId())) { String message = String.format("Unable to schedule restart for the VM %s (%d), VM high availability manager is disabled.", vm.getName(), vm.getId()); if (logger.isDebugEnabled()) { @@ -600,6 +605,11 @@ protected Long restart(final HaWorkVO work) { logger.info("Unable to find vm: " + vmId); return null; } + if (VirtualMachine.State.Error.equals(vm.getState())) { + logger.info("Skipping HA restart for VM {} because it is in Error state", vm); + return null; + } + if (checkAndCancelWorkIfNeeded(work)) { return null; } diff --git a/server/src/test/java/com/cloud/ha/HighAvailabilityManagerImplTest.java b/server/src/test/java/com/cloud/ha/HighAvailabilityManagerImplTest.java index 9274bd1ff085..8ab941b000e4 100644 --- a/server/src/test/java/com/cloud/ha/HighAvailabilityManagerImplTest.java +++ b/server/src/test/java/com/cloud/ha/HighAvailabilityManagerImplTest.java @@ -267,6 +267,54 @@ public void scheduleRestartHostNotSupported() { highAvailabilityManager.scheduleRestart(vm, true); } + @Test + public void scheduleRestartVMInErrorState() { + VMInstanceVO vm = Mockito.mock(VMInstanceVO.class); + Mockito.when(vm.getState()).thenReturn(VirtualMachine.State.Error); + + highAvailabilityManager.scheduleRestart(vm, true); + + Mockito.verifyNoInteractions(_haDao, _itMgr, _alertMgr); + } + + @Test + public void restartVMInErrorState() { + long vmId = 1L; + long workId = 2L; + VMInstanceVO vm = Mockito.mock(VMInstanceVO.class); + + Mockito.when(mockWork.getInstanceId()).thenReturn(vmId); + Mockito.when(mockWork.getId()).thenReturn(workId); + Mockito.when(_haDao.listFutureHaWorkForVm(vmId, workId)).thenReturn(new ArrayList()); + Mockito.when(_haDao.listRunningHaWorkForVm(vmId)).thenReturn(new ArrayList()); + Mockito.when(_itMgr.findById(vmId)).thenReturn(vm); + Mockito.when(vm.getState()).thenReturn(VirtualMachine.State.Error); + + assertNull(highAvailabilityManager.restart(mockWork)); + + Mockito.verifyNoInteractions(_hostDao, _alertMgr, userVmManager, volumeMgr); + Mockito.verify(mockWork, Mockito.never()).setStep(Mockito.any()); + } + + @Test + public void restartVMNotInErrorStateContinuesProcessing() { + long vmId = 1L; + long workId = 2L; + VMInstanceVO vm = Mockito.mock(VMInstanceVO.class); + + Mockito.when(mockWork.getInstanceId()).thenReturn(vmId); + Mockito.when(mockWork.getId()).thenReturn(workId); + Mockito.when(_haDao.listFutureHaWorkForVm(vmId, workId)).thenReturn(new ArrayList()); + Mockito.when(_haDao.listRunningHaWorkForVm(vmId)).thenReturn(new ArrayList()); + Mockito.when(_itMgr.findById(vmId)).thenReturn(vm); + Mockito.when(vm.getState()).thenReturn(VirtualMachine.State.Running); + Mockito.doReturn(true).when(highAvailabilityManagerSpy).checkAndCancelWorkIfNeeded(mockWork); + + assertNull(highAvailabilityManagerSpy.restart(mockWork)); + + Mockito.verify(highAvailabilityManagerSpy).checkAndCancelWorkIfNeeded(mockWork); + } + @Test public void scheduleStop() { VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);