Skip to content

Commit 9e663b0

Browse files
rp-Locharla, Sandeep
authored andcommitted
linstor: Provide /dev/drbd/by-res/ resource paths to CloudStack (apache#12300)
1 parent bd549bd commit 9e663b0

File tree

3 files changed

+38
-21
lines changed

3 files changed

+38
-21
lines changed

plugins/storage/volume/linstor/CHANGELOG.md

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,22 +24,24 @@ All notable changes to Linstor CloudStack plugin will be documented in this file
2424
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
2525
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
2626

27-
## [2025-10-03]
27+
## [2025-12-18]
2828

2929
### Changed
30+
- Provide /dev/drbd/by-res/ resource paths to CloudStack for usage.
31+
32+
## [2025-10-03]
3033

34+
### Changed
3135
- Revert qcow2 snapshot now use sparse/discard options to convert on thin devices.
3236

3337
## [2025-08-05]
3438

3539
### Fixed
36-
3740
- getVolumeStats wasn't correctly working if multiple Linstor clusters/primary storages are used.
3841

3942
## [2025-07-01]
4043

4144
### Fixed
42-
4345
- Regression in 4.19.3 and 4.21.0 with templates from snapshots
4446

4547
## [2025-05-07]
@@ -50,25 +52,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
5052
## [2025-03-13]
5153

5254
### Fixed
53-
5455
- Implemented missing delete datastore, to correctly cleanup on datastore removal
5556

5657
## [2025-02-21]
5758

5859
### Fixed
59-
6060
- Always try to delete cs-...-rst resource before doing a snapshot backup
6161

6262
## [2025-01-27]
6363

6464
### Fixed
65-
6665
- Use of multiple primary storages on the same linstor controller
6766

6867
## [2025-01-20]
6968

7069
### Fixed
71-
7270
- Volume snapshots on zfs used the wrong dataset path to hide/unhide snapdev
7371

7472
## [2024-12-19]
@@ -79,13 +77,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7977
## [2024-12-13]
8078

8179
### Fixed
82-
8380
- Linstor heartbeat check now also ask linstor-controller if there is no connection between nodes
8481

8582
## [2024-12-11]
8683

8784
### Fixed
88-
8985
- Only set allow-two-primaries if a live migration is performed
9086

9187
## [2024-10-28]
@@ -98,17 +94,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9894
## [2024-10-14]
9995

10096
### Added
101-
10297
- Support for ISO direct download to primary storage
10398

10499
## [2024-10-04]
105100

106101
### Added
107-
108102
- Enable qemu discard="unmap" for Linstor block disks
109103

110104
## [2024-08-27]
111105

112106
### Changed
113-
114107
- Allow two primaries(+protocol c) is now set on resource-connection level instead of rd

plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ public KVMPhysicalDisk createPhysicalDisk(String name, KVMStoragePool pool, Qemu
233233
makeResourceAvailable(api, foundRscName, false);
234234

235235
if (!resources.isEmpty() && !resources.get(0).getVolumes().isEmpty()) {
236-
final String devPath = resources.get(0).getVolumes().get(0).getDevicePath();
236+
final String devPath = LinstorUtil.getDevicePathFromResource(resources.get(0));
237237
logger.info("Linstor: Created drbd device: " + devPath);
238238
final KVMPhysicalDisk kvmDisk = new KVMPhysicalDisk(devPath, name, pool);
239239
kvmDisk.setFormat(QemuImg.PhysicalDiskFormat.RAW);
@@ -456,8 +456,9 @@ public boolean disconnectPhysicalDisk(Map<String, String> volumeToDisconnect)
456456
private Optional<ResourceWithVolumes> getResourceByPathOrName(
457457
final List<ResourceWithVolumes> resources, String path) {
458458
return resources.stream()
459-
.filter(rsc -> getLinstorRscName(path).equalsIgnoreCase(rsc.getName()) || rsc.getVolumes().stream()
460-
.anyMatch(v -> path.equals(v.getDevicePath())))
459+
.filter(rsc -> getLinstorRscName(path).equalsIgnoreCase(rsc.getName()) ||
460+
path.equals(LinstorUtil.formatDrbdByResDevicePath(rsc.getName())) ||
461+
rsc.getVolumes().stream().anyMatch(v -> path.equals(v.getDevicePath())))
461462
.findFirst();
462463
}
463464

plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/util/LinstorUtil.java

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,16 @@ public static boolean areResourcesDiskless(DevelopersApi api, String rscName, Co
264264
return false;
265265
}
266266

267+
/**
268+
* Format the device path for DRBD resources.
269+
* @param rscName
270+
* @return
271+
*/
272+
public static String formatDrbdByResDevicePath(String rscName)
273+
{
274+
return String.format("/dev/drbd/by-res/%s/0", rscName);
275+
}
276+
267277
/**
268278
* Try to get the device path for the given resource name.
269279
* This could be made a bit more direct after java-linstor api is fixed for layer data subtypes.
@@ -283,12 +293,7 @@ public static String getDevicePath(DevelopersApi api, String rscName) throws Api
283293
null);
284294
for (ResourceWithVolumes rsc : resources) {
285295
if (!rsc.getVolumes().isEmpty()) {
286-
// CloudStack resource always only have 1 volume
287-
String devicePath = rsc.getVolumes().get(0).getDevicePath();
288-
if (devicePath != null && !devicePath.isEmpty()) {
289-
LOGGER.debug("getDevicePath: {} -> {}", rscName, devicePath);
290-
return devicePath;
291-
}
296+
return LinstorUtil.getDevicePathFromResource(rsc);
292297
}
293298
}
294299

@@ -297,6 +302,24 @@ public static String getDevicePath(DevelopersApi api, String rscName) throws Api
297302
throw new CloudRuntimeException("Linstor: " + errMsg);
298303
}
299304

305+
/**
306+
* Check if the resource has DRBD or not and deliver the correct device path.
307+
* @param rsc
308+
* @return
309+
*/
310+
public static String getDevicePathFromResource(ResourceWithVolumes rsc) {
311+
if (!rsc.getVolumes().isEmpty()) {
312+
// CloudStack resource always only have 1 volume
313+
if (rsc.getLayerObject().getDrbd() != null) {
314+
return formatDrbdByResDevicePath(rsc.getName());
315+
} else {
316+
return rsc.getVolumes().get(0).getDevicePath();
317+
}
318+
}
319+
throw new CloudRuntimeException(
320+
String.format("getDevicePath: Resource %s/%s doesn't have volumes", rsc.getNodeName(), rsc.getName()));
321+
}
322+
300323
public static ApiCallRcList applyAuxProps(DevelopersApi api, String rscName, String dispName, String vmName)
301324
throws ApiException
302325
{

0 commit comments

Comments
 (0)