mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-08 12:41:29 +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>
|
Wen Congyang <wency@cn.fujitsu.com>
|
||||||
Hu Tao <hutao@cn.fujitsu.com>
|
Hu Tao <hutao@cn.fujitsu.com>
|
||||||
Laurent Léonard <laurent@open-minds.org>
|
Laurent Léonard <laurent@open-minds.org>
|
||||||
|
MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp>
|
||||||
|
|
||||||
[....send patches to get your name here....]
|
[....send patches to get your name here....]
|
||||||
|
|
||||||
|
@ -612,6 +612,37 @@
|
|||||||
<ref name="diskspec"/>
|
<ref name="diskspec"/>
|
||||||
</interleave>
|
</interleave>
|
||||||
</group>
|
</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"/>
|
<ref name="diskspec"/>
|
||||||
</choice>
|
</choice>
|
||||||
</element>
|
</element>
|
||||||
|
@ -112,7 +112,8 @@ VIR_ENUM_IMPL(virDomainDeviceAddress, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST,
|
|||||||
VIR_ENUM_IMPL(virDomainDisk, VIR_DOMAIN_DISK_TYPE_LAST,
|
VIR_ENUM_IMPL(virDomainDisk, VIR_DOMAIN_DISK_TYPE_LAST,
|
||||||
"block",
|
"block",
|
||||||
"file",
|
"file",
|
||||||
"dir")
|
"dir",
|
||||||
|
"network")
|
||||||
|
|
||||||
VIR_ENUM_IMPL(virDomainDiskDevice, VIR_DOMAIN_DISK_DEVICE_LAST,
|
VIR_ENUM_IMPL(virDomainDiskDevice, VIR_DOMAIN_DISK_DEVICE_LAST,
|
||||||
"disk",
|
"disk",
|
||||||
@ -141,6 +142,11 @@ VIR_ENUM_IMPL(virDomainDiskErrorPolicy, VIR_DOMAIN_DISK_ERROR_POLICY_LAST,
|
|||||||
"ignore",
|
"ignore",
|
||||||
"enospace")
|
"enospace")
|
||||||
|
|
||||||
|
VIR_ENUM_IMPL(virDomainDiskProtocol, VIR_DOMAIN_DISK_PROTOCOL_LAST,
|
||||||
|
"nbd",
|
||||||
|
"rbd",
|
||||||
|
"sheepdog")
|
||||||
|
|
||||||
VIR_ENUM_IMPL(virDomainController, VIR_DOMAIN_CONTROLLER_TYPE_LAST,
|
VIR_ENUM_IMPL(virDomainController, VIR_DOMAIN_CONTROLLER_TYPE_LAST,
|
||||||
"ide",
|
"ide",
|
||||||
"fdc",
|
"fdc",
|
||||||
@ -508,6 +514,7 @@ void virDomainDiskDefFree(virDomainDiskDefPtr def)
|
|||||||
|
|
||||||
VIR_FREE(def->serial);
|
VIR_FREE(def->serial);
|
||||||
VIR_FREE(def->src);
|
VIR_FREE(def->src);
|
||||||
|
VIR_FREE(def->hosts);
|
||||||
VIR_FREE(def->dst);
|
VIR_FREE(def->dst);
|
||||||
VIR_FREE(def->driverName);
|
VIR_FREE(def->driverName);
|
||||||
VIR_FREE(def->driverType);
|
VIR_FREE(def->driverType);
|
||||||
@ -1574,13 +1581,16 @@ virDomainDiskDefParseXML(virCapsPtr caps,
|
|||||||
xmlNodePtr node,
|
xmlNodePtr node,
|
||||||
int flags) {
|
int flags) {
|
||||||
virDomainDiskDefPtr def;
|
virDomainDiskDefPtr def;
|
||||||
xmlNodePtr cur;
|
xmlNodePtr cur, host;
|
||||||
char *type = NULL;
|
char *type = NULL;
|
||||||
char *device = NULL;
|
char *device = NULL;
|
||||||
char *driverName = NULL;
|
char *driverName = NULL;
|
||||||
char *driverType = NULL;
|
char *driverType = NULL;
|
||||||
char *source = NULL;
|
char *source = NULL;
|
||||||
char *target = NULL;
|
char *target = NULL;
|
||||||
|
char *protocol = NULL;
|
||||||
|
virDomainDiskHostDefPtr hosts = NULL;
|
||||||
|
int nhosts = 0;
|
||||||
char *bus = NULL;
|
char *bus = NULL;
|
||||||
char *cachetag = NULL;
|
char *cachetag = NULL;
|
||||||
char *error_policy = NULL;
|
char *error_policy = NULL;
|
||||||
@ -1607,7 +1617,7 @@ virDomainDiskDefParseXML(virCapsPtr caps,
|
|||||||
cur = node->children;
|
cur = node->children;
|
||||||
while (cur != NULL) {
|
while (cur != NULL) {
|
||||||
if (cur->type == XML_ELEMENT_NODE) {
|
if (cur->type == XML_ELEMENT_NODE) {
|
||||||
if ((source == NULL) &&
|
if ((source == NULL && hosts == NULL) &&
|
||||||
(xmlStrEqual(cur->name, BAD_CAST "source"))) {
|
(xmlStrEqual(cur->name, BAD_CAST "source"))) {
|
||||||
|
|
||||||
switch (def->type) {
|
switch (def->type) {
|
||||||
@ -1620,6 +1630,49 @@ virDomainDiskDefParseXML(virCapsPtr caps,
|
|||||||
case VIR_DOMAIN_DISK_TYPE_DIR:
|
case VIR_DOMAIN_DISK_TYPE_DIR:
|
||||||
source = virXMLPropString(cur, "dir");
|
source = virXMLPropString(cur, "dir");
|
||||||
break;
|
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:
|
default:
|
||||||
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
|
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
_("unexpected disk type %s"),
|
_("unexpected disk type %s"),
|
||||||
@ -1685,7 +1738,7 @@ virDomainDiskDefParseXML(virCapsPtr caps,
|
|||||||
|
|
||||||
/* Only CDROM and Floppy devices are allowed missing source path
|
/* Only CDROM and Floppy devices are allowed missing source path
|
||||||
* to indicate no media present */
|
* 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_CDROM &&
|
||||||
def->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
|
def->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
|
||||||
virDomainReportError(VIR_ERR_NO_SOURCE,
|
virDomainReportError(VIR_ERR_NO_SOURCE,
|
||||||
@ -1791,6 +1844,10 @@ virDomainDiskDefParseXML(virCapsPtr caps,
|
|||||||
source = NULL;
|
source = NULL;
|
||||||
def->dst = target;
|
def->dst = target;
|
||||||
target = NULL;
|
target = NULL;
|
||||||
|
def->hosts = hosts;
|
||||||
|
hosts = NULL;
|
||||||
|
def->nhosts = nhosts;
|
||||||
|
nhosts = 0;
|
||||||
def->driverName = driverName;
|
def->driverName = driverName;
|
||||||
driverName = NULL;
|
driverName = NULL;
|
||||||
def->driverType = driverType;
|
def->driverType = driverType;
|
||||||
@ -1819,6 +1876,13 @@ cleanup:
|
|||||||
VIR_FREE(type);
|
VIR_FREE(type);
|
||||||
VIR_FREE(target);
|
VIR_FREE(target);
|
||||||
VIR_FREE(source);
|
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(device);
|
||||||
VIR_FREE(driverType);
|
VIR_FREE(driverType);
|
||||||
VIR_FREE(driverName);
|
VIR_FREE(driverName);
|
||||||
@ -5909,7 +5973,7 @@ virDomainDiskDefFormat(virBufferPtr buf,
|
|||||||
virBufferVSprintf(buf, "/>\n");
|
virBufferVSprintf(buf, "/>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (def->src) {
|
if (def->src || def->nhosts > 0) {
|
||||||
switch (def->type) {
|
switch (def->type) {
|
||||||
case VIR_DOMAIN_DISK_TYPE_FILE:
|
case VIR_DOMAIN_DISK_TYPE_FILE:
|
||||||
virBufferEscapeString(buf, " <source file='%s'/>\n",
|
virBufferEscapeString(buf, " <source file='%s'/>\n",
|
||||||
@ -5923,6 +5987,27 @@ virDomainDiskDefFormat(virBufferPtr buf,
|
|||||||
virBufferEscapeString(buf, " <source dir='%s'/>\n",
|
virBufferEscapeString(buf, " <source dir='%s'/>\n",
|
||||||
def->src);
|
def->src);
|
||||||
break;
|
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:
|
default:
|
||||||
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
|
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
_("unexpected disk type %s"),
|
_("unexpected disk type %s"),
|
||||||
|
@ -120,6 +120,7 @@ enum virDomainDiskType {
|
|||||||
VIR_DOMAIN_DISK_TYPE_BLOCK,
|
VIR_DOMAIN_DISK_TYPE_BLOCK,
|
||||||
VIR_DOMAIN_DISK_TYPE_FILE,
|
VIR_DOMAIN_DISK_TYPE_FILE,
|
||||||
VIR_DOMAIN_DISK_TYPE_DIR,
|
VIR_DOMAIN_DISK_TYPE_DIR,
|
||||||
|
VIR_DOMAIN_DISK_TYPE_NETWORK,
|
||||||
|
|
||||||
VIR_DOMAIN_DISK_TYPE_LAST
|
VIR_DOMAIN_DISK_TYPE_LAST
|
||||||
};
|
};
|
||||||
@ -164,6 +165,21 @@ enum virDomainDiskErrorPolicy {
|
|||||||
VIR_DOMAIN_DISK_ERROR_POLICY_LAST
|
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 */
|
/* Stores the virtual disk configuration */
|
||||||
typedef struct _virDomainDiskDef virDomainDiskDef;
|
typedef struct _virDomainDiskDef virDomainDiskDef;
|
||||||
typedef virDomainDiskDef *virDomainDiskDefPtr;
|
typedef virDomainDiskDef *virDomainDiskDefPtr;
|
||||||
@ -173,6 +189,9 @@ struct _virDomainDiskDef {
|
|||||||
int bus;
|
int bus;
|
||||||
char *src;
|
char *src;
|
||||||
char *dst;
|
char *dst;
|
||||||
|
int protocol;
|
||||||
|
int nhosts;
|
||||||
|
virDomainDiskHostDefPtr hosts;
|
||||||
char *driverName;
|
char *driverName;
|
||||||
char *driverType;
|
char *driverType;
|
||||||
char *serial;
|
char *serial;
|
||||||
@ -1238,6 +1257,7 @@ VIR_ENUM_DECL(virDomainDiskDevice)
|
|||||||
VIR_ENUM_DECL(virDomainDiskBus)
|
VIR_ENUM_DECL(virDomainDiskBus)
|
||||||
VIR_ENUM_DECL(virDomainDiskCache)
|
VIR_ENUM_DECL(virDomainDiskCache)
|
||||||
VIR_ENUM_DECL(virDomainDiskErrorPolicy)
|
VIR_ENUM_DECL(virDomainDiskErrorPolicy)
|
||||||
|
VIR_ENUM_DECL(virDomainDiskProtocol)
|
||||||
VIR_ENUM_DECL(virDomainController)
|
VIR_ENUM_DECL(virDomainController)
|
||||||
VIR_ENUM_DECL(virDomainControllerModel)
|
VIR_ENUM_DECL(virDomainControllerModel)
|
||||||
VIR_ENUM_DECL(virDomainFS)
|
VIR_ENUM_DECL(virDomainFS)
|
||||||
|
@ -2742,7 +2742,9 @@ qemuBuildDriveStr(virDomainDiskDefPtr disk,
|
|||||||
break;
|
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) {
|
if (disk->type == VIR_DOMAIN_DISK_TYPE_DIR) {
|
||||||
/* QEMU only supports magic FAT format for now */
|
/* QEMU only supports magic FAT format for now */
|
||||||
if (disk->driverType &&
|
if (disk->driverType &&
|
||||||
@ -2761,6 +2763,31 @@ qemuBuildDriveStr(virDomainDiskDefPtr disk,
|
|||||||
virBufferVSprintf(&opt, "file=fat:floppy:%s,", disk->src);
|
virBufferVSprintf(&opt, "file=fat:floppy:%s,", disk->src);
|
||||||
else
|
else
|
||||||
virBufferVSprintf(&opt, "file=fat:%s,", disk->src);
|
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 {
|
} else {
|
||||||
virBufferVSprintf(&opt, "file=%s,", disk->src);
|
virBufferVSprintf(&opt, "file=%s,", disk->src);
|
||||||
}
|
}
|
||||||
@ -4660,6 +4687,30 @@ qemudBuildCommandLine(virConnectPtr conn,
|
|||||||
snprintf(file, PATH_MAX, "fat:floppy:%s", disk->src);
|
snprintf(file, PATH_MAX, "fat:floppy:%s", disk->src);
|
||||||
else
|
else
|
||||||
snprintf(file, PATH_MAX, "fat:%s", disk->src);
|
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 {
|
} else {
|
||||||
snprintf(file, PATH_MAX, "%s", disk->src);
|
snprintf(file, PATH_MAX, "%s", disk->src);
|
||||||
}
|
}
|
||||||
@ -5677,7 +5728,91 @@ qemuParseCommandLineDisk(virCapsPtr caps,
|
|||||||
values[i] = NULL;
|
values[i] = NULL;
|
||||||
if (STRPREFIX(def->src, "/dev/"))
|
if (STRPREFIX(def->src, "/dev/"))
|
||||||
def->type = VIR_DOMAIN_DISK_TYPE_BLOCK;
|
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;
|
def->type = VIR_DOMAIN_DISK_TYPE_FILE;
|
||||||
} else {
|
} else {
|
||||||
def->type = VIR_DOMAIN_DISK_TYPE_FILE;
|
def->type = VIR_DOMAIN_DISK_TYPE_FILE;
|
||||||
@ -6614,7 +6749,19 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
|
|||||||
|
|
||||||
if (STRPREFIX(val, "/dev/"))
|
if (STRPREFIX(val, "/dev/"))
|
||||||
disk->type = VIR_DOMAIN_DISK_TYPE_BLOCK;
|
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;
|
disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
|
||||||
if (STREQ(arg, "-cdrom")) {
|
if (STREQ(arg, "-cdrom")) {
|
||||||
disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
|
disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
|
||||||
@ -6634,7 +6781,73 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
|
|||||||
disk->dst = strdup(arg + 1);
|
disk->dst = strdup(arg + 1);
|
||||||
}
|
}
|
||||||
disk->src = strdup(val);
|
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) {
|
!disk->dst) {
|
||||||
virDomainDiskDefFree(disk);
|
virDomainDiskDefFree(disk);
|
||||||
goto no_memory;
|
goto no_memory;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user