Skip to content

Commit 2c34f5e

Browse files
Merge branch '4.20'
2 parents 93d6ff3 + c6daeb4 commit 2c34f5e

File tree

4 files changed

+38
-21
lines changed

4 files changed

+38
-21
lines changed

engine/storage/snapshot/src/main/java/org/apache/cloudstack/storage/snapshot/SnapshotObject.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,10 +202,15 @@ public boolean isRevertable() {
202202
@Override
203203
public long getPhysicalSize() {
204204
long physicalSize = 0;
205-
SnapshotDataStoreVO snapshotStore = snapshotStoreDao.findByStoreSnapshot(DataStoreRole.Image, store.getId(), snapshot.getId());
206-
if (snapshotStore != null) {
207-
physicalSize = snapshotStore.getPhysicalSize();
205+
for (DataStoreRole role : List.of(DataStoreRole.Image, DataStoreRole.Primary)) {
206+
logger.trace("Retrieving snapshot [{}] size from {} storage.", snapshot.getUuid(), role);
207+
SnapshotDataStoreVO snapshotStore = snapshotStoreDao.findByStoreSnapshot(role, store.getId(), snapshot.getId());
208+
if (snapshotStore != null) {
209+
return snapshotStore.getPhysicalSize();
210+
}
211+
logger.trace("Snapshot [{}] size not found on {} storage.", snapshot.getUuid(), role);
208212
}
213+
logger.warn("Snapshot [{}] reference not found in any storage. There may be an inconsistency on the database.", snapshot.getUuid());
209214
return physicalSize;
210215
}
211216

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-
logger.trace("Start volume stats cache update");
1543+
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-
logger.trace("Done volume stats cache update: {}", volumeStats.size());
1576+
volumeStatsLastUpdate.put(linstorAddr, System.currentTimeMillis());
1577+
logger.debug(String.format("Done volume stats cache update for %s: %d", linstorAddr, volumeStats.size()));
15771578
} catch (ApiException e) {
15781579
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+
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

ui/src/views/infra/zone/ZoneWizardLaunchZone.vue

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2211,7 +2211,11 @@ export default {
22112211
resolve(result)
22122212
}).catch(error => {
22132213
message = error.response.headers['x-description']
2214-
reject(message)
2214+
if (message.includes('is already in the database')) {
2215+
resolve()
2216+
} else {
2217+
reject(message)
2218+
}
22152219
})
22162220
})
22172221
},
@@ -2223,11 +2227,7 @@ export default {
22232227
resolve()
22242228
}).catch(error => {
22252229
message = error.response.headers['x-description']
2226-
if (message.includes('is already in the database')) {
2227-
resolve()
2228-
} else {
2229-
reject(message)
2230-
}
2230+
reject(message)
22312231
})
22322232
})
22332233
},

0 commit comments

Comments
 (0)