virsh snapshot-create-as supports 'file' storage type in --diskspec by default.
But it doesn't support 'block' storage type in the
virshParseSnapshotDiskspec().
So if a snapshot on a block device (e.g. LV) was created, the type of
current running storage source in dumpxml is inconsistent with the actual
backend storage source. It will check file-system type mismatch failed
and return an error message of 'Migration without shared storage is unsafe'
when VM performs a live migration after this snapshot.
Considering virsh has to be able to work remotely that recognizing a block device
by prefix /dev/ or by stat() may be not suitable, so adding a "stype" field
for the --diskspec string which will be either "file" or "block".
e.g. --diskspec vda,snapshot=external,driver=qcow2,stype=block,file=/dev/xxx.
Signed-off-by: Liu Dayu <liu.dayu(a)zte.com.cn>
---
Patch v1:
https://www.redhat.com/archives/libvir-list/2019-June/msg01248.html
Changes in v2:
- Adding a "stype" field for the --diskspec string which will indicate a
"file" or "block" storage type.
---
tools/virsh-snapshot.c | 23 ++++++++++++++++++++---
1 file changed, 20 insertions(+), 3 deletions(-)
diff --git a/tools/virsh-snapshot.c b/tools/virsh-snapshot.c
index e9f0ee0..ec965b2 100644
--- a/tools/virsh-snapshot.c
+++ b/tools/virsh-snapshot.c
@@ -251,10 +251,12 @@ virshParseSnapshotDiskspec(vshControl *ctl, virBufferPtr buf, const
char *str)
const char *name = NULL;
const char *snapshot = NULL;
const char *driver = NULL;
+ const char *stype = NULL;
const char *file = NULL;
char **array = NULL;
int narray;
size_t i;
+ bool isFile = true;
narray = vshStringToArray(str, &array);
if (narray <= 0)
@@ -266,6 +268,8 @@ virshParseSnapshotDiskspec(vshControl *ctl, virBufferPtr buf, const
char *str)
snapshot = array[i] + strlen("snapshot=");
else if (!driver && STRPREFIX(array[i], "driver="))
driver = array[i] + strlen("driver=");
+ else if (!stype && STRPREFIX(array[i], "stype="))
+ stype = array[i] + strlen("stype=");
else if (!file && STRPREFIX(array[i], "file="))
file = array[i] + strlen("file=");
else
@@ -275,13 +279,26 @@ virshParseSnapshotDiskspec(vshControl *ctl, virBufferPtr buf, const
char *str)
virBufferEscapeString(buf, "<disk name='%s'", name);
if (snapshot)
virBufferAsprintf(buf, " snapshot='%s'", snapshot);
+ if (stype) {
+ if (STREQ(stype, "block")) {
+ isFile = false;
+ } else if (STRNEQ(stype, "file")) {
+ vshError(ctl, _("Unknown storage type: '%s'"), stype);
+ goto cleanup;
+ }
+ virBufferAsprintf(buf, " type='%s'", stype);
+ }
if (driver || file) {
virBufferAddLit(buf, ">\n");
virBufferAdjustIndent(buf, 2);
if (driver)
virBufferAsprintf(buf, "<driver type='%s'/>\n",
driver);
- if (file)
- virBufferEscapeString(buf, "<source file='%s'/>\n",
file);
+ if (file) {
+ if (isFile)
+ virBufferEscapeString(buf, "<source
file='%s'/>\n", file);
+ else
+ virBufferEscapeString(buf, "<source
dev='%s'/>\n", file);
+ }
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</disk>\n");
} else {
@@ -351,7 +368,7 @@ static const vshCmdOptDef opts_snapshot_create_as[] = {
},
{.name = "diskspec",
.type = VSH_OT_ARGV,
- .help = N_("disk attributes:
disk[,snapshot=type][,driver=type][,file=name]")
+ .help = N_("disk attributes:
disk[,snapshot=type][,driver=type][,stype=type][,file=name]")
},
{.name = NULL}
};
--
1.8.3.1