---
src/qemu/qemu_command.c | 2 +-
src/qemu/qemu_command.h | 9 ++++
src/qemu/qemu_driver.c | 113 +++++++++++++++++++++++++++++++++++++++++++++---
3 files changed, 116 insertions(+), 8 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index a80559e..d742248 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -3826,7 +3826,7 @@ cleanup:
}
-static int
+int
qemuGetDriveSourceString(int type,
const char *src,
int protocol,
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index 66c23cc..ec944ea 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -312,4 +312,13 @@ qemuParseKeywords(const char *str,
int *retnkeywords,
int allowEmptyValue);
+int qemuGetDriveSourceString(int type,
+ const char *src,
+ int protocol,
+ size_t nhosts,
+ virDomainDiskHostDefPtr hosts,
+ const char *username,
+ const char *secret,
+ char **path);
+
#endif /* __QEMU_COMMAND_H__*/
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index fad8c60..872634f 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -11492,6 +11492,24 @@ cleanup:
return ret;
}
+
+static int
+qemuDomainSnapshotDiskGetSourceString(virDomainSnapshotDiskDefPtr disk,
+ char **source)
+{
+ *source = NULL;
+
+ return qemuGetDriveSourceString(qemuSnapshotDiskGetActualType(disk),
+ disk->file,
+ disk->protocol,
+ disk->nhosts,
+ disk->hosts,
+ NULL,
+ NULL,
+ source);
+}
+
+
typedef enum {
VIR_DISK_CHAIN_NO_ACCESS,
VIR_DISK_CHAIN_READ_ONLY,
@@ -11872,6 +11890,29 @@
qemuDomainSnapshotPrepareDiskExternalOverlayActive(virDomainSnapshotDiskDefPtr d
return 0;
case VIR_DOMAIN_DISK_TYPE_NETWORK:
+ switch ((enum virDomainDiskProtocol) disk->protocol) {
+ case VIR_DOMAIN_DISK_PROTOCOL_GLUSTER:
+ return 0;
+
+ case VIR_DOMAIN_DISK_PROTOCOL_NBD:
+ case VIR_DOMAIN_DISK_PROTOCOL_RBD:
+ case VIR_DOMAIN_DISK_PROTOCOL_SHEEPDOG:
+ case VIR_DOMAIN_DISK_PROTOCOL_ISCSI:
+ case VIR_DOMAIN_DISK_PROTOCOL_HTTP:
+ case VIR_DOMAIN_DISK_PROTOCOL_HTTPS:
+ case VIR_DOMAIN_DISK_PROTOCOL_FTP:
+ case VIR_DOMAIN_DISK_PROTOCOL_FTPS:
+ case VIR_DOMAIN_DISK_PROTOCOL_TFTP:
+ case VIR_DOMAIN_DISK_PROTOCOL_LAST:
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("external active snapshots are not supported on "
+ "'network' disks using '%s'
protocol"),
+ virDomainDiskProtocolTypeToString(disk->protocol));
+ return -1;
+
+ }
+ break;
+
case VIR_DOMAIN_DISK_TYPE_DIR:
case VIR_DOMAIN_DISK_TYPE_VOLUME:
case VIR_DOMAIN_DISK_TYPE_LAST:
@@ -12183,6 +12224,9 @@ qemuDomainSnapshotCreateSingleDiskActive(virConnectPtr conn,
qemuDomainObjPrivatePtr priv = vm->privateData;
char *device = NULL;
char *source = NULL;
+ char *newsource = NULL;
+ virDomainDiskHostDefPtr newhosts = NULL;
+ virDomainDiskHostDefPtr persistHosts = NULL;
int format = snap->format;
const char *formatStr = NULL;
char *persistSource = NULL;
@@ -12197,8 +12241,7 @@ qemuDomainSnapshotCreateSingleDiskActive(virConnectPtr conn,
return -1;
}
- if (virAsprintf(&device, "drive-%s", disk->info.alias) < 0 ||
- (persistDisk && VIR_STRDUP(persistSource, source) < 0))
+ if (virAsprintf(&device, "drive-%s", disk->info.alias) < 0)
goto cleanup;
/* XXX Here, we know we are about to alter disk->backingChain if
@@ -12212,14 +12255,22 @@ qemuDomainSnapshotCreateSingleDiskActive(virConnectPtr conn,
if (!(temppool = virStorageEphemeralFromSnapshotDiskDef(conn, snap)))
goto cleanup;
+ if (qemuDomainSnapshotDiskGetSourceString(snap, &source) < 0)
+ goto cleanup;
+
+ if (VIR_STRDUP(newsource, snap->file) < 0)
+ goto cleanup;
+
+ if (persistDisk &&
+ VIR_STRDUP(persistSource, snap->file) < 0)
+ goto cleanup;
+
switch (snap->type) {
case VIR_DOMAIN_DISK_TYPE_BLOCK:
reuse = true;
/* fallthrough */
case -1: /* type was not provided in snapshot conf */
case VIR_DOMAIN_DISK_TYPE_FILE:
- if (VIR_STRDUP(source, snap->file) < 0)
- goto cleanup;
/* create the stub file and set selinux labels; manipulate disk in
* place, in a way that can be reverted on failure. */
@@ -12239,6 +12290,27 @@ qemuDomainSnapshotCreateSingleDiskActive(virConnectPtr conn,
}
break;
+ case VIR_DOMAIN_DISK_TYPE_NETWORK:
+ switch (snap->protocol) {
+ case VIR_DOMAIN_DISK_PROTOCOL_GLUSTER:
+ if (!(newhosts = virDomainDiskHostDefCopy(snap->nhosts, snap->hosts)))
+ goto cleanup;
+
+ if (persistDisk &&
+ !(persistHosts = virDomainDiskHostDefCopy(snap->nhosts,
snap->hosts)))
+ goto cleanup;
+
+ break;
+
+ default:
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
+ _("snapshots on volumes using '%s' protocol
"
+ "are not supported"),
+ virDomainDiskProtocolTypeToString(snap->protocol));
+ goto cleanup;
+ }
+ break;
+
default:
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
_("snapshots are not supported on '%s'
volumes"),
@@ -12273,17 +12345,33 @@ qemuDomainSnapshotCreateSingleDiskActive(virConnectPtr conn,
/* Update vm in place to match changes. */
need_unlink = false;
+
VIR_FREE(disk->src);
- disk->src = source;
- source = NULL;
+ virDomainDiskHostDefFree(disk->nhosts, disk->hosts);
+
+ disk->src = newsource;
disk->format = format;
disk->type = snap->type;
+ disk->protocol = snap->protocol;
+ disk->nhosts = snap->nhosts;
+ disk->hosts = newhosts;
+
+ newsource = NULL;
+ newhosts = NULL;
+
if (persistDisk) {
VIR_FREE(persistDisk->src);
+ virDomainDiskHostDefFree(persistDisk->nhosts, persistDisk->hosts);
+
persistDisk->src = persistSource;
- persistSource = NULL;
persistDisk->format = format;
persistDisk->type = snap->type;
+ persistDisk->protocol = snap->protocol;
+ persistDisk->nhosts = snap->nhosts;
+ persistDisk->hosts = persistHosts;
+
+ persistSource = NULL;
+ persistHosts = NULL;
}
cleanup:
@@ -12299,7 +12387,10 @@ cleanup:
virStorageEphemeralFree(temppool);
VIR_FREE(device);
VIR_FREE(source);
+ VIR_FREE(newsource);
VIR_FREE(persistSource);
+ virDomainDiskHostDefFree(snap->nhosts, newhosts);
+ virDomainDiskHostDefFree(snap->nhosts, persistHosts);
return ret;
}
@@ -12351,12 +12442,20 @@ qemuDomainSnapshotUndoSingleDiskActive(virConnectPtr conn,
source = NULL;
disk->format = origdisk->format;
disk->type = origdisk->type;
+ disk->protocol = origdisk->protocol;
+ virDomainDiskHostDefFree(disk->nhosts, disk->hosts);
+ disk->nhosts = origdisk->nhosts;
+ disk->hosts = virDomainDiskHostDefCopy(origdisk->nhosts, origdisk->hosts);
if (persistDisk) {
VIR_FREE(persistDisk->src);
persistDisk->src = persistSource;
persistSource = NULL;
persistDisk->format = origdisk->format;
persistDisk->type = origdisk->type;
+ persistDisk->protocol = origdisk->protocol;
+ virDomainDiskHostDefFree(persistDisk->nhosts, persistDisk->hosts);
+ persistDisk->nhosts = origdisk->nhosts;
+ persistDisk->hosts = virDomainDiskHostDefCopy(origdisk->nhosts,
origdisk->hosts);
}
cleanup:
--
1.8.5.1