This is an automated email from the ASF dual-hosted git repository. sureshanaparti pushed a commit to branch 4.22 in repository https://gitbox.apache.org/repos/asf/cloudstack.git
commit 3828a3b744a1cbdbf20a0ff6de2e697452f19e58 Merge: b5fd39fca0d 76e6de7f90e Author: Suresh Kumar Anaparti <[email protected]> AuthorDate: Mon Jan 19 19:50:10 2026 +0530 Merge branch '4.20' into 4.22 .../subsystem/api/storage/SnapshotDataFactory.java | 2 + .../java/com/cloud/storage/dao/SnapshotDao.java | 2 + .../com/cloud/storage/dao/SnapshotDaoImpl.java | 7 ++ .../java/com/cloud/usage/dao/UsageDaoImpl.java | 17 ++-- .../storage/datastore/db/SnapshotDataStoreDao.java | 2 + .../datastore/db/SnapshotDataStoreDaoImpl.java | 7 ++ .../storage/snapshot/DefaultSnapshotStrategy.java | 2 +- .../storage/snapshot/SnapshotDataFactoryImpl.java | 22 ++++- .../storage/snapshot/SnapshotServiceImpl.java | 9 +- .../snapshot/StorageSystemSnapshotStrategy.java | 1 - .../datastore/ObjectInDataStoreManagerImpl.java | 3 + .../storage/datastore/util/StorPoolHelper.java | 2 +- .../storage/snapshot/StorPoolSnapshotStrategy.java | 4 +- .../java/com/cloud/storage/StorageManagerImpl.java | 101 +++++++++++---------- .../storage/snapshot/SnapshotManagerImpl.java | 31 +++---- .../storage/snapshot/SnapshotManagerImplTest.java | 4 +- ui/src/views/compute/DeployVM.vue | 4 +- ui/src/views/compute/wizard/OwnershipSelection.vue | 30 +++++- ui/src/views/network/CreateIsolatedNetworkForm.vue | 2 +- ui/src/views/network/CreateL2NetworkForm.vue | 2 +- ui/src/views/storage/CreateSharedFS.vue | 8 +- ui/src/views/storage/CreateVolume.vue | 4 +- 22 files changed, 162 insertions(+), 104 deletions(-) diff --cc engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDaoImpl.java index 241c3df2e4a,ba76a6b3f41..ac9601389bd --- a/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDaoImpl.java +++ b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDaoImpl.java @@@ -464,17 -340,16 +464,24 @@@ public class SnapshotDataStoreDaoImpl e @Override public List<SnapshotDataStoreVO> findBySnapshotId(long snapshotId) { + SearchCriteria<SnapshotDataStoreVO> sc = searchFilteringStoreIdEqStateEqStoreRoleEqIdEqUpdateCountEqSnapshotIdEqVolumeIdEq.create(); + sc.setParameters(SNAPSHOT_ID, snapshotId); + return listBy(sc); + } + + @Override + public List<SnapshotDataStoreVO> findBySnapshotIdWithNonDestroyedState(long snapshotId) { - SearchCriteria<SnapshotDataStoreVO> sc = idStateNeqSearch.create(); + SearchCriteria<SnapshotDataStoreVO> sc = idStateNinSearch.create(); sc.setParameters(SNAPSHOT_ID, snapshotId); - sc.setParameters(STATE, State.Destroyed); + sc.setParameters(STATE, State.Destroyed.name()); + return listBy(sc); + } + + @Override + public List<SnapshotDataStoreVO> findBySnapshotIdAndNotInDestroyedHiddenState(long snapshotId) { + SearchCriteria<SnapshotDataStoreVO> sc = idStateNinSearch.create(); + sc.setParameters(SNAPSHOT_ID, snapshotId); + sc.setParameters(STATE, State.Destroyed.name(), State.Hidden.name()); return listBy(sc); } diff --cc server/src/main/java/com/cloud/storage/snapshot/SnapshotManagerImpl.java index 56398dd960c,e7606572a07..ff9989acac3 --- a/server/src/main/java/com/cloud/storage/snapshot/SnapshotManagerImpl.java +++ b/server/src/main/java/com/cloud/storage/snapshot/SnapshotManagerImpl.java @@@ -1720,70 -1499,12 +1720,70 @@@ public class SnapshotManagerImpl extend return snapshot; } - protected void backupSnapshotToSecondary(boolean asyncBackup, SnapshotStrategy snapshotStrategy, SnapshotInfo snapshotOnPrimary, List<Long> zoneIds) { + private void postSnapshotDirectlyToSecondary(SnapshotInfo snapshot, SnapshotInfo snapshotOnPrimary, Long snapshotId) { + logger.debug("{} was directly copied to secondary storage because the hypervisor is KVM, the primary storage is file-based and the [{}] configuration" + + " is set to true.", snapshot.getSnapshotVO().toString(), SnapshotInfo.BackupSnapshotAfterTakingSnapshot); + + SnapshotDataStoreVO snapshotStore = _snapshotStoreDao.findBySnapshotIdAndDataStoreRoleAndState(snapshotId, DataStoreRole.Image, ObjectInDataStoreStateMachine.State.Allocated); + + snapshotStore.setInstallPath(snapshotOnPrimary.getPath()); + snapshotStore.setState(ObjectInDataStoreStateMachine.State.Ready); + + _snapshotStoreDao.update(snapshotStore.getId(), snapshotStore); + + snapshotOnPrimary.markBackedUp(); + _snapshotStoreDao.removeBySnapshotStore(snapshotId, snapshotOnPrimary.getDataStore().getId(), snapshotOnPrimary.getDataStore().getRole()); + snapshotDetailsDao.removeDetail(snapshotOnPrimary.getId(), AsyncJob.Constants.MS_ID); + } + + @Override + public boolean isHypervisorKvmAndFileBasedStorage(VolumeInfo volumeInfo, StoragePool storagePool) { + Set<StoragePoolType> fileBasedStores = Set.of(Storage.StoragePoolType.SharedMountPoint, Storage.StoragePoolType.NetworkFilesystem, Storage.StoragePoolType.Filesystem); + return volumeInfo.getHypervisorType() == HypervisorType.KVM && fileBasedStores.contains(storagePool.getPoolType()); + } + + private void copyNewSnapshotToZonesOnPrimary(CreateSnapshotPayload payload, SnapshotInfo snapshot) { + SnapshotStrategy snapshotStrategy; + snapshotStrategy = _storageStrategyFactory.getSnapshotStrategy(snapshot, SnapshotOperation.COPY); + if (snapshotStrategy != null) { + for (Long storagePoolId : payload.getStoragePoolIds()) { + copySnapshotOnPool(snapshot, snapshotStrategy, storagePoolId); + } + } else { + logger.info("Unable to find snapshot strategy to handle the copy of a snapshot with id " + snapshot.getUuid()); + } + } + + private boolean copySnapshotOnPool(SnapshotInfo snapshot, SnapshotStrategy snapshotStrategy, Long storagePoolId) { + DataStore store = dataStoreMgr.getDataStore(storagePoolId, DataStoreRole.Primary); + SnapshotInfo snapshotOnStore = (SnapshotInfo) store.create(snapshot); + + try { + AsyncCallFuture<SnapshotResult> future = snapshotSrv.copySnapshot(snapshot, snapshotOnStore, snapshotStrategy); + SnapshotResult result = future.get(); + if (result.isFailed()) { + logger.debug(String.format("Copy snapshot ID: %d failed for primary storage %s: %s", snapshot.getSnapshotId(), storagePoolId, result.getResult())); + return false; + } + snapshotZoneDao.addSnapshotToZone(snapshot.getId(), snapshotOnStore.getDataCenterId()); + _resourceLimitMgr.incrementResourceCount(CallContext.current().getCallingUserId(), ResourceType.primary_storage, snapshot.getSize()); + if (CallContext.current().getCallingUserId() != Account.ACCOUNT_ID_SYSTEM) { + SnapshotVO snapshotVO = _snapshotDao.findByIdIncludingRemoved(snapshot.getSnapshotId()); + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SNAPSHOT_COPY, CallContext.current().getCallingAccountId(), snapshotOnStore.getDataCenterId(), snapshotVO.getId(), null, null, null, snapshotVO.getSize(), + snapshotVO.getSize(), snapshotVO.getClass().getName(), snapshotVO.getUuid()); + } + } catch (InterruptedException | ExecutionException e) { + throw new RuntimeException("Could not copy the snapshot to another pool", e); + } + return true; + } + + protected void backupSnapshotToSecondary(boolean asyncBackup, SnapshotStrategy snapshotStrategy, SnapshotInfo snapshotOnPrimary, List<Long> zoneIds, List<Long> poolIds) { if (asyncBackup) { - backupSnapshotExecutor.schedule(new BackupSnapshotTask(snapshotOnPrimary, snapshotBackupRetries - 1, snapshotStrategy, zoneIds), 0, TimeUnit.SECONDS); + backupSnapshotExecutor.schedule(new BackupSnapshotTask(snapshotOnPrimary, snapshotBackupRetries - 1, snapshotStrategy, zoneIds, poolIds), 0, TimeUnit.SECONDS); } else { - SnapshotInfo backupedSnapshot = snapshotStrategy.backupSnapshot(snapshotOnPrimary); - if (backupedSnapshot != null) { + SnapshotInfo backedUpSnapshot = snapshotStrategy.backupSnapshot(snapshotOnPrimary); + if (backedUpSnapshot != null) { snapshotStrategy.postSnapshotCreation(snapshotOnPrimary); } } @@@ -1795,10 -1516,9 +1795,10 @@@ SnapshotStrategy snapshotStrategy; List<Long> zoneIds; + List<Long> poolIds; - public BackupSnapshotTask(SnapshotInfo snap, int maxRetries, SnapshotStrategy strategy, List<Long> zoneIds, List<Long> poolIds) { - snapshot = snap; - public BackupSnapshotTask(SnapshotInfo snapshot, int maxRetries, SnapshotStrategy strategy, List<Long> zoneIds) { ++ public BackupSnapshotTask(SnapshotInfo snapshot, int maxRetries, SnapshotStrategy strategy, List<Long> zoneIds, List<Long> poolIds) { + snapshotOnPrimary = snapshot; attempts = maxRetries; snapshotStrategy = strategy; this.zoneIds = zoneIds; @@@ -1809,32 -1528,20 +1809,31 @@@ protected void runInContext() { try { logger.debug("Value of attempts is " + (snapshotBackupRetries - attempts)); + if (Boolean.TRUE.equals(SnapshotInfo.BackupSnapshotAfterTakingSnapshot.value()) && CollectionUtils.isEmpty(poolIds)) { - SnapshotInfo backupedSnapshot = snapshotStrategy.backupSnapshot(snapshot); - ++ SnapshotInfo backupedSnapshot = snapshotStrategy.backupSnapshot(snapshotOnPrimary); + if (backupedSnapshot != null) { - snapshotStrategy.postSnapshotCreation(snapshot); - copyNewSnapshotToZones(snapshot.getId(), snapshot.getDataCenterId(), zoneIds); ++ snapshotStrategy.postSnapshotCreation(snapshotOnPrimary); ++ copyNewSnapshotToZones(snapshotOnPrimary.getId(), snapshotOnPrimary.getDataCenterId(), zoneIds); + } + } - SnapshotInfo backedUpSnapshot = snapshotStrategy.backupSnapshot(snapshotOnPrimary); - if (backedUpSnapshot != null) { - snapshotStrategy.postSnapshotCreation(snapshotOnPrimary); - copyNewSnapshotToZones(snapshotOnPrimary.getId(), snapshotOnPrimary.getDataCenterId(), zoneIds); + if (CollectionUtils.isNotEmpty(poolIds)) { + for (Long poolId: poolIds) { - copySnapshotOnPool(snapshot, snapshotStrategy, poolId); ++ copySnapshotOnPool(snapshotOnPrimary, snapshotStrategy, poolId); + } } } catch (final Exception e) { - if (attempts >= 0) { - logger.debug("Backing up of snapshot failed, for snapshot {}, left with {} more attempts", snapshotOnPrimary, attempts); - backupSnapshotExecutor.schedule(new BackupSnapshotTask(snapshotOnPrimary, --attempts, snapshotStrategy, zoneIds), snapshotBackupRetryInterval, TimeUnit.SECONDS); - } else { - logger.debug("Done with {} attempts in backing up of snapshot {}", snapshotBackupRetries, snapshotOnPrimary.getSnapshotVO()); - snapshotSrv.cleanupOnSnapshotBackupFailure(snapshotOnPrimary); - } + decriseBackupSnapshotAttempts(); + } + } + + private void decriseBackupSnapshotAttempts() { + if (attempts >= 0) { - logger.debug("Backing up of snapshot failed, for snapshot {}, left with {} more attempts", snapshot, attempts); - backupSnapshotExecutor.schedule(new BackupSnapshotTask(snapshot, --attempts, snapshotStrategy, zoneIds, poolIds), snapshotBackupRetryInterval, TimeUnit.SECONDS); ++ logger.debug("Backing up of snapshot failed, for snapshot {}, left with {} more attempts", snapshotOnPrimary, attempts); ++ backupSnapshotExecutor.schedule(new BackupSnapshotTask(snapshotOnPrimary, --attempts, snapshotStrategy, zoneIds, poolIds), snapshotBackupRetryInterval, TimeUnit.SECONDS); + } else { - logger.debug("Done with {} attempts in backing up of snapshot {}", snapshotBackupRetries, snapshot.getSnapshotVO()); - snapshotSrv.cleanupOnSnapshotBackupFailure(snapshot); ++ logger.debug("Done with {} attempts in backing up of snapshot {}", snapshotBackupRetries, snapshotOnPrimary.getSnapshotVO()); ++ snapshotSrv.cleanupOnSnapshotBackupFailure(snapshotOnPrimary); } } } diff --cc ui/src/views/compute/wizard/OwnershipSelection.vue index 59f781a75aa,b29069628db..484ffdb690f --- a/ui/src/views/compute/wizard/OwnershipSelection.vue +++ b/ui/src/views/compute/wizard/OwnershipSelection.vue @@@ -186,9 -188,14 +188,14 @@@ export default this.loading = false }) }, + incrementAndGetRequestToken () { + this.requestToken += 1 + return this.requestToken + }, fetchAccounts () { this.loading = true + const currentToken = this.incrementAndGetRequestToken() - api('listAccounts', { + getAPI('listAccounts', { response: 'json', domainId: this.selectedDomain, showicon: true, @@@ -218,7 -229,8 +229,8 @@@ }, fetchProjects () { this.loading = true + const currentToken = this.incrementAndGetRequestToken() - api('listProjects', { + getAPI('listProjects', { response: 'json', domainId: this.selectedDomain, state: 'Active',
