mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-12 15:52:55 +00:00
add network disk support
This patch adds network disk support to libvirt/QEMU. The currently supported protocols are nbd, rbd, and sheepdog. The XML syntax is like this: <disk type="network" device="disk"> <driver name="qemu" type="raw" /> <source protocol='rbd|sheepdog|nbd' name="...some image identifier..."> <host name="mon1.example.org" port="6000"> <host name="mon2.example.org" port="6000"> <host name="mon3.example.org" port="6000"> </source> <target dev="vda" bus="virtio" /> </disk> Signed-off-by: MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp>
This commit is contained in:
parent
85d5fb19b1
commit
036ad5052b
1
AUTHORS
1
AUTHORS
@ -138,6 +138,7 @@ Patches have also been contributed by:
|
||||
Wen Congyang <wency@cn.fujitsu.com>
|
||||
Hu Tao <hutao@cn.fujitsu.com>
|
||||
Laurent Léonard <laurent@open-minds.org>
|
||||
MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp>
|
||||
|
||||
[....send patches to get your name here....]
|
||||
|
||||
|
@ -612,6 +612,37 @@
|
||||
<ref name="diskspec"/>
|
||||
</interleave>
|
||||
</group>
|
||||
<group>
|
||||
<attribute name="type">
|
||||
<value>network</value>
|
||||
</attribute>
|
||||
<interleave>
|
||||
<optional>
|
||||
<element name="source">
|
||||
<attribute name="protocol">
|
||||
<choice>
|
||||
<value>nbd</value>
|
||||
<value>rbd</value>
|
||||
<value>sheepdog</value>
|
||||
</choice>
|
||||
</attribute>
|
||||
<attribute name="name"/>
|
||||
<zeroOrMore>
|
||||
<element name="host">
|
||||
<attribute name="name">
|
||||
<ref name="genericName"/>
|
||||
</attribute>
|
||||
<attribute name="port">
|
||||
<ref name="unsignedInt"/>
|
||||
</attribute>
|
||||
</element>
|
||||
</zeroOrMore>
|
||||
<empty/>
|
||||
</element>
|
||||
</optional>
|
||||
<ref name="diskspec"/>
|
||||
</interleave>
|
||||
</group>
|
||||
<ref name="diskspec"/>
|
||||
</choice>
|
||||
</element>
|
||||
|
@ -112,7 +112,8 @@ VIR_ENUM_IMPL(virDomainDeviceAddress, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST,
|
||||
VIR_ENUM_IMPL(virDomainDisk, VIR_DOMAIN_DISK_TYPE_LAST,
|
||||
"block",
|
||||
"file",
|
||||
"dir")
|
||||
"dir",
|
||||
"network")
|
||||
|
||||
VIR_ENUM_IMPL(virDomainDiskDevice, VIR_DOMAIN_DISK_DEVICE_LAST,
|
||||
"disk",
|
||||
@ -141,6 +142,11 @@ VIR_ENUM_IMPL(virDomainDiskErrorPolicy, VIR_DOMAIN_DISK_ERROR_POLICY_LAST,
|
||||
"ignore",
|
||||
"enospace")
|
||||
|
||||
VIR_ENUM_IMPL(virDomainDiskProtocol, VIR_DOMAIN_DISK_PROTOCOL_LAST,
|
||||
"nbd",
|
||||
"rbd",
|
||||
"sheepdog")
|
||||
|
||||
VIR_ENUM_IMPL(virDomainController, VIR_DOMAIN_CONTROLLER_TYPE_LAST,
|
||||
"ide",
|
||||
"fdc",
|
||||
@ -508,6 +514,7 @@ void virDomainDiskDefFree(virDomainDiskDefPtr def)
|
||||
|
||||
VIR_FREE(def->serial);
|
||||
VIR_FREE(def->src);
|
||||
VIR_FREE(def->hosts);
|
||||
VIR_FREE(def->dst);
|
||||
VIR_FREE(def->driverName);
|
||||
VIR_FREE(def->driverType);
|
||||
@ -1574,13 +1581,16 @@ virDomainDiskDefParseXML(virCapsPtr caps,
|
||||
xmlNodePtr node,
|
||||
int flags) {
|
||||
virDomainDiskDefPtr def;
|
||||
xmlNodePtr cur;
|
||||
xmlNodePtr cur, host;
|
||||
char *type = NULL;
|
||||
char *device = NULL;
|
||||
char *driverName = NULL;
|
||||
char *driverType = NULL;
|
||||
char *source = NULL;
|
||||
char *target = NULL;
|
||||
char *protocol = NULL;
|
||||
virDomainDiskHostDefPtr hosts = NULL;
|
||||
int nhosts = 0;
|
||||
char *bus = NULL;
|
||||
char *cachetag = NULL;
|
||||
char *error_policy = NULL;
|
||||
@ -1607,7 +1617,7 @@ virDomainDiskDefParseXML(virCapsPtr caps,
|
||||
cur = node->children;
|
||||
while (cur != NULL) {
|
||||
if (cur->type == XML_ELEMENT_NODE) {
|
||||
if ((source == NULL) &&
|
||||
if ((source == NULL && hosts == NULL) &&
|
||||
(xmlStrEqual(cur->name, BAD_CAST "source"))) {
|
||||
|
||||
switch (def->type) {
|
||||
@ -1620,6 +1630,49 @@ virDomainDiskDefParseXML(virCapsPtr caps,
|
||||
case VIR_DOMAIN_DISK_TYPE_DIR:
|
||||
source = virXMLPropString(cur, "dir");
|
||||
break;
|
||||
case VIR_DOMAIN_DISK_TYPE_NETWORK:
|
||||
protocol = virXMLPropString(cur, "protocol");
|
||||
if (protocol == NULL) {
|
||||
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
"%s", _("missing protocol type"));
|
||||
goto error;
|
||||
}
|
||||
def->protocol = virDomainDiskProtocolTypeFromString(protocol);
|
||||
if (def->protocol < 0) {
|
||||
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("unknown protocol type '%s'"),
|
||||
protocol);
|
||||
goto error;
|
||||
}
|
||||
source = virXMLPropString(cur, "name");
|
||||
host = cur->children;
|
||||
while (host != NULL) {
|
||||
if (host->type == XML_ELEMENT_NODE &&
|
||||
xmlStrEqual(host->name, BAD_CAST "host")) {
|
||||
if (VIR_REALLOC_N(hosts, nhosts + 1) < 0) {
|
||||
virReportOOMError();
|
||||
goto error;
|
||||
}
|
||||
hosts[nhosts].name = NULL;
|
||||
hosts[nhosts].port = NULL;
|
||||
nhosts++;
|
||||
|
||||
hosts[nhosts - 1].name = virXMLPropString(host, "name");
|
||||
if (!hosts[nhosts - 1].name) {
|
||||
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
"%s", _("missing name for host"));
|
||||
goto error;
|
||||
}
|
||||
hosts[nhosts - 1].port = virXMLPropString(host, "port");
|
||||
if (!hosts[nhosts - 1].port) {
|
||||
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
"%s", _("missing port for host"));
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
host = host->next;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("unexpected disk type %s"),
|
||||
@ -1685,7 +1738,7 @@ virDomainDiskDefParseXML(virCapsPtr caps,
|
||||
|
||||
/* Only CDROM and Floppy devices are allowed missing source path
|
||||
* to indicate no media present */
|
||||
if (source == NULL &&
|
||||
if (source == NULL && hosts == NULL &&
|
||||
def->device != VIR_DOMAIN_DISK_DEVICE_CDROM &&
|
||||
def->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
|
||||
virDomainReportError(VIR_ERR_NO_SOURCE,
|
||||
@ -1791,6 +1844,10 @@ virDomainDiskDefParseXML(virCapsPtr caps,
|
||||
source = NULL;
|
||||
def->dst = target;
|
||||
target = NULL;
|
||||
def->hosts = hosts;
|
||||
hosts = NULL;
|
||||
def->nhosts = nhosts;
|
||||
nhosts = 0;
|
||||
def->driverName = driverName;
|
||||
driverName = NULL;
|
||||
def->driverType = driverType;
|
||||
@ -1819,6 +1876,13 @@ cleanup:
|
||||
VIR_FREE(type);
|
||||
VIR_FREE(target);
|
||||
VIR_FREE(source);
|
||||
while (nhosts > 0) {
|
||||
VIR_FREE(hosts[nhosts - 1].name);
|
||||
VIR_FREE(hosts[nhosts - 1].port);
|
||||
nhosts--;
|
||||
}
|
||||
VIR_FREE(hosts);
|
||||
VIR_FREE(protocol);
|
||||
VIR_FREE(device);
|
||||
VIR_FREE(driverType);
|
||||
VIR_FREE(driverName);
|
||||
@ -5909,7 +5973,7 @@ virDomainDiskDefFormat(virBufferPtr buf,
|
||||
virBufferVSprintf(buf, "/>\n");
|
||||
}
|
||||
|
||||
if (def->src) {
|
||||
if (def->src || def->nhosts > 0) {
|
||||
switch (def->type) {
|
||||
case VIR_DOMAIN_DISK_TYPE_FILE:
|
||||
virBufferEscapeString(buf, " <source file='%s'/>\n",
|
||||
@ -5923,6 +5987,27 @@ virDomainDiskDefFormat(virBufferPtr buf,
|
||||
virBufferEscapeString(buf, " <source dir='%s'/>\n",
|
||||
def->src);
|
||||
break;
|
||||
case VIR_DOMAIN_DISK_TYPE_NETWORK:
|
||||
virBufferVSprintf(buf, " <source protocol='%s'",
|
||||
virDomainDiskProtocolTypeToString(def->protocol));
|
||||
if (def->src) {
|
||||
virBufferEscapeString(buf, " name='%s'", def->src);
|
||||
}
|
||||
if (def->nhosts == 0) {
|
||||
virBufferVSprintf(buf, "/>\n");
|
||||
} else {
|
||||
int i;
|
||||
|
||||
virBufferVSprintf(buf, ">\n");
|
||||
for (i = 0; i < def->nhosts; i++) {
|
||||
virBufferEscapeString(buf, " <host name='%s'",
|
||||
def->hosts[i].name);
|
||||
virBufferEscapeString(buf, " port='%s'/>\n",
|
||||
def->hosts[i].port);
|
||||
}
|
||||
virBufferVSprintf(buf, " </source>\n");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("unexpected disk type %s"),
|
||||
|
@ -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_NETWORK,
|
||||
|
||||
VIR_DOMAIN_DISK_TYPE_LAST
|
||||
};
|
||||
@ -164,6 +165,21 @@ enum virDomainDiskErrorPolicy {
|
||||
VIR_DOMAIN_DISK_ERROR_POLICY_LAST
|
||||
};
|
||||
|
||||
enum virDomainDiskProtocol {
|
||||
VIR_DOMAIN_DISK_PROTOCOL_NBD,
|
||||
VIR_DOMAIN_DISK_PROTOCOL_RBD,
|
||||
VIR_DOMAIN_DISK_PROTOCOL_SHEEPDOG,
|
||||
|
||||
VIR_DOMAIN_DISK_PROTOCOL_LAST
|
||||
};
|
||||
|
||||
typedef struct _virDomainDiskHostDef virDomainDiskHostDef;
|
||||
typedef virDomainDiskHostDef *virDomainDiskHostDefPtr;
|
||||
struct _virDomainDiskHostDef {
|
||||
char *name;
|
||||
char *port;
|
||||
};
|
||||
|
||||
/* Stores the virtual disk configuration */
|
||||
typedef struct _virDomainDiskDef virDomainDiskDef;
|
||||
typedef virDomainDiskDef *virDomainDiskDefPtr;
|
||||
@ -173,6 +189,9 @@ struct _virDomainDiskDef {
|
||||
int bus;
|
||||
char *src;
|
||||
char *dst;
|
||||
int protocol;
|
||||
int nhosts;
|
||||
virDomainDiskHostDefPtr hosts;
|
||||
char *driverName;
|
||||
char *driverType;
|
||||
char *serial;
|
||||
@ -1238,6 +1257,7 @@ VIR_ENUM_DECL(virDomainDiskDevice)
|
||||
VIR_ENUM_DECL(virDomainDiskBus)
|
||||
VIR_ENUM_DECL(virDomainDiskCache)
|
||||
VIR_ENUM_DECL(virDomainDiskErrorPolicy)
|
||||
VIR_ENUM_DECL(virDomainDiskProtocol)
|
||||
VIR_ENUM_DECL(virDomainController)
|
||||
VIR_ENUM_DECL(virDomainControllerModel)
|
||||
VIR_ENUM_DECL(virDomainFS)
|
||||
|
@ -2742,7 +2742,9 @@ qemuBuildDriveStr(virDomainDiskDefPtr disk,
|
||||
break;
|
||||
}
|
||||
|
||||
if (disk->src) {
|
||||
/* disk->src is NULL when we use nbd disks */
|
||||
if (disk->src || (disk->type == VIR_DOMAIN_DISK_TYPE_NETWORK &&
|
||||
disk->protocol == VIR_DOMAIN_DISK_PROTOCOL_NBD)) {
|
||||
if (disk->type == VIR_DOMAIN_DISK_TYPE_DIR) {
|
||||
/* QEMU only supports magic FAT format for now */
|
||||
if (disk->driverType &&
|
||||
@ -2761,6 +2763,31 @@ 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_NETWORK) {
|
||||
switch (disk->protocol) {
|
||||
case VIR_DOMAIN_DISK_PROTOCOL_NBD:
|
||||
if (disk->nhosts != 1) {
|
||||
qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("NBD accepts only one host"));
|
||||
goto error;
|
||||
}
|
||||
virBufferVSprintf(&opt, "file=nbd:%s:%s,",
|
||||
disk->hosts->name, disk->hosts->port);
|
||||
break;
|
||||
case VIR_DOMAIN_DISK_PROTOCOL_RBD:
|
||||
/* TODO: set monitor hostnames */
|
||||
virBufferVSprintf(&opt, "file=rbd:%s,", disk->src);
|
||||
break;
|
||||
case VIR_DOMAIN_DISK_PROTOCOL_SHEEPDOG:
|
||||
if (disk->nhosts == 0)
|
||||
virBufferVSprintf(&opt, "file=sheepdog:%s,", disk->src);
|
||||
else
|
||||
/* only one host is supported now */
|
||||
virBufferVSprintf(&opt, "file=sheepdog:%s:%s:%s,",
|
||||
disk->hosts->name, disk->hosts->port,
|
||||
disk->src);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
virBufferVSprintf(&opt, "file=%s,", disk->src);
|
||||
}
|
||||
@ -4660,6 +4687,30 @@ 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_NETWORK) {
|
||||
switch (disk->protocol) {
|
||||
case VIR_DOMAIN_DISK_PROTOCOL_NBD:
|
||||
if (disk->nhosts != 1) {
|
||||
qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("NBD accepts only one host"));
|
||||
goto error;
|
||||
}
|
||||
snprintf(file, PATH_MAX, "nbd:%s:%s,",
|
||||
disk->hosts->name, disk->hosts->port);
|
||||
break;
|
||||
case VIR_DOMAIN_DISK_PROTOCOL_RBD:
|
||||
snprintf(file, PATH_MAX, "rbd:%s,", disk->src);
|
||||
break;
|
||||
case VIR_DOMAIN_DISK_PROTOCOL_SHEEPDOG:
|
||||
if (disk->nhosts == 0)
|
||||
snprintf(file, PATH_MAX, "sheepdog:%s,", disk->src);
|
||||
else
|
||||
/* only one host is supported now */
|
||||
snprintf(file, PATH_MAX, "sheepdog:%s:%s:%s,",
|
||||
disk->hosts->name, disk->hosts->port,
|
||||
disk->src);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
snprintf(file, PATH_MAX, "%s", disk->src);
|
||||
}
|
||||
@ -5677,7 +5728,91 @@ qemuParseCommandLineDisk(virCapsPtr caps,
|
||||
values[i] = NULL;
|
||||
if (STRPREFIX(def->src, "/dev/"))
|
||||
def->type = VIR_DOMAIN_DISK_TYPE_BLOCK;
|
||||
else
|
||||
else if (STRPREFIX(def->src, "nbd:")) {
|
||||
char *host, *port;
|
||||
|
||||
def->type = VIR_DOMAIN_DISK_TYPE_NETWORK;
|
||||
host = def->src + strlen("nbd:");
|
||||
port = strchr(host, ':');
|
||||
if (!port) {
|
||||
def = NULL;
|
||||
qemuReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("cannot parse nbd filename '%s'"), def->src);
|
||||
goto cleanup;
|
||||
}
|
||||
*port++ = '\0';
|
||||
if (VIR_ALLOC(def->hosts) < 0) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
def->nhosts = 1;
|
||||
def->hosts->name = strdup(host);
|
||||
if (!def->hosts->name) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
def->hosts->port = strdup(port);
|
||||
if (!def->hosts->port) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
VIR_FREE(def->src);
|
||||
def->src = NULL;
|
||||
} else if (STRPREFIX(def->src, "rbd:")) {
|
||||
char *p = def->src;
|
||||
|
||||
def->type = VIR_DOMAIN_DISK_TYPE_NETWORK;
|
||||
def->src = strdup(p + strlen("rbd:"));
|
||||
if (!def->src) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
VIR_FREE(p);
|
||||
} else if (STRPREFIX(def->src, "sheepdog:")) {
|
||||
char *p = def->src;
|
||||
char *port, *vdi;
|
||||
|
||||
def->type = VIR_DOMAIN_DISK_TYPE_NETWORK;
|
||||
def->src = strdup(p + strlen("sheepdog:"));
|
||||
if (!def->src) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* 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';
|
||||
if (VIR_ALLOC(def->hosts) < 0) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
def->nhosts = 1;
|
||||
def->hosts->name = def->src;
|
||||
def->hosts->port = strdup(port);
|
||||
if (!def->hosts->port) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
def->src = strdup(vdi);
|
||||
if (!def->src) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
VIR_FREE(p);
|
||||
} else
|
||||
def->type = VIR_DOMAIN_DISK_TYPE_FILE;
|
||||
} else {
|
||||
def->type = VIR_DOMAIN_DISK_TYPE_FILE;
|
||||
@ -6614,7 +6749,19 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
|
||||
|
||||
if (STRPREFIX(val, "/dev/"))
|
||||
disk->type = VIR_DOMAIN_DISK_TYPE_BLOCK;
|
||||
else
|
||||
else if (STRPREFIX(val, "nbd:")) {
|
||||
disk->type = VIR_DOMAIN_DISK_TYPE_NETWORK;
|
||||
disk->protocol = VIR_DOMAIN_DISK_PROTOCOL_NBD;
|
||||
val += strlen("nbd:");
|
||||
} else if (STRPREFIX(val, "rbd:")) {
|
||||
disk->type = VIR_DOMAIN_DISK_TYPE_NETWORK;
|
||||
disk->protocol = VIR_DOMAIN_DISK_PROTOCOL_RBD;
|
||||
val += strlen("rbd:");
|
||||
} else if (STRPREFIX(val, "sheepdog:")) {
|
||||
disk->type = VIR_DOMAIN_DISK_TYPE_NETWORK;
|
||||
disk->protocol = VIR_DOMAIN_DISK_PROTOCOL_SHEEPDOG;
|
||||
val += strlen("sheepdog:");
|
||||
} else
|
||||
disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
|
||||
if (STREQ(arg, "-cdrom")) {
|
||||
disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
|
||||
@ -6634,7 +6781,73 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
|
||||
disk->dst = strdup(arg + 1);
|
||||
}
|
||||
disk->src = strdup(val);
|
||||
if (!disk->src ||
|
||||
|
||||
if (disk->type == VIR_DOMAIN_DISK_TYPE_NETWORK) {
|
||||
char *host, *port;
|
||||
|
||||
switch (disk->protocol) {
|
||||
case VIR_DOMAIN_DISK_PROTOCOL_NBD:
|
||||
host = disk->src;
|
||||
port = strchr(host, ':');
|
||||
if (!port) {
|
||||
def = NULL;
|
||||
qemuReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("cannot parse nbd filename '%s'"), disk->src);
|
||||
goto error;
|
||||
}
|
||||
*port++ = '\0';
|
||||
if (VIR_ALLOC(disk->hosts) < 0) {
|
||||
virReportOOMError();
|
||||
goto error;
|
||||
}
|
||||
disk->nhosts = 1;
|
||||
disk->hosts->name = host;
|
||||
disk->hosts->port = strdup(port);
|
||||
if (!disk->hosts->port) {
|
||||
virReportOOMError();
|
||||
goto error;
|
||||
}
|
||||
disk->src = NULL;
|
||||
break;
|
||||
case VIR_DOMAIN_DISK_PROTOCOL_RBD:
|
||||
/* TODO: set monitor hostnames */
|
||||
break;
|
||||
case VIR_DOMAIN_DISK_PROTOCOL_SHEEPDOG:
|
||||
/* disk->src must be [vdiname] or [host]:[port]:[vdiname] */
|
||||
port = strchr(disk->src, ':');
|
||||
if (port) {
|
||||
char *vdi;
|
||||
|
||||
*port++ = '\0';
|
||||
vdi = strchr(port, ':');
|
||||
if (!vdi) {
|
||||
qemuReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("cannot parse sheepdog filename '%s'"), val);
|
||||
goto error;
|
||||
}
|
||||
*vdi++ = '\0';
|
||||
if (VIR_ALLOC(disk->hosts) < 0) {
|
||||
virReportOOMError();
|
||||
goto error;
|
||||
}
|
||||
disk->nhosts = 1;
|
||||
disk->hosts->name = disk->src;
|
||||
disk->hosts->port = strdup(port);
|
||||
if (!disk->hosts->port) {
|
||||
virReportOOMError();
|
||||
goto error;
|
||||
}
|
||||
disk->src = strdup(vdi);
|
||||
if (!disk->src) {
|
||||
virReportOOMError();
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(disk->src || disk->nhosts > 0) ||
|
||||
!disk->dst) {
|
||||
virDomainDiskDefFree(disk);
|
||||
goto no_memory;
|
||||
|
Loading…
x
Reference in New Issue
Block a user