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@xxxxxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list