This is an automated email from the ASF dual-hosted git repository. dahn pushed a commit to branch 4.19 in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/4.19 by this push: new 32cc45e8405 [UI] Allow quiescevm and asyncbackup flags while taking volume snapshot from UI when these are supported for the volume (#10265) 32cc45e8405 is described below commit 32cc45e84059865c08270466218d8706e30f7bf4 Author: Suresh Kumar Anaparti <sureshkumar.anapa...@gmail.com> AuthorDate: Fri May 2 14:15:50 2025 +0530 [UI] Allow quiescevm and asyncbackup flags while taking volume snapshot from UI when these are supported for the volume (#10265) --- .../storage/vmsnapshot/StorageVMSnapshotStrategy.java | 13 +++++++++---- .../storage/vmsnapshot/VMSnapshotStrategyKVMTest.java | 4 +++- .../com/cloud/storage/snapshot/SnapshotManagerImpl.java | 2 +- ui/src/config/section/compute.js | 8 +++++++- ui/src/views/compute/CreateSnapshotWizard.vue | 13 ++++++++++--- ui/src/views/storage/TakeSnapshot.vue | 9 +++++++-- 6 files changed, 37 insertions(+), 12 deletions(-) diff --git a/engine/storage/snapshot/src/main/java/org/apache/cloudstack/storage/vmsnapshot/StorageVMSnapshotStrategy.java b/engine/storage/snapshot/src/main/java/org/apache/cloudstack/storage/vmsnapshot/StorageVMSnapshotStrategy.java index f5d70817333..64d8f0a0df0 100644 --- a/engine/storage/snapshot/src/main/java/org/apache/cloudstack/storage/vmsnapshot/StorageVMSnapshotStrategy.java +++ b/engine/storage/snapshot/src/main/java/org/apache/cloudstack/storage/vmsnapshot/StorageVMSnapshotStrategy.java @@ -183,7 +183,7 @@ public class StorageVMSnapshotStrategy extends DefaultVMSnapshotStrategy { thawAnswer = (FreezeThawVMAnswer) agentMgr.send(hostId, thawCmd); if (thawAnswer != null && thawAnswer.getResult()) { s_logger.info(String.format( - "Virtual machne is thawed. The freeze of virtual machine took %s milliseconds.", + "Virtual machine is thawed. The freeze of virtual machine took %s milliseconds.", TimeUnit.MILLISECONDS.convert(elapsedTime(startFreeze), TimeUnit.NANOSECONDS))); } } else { @@ -429,9 +429,14 @@ public class StorageVMSnapshotStrategy extends DefaultVMSnapshotStrategy { String snapshotName = vmSnapshot.getId() + "_" + vol.getUuid(); SnapshotVO snapshot = new SnapshotVO(vol.getDataCenterId(), vol.getAccountId(), vol.getDomainId(), vol.getId(), vol.getDiskOfferingId(), snapshotName, (short) Snapshot.Type.GROUP.ordinal(), Snapshot.Type.GROUP.name(), vol.getSize(), vol.getMinIops(), vol.getMaxIops(), Hypervisor.HypervisorType.KVM, null); + VMSnapshotOptions options = ((VMSnapshotVO) vmSnapshot).getOptions(); + boolean quiescevm = false; + if (options != null) { + quiescevm = options.needQuiesceVM(); + } snapshot = snapshotDao.persist(snapshot); - vol.addPayload(setPayload(vol, snapshot)); + vol.addPayload(setPayload(vol, snapshot, quiescevm)); SnapshotInfo snapshotInfo = snapshotDataFactory.getSnapshot(snapshot.getId(), vol.getDataStore()); snapshotInfo.addPayload(vol.getpayload()); SnapshotStrategy snapshotStrategy = storageStrategyFactory.getSnapshotStrategy(snapshotInfo, SnapshotOperation.TAKE); @@ -449,14 +454,14 @@ public class StorageVMSnapshotStrategy extends DefaultVMSnapshotStrategy { return snapshotInfo; } - protected CreateSnapshotPayload setPayload(VolumeInfo vol, SnapshotVO snapshotCreate) { + protected CreateSnapshotPayload setPayload(VolumeInfo vol, SnapshotVO snapshotCreate, boolean quiescevm) { CreateSnapshotPayload payload = new CreateSnapshotPayload(); payload.setSnapshotId(snapshotCreate.getId()); payload.setSnapshotPolicyId(SnapshotVO.MANUAL_POLICY_ID); payload.setLocationType(snapshotCreate.getLocationType()); payload.setAccount(accountService.getAccount(vol.getAccountId())); payload.setAsyncBackup(false); - payload.setQuiescevm(false); + payload.setQuiescevm(quiescevm); return payload; } } diff --git a/engine/storage/snapshot/src/test/java/org/apache/cloudstack/storage/vmsnapshot/VMSnapshotStrategyKVMTest.java b/engine/storage/snapshot/src/test/java/org/apache/cloudstack/storage/vmsnapshot/VMSnapshotStrategyKVMTest.java index d438fef5638..21aba803989 100644 --- a/engine/storage/snapshot/src/test/java/org/apache/cloudstack/storage/vmsnapshot/VMSnapshotStrategyKVMTest.java +++ b/engine/storage/snapshot/src/test/java/org/apache/cloudstack/storage/vmsnapshot/VMSnapshotStrategyKVMTest.java @@ -37,6 +37,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy.SnapshotOperation; import org.apache.cloudstack.engine.subsystem.api.storage.StorageStrategyFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.VMSnapshotOptions; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; @@ -151,7 +152,7 @@ public class VMSnapshotStrategyKVMTest extends TestCase{ @Test public void testCreateDiskSnapshotBasedOnStrategy() throws Exception { - VMSnapshot vmSnapshot = Mockito.mock(VMSnapshot.class); + VMSnapshotVO vmSnapshot = Mockito.mock(VMSnapshotVO.class); List<SnapshotInfo> forRollback = new ArrayList<>(); VolumeInfo vol = Mockito.mock(VolumeInfo.class); SnapshotInfo snapshotInfo = Mockito.mock(SnapshotInfo.class); @@ -162,6 +163,7 @@ public class VMSnapshotStrategyKVMTest extends TestCase{ SnapshotVO snapshot = new SnapshotVO(vol.getDataCenterId(), vol.getAccountId(), vol.getDomainId(), vol.getId(),vol.getDiskOfferingId(), vmUuid + "_" + volUuid,(short) SnapshotVO.MANUAL_POLICY_ID, "MANUAL",vol.getSize(),vol.getMinIops(),vol.getMaxIops(), Hypervisor.HypervisorType.KVM, null); + when(vmSnapshot.getOptions()).thenReturn(new VMSnapshotOptions(true)); when(vmSnapshot.getUuid()).thenReturn(vmUuid); when(vol.getUuid()).thenReturn(volUuid); when(_snapshotDao.persist(any())).thenReturn(snapshot); diff --git a/server/src/main/java/com/cloud/storage/snapshot/SnapshotManagerImpl.java b/server/src/main/java/com/cloud/storage/snapshot/SnapshotManagerImpl.java index 940860dd04d..ab4a71903f6 100755 --- a/server/src/main/java/com/cloud/storage/snapshot/SnapshotManagerImpl.java +++ b/server/src/main/java/com/cloud/storage/snapshot/SnapshotManagerImpl.java @@ -1416,7 +1416,7 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement } } catch (CloudRuntimeException cre) { if (s_logger.isDebugEnabled()) { - s_logger.debug("Failed to create snapshot" + cre.getLocalizedMessage()); + s_logger.debug("Failed to create snapshot - " + cre.getLocalizedMessage()); } _resourceLimitMgr.decrementResourceCount(snapshotOwner.getId(), ResourceType.snapshot); _resourceLimitMgr.decrementResourceCount(snapshotOwner.getId(), ResourceType.secondary_storage, new Long(volume.getSize())); diff --git a/ui/src/config/section/compute.js b/ui/src/config/section/compute.js index 2887044a535..b7c2a342d09 100644 --- a/ui/src/config/section/compute.js +++ b/ui/src/config/section/compute.js @@ -184,7 +184,13 @@ export default { label: 'label.action.vmsnapshot.create', docHelp: 'adminguide/virtual_machines.html#virtual-machine-snapshots', dataView: true, - args: ['virtualmachineid', 'name', 'description', 'snapshotmemory', 'quiescevm'], + args: (record, store) => { + var args = ['virtualmachineid', 'name', 'description', 'snapshotmemory'] + if (['KVM', 'VMware'].includes(record.hypervisor)) { + args.push('quiescevm') + } + return args + }, show: (record) => { return ((['Running'].includes(record.state) && record.hypervisor !== 'LXC') || (['Stopped'].includes(record.state) && ((record.hypervisor !== 'KVM' && record.hypervisor !== 'LXC') || diff --git a/ui/src/views/compute/CreateSnapshotWizard.vue b/ui/src/views/compute/CreateSnapshotWizard.vue index 0da42990efa..d19208a1808 100644 --- a/ui/src/views/compute/CreateSnapshotWizard.vue +++ b/ui/src/views/compute/CreateSnapshotWizard.vue @@ -55,13 +55,13 @@ v-model:value="form.name" :placeholder="apiParams.name.description"/> </a-form-item> - <a-form-item name="quiescevm" ref="quiescevm" v-if="isQuiesceVm"> + <a-form-item name="quiescevm" ref="quiescevm" v-if="isQuiesceVm && hypervisorSupportsQuiesceVm"> <template #label> <tooltip-label :title="$t('label.quiescevm')" :tooltip="apiParams.quiescevm.description"/> </template> <a-switch v-model:checked="form.quiescevm"/> </a-form-item> - <a-form-item name="asyncbackup" ref="asyncbackup"> + <a-form-item name="asyncbackup" ref="asyncbackup" v-if="!supportsStorageSnapshot"> <template #label> <tooltip-label :title="$t('label.asyncbackup')" :tooltip="apiParams.asyncbackup.description"/> </template> @@ -98,6 +98,7 @@ export default { return { loading: false, isQuiesceVm: false, + hypervisorSupportsQuiesceVm: false, supportsStorageSnapshot: false, listVolumes: [] } @@ -119,6 +120,9 @@ export default { }, fetchData () { this.loading = true + if (['KVM', 'VMware'].includes(this.resource.hypervisor)) { + this.hypervisorSupportsQuiesceVm = true + } api('listVolumes', { virtualMachineId: this.resource.id, listall: true }) .then(json => { @@ -141,7 +145,10 @@ export default { if (values.asyncbackup) { params.asyncbackup = values.asyncbackup } - params.quiescevm = values.quiescevm + params.quiescevm = false + if (values.quiescevm) { + params.quiescevm = values.quiescevm + } const title = this.$t('label.action.vmstoragesnapshot.create') const description = values.name || values.volumeid diff --git a/ui/src/views/storage/TakeSnapshot.vue b/ui/src/views/storage/TakeSnapshot.vue index ee0eafbb56a..e378664d7fb 100644 --- a/ui/src/views/storage/TakeSnapshot.vue +++ b/ui/src/views/storage/TakeSnapshot.vue @@ -66,10 +66,10 @@ </a-select-option> </a-select> </a-form-item> - <a-form-item :label="$t('label.asyncbackup')" name="asyncbackup" ref="asyncbackup"> + <a-form-item :label="$t('label.asyncbackup')" name="asyncbackup" ref="asyncbackup" v-if="!supportsStorageSnapshot"> <a-switch v-model:checked="form.asyncbackup" /> </a-form-item> - <a-form-item :label="$t('label.quiescevm')"> + <a-form-item :label="$t('label.quiescevm')" name="quiescevm" ref="quiescevm" v-if="quiescevm && hypervisorSupportsQuiesceVm"> <a-switch v-model:checked="form.quiescevm" /> </a-form-item> <a-divider/> @@ -152,6 +152,7 @@ export default { return { actionLoading: false, quiescevm: false, + hypervisorSupportsQuiesceVm: false, supportsStorageSnapshot: false, inputValue: '', inputKey: '', @@ -168,6 +169,10 @@ export default { created () { this.initForm() this.quiescevm = this.resource.quiescevm + if (['KVM', 'VMware'].includes(this.resource.hypervisor)) { + this.hypervisorSupportsQuiesceVm = true + } + this.supportsStorageSnapshot = this.resource.supportsstoragesnapshot this.fetchZoneData() },