From 93782bb5f151e95c4493b8b6d2180c6c63e7eb0b Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Mon, 30 Mar 2026 11:40:55 -0400 Subject: [PATCH] add tests --- .../motion/AncientDataMotionStrategyTest.java | 210 ++++++++++++++++++ .../storage/LibvirtStorageAdaptorTest.java | 60 +++++ 2 files changed, 270 insertions(+) diff --git a/engine/storage/datamotion/src/test/java/org/apache/cloudstack/storage/motion/AncientDataMotionStrategyTest.java b/engine/storage/datamotion/src/test/java/org/apache/cloudstack/storage/motion/AncientDataMotionStrategyTest.java index e167cc0a965..eefc7312bd9 100755 --- a/engine/storage/datamotion/src/test/java/org/apache/cloudstack/storage/motion/AncientDataMotionStrategyTest.java +++ b/engine/storage/datamotion/src/test/java/org/apache/cloudstack/storage/motion/AncientDataMotionStrategyTest.java @@ -28,14 +28,18 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.never; import static org.mockito.Mockito.any; +import com.cloud.storage.ClvmLockManager; import com.cloud.storage.Storage; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePool; import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope; +import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; import org.apache.cloudstack.engine.subsystem.api.storage.HostScope; +import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; import org.apache.cloudstack.engine.subsystem.api.storage.StorageCacheManager; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; @@ -288,4 +292,210 @@ public class AncientDataMotionStrategyTest { canBypassSecondaryStorage = (boolean) method.invoke(strategy, destVolumeInfo, srcVolumeInfo); Assert.assertTrue(canBypassSecondaryStorage); } + + @Test + public void testUpdateLockHostForVolume_CLVMPool_SetsLockHost() throws Exception { + Method method = AncientDataMotionStrategy.class.getDeclaredMethod( + "updateLockHostForVolume", + EndPoint.class, + DataObject.class); + method.setAccessible(true); + + EndPoint endPoint = Mockito.mock(EndPoint.class); + VolumeInfo volumeInfo = Mockito.mock(VolumeInfo.class); + DataStore dataStore = Mockito.mock(DataStore.class, Mockito.withSettings().extraInterfaces(StoragePool.class)); + ClvmLockManager clvmLockManager = Mockito.mock(ClvmLockManager.class); + + Field clvmLockManagerField = AncientDataMotionStrategy.class.getDeclaredField("clvmLockManager"); + clvmLockManagerField.setAccessible(true); + clvmLockManagerField.set(strategy, clvmLockManager); + + Long hostId = 123L; + Long volumeId = 456L; + String volumeUuid = "test-volume-uuid"; + + Mockito.when(endPoint.getId()).thenReturn(hostId); + Mockito.when(volumeInfo.getDataStore()).thenReturn(dataStore); + Mockito.when(volumeInfo.getId()).thenReturn(volumeId); + Mockito.when(volumeInfo.getUuid()).thenReturn(volumeUuid); + Mockito.when(((StoragePool) dataStore).getPoolType()).thenReturn(Storage.StoragePoolType.CLVM); + Mockito.when(clvmLockManager.getClvmLockHostId(volumeId, volumeUuid)).thenReturn(null); + + method.invoke(strategy, endPoint, volumeInfo); + + Mockito.verify(clvmLockManager).setClvmLockHostId(volumeId, hostId); + } + + @Test + public void testUpdateLockHostForVolume_CLVM_NG_Pool_SetsLockHost() throws Exception { + Method method = AncientDataMotionStrategy.class.getDeclaredMethod( + "updateLockHostForVolume", + EndPoint.class, + DataObject.class); + method.setAccessible(true); + + EndPoint endPoint = Mockito.mock(EndPoint.class); + VolumeInfo volumeInfo = Mockito.mock(VolumeInfo.class); + DataStore dataStore = Mockito.mock(DataStore.class, Mockito.withSettings().extraInterfaces(StoragePool.class)); + ClvmLockManager clvmLockManager = Mockito.mock(ClvmLockManager.class); + + Field clvmLockManagerField = AncientDataMotionStrategy.class.getDeclaredField("clvmLockManager"); + clvmLockManagerField.setAccessible(true); + clvmLockManagerField.set(strategy, clvmLockManager); + + Long hostId = 789L; + Long volumeId = 101L; + String volumeUuid = "test-clvm-ng-volume-uuid"; + + Mockito.when(endPoint.getId()).thenReturn(hostId); + Mockito.when(volumeInfo.getDataStore()).thenReturn(dataStore); + Mockito.when(volumeInfo.getId()).thenReturn(volumeId); + Mockito.when(volumeInfo.getUuid()).thenReturn(volumeUuid); + Mockito.when(((StoragePool) dataStore).getPoolType()).thenReturn(Storage.StoragePoolType.CLVM_NG); + Mockito.when(clvmLockManager.getClvmLockHostId(volumeId, volumeUuid)).thenReturn(null); + + try { + method.invoke(strategy, endPoint, volumeInfo); + } catch (InvocationTargetException e) { + e.getCause().printStackTrace(); + throw e; + } + + Mockito.verify(clvmLockManager).setClvmLockHostId(volumeId, hostId); + } + + @Test + public void testUpdateLockHostForVolume_NonCLVMPool_DoesNotSetLockHost() throws Exception { + Method method = AncientDataMotionStrategy.class.getDeclaredMethod( + "updateLockHostForVolume", + EndPoint.class, + DataObject.class); + method.setAccessible(true); + + EndPoint endPoint = Mockito.mock(EndPoint.class); + VolumeInfo volumeInfo = Mockito.mock(VolumeInfo.class); + // Create mock that implements both DataStore and StoragePool interfaces + DataStore dataStore = Mockito.mock(DataStore.class, Mockito.withSettings().extraInterfaces(StoragePool.class)); + ClvmLockManager clvmLockManager = Mockito.mock(ClvmLockManager.class); + + Field clvmLockManagerField = AncientDataMotionStrategy.class.getDeclaredField("clvmLockManager"); + clvmLockManagerField.setAccessible(true); + clvmLockManagerField.set(strategy, clvmLockManager); + + Mockito.when(volumeInfo.getDataStore()).thenReturn(dataStore); + Mockito.when(((StoragePool) dataStore).getPoolType()).thenReturn(Storage.StoragePoolType.NetworkFilesystem); + + method.invoke(strategy, endPoint, volumeInfo); + + Mockito.verify(clvmLockManager, never()).setClvmLockHostId(any(Long.class), any(Long.class)); + Mockito.verify(clvmLockManager, never()).getClvmLockHostId(any(Long.class), any(String.class)); + } + + @Test + public void testUpdateLockHostForVolume_ExistingLockHost_DoesNotOverwrite() throws Exception { + Method method = AncientDataMotionStrategy.class.getDeclaredMethod( + "updateLockHostForVolume", + EndPoint.class, + DataObject.class); + method.setAccessible(true); + + EndPoint endPoint = Mockito.mock(EndPoint.class); + VolumeInfo volumeInfo = Mockito.mock(VolumeInfo.class); + DataStore dataStore = Mockito.mock(DataStore.class, Mockito.withSettings().extraInterfaces(StoragePool.class)); + ClvmLockManager clvmLockManager = Mockito.mock(ClvmLockManager.class); + + Field clvmLockManagerField = AncientDataMotionStrategy.class.getDeclaredField("clvmLockManager"); + clvmLockManagerField.setAccessible(true); + clvmLockManagerField.set(strategy, clvmLockManager); + + Long hostId = 555L; + Long existingHostId = 666L; + Long volumeId = 777L; + String volumeUuid = "existing-lock-volume-uuid"; + + Mockito.when(endPoint.getId()).thenReturn(hostId); + Mockito.when(volumeInfo.getDataStore()).thenReturn(dataStore); + Mockito.when(volumeInfo.getId()).thenReturn(volumeId); + Mockito.when(volumeInfo.getUuid()).thenReturn(volumeUuid); + Mockito.when(((StoragePool) dataStore).getPoolType()).thenReturn(Storage.StoragePoolType.CLVM); + Mockito.when(clvmLockManager.getClvmLockHostId(volumeId, volumeUuid)).thenReturn(existingHostId); + + method.invoke(strategy, endPoint, volumeInfo); + + Mockito.verify(clvmLockManager, never()).setClvmLockHostId(any(Long.class), any(Long.class)); + Mockito.verify(clvmLockManager).getClvmLockHostId(volumeId, volumeUuid); + } + + @Test + public void testUpdateLockHostForVolume_NullEndPoint_DoesNotSetLockHost() throws Exception { + Method method = AncientDataMotionStrategy.class.getDeclaredMethod( + "updateLockHostForVolume", + EndPoint.class, + DataObject.class); + method.setAccessible(true); + + VolumeInfo volumeInfo = + Mockito.mock(VolumeInfo.class); + ClvmLockManager clvmLockManager = + Mockito.mock(ClvmLockManager.class); + + Field clvmLockManagerField = AncientDataMotionStrategy.class.getDeclaredField("clvmLockManager"); + clvmLockManagerField.setAccessible(true); + clvmLockManagerField.set(strategy, clvmLockManager); + + method.invoke(strategy, null, volumeInfo); + + Mockito.verify(clvmLockManager, never()).setClvmLockHostId(any(Long.class), any(Long.class)); + Mockito.verify(clvmLockManager, never()).getClvmLockHostId(any(Long.class), any(String.class)); + } + + @Test + public void testUpdateLockHostForVolume_NonVolumeDataObject_DoesNotSetLockHost() throws Exception { + Method method = AncientDataMotionStrategy.class.getDeclaredMethod( + "updateLockHostForVolume", + EndPoint.class, + DataObject.class); + method.setAccessible(true); + + EndPoint endPoint = + Mockito.mock(EndPoint.class); + SnapshotInfo snapshotInfo = + Mockito.mock(SnapshotInfo.class); + ClvmLockManager clvmLockManager = + Mockito.mock(ClvmLockManager.class); + + Field clvmLockManagerField = AncientDataMotionStrategy.class.getDeclaredField("clvmLockManager"); + clvmLockManagerField.setAccessible(true); + clvmLockManagerField.set(strategy, clvmLockManager); + + method.invoke(strategy, endPoint, snapshotInfo); + + Mockito.verify(clvmLockManager, never()).setClvmLockHostId(any(Long.class), any(Long.class)); + Mockito.verify(clvmLockManager, never()).getClvmLockHostId(any(Long.class), any(String.class)); + } + + @Test + public void testUpdateLockHostForVolume_NullPool_DoesNotSetLockHost() throws Exception { + Method method = AncientDataMotionStrategy.class.getDeclaredMethod( + "updateLockHostForVolume", + EndPoint.class, + DataObject.class); + method.setAccessible(true); + + EndPoint endPoint = + Mockito.mock(EndPoint.class); + VolumeInfo volumeInfo = + Mockito.mock(VolumeInfo.class); + ClvmLockManager clvmLockManager = + Mockito.mock(ClvmLockManager.class); + + Field clvmLockManagerField = AncientDataMotionStrategy.class.getDeclaredField("clvmLockManager"); + clvmLockManagerField.setAccessible(true); + clvmLockManagerField.set(strategy, clvmLockManager); + + method.invoke(strategy, endPoint, volumeInfo); + + Mockito.verify(clvmLockManager, never()).setClvmLockHostId(any(Long.class), any(Long.class)); + Mockito.verify(clvmLockManager, never()).getClvmLockHostId(any(Long.class), any(String.class)); + } } diff --git a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptorTest.java b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptorTest.java index c6e5ef866e1..cfb7a113683 100644 --- a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptorTest.java +++ b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptorTest.java @@ -582,4 +582,64 @@ public class LibvirtStorageAdaptorTest { throw e.getCause(); } } + + @Test(expected = CloudRuntimeException.class) + public void testGetPhysicalDiskViaDirectBlockDevice_VolumeNotFound() throws Throwable { + String volumeUuid = UUID.randomUUID().toString(); + String vgName = "testvg"; + + Mockito.when(mockPool.getLocalPath()).thenReturn(vgName); + + mockScriptConstruction = Mockito.mockConstruction(Script.class, + (mock, context) -> { + when(mock.execute()).thenReturn(" Volume not found"); + }); + + Method method = LibvirtStorageAdaptor.class.getDeclaredMethod( + "getPhysicalDiskViaDirectBlockDevice", + String.class, KVMStoragePool.class); + method.setAccessible(true); + + try { + method.invoke(libvirtStorageAdaptor, volumeUuid, mockPool); + } catch (java.lang.reflect.InvocationTargetException e) { + throw e.getCause(); + } + } + + @Test(expected = CloudRuntimeException.class) + public void testGetPhysicalDiskViaDirectBlockDevice_NullPoolPath() throws Throwable { + String volumeUuid = UUID.randomUUID().toString(); + + Mockito.when(mockPool.getLocalPath()).thenReturn(null); + + Method method = LibvirtStorageAdaptor.class.getDeclaredMethod( + "getPhysicalDiskViaDirectBlockDevice", + String.class, KVMStoragePool.class); + method.setAccessible(true); + + try { + method.invoke(libvirtStorageAdaptor, volumeUuid, mockPool); + } catch (java.lang.reflect.InvocationTargetException e) { + throw e.getCause(); + } + } + + @Test(expected = CloudRuntimeException.class) + public void testGetPhysicalDiskViaDirectBlockDevice_EmptyPoolPath() throws Throwable { + String volumeUuid = UUID.randomUUID().toString(); + + Mockito.when(mockPool.getLocalPath()).thenReturn(""); + + Method method = LibvirtStorageAdaptor.class.getDeclaredMethod( + "getPhysicalDiskViaDirectBlockDevice", + String.class, KVMStoragePool.class); + method.setAccessible(true); + + try { + method.invoke(libvirtStorageAdaptor, volumeUuid, mockPool); + } catch (java.lang.reflect.InvocationTargetException e) { + throw e.getCause(); + } + } }