Skip to content

Commit 7b750ea

Browse files
committed
linstor: fix getVolumeStats if multiple Linstor primary storages are used (apache#11397)
We didn't account for caching the volume stats for each used Linstor cluster, so the first asked Linstor cluster would prevent caching for all the others and so null was returned. Now we have invalidate counters for each Linstor cluster and also store the cache result with the Linstor cluster address prefixed.
1 parent 82c59f6 commit 7b750ea

2 files changed

Lines changed: 24 additions & 12 deletions

File tree

plugins/storage/volume/linstor/CHANGELOG.md

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

8+
## [2025-08-05]
9+
10+
### Fixed
11+
12+
- getVolumeStats wasn't correctly working if multiple Linstor clusters/primary storages are used.
13+
814
## [2025-07-01]
915

1016
### Fixed

plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/driver/LinstorPrimaryDataStoreDriverImpl.java

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
134134
private HostDao _hostDao;
135135
@Inject private VMTemplateDao _vmTemplateDao;
136136

137-
private long volumeStatsLastUpdate = 0L;
137+
private final Map<String, Long> volumeStatsLastUpdate = new HashMap<>();
138138
private final Map<String, Pair<Long, Long>> volumeStats = new HashMap<>();
139139

140140
public LinstorPrimaryDataStoreDriverImpl()
@@ -1532,11 +1532,12 @@ public boolean canProvideVolumeStats() {
15321532

15331533
/**
15341534
* Updates the cache map containing current allocated size data.
1535-
* @param api Linstor Developers api object
1535+
* @param linstorAddr Linstor cluster api address
15361536
*/
1537-
private void fillVolumeStatsCache(DevelopersApi api) {
1537+
private void fillVolumeStatsCache(String linstorAddr) {
1538+
final DevelopersApi api = LinstorUtil.getLinstorAPI(linstorAddr);
15381539
try {
1539-
s_logger.trace("Start volume stats cache update");
1540+
s_logger.trace("Start volume stats cache update for " + linstorAddr);
15401541
List<ResourceWithVolumes> resources = api.viewResources(
15411542
Collections.emptyList(),
15421543
Collections.emptyList(),
@@ -1563,29 +1564,34 @@ private void fillVolumeStatsCache(DevelopersApi api) {
15631564
}
15641565
}
15651566

1566-
volumeStats.clear();
1567+
volumeStats.keySet().removeIf(key -> key.startsWith(linstorAddr));
15671568
for (Map.Entry<String, Long> entry : allocSizeMap.entrySet()) {
15681569
Long reserved = resSizeMap.getOrDefault(entry.getKey(), 0L);
15691570
Pair<Long, Long> volStat = new Pair<>(entry.getValue(), reserved);
1570-
volumeStats.put(entry.getKey(), volStat);
1571+
volumeStats.put(linstorAddr + "/" + entry.getKey(), volStat);
15711572
}
1572-
volumeStatsLastUpdate = System.currentTimeMillis();
1573-
s_logger.trace("Done volume stats cache update: " + volumeStats.size());
1573+
volumeStatsLastUpdate.put(linstorAddr, System.currentTimeMillis());
1574+
s_logger.debug(String.format("Done volume stats cache update for %s: %d", linstorAddr, volumeStats.size()));
15741575
} catch (ApiException e) {
15751576
s_logger.error("Unable to fetch Linstor resources: " + e.getBestMessage());
15761577
}
15771578
}
15781579

15791580
@Override
15801581
public Pair<Long, Long> getVolumeStats(StoragePool storagePool, String volumeId) {
1581-
final DevelopersApi api = LinstorUtil.getLinstorAPI(storagePool.getHostAddress());
1582+
String linstorAddr = storagePool.getHostAddress();
15821583
synchronized (volumeStats) {
1583-
long invalidateCacheTime = volumeStatsLastUpdate +
1584+
long invalidateCacheTime = volumeStatsLastUpdate.getOrDefault(storagePool.getHostAddress(), 0L) +
15841585
LinstorConfigurationManager.VolumeStatsCacheTime.value() * 1000;
15851586
if (invalidateCacheTime < System.currentTimeMillis()) {
1586-
fillVolumeStatsCache(api);
1587+
fillVolumeStatsCache(storagePool.getHostAddress());
1588+
}
1589+
String volumeKey = linstorAddr + "/" + LinstorUtil.RSC_PREFIX + volumeId;
1590+
Pair<Long, Long> sizePair = volumeStats.get(volumeKey);
1591+
if (sizePair == null) {
1592+
s_logger.warn(String.format("Volumestats for %s not found in cache", volumeKey));
15871593
}
1588-
return volumeStats.get(LinstorUtil.RSC_PREFIX + volumeId);
1594+
return sizePair;
15891595
}
15901596
}
15911597

0 commit comments

Comments
 (0)