Skip to content

Commit b8ca6f1

Browse files
mvollmermartinpitt
authored andcommitted
snapshots: Don't list disks in XML
We can control whether or not an external snapshot is made with the "disk only" flag and the memory path, and libvirt will provide defaults for all the disks. Cherry-picked from main commit ebcf07b
1 parent 77ddc73 commit b8ca6f1

File tree

3 files changed

+39
-42
lines changed

3 files changed

+39
-42
lines changed

src/components/vm/snapshots/vmSnapshotsCreateModal.jsx

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -147,22 +147,18 @@ export class CreateSnapshotModal extends React.Component {
147147

148148
onCreate() {
149149
const Dialogs = this.context;
150-
const { vm, isExternal, storagePools } = this.props;
150+
const { vm, isExternal } = this.props;
151151
const { name, description, memoryPath } = this.state;
152-
const disks = Object.values(vm.disks);
153152
const validationError = this.onValidate();
154153

155154
if (!Object.keys(validationError).length) {
156155
this.setState({ inProgress: true });
157156
snapshotCreate({
158-
connectionName: vm.connectionName,
159-
vmId: vm.id,
157+
vm,
160158
name,
161159
description,
162-
memoryPath: vm.state === "running" && memoryPath,
163-
disks,
164160
isExternal,
165-
storagePools
161+
memoryPath: isExternal && vm.state === "running" && memoryPath,
166162
})
167163
.then(() => {
168164
// VM Snapshots do not trigger any events so we have to refresh them manually

src/libvirt-xml-create.js

Lines changed: 6 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ export function getPoolXML({ name, type, source, target }) {
236236
}
237237

238238
// see https://libvirt.org/formatsnapshot.html
239-
export function getSnapshotXML(name, description, disks, memoryPath, isExternal, storagePools, connectionName) {
239+
export function getSnapshotXML(name, description, memoryPath) {
240240
const doc = document.implementation.createDocument('', '', null);
241241

242242
const snapElem = doc.createElement('domainsnapshot');
@@ -253,36 +253,11 @@ export function getSnapshotXML(name, description, disks, memoryPath, isExternal,
253253
snapElem.appendChild(descriptionElem);
254254
}
255255

256-
if (isExternal) {
257-
if (memoryPath) {
258-
const memoryElem = doc.createElement('memory');
259-
memoryElem.setAttribute('snapshot', 'external');
260-
memoryElem.setAttribute('file', memoryPath);
261-
snapElem.appendChild(memoryElem);
262-
}
263-
264-
const disksElem = doc.createElement('disks');
265-
disks.forEach(disk => {
266-
// Disk can have attribute "snapshot" set to "no", which
267-
// means no snapshot should be created of the said disk
268-
// This cannot be configured through cockpit, but we
269-
// should uphold it nevertheless.
270-
//
271-
// See "snapshot" attribute of <disk> element at
272-
// https://libvirt.org/formatdomain.html#hard-drives-floppy-disks-cdroms
273-
if (disk.snapshot == "no")
274-
return;
275-
276-
// Skip disks without source, such as empty media drives.
277-
if (isExternal && disk.type == "file" && !disk.source.file)
278-
return;
279-
280-
const diskElem = doc.createElement('disk');
281-
diskElem.setAttribute('name', disk.target);
282-
diskElem.setAttribute('snapshot', 'external');
283-
disksElem.appendChild(diskElem);
284-
});
285-
snapElem.appendChild(disksElem);
256+
if (memoryPath) {
257+
const memoryElem = doc.createElement('memory');
258+
memoryElem.setAttribute('snapshot', 'external');
259+
memoryElem.setAttribute('file', memoryPath);
260+
snapElem.appendChild(memoryElem);
286261
}
287262

288263
doc.appendChild(snapElem);

src/libvirtApi/snapshot.js

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,37 @@ import { parseDomainSnapshotDumpxml } from '../libvirt-xml-parse.js';
2929
import { call, Enum, timeout } from './helpers.js';
3030
import { logDebug } from '../helpers.js';
3131

32-
export function snapshotCreate({ connectionName, vmId, name, description, memoryPath, disks, isExternal, storagePools }) {
33-
// that flag ought to be implicit for non-running VMs, see https://issues.redhat.com/browse/RHEL-22797
32+
export async function snapshotCreate({ vm, name, description, isExternal, memoryPath }) {
33+
// The "disk only" flag ought to be implicit for non-running VMs, see https://issues.redhat.com/browse/RHEL-22797
34+
35+
// However, "disk only" can be used to request external snapshots
36+
// for a stopped machine. The alternative is to list all disks
37+
// with a snapshot type of "external" in the XML, but then we need
38+
// to worry about which disks to include and which to skip.
39+
40+
// The behavior is as follows:
41+
//
42+
// VM state | disk only | memory path => resulting snapshot type
43+
// --------------------------------------------------------------------
44+
// shutoff | false | null => internal
45+
// shutoff | true | null => external
46+
// running | false | null => internal full system
47+
// running | false | non-null => external full system
48+
// running | true | null => external disk only
49+
//
50+
// Other cases are errors.
51+
3452
const flags = (!isExternal || memoryPath) ? 0 : Enum.VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY;
35-
const xmlDesc = getSnapshotXML(name, description, disks, memoryPath, isExternal, storagePools, connectionName);
36-
return call(connectionName, vmId, 'org.libvirt.Domain', 'SnapshotCreateXML', [xmlDesc, flags], { timeout, type: 'su' });
53+
const xmlDesc = getSnapshotXML(name, description, memoryPath);
54+
55+
// We really don't want to make disk only snapshots of running
56+
// machines by accident.
57+
58+
if (vm.state === "running" && (flags & Enum.VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY))
59+
throw new Error("Cowardly refusing to make a disk-only snapshot of a running machine");
60+
61+
return await call(vm.connectionName, vm.id, 'org.libvirt.Domain', 'SnapshotCreateXML', [xmlDesc, flags],
62+
{ timeout, type: 'su' });
3763
}
3864

3965
export function snapshotCurrent({ connectionName, objPath }) {

0 commit comments

Comments
 (0)