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:
MORITA Kazutaka 2013-02-22 12:39:51 +09:00 committed by Stefan Hajnoczi
parent bf1c852aa9
commit 5d6768e3b8
3 changed files with 117 additions and 56 deletions

View File

@ -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);

View File

@ -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

View File

@ -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/}.