Merge branch '4.20'

This commit is contained in:
Suresh Kumar Anaparti 2025-08-15 19:54:41 +05:30
commit 2c34f5e495
No known key found for this signature in database
GPG Key ID: D7CEAE3A9E71D0AA
4 changed files with 38 additions and 21 deletions

View File

@ -202,10 +202,15 @@ public class SnapshotObject implements SnapshotInfo {
@Override @Override
public long getPhysicalSize() { public long getPhysicalSize() {
long physicalSize = 0; long physicalSize = 0;
SnapshotDataStoreVO snapshotStore = snapshotStoreDao.findByStoreSnapshot(DataStoreRole.Image, store.getId(), snapshot.getId()); for (DataStoreRole role : List.of(DataStoreRole.Image, DataStoreRole.Primary)) {
if (snapshotStore != null) { logger.trace("Retrieving snapshot [{}] size from {} storage.", snapshot.getUuid(), role);
physicalSize = snapshotStore.getPhysicalSize(); SnapshotDataStoreVO snapshotStore = snapshotStoreDao.findByStoreSnapshot(role, store.getId(), snapshot.getId());
if (snapshotStore != null) {
return snapshotStore.getPhysicalSize();
}
logger.trace("Snapshot [{}] size not found on {} storage.", snapshot.getUuid(), role);
} }
logger.warn("Snapshot [{}] reference not found in any storage. There may be an inconsistency on the database.", snapshot.getUuid());
return physicalSize; return physicalSize;
} }

View File

@ -5,6 +5,12 @@ 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/), 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). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2025-08-05]
### Fixed
- getVolumeStats wasn't correctly working if multiple Linstor clusters/primary storages are used.
## [2025-07-01] ## [2025-07-01]
### Fixed ### Fixed

View File

@ -137,7 +137,7 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
private HostDao _hostDao; private HostDao _hostDao;
@Inject private VMTemplateDao _vmTemplateDao; @Inject private VMTemplateDao _vmTemplateDao;
private long volumeStatsLastUpdate = 0L; private final Map<String, Long> volumeStatsLastUpdate = new HashMap<>();
private final Map<String, Pair<Long, Long>> volumeStats = new HashMap<>(); private final Map<String, Pair<Long, Long>> volumeStats = new HashMap<>();
public LinstorPrimaryDataStoreDriverImpl() public LinstorPrimaryDataStoreDriverImpl()
@ -1535,11 +1535,12 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
/** /**
* Updates the cache map containing current allocated size data. * Updates the cache map containing current allocated size data.
* @param api Linstor Developers api object * @param linstorAddr Linstor cluster api address
*/ */
private void fillVolumeStatsCache(DevelopersApi api) { private void fillVolumeStatsCache(String linstorAddr) {
final DevelopersApi api = LinstorUtil.getLinstorAPI(linstorAddr);
try { try {
logger.trace("Start volume stats cache update"); logger.trace("Start volume stats cache update for " + linstorAddr);
List<ResourceWithVolumes> resources = api.viewResources( List<ResourceWithVolumes> resources = api.viewResources(
Collections.emptyList(), Collections.emptyList(),
Collections.emptyList(), Collections.emptyList(),
@ -1566,14 +1567,14 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
} }
} }
volumeStats.clear(); volumeStats.keySet().removeIf(key -> key.startsWith(linstorAddr));
for (Map.Entry<String, Long> entry : allocSizeMap.entrySet()) { for (Map.Entry<String, Long> entry : allocSizeMap.entrySet()) {
Long reserved = resSizeMap.getOrDefault(entry.getKey(), 0L); Long reserved = resSizeMap.getOrDefault(entry.getKey(), 0L);
Pair<Long, Long> volStat = new Pair<>(entry.getValue(), reserved); Pair<Long, Long> volStat = new Pair<>(entry.getValue(), reserved);
volumeStats.put(entry.getKey(), volStat); volumeStats.put(linstorAddr + "/" + entry.getKey(), volStat);
} }
volumeStatsLastUpdate = System.currentTimeMillis(); volumeStatsLastUpdate.put(linstorAddr, System.currentTimeMillis());
logger.trace("Done volume stats cache update: {}", volumeStats.size()); logger.debug(String.format("Done volume stats cache update for %s: %d", linstorAddr, volumeStats.size()));
} catch (ApiException e) { } catch (ApiException e) {
logger.error("Unable to fetch Linstor resources: {}", e.getBestMessage()); logger.error("Unable to fetch Linstor resources: {}", e.getBestMessage());
} }
@ -1581,14 +1582,19 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
@Override @Override
public Pair<Long, Long> getVolumeStats(StoragePool storagePool, String volumeId) { public Pair<Long, Long> getVolumeStats(StoragePool storagePool, String volumeId) {
final DevelopersApi api = LinstorUtil.getLinstorAPI(storagePool.getHostAddress()); String linstorAddr = storagePool.getHostAddress();
synchronized (volumeStats) { synchronized (volumeStats) {
long invalidateCacheTime = volumeStatsLastUpdate + long invalidateCacheTime = volumeStatsLastUpdate.getOrDefault(storagePool.getHostAddress(), 0L) +
LinstorConfigurationManager.VolumeStatsCacheTime.value() * 1000; LinstorConfigurationManager.VolumeStatsCacheTime.value() * 1000;
if (invalidateCacheTime < System.currentTimeMillis()) { if (invalidateCacheTime < System.currentTimeMillis()) {
fillVolumeStatsCache(api); fillVolumeStatsCache(storagePool.getHostAddress());
} }
return volumeStats.get(LinstorUtil.RSC_PREFIX + volumeId); String volumeKey = linstorAddr + "/" + LinstorUtil.RSC_PREFIX + volumeId;
Pair<Long, Long> sizePair = volumeStats.get(volumeKey);
if (sizePair == null) {
logger.warn(String.format("Volumestats for %s not found in cache", volumeKey));
}
return sizePair;
} }
} }

View File

@ -2211,7 +2211,11 @@ export default {
resolve(result) resolve(result)
}).catch(error => { }).catch(error => {
message = error.response.headers['x-description'] message = error.response.headers['x-description']
reject(message) if (message.includes('is already in the database')) {
resolve()
} else {
reject(message)
}
}) })
}) })
}, },
@ -2223,11 +2227,7 @@ export default {
resolve() resolve()
}).catch(error => { }).catch(error => {
message = error.response.headers['x-description'] message = error.response.headers['x-description']
if (message.includes('is already in the database')) { reject(message)
resolve()
} else {
reject(message)
}
}) })
}) })
}, },