From 001c769054b85c8aad92540d06f5f94a72516d83 Mon Sep 17 00:00:00 2001 From: Rene Peinthor Date: Fri, 8 Mar 2024 09:22:49 +0100 Subject: [PATCH] Linstor 4.19 fix selecting non enabled hosts (#8653) * linstor: cleanup resource if copy from template failed * linstor: do not use non enabled hosts for copy operations --- .../LinstorPrimaryDataStoreDriverImpl.java | 27 +++++++------ .../storage/datastore/util/LinstorUtil.java | 38 ++++++++++++------- 2 files changed, 37 insertions(+), 28 deletions(-) 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 ca98dc3dd46..328b3d21d0a 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 @@ -59,6 +59,7 @@ import com.cloud.api.storage.LinstorRevertBackupSnapshotCommand; import com.cloud.configuration.Config; import com.cloud.host.Host; import com.cloud.host.dao.HostDao; +import com.cloud.resource.ResourceState; import com.cloud.storage.DataStoreRole; import com.cloud.storage.ResizeVolumePayload; import com.cloud.storage.SnapshotVO; @@ -214,6 +215,7 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver } throw new CloudRuntimeException("Linstor: Unable to delete resource definition: " + rscDefName); } + s_logger.info(String.format("Linstor: Deleted resource %s", rscDefName)); } catch (ApiException apiEx) { s_logger.error("Linstor: ApiEx - " + apiEx.getMessage()); @@ -865,7 +867,7 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver Host host = null; for (String nodeName : linstorNodeNames) { host = _hostDao.findByName(nodeName); - if (host != null) { + if (host != null && host.getResourceState() == ResourceState.Enabled) { s_logger.info(String.format("Linstor: Make resource %s available on node %s ...", rscName, nodeName)); ApiCallRcList answers = api.resourceMakeAvailableOnNode(rscName, nodeName, new ResourceMakeAvailable()); if (!answers.hasError()) { @@ -892,21 +894,16 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver } private Optional getDiskfullEP(DevelopersApi api, String rscName) throws ApiException { - com.linbit.linstor.api.model.StoragePool linSP = - LinstorUtil.getDiskfulStoragePool(api, rscName); - if (linSP != null) - { - Host host = _hostDao.findByName(linSP.getNodeName()); - if (host == null) - { - s_logger.error("Linstor: Host '" + linSP.getNodeName() + "' not found."); - return Optional.empty(); - } - else - { - return Optional.of(RemoteHostEndPoint.getHypervisorHostEndPoint(host)); + List linSPs = LinstorUtil.getDiskfulStoragePools(api, rscName); + if (linSPs != null) { + for (com.linbit.linstor.api.model.StoragePool sp : linSPs) { + Host host = _hostDao.findByName(sp.getNodeName()); + if (host != null && host.getResourceState() == ResourceState.Enabled) { + return Optional.of(RemoteHostEndPoint.getHypervisorHostEndPoint(host)); + } } } + s_logger.error("Linstor: No diskfull host found."); return Optional.empty(); } @@ -958,9 +955,11 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver } else { answer = new Answer(cmd, false, "Unable to get matching Linstor endpoint."); + deleteResourceDefinition(pool, rscName); } } catch (ApiException exc) { s_logger.error("copy template failed: ", exc); + deleteResourceDefinition(pool, rscName); throw new CloudRuntimeException(exc.getBestMessage()); } return answer; 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 e953c94db22..33cbea0996d 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 @@ -77,16 +77,16 @@ public class LinstorUtil { return nodes.stream().map(Node::getName).collect(Collectors.toList()); } - public static com.linbit.linstor.api.model.StoragePool - getDiskfulStoragePool(@Nonnull DevelopersApi api, @Nonnull String rscName) throws ApiException + public static List + getDiskfulStoragePools(@Nonnull DevelopersApi api, @Nonnull String rscName) throws ApiException { List resources = api.viewResources( - Collections.emptyList(), - Collections.singletonList(rscName), - Collections.emptyList(), - Collections.emptyList(), - null, - null); + Collections.emptyList(), + Collections.singletonList(rscName), + Collections.emptyList(), + Collections.emptyList(), + null, + null); String nodeName = null; String storagePoolName = null; @@ -107,13 +107,23 @@ public class LinstorUtil { } List sps = api.viewStoragePools( - Collections.singletonList(nodeName), - Collections.singletonList(storagePoolName), - Collections.emptyList(), - null, - null + Collections.singletonList(nodeName), + Collections.singletonList(storagePoolName), + Collections.emptyList(), + null, + null ); - return !sps.isEmpty() ? sps.get(0) : null; + return sps != null ? sps : Collections.emptyList(); + } + + public static com.linbit.linstor.api.model.StoragePool + getDiskfulStoragePool(@Nonnull DevelopersApi api, @Nonnull String rscName) throws ApiException + { + List sps = getDiskfulStoragePools(api, rscName); + if (sps != null) { + return !sps.isEmpty() ? sps.get(0) : null; + } + return null; } public static String getSnapshotPath(com.linbit.linstor.api.model.StoragePool sp, String rscName, String snapshotName) {