kvm: support multiple local storage pools (#6147)

* kvm: support multiple local storage pools

* Update #6147: add method configureLocalStorage

* Update #6147: add method validateLocalStorageUUID

* Update #6147: remove underscore

* Update #6147: add unit tests
This commit is contained in:
Wei Zhou 2022-03-25 15:40:30 +01:00 committed by GitHub
parent f0993ce098
commit 5845de4004
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 106 additions and 23 deletions

View File

@ -215,6 +215,8 @@ import org.apache.cloudstack.utils.bytescale.ByteScaleUtils;
public class LibvirtComputingResource extends ServerResourceBase implements ServerResource, VirtualRouterDeployer {
private static final Logger s_logger = Logger.getLogger(LibvirtComputingResource.class);
private static final String CONFIG_VALUES_SEPARATOR = ",";
private static final String LEGACY = "legacy";
private static final String SECURE = "secure";
@ -347,8 +349,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
protected String _pool;
protected String _localGateway;
private boolean _canBridgeFirewall;
protected String _localStoragePath;
protected String _localStorageUUID;
protected boolean _noMemBalloon = false;
protected String _guestCpuArch;
protected String _guestCpuMode;
@ -382,6 +382,13 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
protected String _agentHooksVmOnStopScript = "libvirt-vm-state-change.groovy";
protected String _agentHooksVmOnStopMethod = "onStop";
protected static final String LOCAL_STORAGE_PATH = "local.storage.path";
protected static final String LOCAL_STORAGE_UUID = "local.storage.uuid";
protected static final String DEFAULT_LOCAL_STORAGE_PATH = "/var/lib/libvirt/images/";
protected List<String> localStoragePaths = new ArrayList<>();
protected List<String> localStorageUUIDs = new ArrayList<>();
private static final String CONFIG_DRIVE_ISO_DISK_LABEL = "hdd";
private static final int CONFIG_DRIVE_ISO_DEVICE_ID = 4;
@ -1004,10 +1011,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
}
}
_localStoragePath = (String)params.get("local.storage.path");
if (_localStoragePath == null) {
_localStoragePath = "/var/lib/libvirt/images/";
}
configureLocalStorage(params);
/* Directory to use for Qemu sockets like for the Qemu Guest Agent */
_qemuSocketsPath = new File("/var/lib/libvirt/qemu");
@ -1016,14 +1020,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
_qemuSocketsPath = new File(_qemuSocketsPathVar);
}
final File storagePath = new File(_localStoragePath);
_localStoragePath = storagePath.getAbsolutePath();
_localStorageUUID = (String)params.get("local.storage.uuid");
if (_localStorageUUID == null) {
_localStorageUUID = UUID.randomUUID().toString();
}
value = (String)params.get("scripts.timeout");
_timeout = Duration.standardSeconds(NumbersUtil.parseInt(value, 30 * 60));
@ -1288,6 +1284,43 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
return true;
}
protected void configureLocalStorage(final Map<String, Object> params) throws ConfigurationException {
String localStoragePath = (String)params.get(LOCAL_STORAGE_PATH);
if (localStoragePath == null) {
localStoragePath = DEFAULT_LOCAL_STORAGE_PATH;
}
String localStorageUUIDString = (String)params.get(LOCAL_STORAGE_UUID);
if (localStorageUUIDString == null) {
localStorageUUIDString = UUID.randomUUID().toString();
}
String[] localStorageRelativePaths = localStoragePath.split(CONFIG_VALUES_SEPARATOR);
String[] localStorageUUIDStrings = localStorageUUIDString.split(CONFIG_VALUES_SEPARATOR);
if (localStorageRelativePaths.length != localStorageUUIDStrings.length) {
throw new ConfigurationException("The path and UUID of local storage pools have different length");
}
for (String localStorageRelativePath : localStorageRelativePaths) {
final File storagePath = new File(localStorageRelativePath);
localStoragePaths.add(storagePath.getAbsolutePath());
}
for (String localStorageUUID : localStorageUUIDStrings) {
validateLocalStorageUUID(localStorageUUID);
localStorageUUIDs.add(localStorageUUID);
}
}
private void validateLocalStorageUUID(String localStorageUUID) throws ConfigurationException {
if (StringUtils.isBlank(localStorageUUID)) {
throw new ConfigurationException("The UUID of local storage pools must be non-blank");
}
try {
UUID.fromString(localStorageUUID);
} catch (IllegalArgumentException ex) {
throw new ConfigurationException("The UUID of local storage pool is invalid : " + localStorageUUID);
}
}
public boolean configureHostParams(final Map<String, String> params) {
final File file = PropertiesUtil.findConfigFile("agent.properties");
if (file == null) {
@ -3285,12 +3318,31 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
_hostDistro = cmd.getHostDetails().get("Host.OS");
}
List<StartupCommand> startupCommands = new ArrayList<>();
startupCommands.add(cmd);
for (int i = 0; i < localStoragePaths.size(); i++) {
String localStoragePath = localStoragePaths.get(i);
String localStorageUUID = localStorageUUIDs.get(i);
StartupStorageCommand sscmd = createLocalStoragePool(localStoragePath, localStorageUUID, cmd);
if (sscmd != null) {
startupCommands.add(sscmd);
}
}
StartupCommand[] startupCommandsArray = new StartupCommand[startupCommands.size()];
int i = 0;
for (StartupCommand startupCommand : startupCommands) {
startupCommandsArray[i] = startupCommand;
i++;
}
return startupCommandsArray;
}
private StartupStorageCommand createLocalStoragePool(String localStoragePath, String localStorageUUID, StartupRoutingCommand cmd) {
StartupStorageCommand sscmd = null;
try {
final KVMStoragePool localStoragePool = _storagePoolMgr.createStoragePool(_localStorageUUID, "localhost", -1, _localStoragePath, "", StoragePoolType.Filesystem);
final KVMStoragePool localStoragePool = _storagePoolMgr.createStoragePool(localStorageUUID, "localhost", -1, localStoragePath, "", StoragePoolType.Filesystem);
final com.cloud.agent.api.StoragePoolInfo pi =
new com.cloud.agent.api.StoragePoolInfo(localStoragePool.getUuid(), cmd.getPrivateIpAddress(), _localStoragePath, _localStoragePath,
new com.cloud.agent.api.StoragePoolInfo(localStoragePool.getUuid(), cmd.getPrivateIpAddress(), localStoragePath, localStoragePath,
StoragePoolType.Filesystem, localStoragePool.getCapacity(), localStoragePool.getAvailable());
sscmd = new StartupStorageCommand();
@ -3301,12 +3353,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
} catch (final CloudRuntimeException e) {
s_logger.debug("Unable to initialize local storage pool: " + e);
}
if (sscmd != null) {
return new StartupCommand[] {cmd, sscmd};
} else {
return new StartupCommand[] {cmd};
}
return sscmd;
}
public String diskUuidToSerial(String uuid) {

View File

@ -5841,4 +5841,40 @@ public class LibvirtComputingResourceTest {
return true;
}));
}
private void configLocalStorageTests(Map<String, Object> params) throws ConfigurationException {
LibvirtComputingResource libvirtComputingResourceSpy = Mockito.spy(new LibvirtComputingResource());
libvirtComputingResourceSpy.configureLocalStorage(params);
}
@Test
public void testConfigureLocalStorageWithEmptyParams() throws ConfigurationException {
Map<String, Object> params = new HashMap<>();
configLocalStorageTests(params);
}
@Test
public void testConfigureLocalStorageWithMultiplePaths() throws ConfigurationException {
Map<String, Object> params = new HashMap<>();
params.put(LibvirtComputingResource.LOCAL_STORAGE_PATH, "/var/lib/libvirt/images/,/var/lib/libvirt/images2/");
params.put(LibvirtComputingResource.LOCAL_STORAGE_UUID, UUID.randomUUID().toString() + "," + UUID.randomUUID().toString());
configLocalStorageTests(params);
}
@Test(expected = ConfigurationException.class)
public void testConfigureLocalStorageWithDifferentLength() throws ConfigurationException {
Map<String, Object> params = new HashMap<>();
params.put(LibvirtComputingResource.LOCAL_STORAGE_PATH, "/var/lib/libvirt/images/,/var/lib/libvirt/images2/");
params.put(LibvirtComputingResource.LOCAL_STORAGE_UUID, UUID.randomUUID().toString());
configLocalStorageTests(params);
}
@Test(expected = ConfigurationException.class)
public void testConfigureLocalStorageWithInvalidUUID() throws ConfigurationException {
Map<String, Object> params = new HashMap<>();
params.put(LibvirtComputingResource.LOCAL_STORAGE_PATH, "/var/lib/libvirt/images/");
params.put(LibvirtComputingResource.LOCAL_STORAGE_UUID, "111111");
configLocalStorageTests(params);
}
}