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',

Reply via email to