sheepdog: accept URIs
The URI syntax is consistent with the NBD and Gluster syntax. The syntax is sheepdog[+tcp]://[host:port]/vdiname[#snapid|#tag] Signed-off-by: MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
parent
bf1c852aa9
commit
5d6768e3b8
139
block/sheepdog.c
139
block/sheepdog.c
|
@ -13,6 +13,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
|
#include "qemu/uri.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
#include "qemu/sockets.h"
|
#include "qemu/sockets.h"
|
||||||
#include "block/block_int.h"
|
#include "block/block_int.h"
|
||||||
|
@ -816,8 +817,52 @@ static int get_sheep_fd(BDRVSheepdogState *s)
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sd_parse_uri(BDRVSheepdogState *s, const char *filename,
|
||||||
|
char *vdi, uint32_t *snapid, char *tag)
|
||||||
|
{
|
||||||
|
URI *uri;
|
||||||
|
QueryParams *qp = NULL;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
uri = uri_parse(filename);
|
||||||
|
if (!uri) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uri->path == NULL || !strcmp(uri->path, "/")) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
pstrcpy(vdi, SD_MAX_VDI_LEN, uri->path + 1);
|
||||||
|
|
||||||
|
/* sheepdog[+tcp]://[host:port]/vdiname */
|
||||||
|
s->addr = g_strdup(uri->server ?: SD_DEFAULT_ADDR);
|
||||||
|
if (uri->port) {
|
||||||
|
s->port = g_strdup_printf("%d", uri->port);
|
||||||
|
} else {
|
||||||
|
s->port = g_strdup(SD_DEFAULT_PORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* snapshot tag */
|
||||||
|
if (uri->fragment) {
|
||||||
|
*snapid = strtoul(uri->fragment, NULL, 10);
|
||||||
|
if (*snapid == 0) {
|
||||||
|
pstrcpy(tag, SD_MAX_VDI_TAG_LEN, uri->fragment);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*snapid = CURRENT_VDI_ID; /* search current vdi */
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (qp) {
|
||||||
|
query_params_free(qp);
|
||||||
|
}
|
||||||
|
uri_free(uri);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parse a filename
|
* Parse a filename (old syntax)
|
||||||
*
|
*
|
||||||
* filename must be one of the following formats:
|
* filename must be one of the following formats:
|
||||||
* 1. [vdiname]
|
* 1. [vdiname]
|
||||||
|
@ -836,9 +881,11 @@ static int get_sheep_fd(BDRVSheepdogState *s)
|
||||||
static int parse_vdiname(BDRVSheepdogState *s, const char *filename,
|
static int parse_vdiname(BDRVSheepdogState *s, const char *filename,
|
||||||
char *vdi, uint32_t *snapid, char *tag)
|
char *vdi, uint32_t *snapid, char *tag)
|
||||||
{
|
{
|
||||||
char *p, *q;
|
char *p, *q, *uri;
|
||||||
int nr_sep;
|
const char *host_spec, *vdi_spec;
|
||||||
|
int nr_sep, ret;
|
||||||
|
|
||||||
|
strstart(filename, "sheepdog:", (const char **)&filename);
|
||||||
p = q = g_strdup(filename);
|
p = q = g_strdup(filename);
|
||||||
|
|
||||||
/* count the number of separators */
|
/* count the number of separators */
|
||||||
|
@ -851,38 +898,32 @@ static int parse_vdiname(BDRVSheepdogState *s, const char *filename,
|
||||||
}
|
}
|
||||||
p = q;
|
p = q;
|
||||||
|
|
||||||
/* use the first two tokens as hostname and port number. */
|
/* use the first two tokens as host_spec. */
|
||||||
if (nr_sep >= 2) {
|
if (nr_sep >= 2) {
|
||||||
s->addr = p;
|
host_spec = p;
|
||||||
p = strchr(p, ':');
|
p = strchr(p, ':');
|
||||||
*p++ = '\0';
|
p++;
|
||||||
|
|
||||||
s->port = p;
|
|
||||||
p = strchr(p, ':');
|
p = strchr(p, ':');
|
||||||
*p++ = '\0';
|
*p++ = '\0';
|
||||||
} else {
|
} else {
|
||||||
s->addr = NULL;
|
host_spec = "";
|
||||||
s->port = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pstrcpy(vdi, SD_MAX_VDI_LEN, p);
|
vdi_spec = p;
|
||||||
|
|
||||||
p = strchr(vdi, ':');
|
p = strchr(vdi_spec, ':');
|
||||||
if (p) {
|
if (p) {
|
||||||
*p++ = '\0';
|
*p++ = '#';
|
||||||
*snapid = strtoul(p, NULL, 10);
|
|
||||||
if (*snapid == 0) {
|
|
||||||
pstrcpy(tag, SD_MAX_VDI_TAG_LEN, p);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
*snapid = CURRENT_VDI_ID; /* search current vdi */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->addr == NULL) {
|
uri = g_strdup_printf("sheepdog://%s/%s", host_spec, vdi_spec);
|
||||||
g_free(q);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
ret = sd_parse_uri(s, uri, vdi, snapid, tag);
|
||||||
|
|
||||||
|
g_free(q);
|
||||||
|
g_free(uri);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int find_vdi_name(BDRVSheepdogState *s, char *filename, uint32_t snapid,
|
static int find_vdi_name(BDRVSheepdogState *s, char *filename, uint32_t snapid,
|
||||||
|
@ -1097,16 +1138,19 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags)
|
||||||
uint32_t snapid;
|
uint32_t snapid;
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
|
|
||||||
strstart(filename, "sheepdog:", (const char **)&filename);
|
|
||||||
|
|
||||||
QLIST_INIT(&s->inflight_aio_head);
|
QLIST_INIT(&s->inflight_aio_head);
|
||||||
QLIST_INIT(&s->pending_aio_head);
|
QLIST_INIT(&s->pending_aio_head);
|
||||||
s->fd = -1;
|
s->fd = -1;
|
||||||
|
|
||||||
memset(vdi, 0, sizeof(vdi));
|
memset(vdi, 0, sizeof(vdi));
|
||||||
memset(tag, 0, sizeof(tag));
|
memset(tag, 0, sizeof(tag));
|
||||||
if (parse_vdiname(s, filename, vdi, &snapid, tag) < 0) {
|
|
||||||
ret = -EINVAL;
|
if (strstr(filename, "://")) {
|
||||||
|
ret = sd_parse_uri(s, filename, vdi, &snapid, tag);
|
||||||
|
} else {
|
||||||
|
ret = parse_vdiname(s, filename, vdi, &snapid, tag);
|
||||||
|
}
|
||||||
|
if (ret < 0) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
s->fd = get_sheep_fd(s);
|
s->fd = get_sheep_fd(s);
|
||||||
|
@ -1275,17 +1319,17 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
|
||||||
char vdi[SD_MAX_VDI_LEN], tag[SD_MAX_VDI_TAG_LEN];
|
char vdi[SD_MAX_VDI_LEN], tag[SD_MAX_VDI_TAG_LEN];
|
||||||
uint32_t snapid;
|
uint32_t snapid;
|
||||||
bool prealloc = false;
|
bool prealloc = false;
|
||||||
const char *vdiname;
|
|
||||||
|
|
||||||
s = g_malloc0(sizeof(BDRVSheepdogState));
|
s = g_malloc0(sizeof(BDRVSheepdogState));
|
||||||
|
|
||||||
strstart(filename, "sheepdog:", &vdiname);
|
|
||||||
|
|
||||||
memset(vdi, 0, sizeof(vdi));
|
memset(vdi, 0, sizeof(vdi));
|
||||||
memset(tag, 0, sizeof(tag));
|
memset(tag, 0, sizeof(tag));
|
||||||
if (parse_vdiname(s, vdiname, vdi, &snapid, tag) < 0) {
|
if (strstr(filename, "://")) {
|
||||||
error_report("invalid filename");
|
ret = sd_parse_uri(s, filename, vdi, &snapid, tag);
|
||||||
ret = -EINVAL;
|
} else {
|
||||||
|
ret = parse_vdiname(s, filename, vdi, &snapid, tag);
|
||||||
|
}
|
||||||
|
if (ret < 0) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1392,6 +1436,7 @@ static void sd_close(BlockDriverState *bs)
|
||||||
qemu_aio_set_fd_handler(s->fd, NULL, NULL, NULL, NULL);
|
qemu_aio_set_fd_handler(s->fd, NULL, NULL, NULL, NULL);
|
||||||
closesocket(s->fd);
|
closesocket(s->fd);
|
||||||
g_free(s->addr);
|
g_free(s->addr);
|
||||||
|
g_free(s->port);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t sd_getlength(BlockDriverState *bs)
|
static int64_t sd_getlength(BlockDriverState *bs)
|
||||||
|
@ -2054,7 +2099,7 @@ static QEMUOptionParameter sd_create_options[] = {
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
BlockDriver bdrv_sheepdog = {
|
static BlockDriver bdrv_sheepdog = {
|
||||||
.format_name = "sheepdog",
|
.format_name = "sheepdog",
|
||||||
.protocol_name = "sheepdog",
|
.protocol_name = "sheepdog",
|
||||||
.instance_size = sizeof(BDRVSheepdogState),
|
.instance_size = sizeof(BDRVSheepdogState),
|
||||||
|
@ -2079,8 +2124,34 @@ BlockDriver bdrv_sheepdog = {
|
||||||
.create_options = sd_create_options,
|
.create_options = sd_create_options,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static BlockDriver bdrv_sheepdog_tcp = {
|
||||||
|
.format_name = "sheepdog",
|
||||||
|
.protocol_name = "sheepdog+tcp",
|
||||||
|
.instance_size = sizeof(BDRVSheepdogState),
|
||||||
|
.bdrv_file_open = sd_open,
|
||||||
|
.bdrv_close = sd_close,
|
||||||
|
.bdrv_create = sd_create,
|
||||||
|
.bdrv_getlength = sd_getlength,
|
||||||
|
.bdrv_truncate = sd_truncate,
|
||||||
|
|
||||||
|
.bdrv_co_readv = sd_co_readv,
|
||||||
|
.bdrv_co_writev = sd_co_writev,
|
||||||
|
.bdrv_co_flush_to_disk = sd_co_flush_to_disk,
|
||||||
|
|
||||||
|
.bdrv_snapshot_create = sd_snapshot_create,
|
||||||
|
.bdrv_snapshot_goto = sd_snapshot_goto,
|
||||||
|
.bdrv_snapshot_delete = sd_snapshot_delete,
|
||||||
|
.bdrv_snapshot_list = sd_snapshot_list,
|
||||||
|
|
||||||
|
.bdrv_save_vmstate = sd_save_vmstate,
|
||||||
|
.bdrv_load_vmstate = sd_load_vmstate,
|
||||||
|
|
||||||
|
.create_options = sd_create_options,
|
||||||
|
};
|
||||||
|
|
||||||
static void bdrv_sheepdog_init(void)
|
static void bdrv_sheepdog_init(void)
|
||||||
{
|
{
|
||||||
bdrv_register(&bdrv_sheepdog);
|
bdrv_register(&bdrv_sheepdog);
|
||||||
|
bdrv_register(&bdrv_sheepdog_tcp);
|
||||||
}
|
}
|
||||||
block_init(bdrv_sheepdog_init);
|
block_init(bdrv_sheepdog_init);
|
||||||
|
|
|
@ -830,7 +830,7 @@ QEMU-based virtual machines.
|
||||||
|
|
||||||
You can create a Sheepdog disk image with the command:
|
You can create a Sheepdog disk image with the command:
|
||||||
@example
|
@example
|
||||||
qemu-img create sheepdog:@var{image} @var{size}
|
qemu-img create sheepdog:///@var{image} @var{size}
|
||||||
@end example
|
@end example
|
||||||
where @var{image} is the Sheepdog image name and @var{size} is its
|
where @var{image} is the Sheepdog image name and @var{size} is its
|
||||||
size.
|
size.
|
||||||
|
@ -838,29 +838,29 @@ size.
|
||||||
To import the existing @var{filename} to Sheepdog, you can use a
|
To import the existing @var{filename} to Sheepdog, you can use a
|
||||||
convert command.
|
convert command.
|
||||||
@example
|
@example
|
||||||
qemu-img convert @var{filename} sheepdog:@var{image}
|
qemu-img convert @var{filename} sheepdog:///@var{image}
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
You can boot from the Sheepdog disk image with the command:
|
You can boot from the Sheepdog disk image with the command:
|
||||||
@example
|
@example
|
||||||
qemu-system-i386 sheepdog:@var{image}
|
qemu-system-i386 sheepdog:///@var{image}
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
You can also create a snapshot of the Sheepdog image like qcow2.
|
You can also create a snapshot of the Sheepdog image like qcow2.
|
||||||
@example
|
@example
|
||||||
qemu-img snapshot -c @var{tag} sheepdog:@var{image}
|
qemu-img snapshot -c @var{tag} sheepdog:///@var{image}
|
||||||
@end example
|
@end example
|
||||||
where @var{tag} is a tag name of the newly created snapshot.
|
where @var{tag} is a tag name of the newly created snapshot.
|
||||||
|
|
||||||
To boot from the Sheepdog snapshot, specify the tag name of the
|
To boot from the Sheepdog snapshot, specify the tag name of the
|
||||||
snapshot.
|
snapshot.
|
||||||
@example
|
@example
|
||||||
qemu-system-i386 sheepdog:@var{image}:@var{tag}
|
qemu-system-i386 sheepdog:///@var{image}#@var{tag}
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
You can create a cloned image from the existing snapshot.
|
You can create a cloned image from the existing snapshot.
|
||||||
@example
|
@example
|
||||||
qemu-img create -b sheepdog:@var{base}:@var{tag} sheepdog:@var{image}
|
qemu-img create -b sheepdog:///@var{base}#@var{tag} sheepdog:///@var{image}
|
||||||
@end example
|
@end example
|
||||||
where @var{base} is a image name of the source snapshot and @var{tag}
|
where @var{base} is a image name of the source snapshot and @var{tag}
|
||||||
is its tag name.
|
is its tag name.
|
||||||
|
@ -868,8 +868,8 @@ is its tag name.
|
||||||
If the Sheepdog daemon doesn't run on the local host, you need to
|
If the Sheepdog daemon doesn't run on the local host, you need to
|
||||||
specify one of the Sheepdog servers to connect to.
|
specify one of the Sheepdog servers to connect to.
|
||||||
@example
|
@example
|
||||||
qemu-img create sheepdog:@var{hostname}:@var{port}:@var{image} @var{size}
|
qemu-img create sheepdog://@var{hostname}:@var{port}/@var{image} @var{size}
|
||||||
qemu-system-i386 sheepdog:@var{hostname}:@var{port}:@var{image}
|
qemu-system-i386 sheepdog://@var{hostname}:@var{port}/@var{image}
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
@node disk_images_iscsi
|
@node disk_images_iscsi
|
||||||
|
|
|
@ -2099,23 +2099,13 @@ QEMU supports using either local sheepdog devices or remote networked
|
||||||
devices.
|
devices.
|
||||||
|
|
||||||
Syntax for specifying a sheepdog device
|
Syntax for specifying a sheepdog device
|
||||||
@table @list
|
@example
|
||||||
``sheepdog:<vdiname>''
|
sheepdog[+tcp]://[host:port]/vdiname[#snapid|#tag]
|
||||||
|
@end example
|
||||||
``sheepdog:<vdiname>:<snapid>''
|
|
||||||
|
|
||||||
``sheepdog:<vdiname>:<tag>''
|
|
||||||
|
|
||||||
``sheepdog:<host>:<port>:<vdiname>''
|
|
||||||
|
|
||||||
``sheepdog:<host>:<port>:<vdiname>:<snapid>''
|
|
||||||
|
|
||||||
``sheepdog:<host>:<port>:<vdiname>:<tag>''
|
|
||||||
@end table
|
|
||||||
|
|
||||||
Example
|
Example
|
||||||
@example
|
@example
|
||||||
qemu-system-i386 --drive file=sheepdog:192.0.2.1:30000:MyVirtualMachine
|
qemu-system-i386 --drive file=sheepdog://192.0.2.1:30000/MyVirtualMachine
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
See also @url{http://http://www.osrg.net/sheepdog/}.
|
See also @url{http://http://www.osrg.net/sheepdog/}.
|
||||||
|
|
Loading…
Reference in New Issue