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 66278f827f7b..b38ab382a42d 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 @@ -38,6 +38,7 @@ import com.cloud.storage.Storage; import com.cloud.utils.exception.CloudRuntimeException; import com.linbit.linstor.api.ApiClient; +import com.linbit.linstor.api.ApiConsts; import com.linbit.linstor.api.ApiException; import com.linbit.linstor.api.Configuration; import com.linbit.linstor.api.DevelopersApi; @@ -103,6 +104,10 @@ private void logLinstorAnswer(@Nonnull ApiCallRc answer) { } } + private void logLinstorAnswers(@Nonnull ApiCallRcList answers) { + answers.forEach(this::logLinstorAnswer); + } + private void checkLinstorAnswersThrow(@Nonnull ApiCallRcList answers) { answers.forEach(this::logLinstorAnswer); if (answers.hasError()) @@ -316,23 +321,90 @@ public boolean connectPhysicalDisk(String volumePath, KVMStoragePool pool, Map optRsc; + try + { + List resources = api.viewResources( + Collections.singletonList(localNodeName), + null, + null, + null, + null, + null); + + optRsc = getResourceByPath(resources, volumePath); + } catch (ApiException apiEx) { + // couldn't query linstor controller + s_logger.error(apiEx.getBestMessage()); + return false; + } + + + if (optRsc.isPresent()) { + try { + Resource rsc = optRsc.get(); + + // if diskless resource remove it, in the worst case it will be transformed to a tiebreaker + if (rsc.getFlags() != null && + rsc.getFlags().contains(ApiConsts.FLAG_DRBD_DISKLESS) && + !rsc.getFlags().contains(ApiConsts.FLAG_TIE_BREAKER)) { + ApiCallRcList delAnswers = api.resourceDelete(rsc.getName(), localNodeName); + logLinstorAnswers(delAnswers); + } + + // remove allow-two-primaries + ResourceDefinitionModify rdm = new ResourceDefinitionModify(); + rdm.deleteProps(Collections.singletonList("DrbdOptions/Net/allow-two-primaries")); + ApiCallRcList answers = api.resourceDefinitionModify(rsc.getName(), rdm); + if (answers.hasError()) { + s_logger.error( + String.format("Failed to remove 'allow-two-primaries' on %s: %s", + rsc.getName(), LinstorUtil.getBestErrorMessage(answers))); + // do not fail here as removing allow-two-primaries property isn't fatal + } + } catch (ApiException apiEx) { + s_logger.error(apiEx.getBestMessage()); + // do not fail here as removing allow-two-primaries property or deleting diskless isn't fatal + } + + return true; + } + + s_logger.warn("Linstor: Couldn't find resource for this path: " + volumePath); + return false; + } + @Override public boolean disconnectPhysicalDisk(String volumePath, KVMStoragePool pool) { s_logger.debug("Linstor: disconnectPhysicalDisk " + pool.getUuid() + ":" + volumePath); + if (MapStorageUuidToStoragePool.containsValue(pool)) { + return tryDisconnectLinstor(volumePath, pool); + } return false; } @Override public boolean disconnectPhysicalDisk(Map volumeToDisconnect) { + // as of now this is only relevant for iscsi targets + s_logger.info("Linstor: disconnectPhysicalDisk(Map volumeToDisconnect) called?"); return false; } private Optional getResourceByPath(final List resources, String path) { return resources.stream() .filter(rsc -> rsc.getVolumes().stream() - .anyMatch(v -> v.getDevicePath().equals(path))) + .anyMatch(v -> path.equals(v.getDevicePath()))) .findFirst(); } @@ -353,46 +425,8 @@ public boolean disconnectPhysicalDiskByPath(String localPath) s_logger.debug("Linstor: disconnectPhysicalDiskByPath " + localPath); final KVMStoragePool pool = optFirstPool.get(); - s_logger.debug("Linstor: Using storpool: " + pool.getUuid()); - final DevelopersApi api = getLinstorAPI(pool); - - Optional optRsc; - try { - List resources = api.viewResources( - Collections.singletonList(localNodeName), - null, - null, - null, - null, - null); - - optRsc = getResourceByPath(resources, localPath); - } catch (ApiException apiEx) { - // couldn't query linstor controller - s_logger.error(apiEx.getBestMessage()); - return false; - } - - if (optRsc.isPresent()) { - try { - Resource rsc = optRsc.get(); - ResourceDefinitionModify rdm = new ResourceDefinitionModify(); - rdm.deleteProps(Collections.singletonList("DrbdOptions/Net/allow-two-primaries")); - ApiCallRcList answers = api.resourceDefinitionModify(rsc.getName(), rdm); - if (answers.hasError()) { - s_logger.error( - String.format("Failed to remove 'allow-two-primaries' on %s: %s", - rsc.getName(), LinstorUtil.getBestErrorMessage(answers))); - // do not fail here as removing allow-two-primaries property isn't fatal - } - } catch(ApiException apiEx){ - s_logger.error(apiEx.getBestMessage()); - // do not fail here as removing allow-two-primaries property isn't fatal - } - return true; - } + return tryDisconnectLinstor(localPath, pool); } - s_logger.info("Linstor: Couldn't find resource for this path: " + localPath); return false; }