Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 5 additions & 12 deletions plugins/storage/volume/linstor/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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]
Expand All @@ -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]
Expand All @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ public KVMPhysicalDisk createPhysicalDisk(String name, KVMStoragePool pool, Qemu
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);
Expand Down Expand Up @@ -455,8 +455,9 @@ public boolean disconnectPhysicalDisk(Map<String, String> volumeToDisconnect)
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();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,16 @@ public static boolean areResourcesDiskless(DevelopersApi api, String rscName, Co
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.
Expand All @@ -283,12 +293,7 @@ public static String getDevicePath(DevelopersApi api, String rscName) throws Api
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);
}
}

Expand All @@ -297,6 +302,24 @@ public static String getDevicePath(DevelopersApi api, String rscName) throws Api
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
{
Expand Down
Loading