From 5a7e47d6bb7a89128419f5640144075115c528dd Mon Sep 17 00:00:00 2001 From: Rene Peinthor Date: Wed, 29 May 2024 10:51:27 +0200 Subject: [PATCH] linstor: make getDevicePath more robust Before we only asked the first resource for the device path, if those resource was down or broken, we wouldn't get a device path at all. Now we go through all resource and use the first device path we find, as device path are always equal for all resources. --- .../kvm/storage/LinstorStorageAdaptor.java | 24 ++++---------- .../LinstorPrimaryDataStoreDriverImpl.java | 27 ++------------- .../storage/datastore/util/LinstorUtil.java | 33 +++++++++++++++++++ 3 files changed, 42 insertions(+), 42 deletions(-) diff --git a/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java b/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java index 632b92c80fd3..a3c283699a2b 100644 --- a/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java +++ b/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java @@ -157,24 +157,12 @@ public KVMPhysicalDisk getPhysicalDisk(String name, KVMStoragePool pool) List volumeDefs = api.volumeDefinitionList(rscName, null, null); final long size = volumeDefs.isEmpty() ? 0 : volumeDefs.get(0).getSizeKib() * 1024; - List resources = api.viewResources( - Collections.emptyList(), - Collections.singletonList(rscName), - Collections.emptyList(), - null, - null, - null); - if (!resources.isEmpty() && !resources.get(0).getVolumes().isEmpty()) { - final String devPath = resources.get(0).getVolumes().get(0).getDevicePath(); - final KVMPhysicalDisk kvmDisk = new KVMPhysicalDisk(devPath, name, pool); - kvmDisk.setFormat(QemuImg.PhysicalDiskFormat.RAW); - kvmDisk.setSize(size); - kvmDisk.setVirtualSize(size); - return kvmDisk; - } else { - s_logger.error("Linstor: viewResources didn't return resources or volumes for " + rscName); - throw new CloudRuntimeException("Linstor: viewResources didn't return resources or volumes."); - } + final String devicePath = LinstorUtil.getDevicePath(api, rscName); + final KVMPhysicalDisk kvmDisk = new KVMPhysicalDisk(devicePath, name, pool); + kvmDisk.setFormat(QemuImg.PhysicalDiskFormat.RAW); + kvmDisk.setSize(size); + kvmDisk.setVirtualSize(size); + return kvmDisk; } catch (ApiException apiEx) { s_logger.error(apiEx); throw new CloudRuntimeException(apiEx.getBestMessage(), apiEx); diff --git a/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/driver/LinstorPrimaryDataStoreDriverImpl.java b/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/driver/LinstorPrimaryDataStoreDriverImpl.java index d2d13eafc483..8b9b768d2a42 100644 --- a/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/driver/LinstorPrimaryDataStoreDriverImpl.java +++ b/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/driver/LinstorPrimaryDataStoreDriverImpl.java @@ -28,7 +28,6 @@ import com.linbit.linstor.api.model.ResourceDefinitionCreate; import com.linbit.linstor.api.model.ResourceDefinitionModify; import com.linbit.linstor.api.model.ResourceGroupSpawn; -import com.linbit.linstor.api.model.ResourceWithVolumes; import com.linbit.linstor.api.model.Snapshot; import com.linbit.linstor.api.model.SnapshotRestore; import com.linbit.linstor.api.model.VolumeDefinition; @@ -38,7 +37,6 @@ import javax.inject.Inject; import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -315,25 +313,6 @@ private String checkLinstorAnswers(@Nonnull ApiCallRcList answers) { return answers.stream().filter(ApiCallRc::isError).findFirst().map(ApiCallRc::getMessage).orElse(null); } - private String getDeviceName(DevelopersApi linstorApi, String rscName) throws ApiException { - List resources = linstorApi.viewResources( - Collections.emptyList(), - Collections.singletonList(rscName), - Collections.emptyList(), - null, - null, - null); - if (!resources.isEmpty() && !resources.get(0).getVolumes().isEmpty()) - { - s_logger.info("Linstor: Created drbd device: " + resources.get(0).getVolumes().get(0).getDevicePath()); - return resources.get(0).getVolumes().get(0).getDevicePath(); - } else - { - s_logger.error("Linstor: viewResources didn't return resources or volumes."); - throw new CloudRuntimeException("Linstor: viewResources didn't return resources or volumes."); - } - } - private void applyQoSSettings(StoragePoolVO storagePool, DevelopersApi api, String rscName, Long maxIops) throws ApiException { @@ -420,7 +399,7 @@ private String createResource(VolumeInfo vol, StoragePoolVO storagePoolVO) applyAuxProps(linstorApi, rscName, vol.getName(), vol.getAttachedVmName()); applyQoSSettings(storagePoolVO, linstorApi, rscName, vol.getMaxIops()); - return getDeviceName(linstorApi, rscName); + return LinstorUtil.getDevicePath(linstorApi, rscName); } catch (ApiException apiEx) { s_logger.error("Linstor: ApiEx - " + apiEx.getMessage()); @@ -473,7 +452,7 @@ private String cloneResource(long csCloneId, VolumeInfo volumeInfo, StoragePoolV applyAuxProps(linstorApi, rscName, volumeInfo.getName(), volumeInfo.getAttachedVmName()); applyQoSSettings(storagePoolVO, linstorApi, rscName, volumeInfo.getMaxIops()); - return getDeviceName(linstorApi, rscName); + return LinstorUtil.getDevicePath(linstorApi, rscName); } catch (ApiException apiEx) { s_logger.error("Linstor: ApiEx - " + apiEx.getMessage()); throw new CloudRuntimeException(apiEx.getBestMessage(), apiEx); @@ -520,7 +499,7 @@ private String createResourceFromSnapshot(long csSnapshotId, String rscName, Sto applyAuxProps(linstorApi, rscName, volumeVO.getName(), null); applyQoSSettings(storagePoolVO, linstorApi, rscName, volumeVO.getMaxIops()); - return getDeviceName(linstorApi, rscName); + return LinstorUtil.getDevicePath(linstorApi, rscName); } catch (ApiException apiEx) { s_logger.error("Linstor: ApiEx - " + apiEx.getMessage()); throw new CloudRuntimeException(apiEx.getBestMessage(), apiEx); diff --git a/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/util/LinstorUtil.java b/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/util/LinstorUtil.java index c8544fd3e3e4..8957ae1e16a5 100644 --- a/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/util/LinstorUtil.java +++ b/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/util/LinstorUtil.java @@ -25,6 +25,7 @@ import com.linbit.linstor.api.model.ProviderKind; import com.linbit.linstor.api.model.Resource; import com.linbit.linstor.api.model.ResourceGroup; +import com.linbit.linstor.api.model.ResourceWithVolumes; import com.linbit.linstor.api.model.StoragePool; import java.util.Collections; @@ -109,4 +110,36 @@ public static boolean isResourceInUse(DevelopersApi api, String rscName) throws s_logger.error("isResourceInUse: null returned from resourceList"); return false; } + + /** + * Try to get the device path for the given resource name. + * This could be made a bit more direct after java-linstor api is fixed for layer data subtypes. + * @param api developer api object to use + * @param rscName resource name to get the device path + * @return The device path of the resource. + * @throws ApiException if Linstor API call failed. + * @throws CloudRuntimeException if no device path could be found. + */ + public static String getDevicePath(DevelopersApi api, String rscName) throws ApiException, CloudRuntimeException { + List resources = api.viewResources( + Collections.emptyList(), + Collections.singletonList(rscName), + Collections.emptyList(), + null, + null, + null); + for (ResourceWithVolumes rsc : resources) { + if (!rsc.getVolumes().isEmpty()) { + // CloudStack resource always only have 1 volume + String devicePath = rsc.getVolumes().get(0).getDevicePath(); + if (devicePath != null && !devicePath.isEmpty()) { + s_logger.info(String.format("getDevicePath: %s -> %s", rscName, devicePath)); + return devicePath; + } + } + } + + s_logger.error("viewResources didn't return resources or volumes for " + rscName); + throw new CloudRuntimeException("Linstor: viewResources didn't return resources or volumes for " + rscName); + } }