[Sheepdog] [PATCH] support sheepdog volumes
MORITA Kazutaka
morita.kazutaka at lab.ntt.co.jp
Wed Nov 17 10:19:58 CET 2010
Sheepdog is a distributed storage system for QEMU. It provides highly
available block level storage volumes to VMs like Amazon EBS. This
patch adds support for Sheepdog; we can create VMs with sheepdog
volumes, and attach sheepdog volumes to running machines via the
attach-device command.
Sheepdog volumes can be declared like this:
<disk type='sheepdog' device='disk'>
<driver name='qemu' type='raw' />
<source vdi='volume_name' host='hostname' port='7000'/>
<target dev='vda' bus='virtio' />
</disk>
'host' and 'port' in the source element are optional. If they are not
specified, sheepdog clients use the default value (localhost:7000).
Signed-off-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
---
docs/schemas/domain.rng | 24 ++++++++++++++++++
src/conf/domain_conf.c | 26 ++++++++++++++++++-
src/conf/domain_conf.h | 3 ++
src/qemu/qemu_conf.c | 63 +++++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 113 insertions(+), 3 deletions(-)
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index bbbc846..5802993 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -612,6 +612,30 @@
<ref name="diskspec"/>
</interleave>
</group>
+ <group>
+ <attribute name="type">
+ <value>sheepdog</value>
+ </attribute>
+ <interleave>
+ <optional>
+ <element name="source">
+ <attribute name="vdi">
+ <ref name="genericName"/>
+ </attribute>
+ <optional>
+ <attribute name="host">
+ <ref name="genericName"/>
+ </attribute>
+ <attribute name="port">
+ <ref name="unsignedInt"/>
+ </attribute>
+ </optional>
+ <empty/>
+ </element>
+ </optional>
+ <ref name="diskspec"/>
+ </interleave>
+ </group>
<ref name="diskspec"/>
</choice>
</element>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 30c27db..d0ea0bb 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -113,7 +113,8 @@ VIR_ENUM_IMPL(virDomainDeviceAddress, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST,
VIR_ENUM_IMPL(virDomainDisk, VIR_DOMAIN_DISK_TYPE_LAST,
"block",
"file",
- "dir")
+ "dir",
+ "sheepdog")
VIR_ENUM_IMPL(virDomainDiskDevice, VIR_DOMAIN_DISK_DEVICE_LAST,
"disk",
@@ -505,6 +506,8 @@ void virDomainDiskDefFree(virDomainDiskDefPtr def)
VIR_FREE(def->serial);
VIR_FREE(def->src);
+ VIR_FREE(def->host);
+ VIR_FREE(def->port);
VIR_FREE(def->dst);
VIR_FREE(def->driverName);
VIR_FREE(def->driverType);
@@ -1517,6 +1520,8 @@ virDomainDiskDefParseXML(virCapsPtr caps,
char *driverName = NULL;
char *driverType = NULL;
char *source = NULL;
+ char *host = NULL;
+ char *port = NULL;
char *target = NULL;
char *bus = NULL;
char *cachetag = NULL;
@@ -1557,6 +1562,11 @@ virDomainDiskDefParseXML(virCapsPtr caps,
case VIR_DOMAIN_DISK_TYPE_DIR:
source = virXMLPropString(cur, "dir");
break;
+ case VIR_DOMAIN_DISK_TYPE_SHEEPDOG:
+ source = virXMLPropString(cur, "vdi");
+ host = virXMLPropString(cur, "host");
+ port = virXMLPropString(cur, "port");
+ break;
default:
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
_("unexpected disk type %s"),
@@ -1726,6 +1736,10 @@ virDomainDiskDefParseXML(virCapsPtr caps,
def->src = source;
source = NULL;
+ def->host = host;
+ host = NULL;
+ def->port = port;
+ port = NULL;
def->dst = target;
target = NULL;
def->driverName = driverName;
@@ -1756,6 +1770,8 @@ cleanup:
VIR_FREE(type);
VIR_FREE(target);
VIR_FREE(source);
+ VIR_FREE(host);
+ VIR_FREE(port);
VIR_FREE(device);
VIR_FREE(driverType);
VIR_FREE(driverName);
@@ -5831,6 +5847,14 @@ virDomainDiskDefFormat(virBufferPtr buf,
virBufferEscapeString(buf, " <source dir='%s'/>\n",
def->src);
break;
+ case VIR_DOMAIN_DISK_TYPE_SHEEPDOG:
+ virBufferEscapeString(buf, " <source vdi='%s'", def->src);
+ if (def->host && def->port) {
+ virBufferEscapeString(buf, " host='%s'", def->host);
+ virBufferEscapeString(buf, " port='%s'", def->port);
+ }
+ virBufferVSprintf(buf, "/>\n");
+ break;
default:
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
_("unexpected disk type %s"),
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 7d2d6f5..9c929c4 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -120,6 +120,7 @@ enum virDomainDiskType {
VIR_DOMAIN_DISK_TYPE_BLOCK,
VIR_DOMAIN_DISK_TYPE_FILE,
VIR_DOMAIN_DISK_TYPE_DIR,
+ VIR_DOMAIN_DISK_TYPE_SHEEPDOG,
VIR_DOMAIN_DISK_TYPE_LAST
};
@@ -172,6 +173,8 @@ struct _virDomainDiskDef {
int device;
int bus;
char *src;
+ char *host;
+ char *port;
char *dst;
char *driverName;
char *driverType;
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 83a117a..84f55cb 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -2731,6 +2731,11 @@ qemuBuildDriveStr(virDomainDiskDefPtr disk,
virBufferVSprintf(&opt, "file=fat:floppy:%s,", disk->src);
else
virBufferVSprintf(&opt, "file=fat:%s,", disk->src);
+ } else if (disk->type == VIR_DOMAIN_DISK_TYPE_SHEEPDOG) {
+ if (disk->host && disk->port)
+ virBufferVSprintf(&opt, "file=sheepdog:%s:%s:%s,", disk->host, disk->port, disk->src);
+ else
+ virBufferVSprintf(&opt, "file=sheepdog:%s,", disk->src);
} else {
virBufferVSprintf(&opt, "file=%s,", disk->src);
}
@@ -4720,6 +4725,11 @@ int qemudBuildCommandLine(virConnectPtr conn,
snprintf(file, PATH_MAX, "fat:floppy:%s", disk->src);
else
snprintf(file, PATH_MAX, "fat:%s", disk->src);
+ } else if (disk->type == VIR_DOMAIN_DISK_TYPE_SHEEPDOG) {
+ if (disk->host && disk->port)
+ snprintf(file, PATH_MAX, "sheepdog:%s:%s:%s", disk->host, disk->port, disk->src);
+ else
+ snprintf(file, PATH_MAX, "sheepdog:%s", disk->src);
} else {
snprintf(file, PATH_MAX, "%s", disk->src);
}
@@ -5792,7 +5802,32 @@ qemuParseCommandLineDisk(virCapsPtr caps,
values[i] = NULL;
if (STRPREFIX(def->src, "/dev/"))
def->type = VIR_DOMAIN_DISK_TYPE_BLOCK;
- else
+ else if (STRPREFIX(def->src, "sheepdog:")) {
+ char *p = def->src;
+ char *port, *vdi;
+
+ def->type = VIR_DOMAIN_DISK_TYPE_SHEEPDOG;
+ def->src = strdup(p + strlen("sheepdog:"));
+
+ /* def->src must be [vdiname] or [host]:[port]:[vdiname] */
+ port = strchr(def->src, ':');
+ if (port) {
+ *port++ = '\0';
+ vdi = strchr(port, ':');
+ if (!vdi) {
+ def = NULL;
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot parse sheepdog filename '%s'"), p);
+ goto cleanup;
+ }
+ *vdi++ = '\0';
+ def->host = def->src;
+ def->port = strdup(port);
+ def->src = strdup(vdi);
+ }
+
+ VIR_FREE(p);
+ } else
def->type = VIR_DOMAIN_DISK_TYPE_FILE;
} else {
def->type = VIR_DOMAIN_DISK_TYPE_FILE;
@@ -6729,7 +6764,10 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
if (STRPREFIX(val, "/dev/"))
disk->type = VIR_DOMAIN_DISK_TYPE_BLOCK;
- else
+ else if (STRPREFIX(val, "sheepdog:")) {
+ disk->type = VIR_DOMAIN_DISK_TYPE_SHEEPDOG;
+ val = STRSKIP(val, "sheepdog:");
+ } else
disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
if (STREQ(arg, "-cdrom")) {
disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
@@ -6749,6 +6787,27 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
disk->dst = strdup(arg + 1);
}
disk->src = strdup(val);
+
+ if (disk->type == VIR_DOMAIN_DISK_TYPE_SHEEPDOG) {
+ char *port, *vdi;
+
+ /* disk->src must be [vdiname] or [host]:[port]:[vdiname] */
+ port = strchr(disk->src, ':');
+ if (port) {
+ *port++ = '\0';
+ vdi = strchr(port, ':');
+ if (!vdi) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot parse sheepdog filename '%s'"), val);
+ goto error;
+ }
+ *vdi++ = '\0';
+ disk->host = disk->src;
+ disk->port = strdup(port);
+ disk->src = strdup(vdi);
+ }
+ }
+
if (!disk->src ||
!disk->dst) {
virDomainDiskDefFree(disk);
--
1.7.1
More information about the sheepdog
mailing list