This is an automated email from the ASF dual-hosted git repository.
dahn pushed a commit to branch 4.20
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/4.20 by this push:
new 10dcbd76f0f linstor: Provide /dev/drbd/by-res/ resource paths to
CloudStack (#12300)
10dcbd76f0f is described below
commit 10dcbd76f0fdd2e0eb0674e04e211a3788c8ad89
Author: Rene Peinthor <[email protected]>
AuthorDate: Wed Dec 31 10:55:54 2025 +0100
linstor: Provide /dev/drbd/by-res/ resource paths to CloudStack (#12300)
---
plugins/storage/volume/linstor/CHANGELOG.md | 17 ++++-------
.../kvm/storage/LinstorStorageAdaptor.java | 7 +++--
.../storage/datastore/util/LinstorUtil.java | 35 ++++++++++++++++++----
3 files changed, 38 insertions(+), 21 deletions(-)
diff --git a/plugins/storage/volume/linstor/CHANGELOG.md
b/plugins/storage/volume/linstor/CHANGELOG.md
index 7da3516955d..47d1ddeb06c 100644
--- a/plugins/storage/volume/linstor/CHANGELOG.md
+++ b/plugins/storage/volume/linstor/CHANGELOG.md
@@ -5,22 +5,24 @@ All notable changes to Linstor CloudStack plugin will be
documented in this file
The format is based on [Keep a
Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic
Versioning](https://semver.org/spec/v2.0.0.html).
-## [2025-10-03]
+## [2025-12-18]
### Changed
+- Provide /dev/drbd/by-res/ resource paths to CloudStack for usage.
+
+## [2025-10-03]
+### Changed
- Revert qcow2 snapshot now use sparse/discard options to convert on thin
devices.
## [2025-08-05]
### Fixed
-
- getVolumeStats wasn't correctly working if multiple Linstor clusters/primary
storages are used.
## [2025-07-01]
### Fixed
-
- Regression in 4.19.3 and 4.21.0 with templates from snapshots
## [2025-05-07]
@@ -31,25 +33,21 @@ and this project adheres to [Semantic
Versioning](https://semver.org/spec/v2.0.0
## [2025-03-13]
### Fixed
-
- Implemented missing delete datastore, to correctly cleanup on datastore
removal
## [2025-02-21]
### Fixed
-
- Always try to delete cs-...-rst resource before doing a snapshot backup
## [2025-01-27]
### Fixed
-
- Use of multiple primary storages on the same linstor controller
## [2025-01-20]
### Fixed
-
- Volume snapshots on zfs used the wrong dataset path to hide/unhide snapdev
## [2024-12-19]
@@ -60,13 +58,11 @@ and this project adheres to [Semantic
Versioning](https://semver.org/spec/v2.0.0
## [2024-12-13]
### Fixed
-
- Linstor heartbeat check now also ask linstor-controller if there is no
connection between nodes
## [2024-12-11]
### Fixed
-
- Only set allow-two-primaries if a live migration is performed
## [2024-10-28]
@@ -79,17 +75,14 @@ and this project adheres to [Semantic
Versioning](https://semver.org/spec/v2.0.0
## [2024-10-14]
### Added
-
- Support for ISO direct download to primary storage
## [2024-10-04]
### Added
-
- Enable qemu discard="unmap" for Linstor block disks
## [2024-08-27]
### Changed
-
- Allow two primaries(+protocol c) is now set on resource-connection level
instead of rd
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 a664e7ed03b..1fe318e5163 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
@@ -232,7 +232,7 @@ public class LinstorStorageAdaptor implements
StorageAdaptor {
makeResourceAvailable(api, foundRscName, false);
if (!resources.isEmpty() &&
!resources.get(0).getVolumes().isEmpty()) {
- final String devPath =
resources.get(0).getVolumes().get(0).getDevicePath();
+ final String devPath =
LinstorUtil.getDevicePathFromResource(resources.get(0));
logger.info("Linstor: Created drbd device: " + devPath);
final KVMPhysicalDisk kvmDisk = new KVMPhysicalDisk(devPath,
name, pool);
kvmDisk.setFormat(QemuImg.PhysicalDiskFormat.RAW);
@@ -455,8 +455,9 @@ public class LinstorStorageAdaptor implements
StorageAdaptor {
private Optional<ResourceWithVolumes> getResourceByPathOrName(
final List<ResourceWithVolumes> resources, String path) {
return resources.stream()
- .filter(rsc ->
getLinstorRscName(path).equalsIgnoreCase(rsc.getName()) ||
rsc.getVolumes().stream()
- .anyMatch(v -> path.equals(v.getDevicePath())))
+ .filter(rsc ->
getLinstorRscName(path).equalsIgnoreCase(rsc.getName()) ||
+
path.equals(LinstorUtil.formatDrbdByResDevicePath(rsc.getName())) ||
+ rsc.getVolumes().stream().anyMatch(v ->
path.equals(v.getDevicePath())))
.findFirst();
}
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 9c3c9d32611..4196c12b116 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
@@ -264,6 +264,16 @@ public class LinstorUtil {
return false;
}
+ /**
+ * Format the device path for DRBD resources.
+ * @param rscName
+ * @return
+ */
+ public static String formatDrbdByResDevicePath(String rscName)
+ {
+ return String.format("/dev/drbd/by-res/%s/0", rscName);
+ }
+
/**
* 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.
@@ -283,12 +293,7 @@ public class LinstorUtil {
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()) {
- LOGGER.debug("getDevicePath: {} -> {}", rscName,
devicePath);
- return devicePath;
- }
+ return LinstorUtil.getDevicePathFromResource(rsc);
}
}
@@ -297,6 +302,24 @@ public class LinstorUtil {
throw new CloudRuntimeException("Linstor: " + errMsg);
}
+ /**
+ * Check if the resource has DRBD or not and deliver the correct device
path.
+ * @param rsc
+ * @return
+ */
+ public static String getDevicePathFromResource(ResourceWithVolumes rsc) {
+ if (!rsc.getVolumes().isEmpty()) {
+ // CloudStack resource always only have 1 volume
+ if (rsc.getLayerObject().getDrbd() != null) {
+ return formatDrbdByResDevicePath(rsc.getName());
+ } else {
+ return rsc.getVolumes().get(0).getDevicePath();
+ }
+ }
+ throw new CloudRuntimeException(
+ String.format("getDevicePath: Resource %s/%s doesn't have
volumes", rsc.getNodeName(), rsc.getName()));
+ }
+
public static ApiCallRcList applyAuxProps(DevelopersApi api, String
rscName, String dispName, String vmName)
throws ApiException
{