This is an automated email from the ASF dual-hosted git repository.
rohit pushed a commit to branch 4.20
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/4.20 by this push:
new e8ac477e9f8 engine/orchestration: fix missing vm powerstate update vm
state (#10407)
e8ac477e9f8 is described below
commit e8ac477e9f88389cbab754defd0add98dd192fc0
Author: Abhishek Kumar <[email protected]>
AuthorDate: Tue Feb 25 15:50:27 2025 +0530
engine/orchestration: fix missing vm powerstate update vm state (#10407)
* engine/orchestration: fix missing vm powerstate update vm state
Fixes #10406
VMs were not moving to Stopped state when PowerReportMissing is processed.
Signed-off-by: Abhishek Kumar <[email protected]>
* add unit tests
Signed-off-by: Abhishek Kumar <[email protected]>
* add license
Signed-off-by: Abhishek Kumar <[email protected]>
* add lenient
Signed-off-by: Abhishek Kumar <[email protected]>
---------
Signed-off-by: Abhishek Kumar <[email protected]>
---
.../cloud/vm/VirtualMachinePowerStateSyncImpl.java | 10 +-
.../vm/VirtualMachinePowerStateSyncImplTest.java | 107 +++++++++++++++++++++
2 files changed, 112 insertions(+), 5 deletions(-)
diff --git
a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachinePowerStateSyncImpl.java
b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachinePowerStateSyncImpl.java
index 4b344ac4299..7a1a39ec0f0 100644
---
a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachinePowerStateSyncImpl.java
+++
b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachinePowerStateSyncImpl.java
@@ -77,19 +77,19 @@ public class VirtualMachinePowerStateSyncImpl implements
VirtualMachinePowerStat
processReport(hostId, translatedInfo, force);
}
- private void updateAndPublishVmPowerStates(long hostId, Map<Long,
VirtualMachine.PowerState> instancePowerStates,
- Date updateTime) {
+ protected void updateAndPublishVmPowerStates(long hostId, Map<Long,
VirtualMachine.PowerState> instancePowerStates,
+ Date updateTime) {
if (instancePowerStates.isEmpty()) {
return;
}
Set<Long> vmIds = instancePowerStates.keySet();
- Map<Long, VirtualMachine.PowerState> notUpdated =
_instanceDao.updatePowerState(instancePowerStates, hostId,
- updateTime);
+ Map<Long, VirtualMachine.PowerState> notUpdated =
+ _instanceDao.updatePowerState(instancePowerStates, hostId,
updateTime);
if (notUpdated.size() > vmIds.size()) {
return;
}
for (Long vmId : vmIds) {
- if (!notUpdated.isEmpty() && !notUpdated.containsKey(vmId)) {
+ if (!notUpdated.containsKey(vmId)) {
logger.debug("VM state report is updated. {}, {}, power state:
{}",
() -> hostCache.get(hostId), () -> vmCache.get(vmId),
() -> instancePowerStates.get(vmId));
_messageBus.publish(null,
VirtualMachineManager.Topics.VM_POWER_STATE,
diff --git
a/engine/orchestration/src/test/java/com/cloud/vm/VirtualMachinePowerStateSyncImplTest.java
b/engine/orchestration/src/test/java/com/cloud/vm/VirtualMachinePowerStateSyncImplTest.java
new file mode 100644
index 00000000000..4df14fe22f3
--- /dev/null
+++
b/engine/orchestration/src/test/java/com/cloud/vm/VirtualMachinePowerStateSyncImplTest.java
@@ -0,0 +1,107 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.vm;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.cloudstack.framework.messagebus.MessageBus;
+import org.apache.cloudstack.framework.messagebus.PublishScope;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import com.cloud.host.HostVO;
+import com.cloud.host.dao.HostDao;
+import com.cloud.vm.dao.VMInstanceDao;
+
+@RunWith(MockitoJUnitRunner.class)
+public class VirtualMachinePowerStateSyncImplTest {
+ @Mock
+ MessageBus messageBus;
+ @Mock
+ VMInstanceDao instanceDao;
+ @Mock
+ HostDao hostDao;
+
+ @InjectMocks
+ VirtualMachinePowerStateSyncImpl virtualMachinePowerStateSync = new
VirtualMachinePowerStateSyncImpl();
+
+ @Before
+ public void setup() {
+
Mockito.lenient().when(instanceDao.findById(Mockito.anyLong())).thenReturn(Mockito.mock(VMInstanceVO.class));
+
Mockito.lenient().when(hostDao.findById(Mockito.anyLong())).thenReturn(Mockito.mock(HostVO.class));
+ }
+
+ @Test
+ public void test_updateAndPublishVmPowerStates_emptyStates() {
+ virtualMachinePowerStateSync.updateAndPublishVmPowerStates(1L, new
HashMap<>(), new Date());
+ Mockito.verify(instanceDao,
Mockito.never()).updatePowerState(Mockito.anyMap(), Mockito.anyLong(),
+ Mockito.any(Date.class));
+ }
+
+ @Test
+ public void test_updateAndPublishVmPowerStates_moreNotUpdated() {
+ Map<Long, VirtualMachine.PowerState> powerStates = new HashMap<>();
+ powerStates.put(1L, VirtualMachine.PowerState.PowerOff);
+ Map<Long, VirtualMachine.PowerState> notUpdated = new
HashMap<>(powerStates);
+ notUpdated.put(2L, VirtualMachine.PowerState.PowerOn);
+ Mockito.when(instanceDao.updatePowerState(Mockito.anyMap(),
Mockito.anyLong(),
+ Mockito.any(Date.class))).thenReturn(notUpdated);
+ virtualMachinePowerStateSync.updateAndPublishVmPowerStates(1L,
powerStates, new Date());
+ Mockito.verify(messageBus,
Mockito.never()).publish(Mockito.nullable(String.class), Mockito.anyString(),
+ Mockito.any(PublishScope.class), Mockito.anyLong());
+ }
+
+ @Test
+ public void test_updateAndPublishVmPowerStates_allUpdated() {
+ Map<Long, VirtualMachine.PowerState> powerStates = new HashMap<>();
+ powerStates.put(1L, VirtualMachine.PowerState.PowerOff);
+ Mockito.when(instanceDao.updatePowerState(Mockito.anyMap(),
Mockito.anyLong(),
+ Mockito.any(Date.class))).thenReturn(new HashMap<>());
+ virtualMachinePowerStateSync.updateAndPublishVmPowerStates(1L,
powerStates, new Date());
+ Mockito.verify(messageBus, Mockito.times(1)).publish(null,
+ VirtualMachineManager.Topics.VM_POWER_STATE,
+ PublishScope.GLOBAL,
+ 1L);
+ }
+
+ @Test
+ public void test_updateAndPublishVmPowerStates_partialUpdated() {
+ Map<Long, VirtualMachine.PowerState> powerStates = new HashMap<>();
+ powerStates.put(1L, VirtualMachine.PowerState.PowerOn);
+ powerStates.put(2L, VirtualMachine.PowerState.PowerOff);
+ Map<Long, VirtualMachine.PowerState> notUpdated = new HashMap<>();
+ notUpdated.put(2L, VirtualMachine.PowerState.PowerOff);
+ Mockito.when(instanceDao.updatePowerState(Mockito.anyMap(),
Mockito.anyLong(),
+ Mockito.any(Date.class))).thenReturn(notUpdated);
+ virtualMachinePowerStateSync.updateAndPublishVmPowerStates(1L,
powerStates, new Date());
+ Mockito.verify(messageBus, Mockito.times(1)).publish(null,
+ VirtualMachineManager.Topics.VM_POWER_STATE,
+ PublishScope.GLOBAL,
+ 1L);
+ Mockito.verify(messageBus, Mockito.never()).publish(null,
+ VirtualMachineManager.Topics.VM_POWER_STATE,
+ PublishScope.GLOBAL,
+ 2L);
+ }
+}