2012-08-14 00:09:12 +00:00
|
|
|
/*
|
|
|
|
* snapshot_conf.h: domain snapshot XML processing
|
|
|
|
*
|
2019-02-26 20:14:36 +00:00
|
|
|
* Copyright (C) 2006-2019 Red Hat, Inc.
|
2012-08-14 00:09:12 +00:00
|
|
|
* Copyright (C) 2006-2008 Daniel P. Berrange
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2012-09-20 22:30:55 +00:00
|
|
|
* License along with this library. If not, see
|
2012-08-14 00:09:12 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2019-06-07 20:20:21 +00:00
|
|
|
#pragma once
|
2012-08-14 00:09:12 +00:00
|
|
|
|
2019-06-07 20:20:21 +00:00
|
|
|
#include "internal.h"
|
|
|
|
#include "domain_conf.h"
|
|
|
|
#include "moment_conf.h"
|
|
|
|
#include "virenum.h"
|
2012-08-14 00:09:12 +00:00
|
|
|
|
|
|
|
/* Items related to snapshot state */
|
|
|
|
|
2014-05-11 15:08:51 +00:00
|
|
|
typedef enum {
|
2012-08-13 22:59:57 +00:00
|
|
|
VIR_DOMAIN_SNAPSHOT_LOCATION_DEFAULT = 0,
|
|
|
|
VIR_DOMAIN_SNAPSHOT_LOCATION_NONE,
|
|
|
|
VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL,
|
|
|
|
VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL,
|
2012-08-14 00:09:12 +00:00
|
|
|
|
2012-08-13 22:59:57 +00:00
|
|
|
VIR_DOMAIN_SNAPSHOT_LOCATION_LAST
|
2014-05-11 15:08:51 +00:00
|
|
|
} virDomainSnapshotLocation;
|
2012-08-14 00:09:12 +00:00
|
|
|
|
2019-02-26 20:14:36 +00:00
|
|
|
/**
|
|
|
|
* This enum has to map all known domain states from the public enum
|
|
|
|
* virDomainState, before adding one additional state possible only
|
|
|
|
* for snapshots.
|
|
|
|
*/
|
2014-05-11 15:08:51 +00:00
|
|
|
typedef enum {
|
2019-02-26 20:14:36 +00:00
|
|
|
/* Mapped to public enum */
|
|
|
|
VIR_DOMAIN_SNAPSHOT_NOSTATE = VIR_DOMAIN_NOSTATE,
|
|
|
|
VIR_DOMAIN_SNAPSHOT_RUNNING = VIR_DOMAIN_RUNNING,
|
|
|
|
VIR_DOMAIN_SNAPSHOT_BLOCKED = VIR_DOMAIN_BLOCKED,
|
|
|
|
VIR_DOMAIN_SNAPSHOT_PAUSED = VIR_DOMAIN_PAUSED,
|
|
|
|
VIR_DOMAIN_SNAPSHOT_SHUTDOWN = VIR_DOMAIN_SHUTDOWN,
|
|
|
|
VIR_DOMAIN_SNAPSHOT_SHUTOFF = VIR_DOMAIN_SHUTOFF,
|
|
|
|
VIR_DOMAIN_SNAPSHOT_CRASHED = VIR_DOMAIN_CRASHED,
|
|
|
|
VIR_DOMAIN_SNAPSHOT_PMSUSPENDED = VIR_DOMAIN_PMSUSPENDED,
|
|
|
|
/* Additional enum values local to snapshots */
|
|
|
|
VIR_DOMAIN_SNAPSHOT_DISK_SNAPSHOT,
|
|
|
|
VIR_DOMAIN_SNAPSHOT_LAST
|
2014-05-11 15:08:51 +00:00
|
|
|
} virDomainSnapshotState;
|
2020-01-09 10:39:55 +00:00
|
|
|
G_STATIC_ASSERT((int)VIR_DOMAIN_SNAPSHOT_DISK_SNAPSHOT == VIR_DOMAIN_LAST);
|
2012-08-14 00:09:12 +00:00
|
|
|
|
|
|
|
/* Stores disk-snapshot information */
|
|
|
|
typedef struct _virDomainSnapshotDiskDef virDomainSnapshotDiskDef;
|
|
|
|
typedef virDomainSnapshotDiskDef *virDomainSnapshotDiskDefPtr;
|
|
|
|
struct _virDomainSnapshotDiskDef {
|
2013-11-12 13:15:51 +00:00
|
|
|
char *name; /* name matching the <target dev='...' of the domain */
|
2014-05-11 15:08:51 +00:00
|
|
|
int snapshot; /* virDomainSnapshotLocation */
|
2014-03-29 22:01:05 +00:00
|
|
|
|
2014-05-21 21:21:02 +00:00
|
|
|
/* details of wrapper external file. src is always non-NULL.
|
|
|
|
* XXX optimize this to allow NULL for internal snapshots? */
|
|
|
|
virStorageSourcePtr src;
|
2012-08-14 00:09:12 +00:00
|
|
|
};
|
|
|
|
|
2020-09-21 14:49:26 +00:00
|
|
|
void
|
|
|
|
virDomainSnapshotDiskDefFree(virDomainSnapshotDiskDefPtr disk);
|
|
|
|
|
|
|
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainSnapshotDiskDef, virDomainSnapshotDiskDefFree);
|
|
|
|
|
2012-08-14 00:09:12 +00:00
|
|
|
/* Stores the complete snapshot metadata */
|
|
|
|
struct _virDomainSnapshotDef {
|
2019-05-08 22:10:58 +00:00
|
|
|
virDomainMomentDef parent;
|
2019-03-22 02:02:19 +00:00
|
|
|
|
|
|
|
/* Additional public XML. */
|
2014-05-11 15:08:51 +00:00
|
|
|
int state; /* virDomainSnapshotState */
|
2012-08-14 00:09:12 +00:00
|
|
|
|
2014-05-11 15:08:51 +00:00
|
|
|
int memory; /* virDomainMemorySnapshot */
|
snapshot: new XML for external system checkpoint
Each <domainsnapshot> can now contain an optional <memory>
element that describes how the VM state was handled, similar
to disk snapshots. The new element will always appear in
output; for back-compat, an input that lacks the element will
assume 'no' or 'internal' according to the domain state.
Along with this change, it is now possible to pass <disks> in
the XML for an offline snapshot; this also needs to be wired up
in a future patch, to make it possible to choose internal vs.
external on a per-disk basis for each disk in an offline domain.
At that point, using the --disk-only flag for an offline domain
will be able to work.
For some examples below, remember that qemu supports the
following snapshot actions:
qemu-img: offline external and internal disk
savevm: online internal VM and disk
migrate: online external VM
transaction: online external disk
=====
<domainsnapshot>
<memory snapshot='no'/>
...
</domainsnapshot>
implies that there is no VM state saved (mandatory for
offline and disk-only snapshots, not possible otherwise);
using qemu-img for offline domains and transaction for online.
=====
<domainsnapshot>
<memory snapshot='internal'/>
...
</domainsnapshot>
state is saved inside one of the disks (as in qemu's 'savevm'
system checkpoint implementation). If needed in the future,
we can also add an attribute pointing out _which_ disk saved
the internal state; maybe disk='vda'.
=====
<domainsnapshot>
<memory snapshot='external' file='/path/to/state'/>
...
</domainsnapshot>
This is not wired up yet, but future patches will allow this to
control a combination of 'virsh save /path/to/state' plus disk
snapshots from the same point in time.
=====
So for 1.0.1 (and later, as needed), I plan to implement this table
of combinations, with '*' designating new code and '+' designating
existing code reached through new combinations of xml and/or the
existing DISK_ONLY flag:
domain memory disk disk-only | result
-----------------------------------------
offline omit omit any | memory=no disk=int, via qemu-img
offline no omit any |+memory=no disk=int, via qemu-img
offline omit/no no any | invalid combination (nothing to snapshot)
offline omit/no int any |+memory=no disk=int, via qemu-img
offline omit/no ext any |*memory=no disk=ext, via qemu-img
offline int/ext any any | invalid combination (no memory to save)
online omit omit off | memory=int disk=int, via savevm
online omit omit on | memory=no disk=default, via transaction
online omit no/ext off | unsupported for now
online omit no on | invalid combination (nothing to snapshot)
online omit ext on | memory=no disk=ext, via transaction
online omit int off |+memory=int disk=int, via savevm
online omit int on | unsupported for now
online no omit any |+memory=no disk=default, via transaction
online no no any | invalid combination (nothing to snapshot)
online no int any | unsupported for now
online no ext any |+memory=no disk=ext, via transaction
online int/ext any on | invalid combination (disk-only vs. memory)
online int omit off |+memory=int disk=int, via savevm
online int no/ext off | unsupported for now
online int int off |+memory=int disk=int, via savevm
online ext omit off |*memory=ext disk=default, via migrate+trans
online ext no off |+memory=ext disk=no, via migrate
online ext int off | unsupported for now
online ext ext off |*memory=ext disk=ext, via migrate+transaction
* docs/schemas/domainsnapshot.rng (memory): New RNG element.
* docs/formatsnapshot.html.in: Document it.
* src/conf/snapshot_conf.h (virDomainSnapshotDef): New fields.
* src/conf/domain_conf.c (virDomainSnapshotDefFree)
(virDomainSnapshotDefParseString, virDomainSnapshotDefFormat):
Manage new fields.
* tests/domainsnapshotxml2xmltest.c: New test.
* tests/domainsnapshotxml2xmlin/*.xml: Update existing tests.
* tests/domainsnapshotxml2xmlout/*.xml: Likewise.
2012-10-23 15:12:23 +00:00
|
|
|
char *file; /* memory state file when snapshot is external */
|
|
|
|
|
2012-08-14 00:09:12 +00:00
|
|
|
size_t ndisks; /* should not exceed dom->ndisks */
|
|
|
|
virDomainSnapshotDiskDef *disks;
|
|
|
|
|
2017-06-01 22:44:46 +00:00
|
|
|
virObjectPtr cookie;
|
2012-08-14 00:09:12 +00:00
|
|
|
};
|
|
|
|
|
2019-10-04 16:14:10 +00:00
|
|
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainSnapshotDef, virObjectUnref);
|
|
|
|
|
|
|
|
|
2012-08-14 00:09:12 +00:00
|
|
|
typedef enum {
|
|
|
|
VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE = 1 << 0,
|
|
|
|
VIR_DOMAIN_SNAPSHOT_PARSE_DISKS = 1 << 1,
|
|
|
|
VIR_DOMAIN_SNAPSHOT_PARSE_INTERNAL = 1 << 2,
|
snapshot: new XML for external system checkpoint
Each <domainsnapshot> can now contain an optional <memory>
element that describes how the VM state was handled, similar
to disk snapshots. The new element will always appear in
output; for back-compat, an input that lacks the element will
assume 'no' or 'internal' according to the domain state.
Along with this change, it is now possible to pass <disks> in
the XML for an offline snapshot; this also needs to be wired up
in a future patch, to make it possible to choose internal vs.
external on a per-disk basis for each disk in an offline domain.
At that point, using the --disk-only flag for an offline domain
will be able to work.
For some examples below, remember that qemu supports the
following snapshot actions:
qemu-img: offline external and internal disk
savevm: online internal VM and disk
migrate: online external VM
transaction: online external disk
=====
<domainsnapshot>
<memory snapshot='no'/>
...
</domainsnapshot>
implies that there is no VM state saved (mandatory for
offline and disk-only snapshots, not possible otherwise);
using qemu-img for offline domains and transaction for online.
=====
<domainsnapshot>
<memory snapshot='internal'/>
...
</domainsnapshot>
state is saved inside one of the disks (as in qemu's 'savevm'
system checkpoint implementation). If needed in the future,
we can also add an attribute pointing out _which_ disk saved
the internal state; maybe disk='vda'.
=====
<domainsnapshot>
<memory snapshot='external' file='/path/to/state'/>
...
</domainsnapshot>
This is not wired up yet, but future patches will allow this to
control a combination of 'virsh save /path/to/state' plus disk
snapshots from the same point in time.
=====
So for 1.0.1 (and later, as needed), I plan to implement this table
of combinations, with '*' designating new code and '+' designating
existing code reached through new combinations of xml and/or the
existing DISK_ONLY flag:
domain memory disk disk-only | result
-----------------------------------------
offline omit omit any | memory=no disk=int, via qemu-img
offline no omit any |+memory=no disk=int, via qemu-img
offline omit/no no any | invalid combination (nothing to snapshot)
offline omit/no int any |+memory=no disk=int, via qemu-img
offline omit/no ext any |*memory=no disk=ext, via qemu-img
offline int/ext any any | invalid combination (no memory to save)
online omit omit off | memory=int disk=int, via savevm
online omit omit on | memory=no disk=default, via transaction
online omit no/ext off | unsupported for now
online omit no on | invalid combination (nothing to snapshot)
online omit ext on | memory=no disk=ext, via transaction
online omit int off |+memory=int disk=int, via savevm
online omit int on | unsupported for now
online no omit any |+memory=no disk=default, via transaction
online no no any | invalid combination (nothing to snapshot)
online no int any | unsupported for now
online no ext any |+memory=no disk=ext, via transaction
online int/ext any on | invalid combination (disk-only vs. memory)
online int omit off |+memory=int disk=int, via savevm
online int no/ext off | unsupported for now
online int int off |+memory=int disk=int, via savevm
online ext omit off |*memory=ext disk=default, via migrate+trans
online ext no off |+memory=ext disk=no, via migrate
online ext int off | unsupported for now
online ext ext off |*memory=ext disk=ext, via migrate+transaction
* docs/schemas/domainsnapshot.rng (memory): New RNG element.
* docs/formatsnapshot.html.in: Document it.
* src/conf/snapshot_conf.h (virDomainSnapshotDef): New fields.
* src/conf/domain_conf.c (virDomainSnapshotDefFree)
(virDomainSnapshotDefParseString, virDomainSnapshotDefFormat):
Manage new fields.
* tests/domainsnapshotxml2xmltest.c: New test.
* tests/domainsnapshotxml2xmlin/*.xml: Update existing tests.
* tests/domainsnapshotxml2xmlout/*.xml: Likewise.
2012-10-23 15:12:23 +00:00
|
|
|
VIR_DOMAIN_SNAPSHOT_PARSE_OFFLINE = 1 << 3,
|
2019-07-06 03:02:03 +00:00
|
|
|
VIR_DOMAIN_SNAPSHOT_PARSE_VALIDATE = 1 << 4,
|
2012-08-14 00:09:12 +00:00
|
|
|
} virDomainSnapshotParseFlags;
|
|
|
|
|
2019-02-15 20:43:43 +00:00
|
|
|
typedef enum {
|
|
|
|
VIR_DOMAIN_SNAPSHOT_FORMAT_SECURE = 1 << 0,
|
|
|
|
VIR_DOMAIN_SNAPSHOT_FORMAT_INTERNAL = 1 << 1,
|
snapshot: Drop virDomainSnapshotDef.current
The only use for the 'current' member of virDomainSnapshotDef was with
the PARSE/FORMAT_INTERNAL flag for controlling an internal-use
<active> element marking whether a particular snapshot definition was
current, and even then, only by the qemu driver on output, and by qemu
and test driver on input. But this duplicates vm->snapshot_current,
and gets in the way of potential simplifications to have qemu store a
single file for all snapshots rather than one file per snapshot. Get
rid of the member by adding a bool* parameter during parse (ignored if
the PARSE_INTERNAL flag is not set), and by adding a new flag during
format (if FORMAT_INTERNAL is set, the value printed in <active>
depends on the new FORMAT_CURRENT).
Then update the qemu driver accordingly, which involves hoisting
assignments to vm->current_snapshot to occur prior to any point where
a snapshot XML file is written (although qemu kept
vm->current_snapshot and snapshot->def_current in sync by the end of
the function, they were not always identical in the middle of
functions, so the shuffling gets a bit interesting). Later patches
will clean up some of that confusing churn to vm->current_snapshot.
Note: even if later patches refactor qemu to no longer use
FORMAT_INTERNAL for output (by storing bulk snapshot XML instead), we
will always need PARSE_INTERNAL for input (because on upgrade, a new
libvirt still has to parse XML left from a previous libvirt).
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: John Ferlan <jferlan@redhat.com>
2019-03-19 03:56:19 +00:00
|
|
|
VIR_DOMAIN_SNAPSHOT_FORMAT_CURRENT = 1 << 2,
|
2019-02-15 20:43:43 +00:00
|
|
|
} virDomainSnapshotFormatFlags;
|
|
|
|
|
|
|
|
unsigned int virDomainSnapshotFormatConvertXMLFlags(unsigned int flags);
|
|
|
|
|
2012-08-14 00:09:12 +00:00
|
|
|
virDomainSnapshotDefPtr virDomainSnapshotDefParseString(const char *xmlStr,
|
2013-03-31 18:03:42 +00:00
|
|
|
virDomainXMLOptionPtr xmlopt,
|
2019-08-06 12:19:35 +00:00
|
|
|
void *parseOpaque,
|
snapshot: Drop virDomainSnapshotDef.current
The only use for the 'current' member of virDomainSnapshotDef was with
the PARSE/FORMAT_INTERNAL flag for controlling an internal-use
<active> element marking whether a particular snapshot definition was
current, and even then, only by the qemu driver on output, and by qemu
and test driver on input. But this duplicates vm->snapshot_current,
and gets in the way of potential simplifications to have qemu store a
single file for all snapshots rather than one file per snapshot. Get
rid of the member by adding a bool* parameter during parse (ignored if
the PARSE_INTERNAL flag is not set), and by adding a new flag during
format (if FORMAT_INTERNAL is set, the value printed in <active>
depends on the new FORMAT_CURRENT).
Then update the qemu driver accordingly, which involves hoisting
assignments to vm->current_snapshot to occur prior to any point where
a snapshot XML file is written (although qemu kept
vm->current_snapshot and snapshot->def_current in sync by the end of
the function, they were not always identical in the middle of
functions, so the shuffling gets a bit interesting). Later patches
will clean up some of that confusing churn to vm->current_snapshot.
Note: even if later patches refactor qemu to no longer use
FORMAT_INTERNAL for output (by storing bulk snapshot XML instead), we
will always need PARSE_INTERNAL for input (because on upgrade, a new
libvirt still has to parse XML left from a previous libvirt).
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: John Ferlan <jferlan@redhat.com>
2019-03-19 03:56:19 +00:00
|
|
|
bool *current,
|
2012-08-14 00:09:12 +00:00
|
|
|
unsigned int flags);
|
2013-08-07 14:34:40 +00:00
|
|
|
virDomainSnapshotDefPtr virDomainSnapshotDefParseNode(xmlDocPtr xml,
|
|
|
|
xmlNodePtr root,
|
|
|
|
virDomainXMLOptionPtr xmlopt,
|
2019-08-06 12:19:35 +00:00
|
|
|
void *parseOpaque,
|
snapshot: Drop virDomainSnapshotDef.current
The only use for the 'current' member of virDomainSnapshotDef was with
the PARSE/FORMAT_INTERNAL flag for controlling an internal-use
<active> element marking whether a particular snapshot definition was
current, and even then, only by the qemu driver on output, and by qemu
and test driver on input. But this duplicates vm->snapshot_current,
and gets in the way of potential simplifications to have qemu store a
single file for all snapshots rather than one file per snapshot. Get
rid of the member by adding a bool* parameter during parse (ignored if
the PARSE_INTERNAL flag is not set), and by adding a new flag during
format (if FORMAT_INTERNAL is set, the value printed in <active>
depends on the new FORMAT_CURRENT).
Then update the qemu driver accordingly, which involves hoisting
assignments to vm->current_snapshot to occur prior to any point where
a snapshot XML file is written (although qemu kept
vm->current_snapshot and snapshot->def_current in sync by the end of
the function, they were not always identical in the middle of
functions, so the shuffling gets a bit interesting). Later patches
will clean up some of that confusing churn to vm->current_snapshot.
Note: even if later patches refactor qemu to no longer use
FORMAT_INTERNAL for output (by storing bulk snapshot XML instead), we
will always need PARSE_INTERNAL for input (because on upgrade, a new
libvirt still has to parse XML left from a previous libvirt).
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: John Ferlan <jferlan@redhat.com>
2019-03-19 03:56:19 +00:00
|
|
|
bool *current,
|
2013-08-07 14:34:40 +00:00
|
|
|
unsigned int flags);
|
2019-05-08 18:30:38 +00:00
|
|
|
virDomainSnapshotDefPtr virDomainSnapshotDefNew(void);
|
2019-02-21 15:43:49 +00:00
|
|
|
char *virDomainSnapshotDefFormat(const char *uuidstr,
|
2012-08-14 00:09:12 +00:00
|
|
|
virDomainSnapshotDefPtr def,
|
2017-06-01 22:27:33 +00:00
|
|
|
virDomainXMLOptionPtr xmlopt,
|
2019-02-15 20:43:43 +00:00
|
|
|
unsigned int flags);
|
2012-08-14 00:09:12 +00:00
|
|
|
int virDomainSnapshotAlignDisks(virDomainSnapshotDefPtr snapshot,
|
|
|
|
int default_snapshot,
|
|
|
|
bool require_match);
|
|
|
|
|
2013-01-03 13:10:39 +00:00
|
|
|
bool virDomainSnapshotDefIsExternal(virDomainSnapshotDefPtr def);
|
2019-03-22 04:45:25 +00:00
|
|
|
bool virDomainSnapshotIsExternal(virDomainMomentObjPtr snap);
|
2012-10-19 09:55:36 +00:00
|
|
|
|
2019-09-20 10:25:51 +00:00
|
|
|
int virDomainSnapshotRedefinePrep(virDomainObjPtr vm,
|
2013-08-21 20:39:02 +00:00
|
|
|
virDomainSnapshotDefPtr *def,
|
2019-03-22 04:45:25 +00:00
|
|
|
virDomainMomentObjPtr *snap,
|
2017-05-19 13:07:15 +00:00
|
|
|
virDomainXMLOptionPtr xmlopt,
|
2013-08-21 20:39:02 +00:00
|
|
|
unsigned int flags);
|
|
|
|
|
2019-03-15 02:12:51 +00:00
|
|
|
int virDomainSnapshotRedefineValidate(virDomainSnapshotDefPtr def,
|
|
|
|
const unsigned char *domain_uuid,
|
2019-03-22 04:45:25 +00:00
|
|
|
virDomainMomentObjPtr other,
|
2019-03-15 02:12:51 +00:00
|
|
|
virDomainXMLOptionPtr xmlopt,
|
|
|
|
unsigned int flags);
|
|
|
|
|
2019-01-20 16:04:56 +00:00
|
|
|
VIR_ENUM_DECL(virDomainSnapshotLocation);
|
|
|
|
VIR_ENUM_DECL(virDomainSnapshotState);
|