Skip to content

Commit 32cc45e

Browse files
[UI] Allow quiescevm and asyncbackup flags while taking volume snapshot from UI when these are supported for the volume (#10265)
1 parent 4c072b5 commit 32cc45e

File tree

6 files changed

+37
-12
lines changed

6 files changed

+37
-12
lines changed

engine/storage/snapshot/src/main/java/org/apache/cloudstack/storage/vmsnapshot/StorageVMSnapshotStrategy.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ public VMSnapshot takeVMSnapshot(VMSnapshot vmSnapshot) {
183183
thawAnswer = (FreezeThawVMAnswer) agentMgr.send(hostId, thawCmd);
184184
if (thawAnswer != null && thawAnswer.getResult()) {
185185
s_logger.info(String.format(
186-
"Virtual machne is thawed. The freeze of virtual machine took %s milliseconds.",
186+
"Virtual machine is thawed. The freeze of virtual machine took %s milliseconds.",
187187
TimeUnit.MILLISECONDS.convert(elapsedTime(startFreeze), TimeUnit.NANOSECONDS)));
188188
}
189189
} else {
@@ -429,9 +429,14 @@ protected SnapshotInfo createDiskSnapshot(VMSnapshot vmSnapshot, List<SnapshotIn
429429
String snapshotName = vmSnapshot.getId() + "_" + vol.getUuid();
430430
SnapshotVO snapshot = new SnapshotVO(vol.getDataCenterId(), vol.getAccountId(), vol.getDomainId(), vol.getId(), vol.getDiskOfferingId(),
431431
snapshotName, (short) Snapshot.Type.GROUP.ordinal(), Snapshot.Type.GROUP.name(), vol.getSize(), vol.getMinIops(), vol.getMaxIops(), Hypervisor.HypervisorType.KVM, null);
432+
VMSnapshotOptions options = ((VMSnapshotVO) vmSnapshot).getOptions();
433+
boolean quiescevm = false;
434+
if (options != null) {
435+
quiescevm = options.needQuiesceVM();
436+
}
432437

433438
snapshot = snapshotDao.persist(snapshot);
434-
vol.addPayload(setPayload(vol, snapshot));
439+
vol.addPayload(setPayload(vol, snapshot, quiescevm));
435440
SnapshotInfo snapshotInfo = snapshotDataFactory.getSnapshot(snapshot.getId(), vol.getDataStore());
436441
snapshotInfo.addPayload(vol.getpayload());
437442
SnapshotStrategy snapshotStrategy = storageStrategyFactory.getSnapshotStrategy(snapshotInfo, SnapshotOperation.TAKE);
@@ -449,14 +454,14 @@ protected SnapshotInfo createDiskSnapshot(VMSnapshot vmSnapshot, List<SnapshotIn
449454
return snapshotInfo;
450455
}
451456

452-
protected CreateSnapshotPayload setPayload(VolumeInfo vol, SnapshotVO snapshotCreate) {
457+
protected CreateSnapshotPayload setPayload(VolumeInfo vol, SnapshotVO snapshotCreate, boolean quiescevm) {
453458
CreateSnapshotPayload payload = new CreateSnapshotPayload();
454459
payload.setSnapshotId(snapshotCreate.getId());
455460
payload.setSnapshotPolicyId(SnapshotVO.MANUAL_POLICY_ID);
456461
payload.setLocationType(snapshotCreate.getLocationType());
457462
payload.setAccount(accountService.getAccount(vol.getAccountId()));
458463
payload.setAsyncBackup(false);
459-
payload.setQuiescevm(false);
464+
payload.setQuiescevm(quiescevm);
460465
return payload;
461466
}
462467
}

engine/storage/snapshot/src/test/java/org/apache/cloudstack/storage/vmsnapshot/VMSnapshotStrategyKVMTest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy;
3838
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy.SnapshotOperation;
3939
import org.apache.cloudstack.engine.subsystem.api.storage.StorageStrategyFactory;
40+
import org.apache.cloudstack.engine.subsystem.api.storage.VMSnapshotOptions;
4041
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
4142
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
4243
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
@@ -151,7 +152,7 @@ public void setUp() throws Exception {
151152

152153
@Test
153154
public void testCreateDiskSnapshotBasedOnStrategy() throws Exception {
154-
VMSnapshot vmSnapshot = Mockito.mock(VMSnapshot.class);
155+
VMSnapshotVO vmSnapshot = Mockito.mock(VMSnapshotVO.class);
155156
List<SnapshotInfo> forRollback = new ArrayList<>();
156157
VolumeInfo vol = Mockito.mock(VolumeInfo.class);
157158
SnapshotInfo snapshotInfo = Mockito.mock(SnapshotInfo.class);
@@ -162,6 +163,7 @@ public void testCreateDiskSnapshotBasedOnStrategy() throws Exception {
162163
SnapshotVO snapshot = new SnapshotVO(vol.getDataCenterId(), vol.getAccountId(), vol.getDomainId(),
163164
vol.getId(),vol.getDiskOfferingId(), vmUuid + "_" + volUuid,(short) SnapshotVO.MANUAL_POLICY_ID,
164165
"MANUAL",vol.getSize(),vol.getMinIops(),vol.getMaxIops(), Hypervisor.HypervisorType.KVM, null);
166+
when(vmSnapshot.getOptions()).thenReturn(new VMSnapshotOptions(true));
165167
when(vmSnapshot.getUuid()).thenReturn(vmUuid);
166168
when(vol.getUuid()).thenReturn(volUuid);
167169
when(_snapshotDao.persist(any())).thenReturn(snapshot);

server/src/main/java/com/cloud/storage/snapshot/SnapshotManagerImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1416,7 +1416,7 @@ public SnapshotInfo takeSnapshot(VolumeInfo volume) throws ResourceAllocationExc
14161416
}
14171417
} catch (CloudRuntimeException cre) {
14181418
if (s_logger.isDebugEnabled()) {
1419-
s_logger.debug("Failed to create snapshot" + cre.getLocalizedMessage());
1419+
s_logger.debug("Failed to create snapshot - " + cre.getLocalizedMessage());
14201420
}
14211421
_resourceLimitMgr.decrementResourceCount(snapshotOwner.getId(), ResourceType.snapshot);
14221422
_resourceLimitMgr.decrementResourceCount(snapshotOwner.getId(), ResourceType.secondary_storage, new Long(volume.getSize()));

ui/src/config/section/compute.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,13 @@ export default {
184184
label: 'label.action.vmsnapshot.create',
185185
docHelp: 'adminguide/virtual_machines.html#virtual-machine-snapshots',
186186
dataView: true,
187-
args: ['virtualmachineid', 'name', 'description', 'snapshotmemory', 'quiescevm'],
187+
args: (record, store) => {
188+
var args = ['virtualmachineid', 'name', 'description', 'snapshotmemory']
189+
if (['KVM', 'VMware'].includes(record.hypervisor)) {
190+
args.push('quiescevm')
191+
}
192+
return args
193+
},
188194
show: (record) => {
189195
return ((['Running'].includes(record.state) && record.hypervisor !== 'LXC') ||
190196
(['Stopped'].includes(record.state) && ((record.hypervisor !== 'KVM' && record.hypervisor !== 'LXC') ||

ui/src/views/compute/CreateSnapshotWizard.vue

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,13 @@
5555
v-model:value="form.name"
5656
:placeholder="apiParams.name.description"/>
5757
</a-form-item>
58-
<a-form-item name="quiescevm" ref="quiescevm" v-if="isQuiesceVm">
58+
<a-form-item name="quiescevm" ref="quiescevm" v-if="isQuiesceVm && hypervisorSupportsQuiesceVm">
5959
<template #label>
6060
<tooltip-label :title="$t('label.quiescevm')" :tooltip="apiParams.quiescevm.description"/>
6161
</template>
6262
<a-switch v-model:checked="form.quiescevm"/>
6363
</a-form-item>
64-
<a-form-item name="asyncbackup" ref="asyncbackup">
64+
<a-form-item name="asyncbackup" ref="asyncbackup" v-if="!supportsStorageSnapshot">
6565
<template #label>
6666
<tooltip-label :title="$t('label.asyncbackup')" :tooltip="apiParams.asyncbackup.description"/>
6767
</template>
@@ -98,6 +98,7 @@ export default {
9898
return {
9999
loading: false,
100100
isQuiesceVm: false,
101+
hypervisorSupportsQuiesceVm: false,
101102
supportsStorageSnapshot: false,
102103
listVolumes: []
103104
}
@@ -119,6 +120,9 @@ export default {
119120
},
120121
fetchData () {
121122
this.loading = true
123+
if (['KVM', 'VMware'].includes(this.resource.hypervisor)) {
124+
this.hypervisorSupportsQuiesceVm = true
125+
}
122126
123127
api('listVolumes', { virtualMachineId: this.resource.id, listall: true })
124128
.then(json => {
@@ -141,7 +145,10 @@ export default {
141145
if (values.asyncbackup) {
142146
params.asyncbackup = values.asyncbackup
143147
}
144-
params.quiescevm = values.quiescevm
148+
params.quiescevm = false
149+
if (values.quiescevm) {
150+
params.quiescevm = values.quiescevm
151+
}
145152
146153
const title = this.$t('label.action.vmstoragesnapshot.create')
147154
const description = values.name || values.volumeid

ui/src/views/storage/TakeSnapshot.vue

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,10 @@
6666
</a-select-option>
6767
</a-select>
6868
</a-form-item>
69-
<a-form-item :label="$t('label.asyncbackup')" name="asyncbackup" ref="asyncbackup">
69+
<a-form-item :label="$t('label.asyncbackup')" name="asyncbackup" ref="asyncbackup" v-if="!supportsStorageSnapshot">
7070
<a-switch v-model:checked="form.asyncbackup" />
7171
</a-form-item>
72-
<a-form-item :label="$t('label.quiescevm')">
72+
<a-form-item :label="$t('label.quiescevm')" name="quiescevm" ref="quiescevm" v-if="quiescevm && hypervisorSupportsQuiesceVm">
7373
<a-switch v-model:checked="form.quiescevm" />
7474
</a-form-item>
7575
<a-divider/>
@@ -152,6 +152,7 @@ export default {
152152
return {
153153
actionLoading: false,
154154
quiescevm: false,
155+
hypervisorSupportsQuiesceVm: false,
155156
supportsStorageSnapshot: false,
156157
inputValue: '',
157158
inputKey: '',
@@ -168,6 +169,10 @@ export default {
168169
created () {
169170
this.initForm()
170171
this.quiescevm = this.resource.quiescevm
172+
if (['KVM', 'VMware'].includes(this.resource.hypervisor)) {
173+
this.hypervisorSupportsQuiesceVm = true
174+
}
175+
171176
this.supportsStorageSnapshot = this.resource.supportsstoragesnapshot
172177
this.fetchZoneData()
173178
},

0 commit comments

Comments
 (0)