mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-07 17:28:15 +00:00
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: Josh Durgin <joshd@hq.newdream.net>
This commit is contained in:
parent
036ad5052b
commit
85400fb992
1
AUTHORS
1
AUTHORS
@ -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 @@
|
|||||||
<value>sheepdog</value>
|
<value>sheepdog</value>
|
||||||
</choice>
|
</choice>
|
||||||
</attribute>
|
</attribute>
|
||||||
|
<optional>
|
||||||
<attribute name="name"/>
|
<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 @@
|
|||||||
<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)
|
|||||||
|
|
||||||
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,
|
|||||||
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:
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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,
|
|||||||
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,
|
|||||||
while (curr && *curr != '\0') {
|
while (curr && *curr != '\0') {
|
||||||
char *arg;
|
char *arg;
|
||||||
const char *next;
|
const char *next;
|
||||||
if (*curr == '\'') {
|
|
||||||
|
start = curr;
|
||||||
|
/* accept a space in CEPH_ARGS */
|
||||||
|
if (STRPREFIX(curr, "CEPH_ARGS=-m ")) {
|
||||||
|
start += strlen("CEPH_ARGS=-m ");
|
||||||
|
}
|
||||||
|
if (*start == '\'') {
|
||||||
|
if (start == curr)
|
||||||
curr++;
|
curr++;
|
||||||
next = strchr(curr, '\'');
|
next = strchr(start + 1, '\'');
|
||||||
} else if (*curr == '"') {
|
} else if (*start == '"') {
|
||||||
|
if (start == curr)
|
||||||
curr++;
|
curr++;
|
||||||
next = strchr(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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user