add more tests

This commit is contained in:
Pearl Dsilva 2026-03-30 16:35:19 -04:00
parent f84a507224
commit e45a43db29
3 changed files with 518 additions and 1 deletions

View File

@ -0,0 +1,341 @@
// 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.hypervisor.kvm.resource.wrapper;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyMap;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.HashMap;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.ModifyStoragePoolAnswer;
import com.cloud.agent.api.ModifyStoragePoolCommand;
import com.cloud.agent.api.to.StorageFilerTO;
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
import com.cloud.hypervisor.kvm.storage.KVMStoragePool;
import com.cloud.hypervisor.kvm.storage.KVMStoragePoolManager;
import com.cloud.storage.Storage.StoragePoolType;
@RunWith(MockitoJUnitRunner.class)
public class LibvirtModifyStoragePoolCommandWrapperTest {
@Mock
private LibvirtComputingResource libvirtComputingResource;
@Mock
private KVMStoragePoolManager storagePoolManager;
@Mock
private ModifyStoragePoolCommand command;
@Mock
private StorageFilerTO storageFilerTO;
@Mock
private KVMStoragePool storagePool;
private LibvirtModifyStoragePoolCommandWrapper wrapper;
@Before
public void setUp() {
wrapper = new LibvirtModifyStoragePoolCommandWrapper();
when(libvirtComputingResource.getStoragePoolMgr()).thenReturn(storagePoolManager);
}
@Test
public void testAddClvmStoragePoolWithoutDetails() {
when(command.getAdd()).thenReturn(true);
when(command.getPool()).thenReturn(storageFilerTO);
when(command.getDetails()).thenReturn(null);
when(storageFilerTO.getUuid()).thenReturn("pool-uuid");
when(storageFilerTO.getHost()).thenReturn("192.168.1.100");
when(storageFilerTO.getPort()).thenReturn(0);
when(storageFilerTO.getPath()).thenReturn("/vg0");
when(storageFilerTO.getUserInfo()).thenReturn(null);
when(storageFilerTO.getType()).thenReturn(StoragePoolType.CLVM);
when(storagePool.getCapacity()).thenReturn(1000000L);
when(storagePool.getAvailable()).thenReturn(500000L);
when(storagePool.getDetails()).thenReturn(new HashMap<>());
when(storagePoolManager.createStoragePool(eq("pool-uuid"), eq("192.168.1.100"), eq(0),
eq("/vg0"), eq(null), eq(StoragePoolType.CLVM), anyMap()))
.thenReturn(storagePool);
Answer answer = wrapper.execute(command, libvirtComputingResource);
assertTrue("Answer should indicate success. Details: " + answer.getDetails(), answer.getResult());
assertTrue("Answer should be ModifyStoragePoolAnswer", answer instanceof ModifyStoragePoolAnswer);
// Verify the details were passed correctly
ArgumentCaptor<Map<String, String>> detailsCaptor = ArgumentCaptor.forClass(Map.class);
verify(storagePoolManager).createStoragePool(eq("pool-uuid"), eq("192.168.1.100"), eq(0),
eq("/vg0"), eq(null), eq(StoragePoolType.CLVM), detailsCaptor.capture());
Map<String, String> capturedDetails = detailsCaptor.getValue();
assertNotNull("Details should not be null", capturedDetails);
assertEquals("CLVM_SECURE_ZERO_FILL should default to false",
"false", capturedDetails.get(KVMStoragePool.CLVM_SECURE_ZERO_FILL));
}
@Test
public void testAddClvmNgStoragePoolWithEmptyDetails() {
when(command.getAdd()).thenReturn(true);
when(command.getPool()).thenReturn(storageFilerTO);
when(command.getDetails()).thenReturn(new HashMap<>());
when(storageFilerTO.getUuid()).thenReturn("pool-uuid");
when(storageFilerTO.getHost()).thenReturn("192.168.1.100");
when(storageFilerTO.getPort()).thenReturn(0);
when(storageFilerTO.getPath()).thenReturn("/vg0");
when(storageFilerTO.getUserInfo()).thenReturn(null);
when(storageFilerTO.getType()).thenReturn(StoragePoolType.CLVM_NG);
when(storagePool.getCapacity()).thenReturn(2000000L);
when(storagePool.getAvailable()).thenReturn(1000000L);
when(storagePool.getDetails()).thenReturn(new HashMap<>());
when(storagePoolManager.createStoragePool(eq("pool-uuid"), eq("192.168.1.100"), eq(0),
eq("/vg0"), eq(null), eq(StoragePoolType.CLVM_NG), anyMap()))
.thenReturn(storagePool);
Answer answer = wrapper.execute(command, libvirtComputingResource);
assertTrue("Answer should indicate success", answer.getResult());
ArgumentCaptor<Map<String, String>> detailsCaptor = ArgumentCaptor.forClass(Map.class);
verify(storagePoolManager).createStoragePool(eq("pool-uuid"), eq("192.168.1.100"), eq(0),
eq("/vg0"), eq(null), eq(StoragePoolType.CLVM_NG), detailsCaptor.capture());
Map<String, String> capturedDetails = detailsCaptor.getValue();
assertNotNull("Details should not be null", capturedDetails);
assertEquals("CLVM_SECURE_ZERO_FILL should default to false",
"false", capturedDetails.get(KVMStoragePool.CLVM_SECURE_ZERO_FILL));
}
@Test
public void testAddClvmStoragePoolWithExistingSecureZeroFillSetting() {
Map<String, String> details = new HashMap<>();
details.put(KVMStoragePool.CLVM_SECURE_ZERO_FILL, "true");
details.put("someOtherKey", "someValue");
when(command.getAdd()).thenReturn(true);
when(command.getPool()).thenReturn(storageFilerTO);
when(command.getDetails()).thenReturn(details);
when(storageFilerTO.getUuid()).thenReturn("pool-uuid");
when(storageFilerTO.getHost()).thenReturn("192.168.1.100");
when(storageFilerTO.getPort()).thenReturn(0);
when(storageFilerTO.getPath()).thenReturn("/vg0");
when(storageFilerTO.getUserInfo()).thenReturn(null);
when(storageFilerTO.getType()).thenReturn(StoragePoolType.CLVM);
when(storagePool.getCapacity()).thenReturn(1000000L);
when(storagePool.getAvailable()).thenReturn(500000L);
when(storagePool.getDetails()).thenReturn(new HashMap<>());
when(storagePoolManager.createStoragePool(eq("pool-uuid"), eq("192.168.1.100"), eq(0),
eq("/vg0"), eq(null), eq(StoragePoolType.CLVM), anyMap()))
.thenReturn(storagePool);
Answer answer = wrapper.execute(command, libvirtComputingResource);
assertTrue("Answer should indicate success", answer.getResult());
ArgumentCaptor<Map<String, String>> detailsCaptor = ArgumentCaptor.forClass(Map.class);
verify(storagePoolManager).createStoragePool(eq("pool-uuid"), eq("192.168.1.100"), eq(0),
eq("/vg0"), eq(null), eq(StoragePoolType.CLVM), detailsCaptor.capture());
Map<String, String> capturedDetails = detailsCaptor.getValue();
assertNotNull("Details should not be null", capturedDetails);
assertEquals("CLVM_SECURE_ZERO_FILL should preserve existing value",
"true", capturedDetails.get(KVMStoragePool.CLVM_SECURE_ZERO_FILL));
assertEquals("Other details should be preserved",
"someValue", capturedDetails.get("someOtherKey"));
}
@Test
public void testAddClvmStoragePoolPreservesOtherDetailsWhenAddingDefault() {
Map<String, String> details = new HashMap<>();
details.put("customKey1", "value1");
details.put("customKey2", "value2");
when(command.getAdd()).thenReturn(true);
when(command.getPool()).thenReturn(storageFilerTO);
when(command.getDetails()).thenReturn(details);
when(storageFilerTO.getUuid()).thenReturn("pool-uuid");
when(storageFilerTO.getHost()).thenReturn("192.168.1.100");
when(storageFilerTO.getPort()).thenReturn(0);
when(storageFilerTO.getPath()).thenReturn("/vg0");
when(storageFilerTO.getUserInfo()).thenReturn(null);
when(storageFilerTO.getType()).thenReturn(StoragePoolType.CLVM_NG);
when(storagePool.getCapacity()).thenReturn(1000000L);
when(storagePool.getAvailable()).thenReturn(500000L);
when(storagePool.getDetails()).thenReturn(new HashMap<>());
when(storagePoolManager.createStoragePool(eq("pool-uuid"), eq("192.168.1.100"), eq(0),
eq("/vg0"), eq(null), eq(StoragePoolType.CLVM_NG), anyMap()))
.thenReturn(storagePool);
Answer answer = wrapper.execute(command, libvirtComputingResource);
assertTrue("Answer should indicate success", answer.getResult());
ArgumentCaptor<Map<String, String>> detailsCaptor = ArgumentCaptor.forClass(Map.class);
verify(storagePoolManager).createStoragePool(eq("pool-uuid"), eq("192.168.1.100"), eq(0),
eq("/vg0"), eq(null), eq(StoragePoolType.CLVM_NG), detailsCaptor.capture());
Map<String, String> capturedDetails = detailsCaptor.getValue();
assertNotNull("Details should not be null", capturedDetails);
assertEquals("CLVM_SECURE_ZERO_FILL should default to false",
"false", capturedDetails.get(KVMStoragePool.CLVM_SECURE_ZERO_FILL));
assertEquals("Custom details should be preserved",
"value1", capturedDetails.get("customKey1"));
assertEquals("Custom details should be preserved",
"value2", capturedDetails.get("customKey2"));
}
@Test
public void testDeleteClvmStoragePoolSuccess() {
when(command.getAdd()).thenReturn(false);
when(command.getPool()).thenReturn(storageFilerTO);
when(command.getDetails()).thenReturn(null);
when(storageFilerTO.getUuid()).thenReturn("pool-uuid");
when(storageFilerTO.getType()).thenReturn(StoragePoolType.CLVM);
when(storagePoolManager.deleteStoragePool(StoragePoolType.CLVM, "pool-uuid", null))
.thenReturn(true);
Answer answer = wrapper.execute(command, libvirtComputingResource);
assertTrue("Answer should indicate success", answer.getResult());
verify(storagePoolManager).deleteStoragePool(StoragePoolType.CLVM, "pool-uuid", null);
}
@Test
public void testDeleteClvmNgStoragePoolSuccess() {
when(command.getAdd()).thenReturn(false);
when(command.getPool()).thenReturn(storageFilerTO);
when(command.getDetails()).thenReturn(null);
when(storageFilerTO.getUuid()).thenReturn("pool-uuid");
when(storageFilerTO.getType()).thenReturn(StoragePoolType.CLVM_NG);
when(storagePoolManager.deleteStoragePool(StoragePoolType.CLVM_NG, "pool-uuid", null))
.thenReturn(true);
Answer answer = wrapper.execute(command, libvirtComputingResource);
assertTrue("Answer should indicate success", answer.getResult());
verify(storagePoolManager).deleteStoragePool(StoragePoolType.CLVM_NG, "pool-uuid", null);
}
@Test
public void testDeleteClvmStoragePoolFailure() {
when(command.getAdd()).thenReturn(false);
when(command.getPool()).thenReturn(storageFilerTO);
when(command.getDetails()).thenReturn(null);
when(storageFilerTO.getUuid()).thenReturn("pool-uuid");
when(storageFilerTO.getType()).thenReturn(StoragePoolType.CLVM);
when(storagePoolManager.deleteStoragePool(StoragePoolType.CLVM, "pool-uuid", null))
.thenReturn(false);
Answer answer = wrapper.execute(command, libvirtComputingResource);
assertFalse("Answer should indicate failure", answer.getResult());
assertEquals("Failed to delete storage pool", answer.getDetails());
}
@Test
public void testAddClvmStoragePoolCreationFailure() {
when(command.getAdd()).thenReturn(true);
when(command.getPool()).thenReturn(storageFilerTO);
when(command.getDetails()).thenReturn(null);
when(storageFilerTO.getUuid()).thenReturn("pool-uuid");
when(storageFilerTO.getHost()).thenReturn("192.168.1.100");
when(storageFilerTO.getPort()).thenReturn(0);
when(storageFilerTO.getPath()).thenReturn("/vg0");
when(storageFilerTO.getUserInfo()).thenReturn(null);
when(storageFilerTO.getType()).thenReturn(StoragePoolType.CLVM);
when(storagePoolManager.createStoragePool(eq("pool-uuid"), eq("192.168.1.100"), eq(0),
eq("/vg0"), eq(null), eq(StoragePoolType.CLVM), anyMap()))
.thenReturn(null);
Answer answer = wrapper.execute(command, libvirtComputingResource);
assertFalse("Answer should indicate failure", answer.getResult());
assertEquals(" Failed to create storage pool", answer.getDetails());
}
@Test
public void testAddNfsStoragePoolDoesNotSetClvmSecureZeroFill() {
when(command.getAdd()).thenReturn(true);
when(command.getPool()).thenReturn(storageFilerTO);
when(command.getDetails()).thenReturn(null);
when(storageFilerTO.getUuid()).thenReturn("pool-uuid");
when(storageFilerTO.getHost()).thenReturn("nfs.server.com");
when(storageFilerTO.getPort()).thenReturn(0);
when(storageFilerTO.getPath()).thenReturn("/export/nfs");
when(storageFilerTO.getUserInfo()).thenReturn(null);
when(storageFilerTO.getType()).thenReturn(StoragePoolType.NetworkFilesystem);
when(storagePool.getCapacity()).thenReturn(1000000L);
when(storagePool.getAvailable()).thenReturn(500000L);
when(storagePool.getDetails()).thenReturn(new HashMap<>());
when(storagePoolManager.createStoragePool(eq("pool-uuid"), eq("nfs.server.com"), eq(0),
eq("/export/nfs"), eq(null), eq(StoragePoolType.NetworkFilesystem), anyMap()))
.thenReturn(storagePool);
Answer answer = wrapper.execute(command, libvirtComputingResource);
assertTrue("Answer should indicate success", answer.getResult());
ArgumentCaptor<Map<String, String>> detailsCaptor = ArgumentCaptor.forClass(Map.class);
verify(storagePoolManager).createStoragePool(eq("pool-uuid"), eq("nfs.server.com"), eq(0),
eq("/export/nfs"), eq(null), eq(StoragePoolType.NetworkFilesystem), detailsCaptor.capture());
Map<String, String> capturedDetails = detailsCaptor.getValue();
assertNotNull("Details should not be null", capturedDetails);
assertEquals("CLVM_SECURE_ZERO_FILL gets added for all pools",
"false", capturedDetails.get(KVMStoragePool.CLVM_SECURE_ZERO_FILL));
}
}

