mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-24 22:55:23 +00:00
Add API for issuing 'pci_add storage' monitor command
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Add new API qemuMonitorAddPCIDisk() * src/qemu/qemu_driver.c: Convert over to using the new qemuMonitorAddPCIDisk() method, and remove now obsolete qemudEscape() method
This commit is contained in:
parent
3e11f9ff90
commit
85df93399c
@ -3093,83 +3093,6 @@ cleanup:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static char *qemudEscape(const char *in, int shell)
|
|
||||||
{
|
|
||||||
int len = 0;
|
|
||||||
int i, j;
|
|
||||||
char *out;
|
|
||||||
|
|
||||||
/* To pass through the QEMU monitor, we need to use escape
|
|
||||||
sequences: \r, \n, \", \\
|
|
||||||
|
|
||||||
To pass through both QEMU + the shell, we need to escape
|
|
||||||
the single character ' as the five characters '\\''
|
|
||||||
*/
|
|
||||||
|
|
||||||
for (i = 0; in[i] != '\0'; i++) {
|
|
||||||
switch(in[i]) {
|
|
||||||
case '\r':
|
|
||||||
case '\n':
|
|
||||||
case '"':
|
|
||||||
case '\\':
|
|
||||||
len += 2;
|
|
||||||
break;
|
|
||||||
case '\'':
|
|
||||||
if (shell)
|
|
||||||
len += 5;
|
|
||||||
else
|
|
||||||
len += 1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
len += 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (VIR_ALLOC_N(out, len + 1) < 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
for (i = j = 0; in[i] != '\0'; i++) {
|
|
||||||
switch(in[i]) {
|
|
||||||
case '\r':
|
|
||||||
out[j++] = '\\';
|
|
||||||
out[j++] = 'r';
|
|
||||||
break;
|
|
||||||
case '\n':
|
|
||||||
out[j++] = '\\';
|
|
||||||
out[j++] = 'n';
|
|
||||||
break;
|
|
||||||
case '"':
|
|
||||||
case '\\':
|
|
||||||
out[j++] = '\\';
|
|
||||||
out[j++] = in[i];
|
|
||||||
break;
|
|
||||||
case '\'':
|
|
||||||
if (shell) {
|
|
||||||
out[j++] = '\'';
|
|
||||||
out[j++] = '\\';
|
|
||||||
out[j++] = '\\';
|
|
||||||
out[j++] = '\'';
|
|
||||||
out[j++] = '\'';
|
|
||||||
} else {
|
|
||||||
out[j++] = in[i];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
out[j++] = in[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
out[j] = '\0';
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *qemudEscapeMonitorArg(const char *in)
|
|
||||||
{
|
|
||||||
return qemudEscape(in, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define QEMUD_SAVE_MAGIC "LibvirtQemudSave"
|
#define QEMUD_SAVE_MAGIC "LibvirtQemudSave"
|
||||||
#define QEMUD_SAVE_VERSION 2
|
#define QEMUD_SAVE_VERSION 2
|
||||||
|
|
||||||
@ -4626,12 +4549,8 @@ static int qemudDomainAttachPciDiskDevice(virConnectPtr conn,
|
|||||||
virDomainObjPtr vm,
|
virDomainObjPtr vm,
|
||||||
virDomainDeviceDefPtr dev)
|
virDomainDeviceDefPtr dev)
|
||||||
{
|
{
|
||||||
int ret, i;
|
int i;
|
||||||
char *cmd, *reply;
|
|
||||||
char *safe_path;
|
|
||||||
const char* type = virDomainDiskBusTypeToString(dev->data.disk->bus);
|
const char* type = virDomainDiskBusTypeToString(dev->data.disk->bus);
|
||||||
int tryOldSyntax = 0;
|
|
||||||
unsigned domain, bus, slot;
|
|
||||||
|
|
||||||
for (i = 0 ; i < vm->def->ndisks ; i++) {
|
for (i = 0 ; i < vm->def->ndisks ; i++) {
|
||||||
if (STREQ(vm->def->disks[i]->dst, dev->data.disk->dst)) {
|
if (STREQ(vm->def->disks[i]->dst, dev->data.disk->dst)) {
|
||||||
@ -4646,48 +4565,13 @@ static int qemudDomainAttachPciDiskDevice(virConnectPtr conn,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
try_command:
|
if (qemuMonitorAddPCIDisk(vm,
|
||||||
safe_path = qemudEscapeMonitorArg(dev->data.disk->src);
|
dev->data.disk->src,
|
||||||
if (!safe_path) {
|
type,
|
||||||
virReportOOMError(conn);
|
&dev->data.disk->pci_addr.domain,
|
||||||
|
&dev->data.disk->pci_addr.bus,
|
||||||
|
&dev->data.disk->pci_addr.slot) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
ret = virAsprintf(&cmd, "pci_add %s storage file=%s,if=%s",
|
|
||||||
(tryOldSyntax ? "0": "pci_addr=auto"), safe_path, type);
|
|
||||||
VIR_FREE(safe_path);
|
|
||||||
if (ret == -1) {
|
|
||||||
virReportOOMError(conn);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
|
|
||||||
qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
|
|
||||||
_("cannot attach %s disk"), type);
|
|
||||||
VIR_FREE(cmd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
VIR_FREE(cmd);
|
|
||||||
|
|
||||||
if (qemudParsePciAddReply(vm, reply, &domain, &bus, &slot) < 0) {
|
|
||||||
if (!tryOldSyntax && strstr(reply, "invalid char in expression")) {
|
|
||||||
VIR_FREE(reply);
|
|
||||||
tryOldSyntax = 1;
|
|
||||||
goto try_command;
|
|
||||||
}
|
|
||||||
|
|
||||||
qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
|
|
||||||
_("adding %s disk failed: %s"), type, reply);
|
|
||||||
VIR_FREE(reply);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
VIR_FREE(reply);
|
|
||||||
|
|
||||||
dev->data.disk->pci_addr.domain = domain;
|
|
||||||
dev->data.disk->pci_addr.bus = bus;
|
|
||||||
dev->data.disk->pci_addr.slot = slot;
|
|
||||||
|
|
||||||
virDomainDiskInsertPreAlloced(vm->def, dev->data.disk);
|
virDomainDiskInsertPreAlloced(vm->def, dev->data.disk);
|
||||||
|
|
||||||
|
@ -1437,6 +1437,62 @@ cleanup:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int qemuMonitorAddPCIDisk(const virDomainObjPtr vm,
|
||||||
|
const char *path,
|
||||||
|
const char *bus,
|
||||||
|
unsigned *guestDomain,
|
||||||
|
unsigned *guestBus,
|
||||||
|
unsigned *guestSlot) {
|
||||||
|
char *cmd = NULL;
|
||||||
|
char *reply = NULL;
|
||||||
|
char *safe_path = NULL;
|
||||||
|
int tryOldSyntax = 0;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
safe_path = qemudEscapeMonitorArg(path);
|
||||||
|
if (!safe_path) {
|
||||||
|
virReportOOMError(NULL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
try_command:
|
||||||
|
if (virAsprintf(&cmd, "pci_add %s storage file=%s,if=%s",
|
||||||
|
(tryOldSyntax ? "0": "pci_addr=auto"), safe_path, bus) < 0) {
|
||||||
|
virReportOOMError(NULL);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
|
||||||
|
qemudReportError(NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED,
|
||||||
|
_("cannot attach %s disk %s"), bus, path);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qemuMonitorParsePciAddReply(vm, reply,
|
||||||
|
guestDomain, guestBus, guestSlot) < 0) {
|
||||||
|
if (!tryOldSyntax && strstr(reply, "invalid char in expression")) {
|
||||||
|
VIR_FREE(reply);
|
||||||
|
VIR_FREE(cmd);
|
||||||
|
tryOldSyntax = 1;
|
||||||
|
goto try_command;
|
||||||
|
}
|
||||||
|
|
||||||
|
qemudReportError (NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED,
|
||||||
|
_("adding %s disk failed %s: %s"), bus, path, reply);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
VIR_FREE(safe_path);
|
||||||
|
VIR_FREE(cmd);
|
||||||
|
VIR_FREE(reply);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int qemuMonitorRemovePCIDevice(const virDomainObjPtr vm,
|
int qemuMonitorRemovePCIDevice(const virDomainObjPtr vm,
|
||||||
unsigned guestDomain,
|
unsigned guestDomain,
|
||||||
unsigned guestBus,
|
unsigned guestBus,
|
||||||
|
@ -137,6 +137,9 @@ int qemuMonitorMigrateToCommand(const virDomainObjPtr vm,
|
|||||||
const char *target);
|
const char *target);
|
||||||
|
|
||||||
|
|
||||||
|
/* XXX disk driver type eg, qcow/etc.
|
||||||
|
* XXX cache mode
|
||||||
|
*/
|
||||||
int qemuMonitorAddUSBDisk(const virDomainObjPtr vm,
|
int qemuMonitorAddUSBDisk(const virDomainObjPtr vm,
|
||||||
const char *path);
|
const char *path);
|
||||||
|
|
||||||
@ -157,6 +160,16 @@ int qemuMonitorAddPCIHostDevice(const virDomainObjPtr vm,
|
|||||||
unsigned *guestBus,
|
unsigned *guestBus,
|
||||||
unsigned *guestSlot);
|
unsigned *guestSlot);
|
||||||
|
|
||||||
|
/* XXX disk driver type eg, qcow/etc.
|
||||||
|
* XXX cache mode
|
||||||
|
*/
|
||||||
|
int qemuMonitorAddPCIDisk(const virDomainObjPtr vm,
|
||||||
|
const char *path,
|
||||||
|
const char *bus,
|
||||||
|
unsigned *guestDomain,
|
||||||
|
unsigned *guestBus,
|
||||||
|
unsigned *guestSlot);
|
||||||
|
|
||||||
int qemuMonitorRemovePCIDevice(const virDomainObjPtr vm,
|
int qemuMonitorRemovePCIDevice(const virDomainObjPtr vm,
|
||||||
unsigned guestDomain,
|
unsigned guestDomain,
|
||||||
unsigned guestBus,
|
unsigned guestBus,
|
||||||
|
Loading…
Reference in New Issue
Block a user