return -1;
}
+ if (virStorageSourceNetworkProtocolPathSplit(src->path, src->protocol, NULL, NULL) < 0)
+ return -1;
+
if (virXMLPropTristateBool(node, "tls", VIR_XML_PROP_NONE,
&src->haveTLS) < 0)
return -1;
}
}
- /* for historical reasons we store the volume and image name in one XML
- * element although it complicates thing when attempting to access them. */
- if (src->path &&
- (src->protocol == VIR_STORAGE_NET_PROTOCOL_GLUSTER ||
- src->protocol == VIR_STORAGE_NET_PROTOCOL_RBD)) {
- char *tmp;
- if (!(tmp = strchr(src->path, '/')) ||
- tmp == src->path) {
- virReportError(VIR_ERR_XML_ERROR,
- _("can't split path '%1$s' into pool name and image name"),
- src->path);
- return -1;
- }
-
- src->volume = src->path;
-
- src->path = g_strdup(tmp + 1);
-
- tmp[0] = '\0';
- }
-
/* snapshot currently works only for remote disks */
src->snapshot = virXPathString("string(./snapshot/@name)", ctxt);
unsigned int flags)
{
size_t n;
- g_autofree char *path = NULL;
virBufferAsprintf(attrBuf, " protocol='%s'",
virStorageNetProtocolTypeToString(src->protocol));
- if (src->volume)
- path = g_strdup_printf("%s/%s", src->volume, src->path);
-
- virBufferEscapeString(attrBuf, " name='%s'", path ? path : src->path);
+ virBufferEscapeString(attrBuf, " name='%s'", src->path);
virBufferEscapeString(attrBuf, " query='%s'", src->query);
if (src->haveTLS != VIR_TRISTATE_BOOL_ABSENT &&
def->path = g_strdup(src->path);
def->fdgroup = g_strdup(src->fdgroup);
- def->volume = g_strdup(src->volume);
def->relPath = g_strdup(src->relPath);
def->backingStoreRaw = g_strdup(src->backingStoreRaw);
def->backingStoreRawFormat = src->backingStoreRawFormat;
return false;
if (STRNEQ_NULLABLE(a->path, b->path) ||
- STRNEQ_NULLABLE(a->volume, b->volume) ||
STRNEQ_NULLABLE(a->snapshot, b->snapshot))
return false;
VIR_FREE(def->path);
VIR_FREE(def->fdgroup);
- VIR_FREE(def->volume);
VIR_FREE(def->vdpadev);
VIR_FREE(def->snapshot);
VIR_FREE(def->configFile);
{
return g_object_new(vir_storage_source_fd_tuple_get_type(), NULL);
}
+
+
+/**
+ * virStorageSourceNetworkProtocolPathSplit:
+ * @path: path to split
+ * @protocol: protocol
+ * @pool: filled with pool name (may be NULL)
+ * @image: filled with image name (may be NULL)
+ *
+ * Historically libvirt accepted the specification of Gluster's volume and
+ * RBD's pool as part of the 'path' field, but internally many places require
+ * individual components.
+ *
+ * This helper validates and splits the path as appropriate for given protocol.
+ * It's useful for 'gluster' and 'rbd' protocol but for validation can be called
+ * with any protocol.
+ */
+int
+virStorageSourceNetworkProtocolPathSplit(const char *path,
+ virStorageNetProtocol protocol,
+ char **pool,
+ char **image)
+{
+
+ g_autofree char *pathcopy = g_strdup(path);
+ char *tmp;
+
+ if (protocol != VIR_STORAGE_NET_PROTOCOL_GLUSTER &&
+ protocol != VIR_STORAGE_NET_PROTOCOL_RBD) {
+
+ if (image)
+ *image = g_steal_pointer(&pathcopy);
+
+ return 0;
+ }
+
+ if (!(tmp = strchr(pathcopy, '/')) || tmp == pathcopy) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("can't split path '%1$s' into pool name and image name"),
+ pathcopy);
+ return -1;
+ }
+
+ tmp[0] = '\0';
+
+ if (pool)
+ *pool = g_steal_pointer(&pathcopy);
+
+ if (image)
+ *image = g_strdup(tmp + 1);
+
+ return 0;
+}
char *path;
char *fdgroup; /* name of group of file descriptors the user wishes to use instead of 'path' */
virStorageNetProtocol protocol;
- char *volume; /* volume name for remote storage */
char *snapshot; /* for storage systems supporting internal snapshots */
char *configFile; /* some storage systems use config file as part of
the source definition */
virStorageSourceInitiatorClear(virStorageSourceInitiatorDef *initiator);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virStorageAuthDef, virStorageAuthDefFree);
+
+int
+virStorageSourceNetworkProtocolPathSplit(const char *path,
+ virStorageNetProtocol protocol,
+ char **pool,
+ char **image);
virStorageSourceIsSameLocation;
virStorageSourceNetCookiesValidate;
virStorageSourceNetworkAssignDefaultPorts;
+virStorageSourceNetworkProtocolPathSplit;
virStorageSourceNew;
virStorageSourceNVMeDefFree;
virStorageSourcePoolDefFree;
return NULL;
}
- virBufferStrcat(&buf, "rbd:", src->volume, "/", src->path, NULL);
+ virBufferStrcat(&buf, "rbd:", src->path, NULL);
if (username) {
virBufferEscape(&buf, '\\', ":", ":id=%s", username);
return NULL;
}
- virBufferStrcat(&buf, "rbd:", src->volume, "/", src->path, NULL);
+ virBufferStrcat(&buf, "rbd:", src->path, NULL);
virBufferAddLit(&buf, ":auth_supported=none");
}
if (src->path) {
- if (src->volume) {
- uri->path = g_strdup_printf("/%s/%s", src->volume, src->path);
- } else {
- uri->path = g_strdup_printf("%s%s",
- g_path_is_absolute(src->path) ? "" : "/",
- src->path);
- }
+ uri->path = g_strdup_printf("%s%s",
+ g_path_is_absolute(src->path) ? "" : "/",
+ src->path);
}
uri->query = g_strdup(src->query);
{
g_autoptr(virJSONValue) servers = NULL;
g_autoptr(virJSONValue) props = NULL;
+ g_autofree char *volume = NULL;
+ g_autofree char *path = NULL;
if (!(servers = qemuBlockStorageSourceBuildHostsJSONSocketAddress(src)))
return NULL;
+ if (virStorageSourceNetworkProtocolPathSplit(src->path,
+ VIR_STORAGE_NET_PROTOCOL_GLUSTER,
+ &volume, &path) < 0)
+ return NULL;
+
/* { driver:"gluster",
* volume:"testvol",
* path:"/a.img",
* {type:"unix", socket:"/tmp/glusterd.socket"}, ...]}
*/
if (virJSONValueObjectAdd(&props,
- "s:volume", src->volume,
- "s:path", src->path,
+ "s:volume", volume,
+ "s:path", path,
"a:server", &servers, NULL) < 0)
return NULL;
const char *username = NULL;
g_autoptr(virJSONValue) authmodes = NULL;
const char *keysecret = NULL;
+ g_autofree char *pool = NULL;
+ g_autofree char *image = NULL;
+
+ if (virStorageSourceNetworkProtocolPathSplit(src->path,
+ VIR_STORAGE_NET_PROTOCOL_RBD,
+ &pool, &image) < 0)
+ return NULL;
if (src->nhosts > 0 &&
!(servers = qemuBlockStorageSourceBuildHostsJSONInetSocketAddress(src)))
}
if (virJSONValueObjectAdd(&ret,
- "s:pool", src->volume,
- "s:image", src->path,
+ "s:pool", pool,
+ "s:image", image,
"S:snapshot", src->snapshot,
"S:conf", src->configFile,
"A:server", &servers,
typedef struct _virStorageFileBackendGlusterPriv virStorageFileBackendGlusterPriv;
struct _virStorageFileBackendGlusterPriv {
glfs_t *vol;
+ char *image;
};
static void
virStorageDriverData *drv = src->drv;
virStorageFileBackendGlusterPriv *priv = drv->priv;
- VIR_DEBUG("deinitializing gluster storage file %p (gluster://%s:%u/%s%s)",
- src, src->hosts->name, src->hosts->port, src->volume, src->path);
+ VIR_DEBUG("deinitializing gluster storage file %p (gluster://%s:%u/%s)",
+ src, src->hosts->name, src->hosts->port, src->path);
if (priv->vol)
glfs_fini(priv->vol);
+ VIR_FREE(priv->image);
VIR_FREE(priv);
drv->priv = NULL;
}
{
virStorageDriverData *drv = src->drv;
g_autofree virStorageFileBackendGlusterPriv *priv = NULL;
+ g_autofree char *volume = NULL;
+ g_autofree char *image = NULL;
size_t i;
- if (!src->volume) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("missing gluster volume name for path '%1$s'"),
- src->path);
+ if (virStorageSourceNetworkProtocolPathSplit(src->path,
+ VIR_STORAGE_NET_PROTOCOL_GLUSTER,
+ &volume, &image) < 0)
return -1;
- }
priv = g_new0(virStorageFileBackendGlusterPriv, 1);
VIR_DEBUG("initializing gluster storage file %p "
"(priv='%p' volume='%s' path='%s') as [%u:%u]",
- src, priv, src->volume, src->path,
+ src, priv, volume, image,
(unsigned int)drv->uid, (unsigned int)drv->gid);
- if (!(priv->vol = glfs_new(src->volume))) {
+ if (!(priv->vol = glfs_new(volume))) {
virReportError(VIR_ERR_OPERATION_FAILED,
- _("failed to create glfs object for '%1$s'"), src->volume);
+ _("failed to create glfs object for '%1$s'"), volume);
return -1;
}
return -1;
}
+ priv->image = g_steal_pointer(&image);
drv->priv = g_steal_pointer(&priv);
return 0;
virStorageFileBackendGlusterPriv *priv = drv->priv;
glfs_fd_t *fd = NULL;
- if (!(fd = glfs_creat(priv->vol, src->path,
+ if (!(fd = glfs_creat(priv->vol, priv->image,
O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR)))
return -1;
virStorageDriverData *drv = src->drv;
virStorageFileBackendGlusterPriv *priv = drv->priv;
- return glfs_unlink(priv->vol, src->path);
+ return glfs_unlink(priv->vol, priv->image);
}
virStorageDriverData *drv = src->drv;
virStorageFileBackendGlusterPriv *priv = drv->priv;
- return glfs_stat(priv->vol, src->path, st);
+ return glfs_stat(priv->vol, priv->image, st);
}
*buf = NULL;
- if (!(fd = glfs_open(priv->vol, src->path, O_RDONLY))) {
+ if (!(fd = glfs_open(priv->vol, priv->image, O_RDONLY))) {
virReportSystemError(errno, _("Failed to open file '%1$s'"),
- src->path);
+ priv->image);
return -1;
}
if (offset > 0) {
if (glfs_lseek(fd, offset, SEEK_SET) == (off_t) -1) {
- virReportSystemError(errno, _("cannot seek into '%1$s'"), src->path);
+ virReportSystemError(errno, _("cannot seek into '%1$s'"), priv->image);
goto cleanup;
}
}
continue;
if (r < 0) {
VIR_FREE(*buf);
- virReportSystemError(errno, _("unable to read '%1$s'"), src->path);
+ virReportSystemError(errno, _("unable to read '%1$s'"), priv->image);
return r;
}
if (r == 0)
virStorageDriverData *drv = src->drv;
virStorageFileBackendGlusterPriv *priv = drv->priv;
- return glfs_access(priv->vol, src->path, mode);
+ return glfs_access(priv->vol, priv->image, mode);
}
static int
virStorageDriverData *drv = src->drv;
virStorageFileBackendGlusterPriv *priv = drv->priv;
- return glfs_chown(priv->vol, src->path, uid, gid);
+ return glfs_chown(priv->vol, priv->image, uid, gid);
}
def->nhosts = parent->nhosts;
}
-
- def->volume = g_strdup(parent->volume);
} else {
/* set the type to _FILE, the caller shall update it to the actual type */
def->type = VIR_STORAGE_TYPE_FILE;
src->path = g_strdup(path);
if (src->protocol == VIR_STORAGE_NET_PROTOCOL_GLUSTER) {
- char *tmp;
-
- if (!src->path) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("missing volume name and path for gluster volume"));
- return -1;
- }
-
- if (!(tmp = strchr(src->path, '/')) ||
- tmp == src->path) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("missing volume name or file name in gluster source path '%1$s'"),
- src->path);
+ if (virStorageSourceNetworkProtocolPathSplit(src->path, src->protocol,
+ NULL, NULL) < 0)
return -1;
- }
-
- src->volume = src->path;
-
- src->path = g_strdup(tmp + 1);
-
- tmp[0] = '\0';
}
src->hosts->port = uri->port;
*p = '\0';
}
- /* pool vs. image name */
- if ((p = strchr(src->path, '/'))) {
- src->volume = g_steal_pointer(&src->path);
- src->path = g_strdup(p + 1);
- *p = '\0';
- }
-
/* options */
if (!options)
return 0; /* all done */
src->type = VIR_STORAGE_TYPE_NETWORK;
src->protocol = VIR_STORAGE_NET_PROTOCOL_GLUSTER;
- src->volume = g_strdup(volume);
- src->path = g_strdup(path);
+ src->path = g_strdup_printf("%s/%s", volume, path);
nservers = virJSONValueArraySize(server);
if (nservers == 0) {
return -1;
}
- src->volume = g_strdup(pool);
- src->path = g_strdup(image);
+ src->path = g_strdup_printf("%s/%s", pool, image);
src->snapshot = g_strdup(snapshot);
src->configFile = g_strdup(conf);