提交 85400fb9 编写于 作者: J Josh Durgin 提交者: Eric Blake

qemu: Add RBD support and some network disk fixes

Changes common to all network disks:
-Make source name optional in the domain schema, since NBD doesn't use it
-Add a hostName type to the domain schema, and use it instead of genericName, which doesn't include .
-Don't leak host names or ports
-Set the source protocol in qemuParseCommandline
Signed-off-by: NJosh Durgin <joshd@hq.newdream.net>
上级 036ad505
...@@ -139,6 +139,7 @@ Patches have also been contributed by: ...@@ -139,6 +139,7 @@ Patches have also been contributed by:
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> MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp>
Josh Durgin <joshd@hq.newdream.net>
[....send patches to get your name here....] [....send patches to get your name here....]
......
...@@ -626,11 +626,13 @@ ...@@ -626,11 +626,13 @@
<value>sheepdog</value> <value>sheepdog</value>
</choice> </choice>
</attribute> </attribute>
<attribute name="name"/> <optional>
<attribute name="name"/>
</optional>
<zeroOrMore> <zeroOrMore>
<element name="host"> <element name="host">
<attribute name="name"> <attribute name="name">
<ref name="genericName"/> <ref name="hostName"/>
</attribute> </attribute>
<attribute name="port"> <attribute name="port">
<ref name="unsignedInt"/> <ref name="unsignedInt"/>
...@@ -2024,6 +2026,11 @@ ...@@ -2024,6 +2026,11 @@
<param name="minInclusive">1</param> <param name="minInclusive">1</param>
</data> </data>
</define> </define>
<define name="hostName">
<data type="string">
<param name="pattern">[a-zA-Z0-9\.\-]+</param>
</data>
</define>
<define name="PortNumber"> <define name="PortNumber">
<data type="short"> <data type="short">
<param name="minInclusive">-1</param> <param name="minInclusive">-1</param>
......
...@@ -509,21 +509,34 @@ void virDomainInputDefFree(virDomainInputDefPtr def) ...@@ -509,21 +509,34 @@ void virDomainInputDefFree(virDomainInputDefPtr def)
void virDomainDiskDefFree(virDomainDiskDefPtr def) void virDomainDiskDefFree(virDomainDiskDefPtr def)
{ {
unsigned int i;
if (!def) if (!def)
return; return;
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);
virStorageEncryptionFree(def->encryption); virStorageEncryptionFree(def->encryption);
virDomainDeviceInfoClear(&def->info); virDomainDeviceInfoClear(&def->info);
for (i = 0 ; i < def->nhosts ; i++)
virDomainDiskHostDefFree(&def->hosts[i]);
VIR_FREE(def); VIR_FREE(def);
} }
void virDomainDiskHostDefFree(virDomainDiskHostDefPtr def)
{
if (!def)
return;
VIR_FREE(def->name);
VIR_FREE(def->port);
}
void virDomainControllerDefFree(virDomainControllerDefPtr def) void virDomainControllerDefFree(virDomainControllerDefPtr def)
{ {
if (!def) if (!def)
...@@ -1644,7 +1657,12 @@ virDomainDiskDefParseXML(virCapsPtr caps, ...@@ -1644,7 +1657,12 @@ virDomainDiskDefParseXML(virCapsPtr caps,
protocol); protocol);
goto error; goto error;
} }
source = virXMLPropString(cur, "name"); if (!(source = virXMLPropString(cur, "name")) &&
def->protocol != VIR_DOMAIN_DISK_PROTOCOL_NBD) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
_("missing name for disk source"));
goto error;
}
host = cur->children; host = cur->children;
while (host != NULL) { while (host != NULL) {
if (host->type == XML_ELEMENT_NODE && if (host->type == XML_ELEMENT_NODE &&
...@@ -1877,8 +1895,7 @@ cleanup: ...@@ -1877,8 +1895,7 @@ cleanup:
VIR_FREE(target); VIR_FREE(target);
VIR_FREE(source); VIR_FREE(source);
while (nhosts > 0) { while (nhosts > 0) {
VIR_FREE(hosts[nhosts - 1].name); virDomainDiskHostDefFree(&hosts[nhosts - 1]);
VIR_FREE(hosts[nhosts - 1].port);
nhosts--; nhosts--;
} }
VIR_FREE(hosts); VIR_FREE(hosts);
......
...@@ -1071,6 +1071,7 @@ virDomainObjPtr virDomainFindByName(const virDomainObjListPtr doms, ...@@ -1071,6 +1071,7 @@ virDomainObjPtr virDomainFindByName(const virDomainObjListPtr doms,
void virDomainGraphicsDefFree(virDomainGraphicsDefPtr def); void virDomainGraphicsDefFree(virDomainGraphicsDefPtr def);
void virDomainInputDefFree(virDomainInputDefPtr def); void virDomainInputDefFree(virDomainInputDefPtr def);
void virDomainDiskDefFree(virDomainDiskDefPtr def); void virDomainDiskDefFree(virDomainDiskDefPtr def);
void virDomainDiskHostDefFree(virDomainDiskHostDefPtr def);
void virDomainControllerDefFree(virDomainControllerDefPtr def); void virDomainControllerDefFree(virDomainControllerDefPtr def);
void virDomainFSDefFree(virDomainFSDefPtr def); void virDomainFSDefFree(virDomainFSDefPtr def);
void virDomainNetDefFree(virDomainNetDefPtr def); void virDomainNetDefFree(virDomainNetDefPtr def);
......
...@@ -4026,6 +4026,8 @@ qemudBuildCommandLine(virConnectPtr conn, ...@@ -4026,6 +4026,8 @@ qemudBuildCommandLine(virConnectPtr conn,
int last_good_net = -1; int last_good_net = -1;
bool hasHwVirt = false; bool hasHwVirt = false;
virCommandPtr cmd; virCommandPtr cmd;
bool has_rbd_hosts = false;
virBuffer rbd_hosts = VIR_BUFFER_INITIALIZER;
uname_normalize(&ut); uname_normalize(&ut);
...@@ -4566,6 +4568,7 @@ qemudBuildCommandLine(virConnectPtr conn, ...@@ -4566,6 +4568,7 @@ qemudBuildCommandLine(virConnectPtr conn,
int bootable = 0; int bootable = 0;
virDomainDiskDefPtr disk = def->disks[i]; virDomainDiskDefPtr disk = def->disks[i];
int withDeviceArg = 0; int withDeviceArg = 0;
int j;
/* Unless we have -device, then USB disks need special /* Unless we have -device, then USB disks need special
handling */ handling */
...@@ -4615,6 +4618,27 @@ qemudBuildCommandLine(virConnectPtr conn, ...@@ -4615,6 +4618,27 @@ qemudBuildCommandLine(virConnectPtr conn,
virCommandAddArg(cmd, optstr); virCommandAddArg(cmd, optstr);
VIR_FREE(optstr); VIR_FREE(optstr);
if (disk->type == VIR_DOMAIN_DISK_TYPE_NETWORK &&
disk->protocol == VIR_DOMAIN_DISK_PROTOCOL_RBD) {
for (j = 0 ; j < disk->nhosts ; j++) {
if (!has_rbd_hosts) {
virBufferAddLit(&rbd_hosts, "-m ");
has_rbd_hosts = true;
} else {
virBufferAddLit(&rbd_hosts, ",");
}
virDomainDiskHostDefPtr host = &disk->hosts[j];
if (host->port) {
virBufferVSprintf(&rbd_hosts, "%s:%s",
host->name,
host->port);
} else {
virBufferVSprintf(&rbd_hosts, "%s",
host->name);
}
}
}
if (withDeviceArg) { if (withDeviceArg) {
if (disk->bus == VIR_DOMAIN_DISK_BUS_FDC) { if (disk->bus == VIR_DOMAIN_DISK_BUS_FDC) {
virCommandAddArg(cmd, "-global"); virCommandAddArg(cmd, "-global");
...@@ -4637,6 +4661,7 @@ qemudBuildCommandLine(virConnectPtr conn, ...@@ -4637,6 +4661,7 @@ qemudBuildCommandLine(virConnectPtr conn,
char dev[NAME_MAX]; char dev[NAME_MAX];
char file[PATH_MAX]; char file[PATH_MAX];
virDomainDiskDefPtr disk = def->disks[i]; virDomainDiskDefPtr disk = def->disks[i];
int j;
if (disk->bus == VIR_DOMAIN_DISK_BUS_USB) { if (disk->bus == VIR_DOMAIN_DISK_BUS_USB) {
if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK) { if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
...@@ -4700,6 +4725,23 @@ qemudBuildCommandLine(virConnectPtr conn, ...@@ -4700,6 +4725,23 @@ qemudBuildCommandLine(virConnectPtr conn,
break; break;
case VIR_DOMAIN_DISK_PROTOCOL_RBD: case VIR_DOMAIN_DISK_PROTOCOL_RBD:
snprintf(file, PATH_MAX, "rbd:%s,", disk->src); snprintf(file, PATH_MAX, "rbd:%s,", disk->src);
for (j = 0 ; j < disk->nhosts ; j++) {
if (!has_rbd_hosts) {
virBufferAddLit(&rbd_hosts, "-m ");
has_rbd_hosts = true;
} else {
virBufferAddLit(&rbd_hosts, ",");
}
virDomainDiskHostDefPtr host = &disk->hosts[j];
if (host->port) {
virBufferVSprintf(&rbd_hosts, "%s:%s",
host->name,
host->port);
} else {
virBufferVSprintf(&rbd_hosts, "%s",
host->name);
}
}
break; break;
case VIR_DOMAIN_DISK_PROTOCOL_SHEEPDOG: case VIR_DOMAIN_DISK_PROTOCOL_SHEEPDOG:
if (disk->nhosts == 0) if (disk->nhosts == 0)
...@@ -4719,6 +4761,13 @@ qemudBuildCommandLine(virConnectPtr conn, ...@@ -4719,6 +4761,13 @@ qemudBuildCommandLine(virConnectPtr conn,
} }
} }
if (virBufferError(&rbd_hosts)) {
virBufferFreeAndReset(&rbd_hosts);
goto no_memory;
}
if (has_rbd_hosts)
virCommandAddEnvPair(cmd, "CEPH_ARGS", virBufferContentAndReset(&rbd_hosts));
if (qemuCmdFlags & QEMUD_CMD_FLAG_FSDEV) { if (qemuCmdFlags & QEMUD_CMD_FLAG_FSDEV) {
for (i = 0 ; i < def->nfss ; i++) { for (i = 0 ; i < def->nfss ; i++) {
char *optstr; char *optstr;
...@@ -5488,6 +5537,7 @@ static int qemuStringToArgvEnv(const char *args, ...@@ -5488,6 +5537,7 @@ static int qemuStringToArgvEnv(const char *args,
int envend; int envend;
int i; int i;
const char *curr = args; const char *curr = args;
const char *start;
const char **progenv = NULL; const char **progenv = NULL;
const char **progargv = NULL; const char **progargv = NULL;
...@@ -5495,14 +5545,22 @@ static int qemuStringToArgvEnv(const char *args, ...@@ -5495,14 +5545,22 @@ static int qemuStringToArgvEnv(const char *args,
while (curr && *curr != '\0') { while (curr && *curr != '\0') {
char *arg; char *arg;
const char *next; const char *next;
if (*curr == '\'') {
curr++; start = curr;
next = strchr(curr, '\''); /* accept a space in CEPH_ARGS */
} else if (*curr == '"') { if (STRPREFIX(curr, "CEPH_ARGS=-m ")) {
curr++; start += strlen("CEPH_ARGS=-m ");
next = strchr(curr, '"'); }
if (*start == '\'') {
if (start == curr)
curr++;
next = strchr(start + 1, '\'');
} else if (*start == '"') {
if (start == curr)
curr++;
next = strchr(start + 1, '"');
} else { } else {
next = strchr(curr, ' '); next = strchr(start, ' ');
} }
if (!next) if (!next)
next = strchr(curr, '\n'); next = strchr(curr, '\n');
...@@ -5732,6 +5790,7 @@ qemuParseCommandLineDisk(virCapsPtr caps, ...@@ -5732,6 +5790,7 @@ qemuParseCommandLineDisk(virCapsPtr caps,
char *host, *port; char *host, *port;
def->type = VIR_DOMAIN_DISK_TYPE_NETWORK; def->type = VIR_DOMAIN_DISK_TYPE_NETWORK;
def->protocol = VIR_DOMAIN_DISK_PROTOCOL_NBD;
host = def->src + strlen("nbd:"); host = def->src + strlen("nbd:");
port = strchr(host, ':'); port = strchr(host, ':');
if (!port) { if (!port) {
...@@ -5763,6 +5822,7 @@ qemuParseCommandLineDisk(virCapsPtr caps, ...@@ -5763,6 +5822,7 @@ qemuParseCommandLineDisk(virCapsPtr caps,
char *p = def->src; char *p = def->src;
def->type = VIR_DOMAIN_DISK_TYPE_NETWORK; def->type = VIR_DOMAIN_DISK_TYPE_NETWORK;
def->protocol = VIR_DOMAIN_DISK_PROTOCOL_RBD;
def->src = strdup(p + strlen("rbd:")); def->src = strdup(p + strlen("rbd:"));
if (!def->src) { if (!def->src) {
virReportOOMError(); virReportOOMError();
...@@ -5775,6 +5835,7 @@ qemuParseCommandLineDisk(virCapsPtr caps, ...@@ -5775,6 +5835,7 @@ qemuParseCommandLineDisk(virCapsPtr caps,
char *port, *vdi; char *port, *vdi;
def->type = VIR_DOMAIN_DISK_TYPE_NETWORK; def->type = VIR_DOMAIN_DISK_TYPE_NETWORK;
def->protocol = VIR_DOMAIN_DISK_PROTOCOL_SHEEPDOG;
def->src = strdup(p + strlen("sheepdog:")); def->src = strdup(p + strlen("sheepdog:"));
if (!def->src) { if (!def->src) {
virReportOOMError(); virReportOOMError();
...@@ -5890,7 +5951,8 @@ qemuParseCommandLineDisk(virCapsPtr caps, ...@@ -5890,7 +5951,8 @@ qemuParseCommandLineDisk(virCapsPtr caps,
} }
if (!def->src && if (!def->src &&
def->device == VIR_DOMAIN_DISK_DEVICE_DISK) { def->device == VIR_DOMAIN_DISK_DEVICE_DISK &&
def->type != VIR_DOMAIN_DISK_TYPE_NETWORK) {
qemuReportError(VIR_ERR_INTERNAL_ERROR, qemuReportError(VIR_ERR_INTERNAL_ERROR,
_("missing file parameter in drive '%s'"), val); _("missing file parameter in drive '%s'"), val);
virDomainDiskDefFree(def); virDomainDiskDefFree(def);
...@@ -6810,7 +6872,7 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps, ...@@ -6810,7 +6872,7 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
disk->src = NULL; disk->src = NULL;
break; break;
case VIR_DOMAIN_DISK_PROTOCOL_RBD: case VIR_DOMAIN_DISK_PROTOCOL_RBD:
/* TODO: set monitor hostnames */ /* handled later since the hosts for all disks are in CEPH_ARGS */
break; break;
case VIR_DOMAIN_DISK_PROTOCOL_SHEEPDOG: case VIR_DOMAIN_DISK_PROTOCOL_SHEEPDOG:
/* disk->src must be [vdiname] or [host]:[port]:[vdiname] */ /* disk->src must be [vdiname] or [host]:[port]:[vdiname] */
...@@ -7137,6 +7199,69 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps, ...@@ -7137,6 +7199,69 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
} }
#undef WANT_VALUE #undef WANT_VALUE
if (def->ndisks > 0) {
const char *ceph_args = qemuFindEnv(progenv, "CEPH_ARGS");
if (ceph_args) {
char *hosts, *port, *saveptr, *token;
virDomainDiskDefPtr first_rbd_disk = NULL;
for (i = 0 ; i < def->ndisks ; i++) {
virDomainDiskDefPtr disk = def->disks[i];
if (disk->type == VIR_DOMAIN_DISK_TYPE_NETWORK &&
disk->protocol == VIR_DOMAIN_DISK_PROTOCOL_RBD) {
first_rbd_disk = disk;
break;
}
}
if (!first_rbd_disk) {
qemuReportError(VIR_ERR_INTERNAL_ERROR,
_("CEPH_ARGS was set without an rbd disk"));
goto error;
}
/* CEPH_ARGS should be: -m host1[:port1][,host2[:port2]]... */
if (!STRPREFIX(ceph_args, "-m ")) {
qemuReportError(VIR_ERR_INTERNAL_ERROR,
_("could not parse CEPH_ARGS '%s'"), ceph_args);
goto error;
}
hosts = strdup(strchr(ceph_args, ' ') + 1);
if (!hosts)
goto no_memory;
first_rbd_disk->nhosts = 0;
token = strtok_r(hosts, ",", &saveptr);
while (token != NULL) {
if (VIR_REALLOC_N(first_rbd_disk->hosts, first_rbd_disk->nhosts + 1) < 0) {
VIR_FREE(hosts);
goto no_memory;
}
port = strchr(token, ':');
if (port) {
*port++ = '\0';
port = strdup(port);
if (!port) {
VIR_FREE(hosts);
goto no_memory;
}
}
first_rbd_disk->hosts[first_rbd_disk->nhosts].port = port;
first_rbd_disk->hosts[first_rbd_disk->nhosts].name = strdup(token);
if (!first_rbd_disk->hosts[first_rbd_disk->nhosts].name) {
VIR_FREE(hosts);
goto no_memory;
}
first_rbd_disk->nhosts++;
token = strtok_r(NULL, ",", &saveptr);
}
VIR_FREE(hosts);
if (first_rbd_disk->nhosts == 0) {
qemuReportError(VIR_ERR_INTERNAL_ERROR,
_("found no rbd hosts in CEPH_ARGS '%s'"), ceph_args);
goto error;
}
}
}
if (!nographics && def->ngraphics == 0) { if (!nographics && def->ngraphics == 0) {
virDomainGraphicsDefPtr sdl; virDomainGraphicsDefPtr sdl;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册