提交 6d9c4758 编写于 作者: D Daniel P. Berrange

Add APIs for issuing 'eject' and 'change dev' monitor commands

* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Add new APis
  qemuMonitorChangeMedia and qemuMonitorEjectMedia. Pull in code
  for qemudEscape
* src/qemu/qemu_driver.c: Remove code that directly issues 'eject'
  and 'change' commands in favour of API calls.
上级 eff29c8b
......@@ -4572,9 +4572,9 @@ static int qemudDomainChangeEjectableMedia(virConnectPtr conn,
unsigned int qemuCmdFlags)
{
virDomainDiskDefPtr origdisk = NULL, newdisk;
char *cmd, *reply, *safe_path;
char *devname = NULL;
int i;
int ret;
origdisk = NULL;
newdisk = dev->data.disk;
......@@ -4620,53 +4620,19 @@ static int qemudDomainChangeEjectableMedia(virConnectPtr conn,
}
if (newdisk->src) {
safe_path = qemudEscapeMonitorArg(newdisk->src);
if (!safe_path) {
virReportOOMError(conn);
VIR_FREE(devname);
return -1;
}
if (virAsprintf(&cmd, "change %s \"%s\"", devname, safe_path) == -1) {
virReportOOMError(conn);
VIR_FREE(safe_path);
VIR_FREE(devname);
return -1;
}
VIR_FREE(safe_path);
} else if (virAsprintf(&cmd, "eject %s", devname) == -1) {
virReportOOMError(conn);
VIR_FREE(devname);
return -1;
}
VIR_FREE(devname);
if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("could not change cdrom media"));
VIR_FREE(cmd);
return -1;
ret = qemuMonitorChangeMedia(vm, devname, newdisk->src);
} else {
ret = qemuMonitorEjectMedia(vm, devname);
}
/* If the command failed qemu prints:
* device not found, device is locked ...
* No message is printed on success it seems */
DEBUG ("%s: ejectable media change reply: %s", vm->def->name, reply);
if (strstr(reply, "\ndevice ")) {
qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
_("changing cdrom media failed: %s"), reply);
VIR_FREE(reply);
VIR_FREE(cmd);
return -1;
if (ret == 0) {
VIR_FREE(origdisk->src);
origdisk->src = newdisk->src;
newdisk->src = NULL;
origdisk->type = newdisk->type;
}
VIR_FREE(reply);
VIR_FREE(cmd);
VIR_FREE(origdisk->src);
origdisk->src = newdisk->src;
newdisk->src = NULL;
origdisk->type = newdisk->type;
return 0;
return ret;
}
static int
......
......@@ -40,6 +40,84 @@
#define VIR_FROM_THIS VIR_FROM_QEMU
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);
}
/* Throw away any data available on the monitor
* This is done before executing a command, in order
* to allow re-synchronization if something went badly
......@@ -651,3 +729,84 @@ int qemuMonitorSetBalloon(const virDomainObjPtr vm,
return ret;
}
int qemuMonitorEjectMedia(const virDomainObjPtr vm,
const char *devname)
{
char *cmd = NULL;
char *reply = NULL;
int ret = -1;
if (virAsprintf(&cmd, "eject %s", devname) < 0) {
virReportOOMError(NULL);
goto cleanup;
}
if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
qemudReportError(NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED,
_("could not eject media on %s"), devname);
goto cleanup;
}
/* If the command failed qemu prints:
* device not found, device is locked ...
* No message is printed on success it seems */
DEBUG ("%s: ejectable media change reply: %s", vm->def->name, reply);
if (strstr(reply, "\ndevice ")) {
qemudReportError(NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED,
_("could not eject media on %s: %s"), devname, reply);
goto cleanup;
}
ret = 0;
cleanup:
VIR_FREE(reply);
VIR_FREE(cmd);
return ret;
}
int qemuMonitorChangeMedia(const virDomainObjPtr vm,
const char *devname,
const char *newmedia)
{
char *cmd = NULL;
char *reply = NULL;
char *safepath = NULL;
int ret = -1;
if (!(safepath = qemudEscapeMonitorArg(newmedia))) {
virReportOOMError(NULL);
goto cleanup;
}
if (virAsprintf(&cmd, "change %s \"%s\"", devname, safepath) < 0) {
virReportOOMError(NULL);
goto cleanup;
}
if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
qemudReportError(NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED,
_("could not eject media on %s"), devname);
goto cleanup;
}
/* If the command failed qemu prints:
* device not found, device is locked ...
* No message is printed on success it seems */
DEBUG ("%s: ejectable media change reply: %s", vm->def->name, reply);
if (strstr(reply, "\ndevice ")) {
qemudReportError(NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED,
_("could not eject media on %s: %s"), devname, reply);
goto cleanup;
}
ret = 0;
cleanup:
VIR_FREE(reply);
VIR_FREE(cmd);
VIR_FREE(safepath);
return ret;
}
......@@ -81,4 +81,14 @@ int qemuMonitorSetVNCPassword(const virDomainObjPtr vm,
int qemuMonitorSetBalloon(const virDomainObjPtr vm,
unsigned long newmem);
/* XXX should we pass the virDomainDiskDefPtr instead
* and hide devname details inside monitor. Reconsider
* this when doing the QMP implementation
*/
int qemuMonitorEjectMedia(const virDomainObjPtr vm,
const char *devname);
int qemuMonitorChangeMedia(const virDomainObjPtr vm,
const char *devname,
const char *newmedia);
#endif /* QEMU_MONITOR_TEXT_H */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册