View File

@ -638,7 +638,7 @@ public class UriUtils {
if (url.startsWith("rbd://")) {
return getRbdUrlInfo(url);
}
if (url.startsWith("clvm://") || url.startsWith("clvm_ng://")) {
if (url.toLowerCase().startsWith("clvm://") || url.toLowerCase().startsWith("clvm_ng://")) {
return getClvmUrlInfo(url);
}
URI uri = new URI(UriUtils.encodeURIComponent(url));

View File

@ -283,4 +283,180 @@ public class UriUtilsTest {
Pair<String, Integer> url2 = UriUtils.validateUrl("https://www.apache.org");
Assert.assertEquals(url2.first(), "www.apache.org");
}
@Test
public void testGetClvmUriInfoBasic() {
String host = "10.11.12.13";
String url1 = String.format("clvm://%s/vg0/lv0", host);
String url2 = String.format("clvm://%s/vg0", host);
String url3 = String.format("clvm://%s", host);
UriUtils.UriInfo info1 = UriUtils.getUriInfo(url1);
Assert.assertEquals("clvm", info1.getScheme());
Assert.assertEquals(host, info1.getStorageHost());
Assert.assertEquals("/vg0/lv0", info1.getStoragePath());
Assert.assertNull(info1.getUserInfo());
Assert.assertEquals(-1, info1.getPort());
Assert.assertEquals(url1, info1.toString());
UriUtils.UriInfo info2 = UriUtils.getUriInfo(url2);
Assert.assertEquals("clvm", info2.getScheme());
Assert.assertEquals(host, info2.getStorageHost());
Assert.assertEquals("/vg0", info2.getStoragePath());
UriUtils.UriInfo info3 = UriUtils.getUriInfo(url3);
Assert.assertEquals("clvm", info3.getScheme());
Assert.assertEquals(host, info3.getStorageHost());
Assert.assertEquals("/", info3.getStoragePath());
}
@Test
public void testGetClvmNgUriInfoBasic() {
String host = "10.11.12.13";
String url1 = String.format("clvm_ng://%s/vg0/lv0", host);
String url2 = String.format("clvm_ng://%s/vg0", host);
String url3 = String.format("clvm_ng://%s", host);
UriUtils.UriInfo info1 = UriUtils.getUriInfo(url1);
Assert.assertEquals("clvm_ng", info1.getScheme());
Assert.assertEquals(host, info1.getStorageHost());
Assert.assertEquals("/vg0/lv0", info1.getStoragePath());
Assert.assertNull(info1.getUserInfo());
Assert.assertEquals(-1, info1.getPort());
Assert.assertEquals(url1, info1.toString());
UriUtils.UriInfo info2 = UriUtils.getUriInfo(url2);
Assert.assertEquals("clvm_ng", info2.getScheme());
Assert.assertEquals(host, info2.getStorageHost());
Assert.assertEquals("/vg0", info2.getStoragePath());
UriUtils.UriInfo info3 = UriUtils.getUriInfo(url3);
Assert.assertEquals("clvm_ng", info3.getScheme());
Assert.assertEquals(host, info3.getStorageHost());
Assert.assertEquals("/", info3.getStoragePath());
}
@Test
public void testGetClvmUriInfoNoHost() {
String url1 = "clvm:///vg0/lv0";
String url2 = "clvm_ng:///vg0/lv0";
UriUtils.UriInfo info1 = UriUtils.getUriInfo(url1);
Assert.assertEquals("clvm", info1.getScheme());
Assert.assertEquals("localhost", info1.getStorageHost());
Assert.assertEquals("/vg0/lv0", info1.getStoragePath());
UriUtils.UriInfo info2 = UriUtils.getUriInfo(url2);
Assert.assertEquals("clvm_ng", info2.getScheme());
Assert.assertEquals("localhost", info2.getStorageHost());
Assert.assertEquals("/vg0/lv0", info2.getStoragePath());
}
@Test
public void testGetClvmUriInfoMultipleSlashes() {
String url1 = "clvm://host1//vg0//lv0";
String url2 = "clvm_ng://host2///vg1///lv1";
UriUtils.UriInfo info1 = UriUtils.getUriInfo(url1);
Assert.assertEquals("clvm", info1.getScheme());
Assert.assertEquals("host1", info1.getStorageHost());
Assert.assertEquals("/vg0//lv0", info1.getStoragePath());
UriUtils.UriInfo info2 = UriUtils.getUriInfo(url2);
Assert.assertEquals("clvm_ng", info2.getScheme());
Assert.assertEquals("host2", info2.getStorageHost());
Assert.assertEquals("/vg1///lv1", info2.getStoragePath());
}
@Test
public void testGetClvmUriInfoComplexPaths() {
String host = "storage-node1";
String url1 = String.format("clvm://%s/vg-name-with-dashes/lv_name_with_underscores", host);
String url2 = String.format("clvm_ng://%s/vg.name.with.dots/lv-123-456", host);
UriUtils.UriInfo info1 = UriUtils.getUriInfo(url1);
Assert.assertEquals("clvm", info1.getScheme());
Assert.assertEquals(host, info1.getStorageHost());
Assert.assertEquals("/vg-name-with-dashes/lv_name_with_underscores", info1.getStoragePath());
UriUtils.UriInfo info2 = UriUtils.getUriInfo(url2);
Assert.assertEquals("clvm_ng", info2.getScheme());
Assert.assertEquals(host, info2.getStorageHost());
Assert.assertEquals("/vg.name.with.dots/lv-123-456", info2.getStoragePath());
}
@Test
public void testGetClvmUriInfoHostnames() {
String[] hosts = {
"localhost",
"node1",
"storage-node-1",
"storage.example.com",
"10.0.0.1",
"192.168.1.100"
};
for (String host : hosts) {
String clvmUrl = String.format("clvm://%s/vg0/lv0", host);
String clvmNgUrl = String.format("clvm_ng://%s/vg0/lv0", host);
UriUtils.UriInfo clvmInfo = UriUtils.getUriInfo(clvmUrl);
Assert.assertEquals("clvm", clvmInfo.getScheme());
Assert.assertEquals(host, clvmInfo.getStorageHost());
Assert.assertEquals("/vg0/lv0", clvmInfo.getStoragePath());
UriUtils.UriInfo clvmNgInfo = UriUtils.getUriInfo(clvmNgUrl);
Assert.assertEquals("clvm_ng", clvmNgInfo.getScheme());
Assert.assertEquals(host, clvmNgInfo.getStorageHost());
Assert.assertEquals("/vg0/lv0", clvmNgInfo.getStoragePath());
}
}
@Test
public void testGetClvmUriInfoToString() {
String url1 = "clvm://host1/vg0/lv0";
String url2 = "clvm_ng://host2/vg1/lv1";
String url3 = "clvm://localhost/vg0";
Assert.assertEquals(url1, UriUtils.getUriInfo(url1).toString());
Assert.assertEquals(url2, UriUtils.getUriInfo(url2).toString());
Assert.assertEquals(url3, UriUtils.getUriInfo(url3).toString());
}
@Test
public void testGetClvmUriInfoCaseInsensitive() {
String url1 = "CLVM://host1/vg0/lv0";
String url2 = "ClVm://host2/vg1/lv1";
String url3 = "CLVM_NG://host3/vg2/lv2";
String url4 = "clvm_NG://host4/vg3/lv3";
UriUtils.UriInfo info1 = UriUtils.getUriInfo(url1);
Assert.assertEquals("clvm", info1.getScheme());
Assert.assertEquals("host1", info1.getStorageHost());
UriUtils.UriInfo info2 = UriUtils.getUriInfo(url2);
Assert.assertEquals("clvm", info2.getScheme());
Assert.assertEquals("host2", info2.getStorageHost());
UriUtils.UriInfo info3 = UriUtils.getUriInfo(url3);
Assert.assertEquals("clvm_ng", info3.getScheme());
Assert.assertEquals("host3", info3.getStorageHost());
UriUtils.UriInfo info4 = UriUtils.getUriInfo(url4);
Assert.assertEquals("clvm_ng", info4.getScheme());
Assert.assertEquals("host4", info4.getStorageHost());
}
@Test
public void testGetClvmUriInfoIntegration() {
String host = "clvm-host";
String clvmUrl = String.format("clvm://%s/vg0/lv0", host);
String clvmNgUrl = String.format("clvm_ng://%s/vg1/lv1", host);
testGetUriInfoInternal(clvmUrl, host);
testGetUriInfoInternal(clvmNgUrl, host);
}
}