Skip to content

Commit 25f93b1

Browse files
authored
linstor: fix getVolumeStats if multiple Linstor primary storages are used (#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 d4bd587 commit 25f93b1

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

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

141141
public LinstorPrimaryDataStoreDriverImpl()
@@ -1533,11 +1533,12 @@ public boolean canProvideVolumeStats() {
15331533

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

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

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

0 commit comments

Comments
 (0)