qemu: snapshot: Add support for external active snapshots on gluster

Add support for gluster backed images as sources for snapshots in the
qemu driver. This will also simplify adding further network backed
volumes as sources for snapshot in case qemu will support them.
This commit is contained in:
Peter Krempa 2013-11-25 18:56:24 +01:00
parent 7183d7d2e8
commit 3cf074ee40
4 changed files with 119 additions and 10 deletions

View File

@ -183,8 +183,9 @@
documentation for further information. documentation for further information.
Libvirt currently supports the <code>type</code> element in the qemu Libvirt currently supports the <code>type</code> element in the qemu
driver and supported values are <code>file</code> and driver and supported values are <code>file</code>, <code>block</code>
<code>block</code> <span class="since">(since 1.2.2)</span>. and <code>network</code> with a protocol of <code>gluster</code>
<span class="since">(since 1.2.2)</span>.
</dd> </dd>
</dl> </dl>
</dd> </dd>

View File

@ -3822,7 +3822,7 @@ cleanup:
} }
static int int
qemuGetDriveSourceString(int type, qemuGetDriveSourceString(int type,
const char *src, const char *src,
int protocol, int protocol,

View File

@ -313,4 +313,13 @@ qemuParseKeywords(const char *str,
int *retnkeywords, int *retnkeywords,
int allowEmptyValue); 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__*/ #endif /* __QEMU_COMMAND_H__*/

View File

@ -11933,6 +11933,24 @@ cleanup:
return ret; return ret;
} }
static int
qemuDomainSnapshotDiskGetSourceString(virDomainSnapshotDiskDefPtr disk,
char **source)
{
*source = NULL;
return qemuGetDriveSourceString(virDomainSnapshotDiskGetActualType(disk),
disk->file,
disk->protocol,
disk->nhosts,
disk->hosts,
NULL,
NULL,
source);
}
typedef enum { typedef enum {
VIR_DISK_CHAIN_NO_ACCESS, VIR_DISK_CHAIN_NO_ACCESS,
VIR_DISK_CHAIN_READ_ONLY, VIR_DISK_CHAIN_READ_ONLY,
@ -12330,6 +12348,29 @@ qemuDomainSnapshotPrepareDiskExternalOverlayActive(virDomainSnapshotDiskDefPtr d
return 0; return 0;
case VIR_DOMAIN_DISK_TYPE_NETWORK: 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_DIR:
case VIR_DOMAIN_DISK_TYPE_VOLUME: case VIR_DOMAIN_DISK_TYPE_VOLUME:
case VIR_DOMAIN_DISK_TYPE_LAST: case VIR_DOMAIN_DISK_TYPE_LAST:
@ -12637,6 +12678,9 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainObjPrivatePtr priv = vm->privateData;
char *device = NULL; char *device = NULL;
char *source = NULL; char *source = NULL;
char *newsource = NULL;
virDomainDiskHostDefPtr newhosts = NULL;
virDomainDiskHostDefPtr persistHosts = NULL;
int format = snap->format; int format = snap->format;
const char *formatStr = NULL; const char *formatStr = NULL;
char *persistSource = NULL; char *persistSource = NULL;
@ -12651,8 +12695,7 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
return -1; return -1;
} }
if (virAsprintf(&device, "drive-%s", disk->info.alias) < 0 || if (virAsprintf(&device, "drive-%s", disk->info.alias) < 0)
(persistDisk && VIR_STRDUP(persistSource, source) < 0))
goto cleanup; goto cleanup;
/* XXX Here, we know we are about to alter disk->backingChain if /* XXX Here, we know we are about to alter disk->backingChain if
@ -12666,13 +12709,21 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
if (!(snapfile = virStorageFileInitFromSnapshotDef(snap))) if (!(snapfile = virStorageFileInitFromSnapshotDef(snap)))
goto cleanup; 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) { switch (snap->type) {
case VIR_DOMAIN_DISK_TYPE_BLOCK: case VIR_DOMAIN_DISK_TYPE_BLOCK:
reuse = true; reuse = true;
/* fallthrough */ /* fallthrough */
case VIR_DOMAIN_DISK_TYPE_FILE: 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 /* create the stub file and set selinux labels; manipulate disk in
* place, in a way that can be reverted on failure. */ * place, in a way that can be reverted on failure. */
@ -12692,6 +12743,27 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
} }
break; 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: default:
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
_("snapshots are not supported on '%s' volumes"), _("snapshots are not supported on '%s' volumes"),
@ -12727,17 +12799,33 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
/* Update vm in place to match changes. */ /* Update vm in place to match changes. */
need_unlink = false; need_unlink = false;
VIR_FREE(disk->src); VIR_FREE(disk->src);
disk->src = source; virDomainDiskHostDefFree(disk->nhosts, disk->hosts);
source = NULL;
disk->src = newsource;
disk->format = format; disk->format = format;
disk->type = snap->type; disk->type = snap->type;
disk->protocol = snap->protocol;
disk->nhosts = snap->nhosts;
disk->hosts = newhosts;
newsource = NULL;
newhosts = NULL;
if (persistDisk) { if (persistDisk) {
VIR_FREE(persistDisk->src); VIR_FREE(persistDisk->src);
virDomainDiskHostDefFree(persistDisk->nhosts, persistDisk->hosts);
persistDisk->src = persistSource; persistDisk->src = persistSource;
persistSource = NULL;
persistDisk->format = format; persistDisk->format = format;
persistDisk->type = snap->type; persistDisk->type = snap->type;
persistDisk->protocol = snap->protocol;
persistDisk->nhosts = snap->nhosts;
persistDisk->hosts = persistHosts;
persistSource = NULL;
persistHosts = NULL;
} }
cleanup: cleanup:
@ -12746,7 +12834,10 @@ cleanup:
virStorageFileFree(snapfile); virStorageFileFree(snapfile);
VIR_FREE(device); VIR_FREE(device);
VIR_FREE(source); VIR_FREE(source);
VIR_FREE(newsource);
VIR_FREE(persistSource); VIR_FREE(persistSource);
virDomainDiskHostDefFree(snap->nhosts, newhosts);
virDomainDiskHostDefFree(snap->nhosts, persistHosts);
return ret; return ret;
} }
@ -12785,12 +12876,20 @@ qemuDomainSnapshotUndoSingleDiskActive(virQEMUDriverPtr driver,
source = NULL; source = NULL;
disk->format = origdisk->format; disk->format = origdisk->format;
disk->type = origdisk->type; 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) { if (persistDisk) {
VIR_FREE(persistDisk->src); VIR_FREE(persistDisk->src);
persistDisk->src = persistSource; persistDisk->src = persistSource;
persistSource = NULL; persistSource = NULL;
persistDisk->format = origdisk->format; persistDisk->format = origdisk->format;
persistDisk->type = origdisk->type; 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: cleanup: