Skip to content

Commit 2740033

Browse files
rp-dhslove
authored andcommitted
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 73df078 commit 2740033

File tree

2 files changed

+24
-12
lines changed

2 files changed

+24
-12
lines changed

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
@@ -137,7 +137,7 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
137137
private HostDao _hostDao;
138138
@Inject private VMTemplateDao _vmTemplateDao;
139139

140-
private long volumeStatsLastUpdate = 0L;
140+
private final Map<String, Long> volumeStatsLastUpdate = new HashMap<>();
141141
private final Map<String, Pair<Long, Long>> volumeStats = new HashMap<>();
142142

143143
public LinstorPrimaryDataStoreDriverImpl()
@@ -1535,11 +1535,12 @@ public boolean canProvideVolumeStats() {
15351535

15361536
/**
15371537
* Updates the cache map containing current allocated size data.
1538-
* @param api Linstor Developers api object
1538+
* @param linstorAddr Linstor cluster api address
15391539
*/
1540-
private void fillVolumeStatsCache(DevelopersApi api) {
1540+
private void fillVolumeStatsCache(String linstorAddr) {
1541+
final DevelopersApi api = LinstorUtil.getLinstorAPI(linstorAddr);
15411542
try {
1542-
s_logger.trace("Start volume stats cache update");
1543+
s_logger.trace("Start volume stats cache update for " + linstorAddr);
15431544
List<ResourceWithVolumes> resources = api.viewResources(
15441545
Collections.emptyList(),
15451546
Collections.emptyList(),
@@ -1566,29 +1567,34 @@ private void fillVolumeStatsCache(DevelopersApi api) {
15661567
}
15671568
}
15681569

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

15821583
@Override
15831584
public Pair<Long, Long> getVolumeStats(StoragePool storagePool, String volumeId) {
1584-
final DevelopersApi api = LinstorUtil.getLinstorAPI(storagePool.getHostAddress());
1585+
String linstorAddr = storagePool.getHostAddress();
15851586
synchronized (volumeStats) {
1586-
long invalidateCacheTime = volumeStatsLastUpdate +
1587+
long invalidateCacheTime = volumeStatsLastUpdate.getOrDefault(storagePool.getHostAddress(), 0L) +
15871588
LinstorConfigurationManager.VolumeStatsCacheTime.value() * 1000;
15881589
if (invalidateCacheTime < System.currentTimeMillis()) {
1589-
fillVolumeStatsCache(api);
1590+
fillVolumeStatsCache(storagePool.getHostAddress());
1591+
}
1592+
String volumeKey = linstorAddr + "/" + LinstorUtil.RSC_PREFIX + volumeId;
1593+
Pair<Long, Long> sizePair = volumeStats.get(volumeKey);
1594+
if (sizePair == null) {
1595+
s_logger.warn(String.format("Volumestats for %s not found in cache", volumeKey));
15901596
}
1591-
return volumeStats.get(LinstorUtil.RSC_PREFIX + volumeId);
1597+
return sizePair;
15921598
}
15931599
}
15941600

0 commit comments

Comments
 (0)