diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 40c385e181..01505cbf3d 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -5002,6 +5002,27 @@ virDomainDiskSourceParse(xmlNodePtr node, goto cleanup; } + /* for historical reasons the volume name for gluster volume is stored + * as a part of the path. This is hard to work with when dealing with + * relative names. Split out the volume into a separate variable */ + if (src->path && src->protocol == VIR_STORAGE_NET_PROTOCOL_GLUSTER) { + char *tmp; + if (!(tmp = strchr(src->path, '/')) || + tmp == src->path) { + virReportError(VIR_ERR_XML_ERROR, + _("missing volume name or file name in " + "gluster source path '%s'"), src->path); + goto cleanup; + } + + src->volume = src->path; + + if (VIR_STRDUP(src->path, tmp) < 0) + goto cleanup; + + tmp[0] = '\0'; + } + child = node->children; while (child != NULL) { if (child->type == XML_ELEMENT_NODE && @@ -14841,6 +14862,7 @@ virDomainDiskSourceFormat(virBufferPtr buf, unsigned int flags) { size_t n; + char *path = NULL; const char *startupPolicy = NULL; if (policy) @@ -14876,7 +14898,16 @@ virDomainDiskSourceFormat(virBufferPtr buf, case VIR_STORAGE_TYPE_NETWORK: virBufferAsprintf(buf, "protocol)); - virBufferEscapeString(buf, " name='%s'", src->path); + + + if (src->volume) { + if (virAsprintf(&path, "%s%s", src->volume, src->path) < 0) + return -1; + } + + virBufferEscapeString(buf, " name='%s'", path ? path : src->path); + + VIR_FREE(path); if (src->nhosts == 0) { virBufferAddLit(buf, "/>\n"); diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 193959f5d1..31d078199c 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -3058,6 +3058,7 @@ qemuNetworkDriveGetPort(int protocol, static char * qemuBuildNetworkDriveURI(int protocol, const char *src, + const char *volume, size_t nhosts, virStorageNetHostDefPtr hosts, const char *username, @@ -3157,11 +3158,18 @@ qemuBuildNetworkDriveURI(int protocol, if ((uri->port = qemuNetworkDriveGetPort(protocol, hosts->port)) < 0) goto cleanup; - if (src && - virAsprintf(&uri->path, "%s%s", - src[0] == '/' ? "" : "/", - src) < 0) - goto cleanup; + if (src) { + if (volume) { + if (virAsprintf(&uri->path, "/%s%s", + volume, src) < 0) + goto cleanup; + } else { + if (virAsprintf(&uri->path, "%s%s", + src[0] == '/' ? "" : "/", + src) < 0) + goto cleanup; + } + } if (hosts->socket && virAsprintf(&uri->query, "socket=%s", hosts->socket) < 0) @@ -3323,6 +3331,7 @@ qemuGetDriveSourceString(virStorageSourcePtr src, case VIR_STORAGE_TYPE_NETWORK: if (!(*source = qemuBuildNetworkDriveURI(src->protocol, src->path, + src->volume, src->nhosts, src->hosts, username, diff --git a/src/storage/storage_backend_gluster.c b/src/storage/storage_backend_gluster.c index 2f0592f76e..8679d968f8 100644 --- a/src/storage/storage_backend_gluster.c +++ b/src/storage/storage_backend_gluster.c @@ -533,8 +533,6 @@ typedef virStorageFileBackendGlusterPriv *virStorageFileBackendGlusterPrivPtr; struct _virStorageFileBackendGlusterPriv { glfs_t *vol; - char *volname; - char *path; }; @@ -547,7 +545,6 @@ virStorageFileBackendGlusterDeinit(virStorageSourcePtr src) if (priv->vol) glfs_fini(priv->vol); - VIR_FREE(priv->volname); VIR_FREE(priv); src->drv->priv = NULL; @@ -564,21 +561,14 @@ virStorageFileBackendGlusterInit(virStorageSourcePtr src) VIR_DEBUG("initializing gluster storage file %p(%s/%s)", src, hostname, src->path); - if (VIR_ALLOC(priv) < 0) - return -1; - - if (VIR_STRDUP(priv->volname, src->path) < 0) - goto error; - - if (!(priv->path = strchr(priv->volname, '/'))) { + if (!src->volume) { virReportError(VIR_ERR_INTERNAL_ERROR, - _("invalid path of gluster volume: '%s'"), - src->path); - goto error; + _("missing gluster volume name for path '%s'"), src->path); + return -1; } - *priv->path = '\0'; - priv->path++; + if (VIR_ALLOC(priv) < 0) + return -1; if (host->port && virStrToLong_i(host->port, NULL, 10, &port) < 0) { @@ -591,7 +581,7 @@ virStorageFileBackendGlusterInit(virStorageSourcePtr src) if (host->transport == VIR_STORAGE_NET_HOST_TRANS_UNIX) hostname = host->socket; - if (!(priv->vol = glfs_new(priv->volname))) { + if (!(priv->vol = glfs_new(src->volume))) { virReportOOMError(); goto error; } @@ -617,7 +607,6 @@ virStorageFileBackendGlusterInit(virStorageSourcePtr src) return 0; error: - VIR_FREE(priv->volname); if (priv->vol) glfs_fini(priv->vol); VIR_FREE(priv); @@ -632,7 +621,7 @@ virStorageFileBackendGlusterUnlink(virStorageSourcePtr src) virStorageFileBackendGlusterPrivPtr priv = src->drv->priv; int ret; - ret = glfs_unlink(priv->vol, priv->path); + ret = glfs_unlink(priv->vol, src->path); /* preserve errno */ VIR_DEBUG("removing storage file %p(%s/%s): ret=%d, errno=%d", @@ -648,7 +637,7 @@ virStorageFileBackendGlusterStat(virStorageSourcePtr src, virStorageFileBackendGlusterPrivPtr priv = src->drv->priv; int ret; - ret = glfs_stat(priv->vol, priv->path, st); + ret = glfs_stat(priv->vol, src->path, st); /* preserve errno */ VIR_DEBUG("stat of storage file %p(%s/%s): ret=%d, errno=%d", diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c index 5c1ab6204b..856b72620d 100644 --- a/src/util/virstoragefile.c +++ b/src/util/virstoragefile.c @@ -1757,6 +1757,7 @@ virStorageSourceClear(virStorageSourcePtr def) return; VIR_FREE(def->path); + VIR_FREE(def->volume); virStorageSourcePoolDefFree(def->srcpool); VIR_FREE(def->driverName); virBitmapFree(def->features); diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h index f875b6999d..d3560a82a1 100644 --- a/src/util/virstoragefile.h +++ b/src/util/virstoragefile.h @@ -212,6 +212,7 @@ struct _virStorageSource { int type; /* virStorageType */ char *path; int protocol; /* virStorageNetProtocol */ + char *volume; /* volume name for remote storage */ size_t nhosts; virStorageNetHostDefPtr hosts; virStorageSourcePoolDefPtr srcpool;