|
28 | 28 | import com.linbit.linstor.api.model.ResourceDefinitionCloneRequest; |
29 | 29 | import com.linbit.linstor.api.model.ResourceDefinitionCloneStarted; |
30 | 30 | import com.linbit.linstor.api.model.ResourceDefinitionCreate; |
31 | | - |
32 | 31 | import com.linbit.linstor.api.model.ResourceDefinitionModify; |
33 | 32 | import com.linbit.linstor.api.model.ResourceGroup; |
34 | 33 | import com.linbit.linstor.api.model.ResourceGroupSpawn; |
35 | 34 | import com.linbit.linstor.api.model.ResourceMakeAvailable; |
| 35 | +import com.linbit.linstor.api.model.ResourceWithVolumes; |
36 | 36 | import com.linbit.linstor.api.model.Snapshot; |
37 | 37 | import com.linbit.linstor.api.model.SnapshotRestore; |
38 | 38 | import com.linbit.linstor.api.model.VolumeDefinition; |
@@ -134,6 +134,9 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver |
134 | 134 | @Inject |
135 | 135 | private HostDao _hostDao; |
136 | 136 |
|
| 137 | + private long volumeStatsLastUpdate = 0L; |
| 138 | + private final Map<String, Pair<Long, Long>> volumeStats = new HashMap<>(); |
| 139 | + |
137 | 140 | public LinstorPrimaryDataStoreDriverImpl() |
138 | 141 | { |
139 | 142 | } |
@@ -403,9 +406,9 @@ private void applyQoSSettings(StoragePoolVO storagePool, DevelopersApi api, Stri |
403 | 406 | } |
404 | 407 | } |
405 | 408 |
|
406 | | - private String getRscGrp(StoragePoolVO storagePoolVO) { |
407 | | - return storagePoolVO.getUserInfo() != null && !storagePoolVO.getUserInfo().isEmpty() ? |
408 | | - storagePoolVO.getUserInfo() : "DfltRscGrp"; |
| 409 | + private String getRscGrp(StoragePool storagePool) { |
| 410 | + return storagePool.getUserInfo() != null && !storagePool.getUserInfo().isEmpty() ? |
| 411 | + storagePool.getUserInfo() : "DfltRscGrp"; |
409 | 412 | } |
410 | 413 |
|
411 | 414 | /** |
@@ -618,7 +621,7 @@ private void resizeResource(DevelopersApi api, String resourceName, long sizeByt |
618 | 621 | */ |
619 | 622 | private void updateRscGrpIfNecessary(DevelopersApi api, String rscName, String tgtRscGrp) throws ApiException { |
620 | 623 | List<ResourceDefinition> rscDfns = api.resourceDefinitionList( |
621 | | - Collections.singletonList(rscName), null, null, null); |
| 624 | + Collections.singletonList(rscName), false, null, null, null); |
622 | 625 | if (rscDfns != null && !rscDfns.isEmpty()) { |
623 | 626 | ResourceDefinition rscDfn = rscDfns.get(0); |
624 | 627 |
|
@@ -648,7 +651,7 @@ private void updateRscGrpIfNecessary(DevelopersApi api, String rscName, String t |
648 | 651 | private void deleteTemplateForProps( |
649 | 652 | DevelopersApi api, String rscName) throws ApiException { |
650 | 653 | List<ResourceDefinition> rdList = api.resourceDefinitionList( |
651 | | - Collections.singletonList(rscName), null, null, null); |
| 654 | + Collections.singletonList(rscName), false, null, null, null); |
652 | 655 |
|
653 | 656 | if (CollectionUtils.isNotEmpty(rdList)) { |
654 | 657 | ResourceDefinitionModify rdm = new ResourceDefinitionModify(); |
@@ -1506,22 +1509,77 @@ public void takeSnapshot(SnapshotInfo snapshotInfo, AsyncCompletionCallback<Crea |
1506 | 1509 |
|
1507 | 1510 | @Override |
1508 | 1511 | public boolean canProvideStorageStats() { |
1509 | | - return false; |
| 1512 | + return true; |
1510 | 1513 | } |
1511 | 1514 |
|
1512 | 1515 | @Override |
1513 | 1516 | public Pair<Long, Long> getStorageStats(StoragePool storagePool) { |
1514 | | - return null; |
| 1517 | + logger.debug(String.format("Requesting storage stats: %s", storagePool)); |
| 1518 | + return LinstorUtil.getStorageStats(storagePool.getHostAddress(), getRscGrp(storagePool)); |
1515 | 1519 | } |
1516 | 1520 |
|
1517 | 1521 | @Override |
1518 | 1522 | public boolean canProvideVolumeStats() { |
1519 | | - return false; |
| 1523 | + return LinstorConfigurationManager.VolumeStatsCacheTime.value() > 0; |
| 1524 | + } |
| 1525 | + |
| 1526 | + /** |
| 1527 | + * Updates the cache map containing current allocated size data. |
| 1528 | + * @param api Linstor Developers api object |
| 1529 | + */ |
| 1530 | + private void fillVolumeStatsCache(DevelopersApi api) { |
| 1531 | + try { |
| 1532 | + logger.trace("Start volume stats cache update"); |
| 1533 | + List<ResourceWithVolumes> resources = api.viewResources( |
| 1534 | + Collections.emptyList(), |
| 1535 | + Collections.emptyList(), |
| 1536 | + Collections.emptyList(), |
| 1537 | + null, |
| 1538 | + null, |
| 1539 | + null); |
| 1540 | + |
| 1541 | + List<ResourceDefinition> rscDfns = api.resourceDefinitionList( |
| 1542 | + Collections.emptyList(), true, null, null, null); |
| 1543 | + |
| 1544 | + HashMap<String, Long> resSizeMap = new HashMap<>(); |
| 1545 | + for (ResourceDefinition rscDfn : rscDfns) { |
| 1546 | + if (CollectionUtils.isNotEmpty(rscDfn.getVolumeDefinitions())) { |
| 1547 | + resSizeMap.put(rscDfn.getName(), rscDfn.getVolumeDefinitions().get(0).getSizeKib() * 1024); |
| 1548 | + } |
| 1549 | + } |
| 1550 | + |
| 1551 | + HashMap<String, Long> allocSizeMap = new HashMap<>(); |
| 1552 | + for (ResourceWithVolumes rsc : resources) { |
| 1553 | + if (!LinstorUtil.isRscDiskless(rsc) && !rsc.getVolumes().isEmpty()) { |
| 1554 | + long allocatedBytes = allocSizeMap.getOrDefault(rsc.getName(), 0L); |
| 1555 | + allocSizeMap.put(rsc.getName(), Math.max(allocatedBytes, rsc.getVolumes().get(0).getAllocatedSizeKib() * 1024)); |
| 1556 | + } |
| 1557 | + } |
| 1558 | + |
| 1559 | + volumeStats.clear(); |
| 1560 | + for (Map.Entry<String, Long> entry : allocSizeMap.entrySet()) { |
| 1561 | + Long reserved = resSizeMap.getOrDefault(entry.getKey(), 0L); |
| 1562 | + Pair<Long, Long> volStat = new Pair<>(entry.getValue(), reserved); |
| 1563 | + volumeStats.put(entry.getKey(), volStat); |
| 1564 | + } |
| 1565 | + volumeStatsLastUpdate = System.currentTimeMillis(); |
| 1566 | + logger.trace("Done volume stats cache update: {}", volumeStats.size()); |
| 1567 | + } catch (ApiException e) { |
| 1568 | + logger.error("Unable to fetch Linstor resources: {}", e.getBestMessage()); |
| 1569 | + } |
1520 | 1570 | } |
1521 | 1571 |
|
1522 | 1572 | @Override |
1523 | 1573 | public Pair<Long, Long> getVolumeStats(StoragePool storagePool, String volumeId) { |
1524 | | - return null; |
| 1574 | + final DevelopersApi api = LinstorUtil.getLinstorAPI(storagePool.getHostAddress()); |
| 1575 | + synchronized (volumeStats) { |
| 1576 | + long invalidateCacheTime = volumeStatsLastUpdate + |
| 1577 | + LinstorConfigurationManager.VolumeStatsCacheTime.value() * 1000; |
| 1578 | + if (invalidateCacheTime < System.currentTimeMillis()) { |
| 1579 | + fillVolumeStatsCache(api); |
| 1580 | + } |
| 1581 | + return volumeStats.get(LinstorUtil.RSC_PREFIX + volumeId); |
| 1582 | + } |
1525 | 1583 | } |
1526 | 1584 |
|
1527 | 1585 | @Override |
|
0 commit comments