mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-11 07:17:44 +00:00
Wire up QEMU implementation for virDomainOpenGraphics
The QEMU monitor command 'add_client' can be used to connect to a VNC or SPICE graphics display. This allows for implementation of the virDomainOpenGraphics API * src/qemu/qemu_driver.c: Implement virDomainOpenGraphics * src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h, src/qemu/qemu_monitor_json.c, src/qemu/qemu_monitor_json.h, src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h: Add binding for 'add_client' command
This commit is contained in:
parent
6aa27da287
commit
f877fed36f
@ -919,6 +919,7 @@ qemudSupportsFeature (virConnectPtr conn ATTRIBUTE_UNUSED, int feature)
|
||||
case VIR_DRV_FEATURE_MIGRATION_V3:
|
||||
case VIR_DRV_FEATURE_MIGRATION_P2P:
|
||||
case VIR_DRV_FEATURE_MIGRATE_CHANGE_PROTECTION:
|
||||
case VIR_DRV_FEATURE_FD_PASSING:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
@ -10660,6 +10661,76 @@ qemuDomainBlockPull(virDomainPtr dom, const char *path, unsigned long bandwidth,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
qemuDomainOpenGraphics(virDomainPtr dom,
|
||||
unsigned int idx,
|
||||
int fd,
|
||||
unsigned int flags)
|
||||
{
|
||||
struct qemud_driver *driver = dom->conn->privateData;
|
||||
virDomainObjPtr vm = NULL;
|
||||
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
||||
int ret = -1;
|
||||
qemuDomainObjPrivatePtr priv;
|
||||
const char *protocol;
|
||||
|
||||
virCheckFlags(VIR_DOMAIN_OPEN_GRAPHICS_SKIPAUTH, -1);
|
||||
|
||||
qemuDriverLock(driver);
|
||||
virUUIDFormat(dom->uuid, uuidstr);
|
||||
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
||||
if (!vm) {
|
||||
qemuReportError(VIR_ERR_NO_DOMAIN,
|
||||
_("no domain with matching uuid '%s'"), uuidstr);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!virDomainObjIsActive(vm)) {
|
||||
qemuReportError(VIR_ERR_OPERATION_INVALID,
|
||||
"%s", _("domain is not running"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
priv = vm->privateData;
|
||||
|
||||
if (idx >= vm->def->ngraphics) {
|
||||
qemuReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("No graphics backend with index %d"), idx);
|
||||
goto cleanup;
|
||||
}
|
||||
switch (vm->def->graphics[idx]->type) {
|
||||
case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
|
||||
protocol = "vnc";
|
||||
break;
|
||||
case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
|
||||
protocol = "spice";
|
||||
break;
|
||||
default:
|
||||
qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||
_("Can only open VNC or SPICE graphics backends, not %s"),
|
||||
virDomainGraphicsTypeToString(vm->def->graphics[idx]->type));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) < 0)
|
||||
goto cleanup;
|
||||
qemuDomainObjEnterMonitorWithDriver(driver, vm);
|
||||
ret = qemuMonitorOpenGraphics(priv->mon, protocol, fd, "graphicsfd",
|
||||
(flags & VIR_DOMAIN_OPEN_GRAPHICS_SKIPAUTH) != 0);
|
||||
qemuDomainObjExitMonitorWithDriver(driver, vm);
|
||||
if (qemuDomainObjEndJob(driver, vm) == 0) {
|
||||
vm = NULL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (vm)
|
||||
virDomainObjUnlock(vm);
|
||||
qemuDriverUnlock(driver);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static virDriver qemuDriver = {
|
||||
.no = VIR_DRV_QEMU,
|
||||
.name = "QEMU",
|
||||
@ -10790,6 +10861,7 @@ static virDriver qemuDriver = {
|
||||
.qemuDomainMonitorCommand = qemuDomainMonitorCommand, /* 0.8.3 */
|
||||
.qemuDomainAttach = qemuDomainAttach, /* 0.9.4 */
|
||||
.domainOpenConsole = qemuDomainOpenConsole, /* 0.8.6 */
|
||||
.domainOpenGraphics = qemuDomainOpenGraphics, /* 0.9.7 */
|
||||
.domainInjectNMI = qemuDomainInjectNMI, /* 0.9.2 */
|
||||
.domainMigrateBegin3 = qemuDomainMigrateBegin3, /* 0.9.2 */
|
||||
.domainMigratePrepare3 = qemuDomainMigratePrepare3, /* 0.9.2 */
|
||||
|
@ -2616,3 +2616,36 @@ int qemuMonitorVMStatusToPausedReason(const char *status)
|
||||
}
|
||||
return VIR_DOMAIN_PAUSED_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
int qemuMonitorOpenGraphics(qemuMonitorPtr mon,
|
||||
const char *protocol,
|
||||
int fd,
|
||||
const char *fdname,
|
||||
bool skipauth)
|
||||
{
|
||||
VIR_DEBUG("mon=%p protocol=%s fd=%d fdname=%s skipauth=%d",
|
||||
mon, protocol, fd, NULLSTR(fdname), skipauth);
|
||||
int ret;
|
||||
|
||||
if (!mon) {
|
||||
qemuReportError(VIR_ERR_INVALID_ARG, "%s",
|
||||
_("monitor must not be NULL"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (qemuMonitorSendFileHandle(mon, fdname, fd) < 0)
|
||||
return -1;
|
||||
|
||||
if (mon->json)
|
||||
ret = qemuMonitorJSONOpenGraphics(mon, protocol, fdname, skipauth);
|
||||
else
|
||||
ret = qemuMonitorTextOpenGraphics(mon, protocol, fdname, skipauth);
|
||||
|
||||
if (ret < 0) {
|
||||
if (qemuMonitorCloseFileHandle(mon, fdname) < 0)
|
||||
VIR_WARN("failed to close device handle '%s'", fdname);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -515,6 +515,12 @@ int qemuMonitorBlockJob(qemuMonitorPtr mon,
|
||||
virDomainBlockJobInfoPtr info,
|
||||
int mode);
|
||||
|
||||
int qemuMonitorOpenGraphics(qemuMonitorPtr mon,
|
||||
const char *protocol,
|
||||
int fd,
|
||||
const char *fdname,
|
||||
bool skipauth);
|
||||
|
||||
/**
|
||||
* When running two dd process and using <> redirection, we need a
|
||||
* shell that will not truncate files. These two strings serve that
|
||||
|
@ -3249,3 +3249,30 @@ int qemuMonitorJSONBlockJob(qemuMonitorPtr mon,
|
||||
virJSONValueFree(reply);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int qemuMonitorJSONOpenGraphics(qemuMonitorPtr mon,
|
||||
const char *protocol,
|
||||
const char *fdname,
|
||||
bool skipauth)
|
||||
{
|
||||
int ret;
|
||||
virJSONValuePtr cmd, reply = NULL;
|
||||
|
||||
cmd = qemuMonitorJSONMakeCommand("add_client",
|
||||
"s:protocol", protocol,
|
||||
"s:fdname", fdname,
|
||||
"b:skipauth", skipauth,
|
||||
NULL);
|
||||
|
||||
if (!cmd)
|
||||
return -1;
|
||||
|
||||
ret = qemuMonitorJSONCommand(mon, cmd, &reply);
|
||||
|
||||
if (ret == 0)
|
||||
ret = qemuMonitorJSONCheckError(cmd, reply);
|
||||
|
||||
virJSONValueFree(cmd);
|
||||
virJSONValueFree(reply);
|
||||
return ret;
|
||||
}
|
||||
|
@ -250,4 +250,9 @@ int qemuMonitorJSONSetLink(qemuMonitorPtr mon,
|
||||
const char *name,
|
||||
enum virDomainNetInterfaceLinkState state);
|
||||
|
||||
int qemuMonitorJSONOpenGraphics(qemuMonitorPtr mon,
|
||||
const char *protocol,
|
||||
const char *fdname,
|
||||
bool skipauth);
|
||||
|
||||
#endif /* QEMU_MONITOR_JSON_H */
|
||||
|
@ -3397,3 +3397,35 @@ cleanup:
|
||||
VIR_FREE(reply);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int qemuMonitorTextOpenGraphics(qemuMonitorPtr mon,
|
||||
const char *protocol,
|
||||
const char *fdname,
|
||||
bool skipauth)
|
||||
{
|
||||
char *cmd = NULL;
|
||||
char *reply = NULL;
|
||||
int ret = -1;
|
||||
|
||||
if (virAsprintf(&cmd, "add_client %s %s %d", protocol, fdname, skipauth ? 0 : 1) < 0){
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0) {
|
||||
qemuReportError(VIR_ERR_OPERATION_FAILED,
|
||||
"%s", _("adding graphics client failed"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (STRNEQ(reply, ""))
|
||||
goto cleanup;
|
||||
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
VIR_FREE(reply);
|
||||
VIR_FREE(cmd);
|
||||
return ret;
|
||||
}
|
||||
|
@ -243,4 +243,9 @@ int qemuMonitorTextSetLink(qemuMonitorPtr mon,
|
||||
const char *name,
|
||||
enum virDomainNetInterfaceLinkState state);
|
||||
|
||||
int qemuMonitorTextOpenGraphics(qemuMonitorPtr mon,
|
||||
const char *protocol,
|
||||
const char *fdname,
|
||||
bool skipauth);
|
||||
|
||||
#endif /* QEMU_MONITOR_TEXT_H */
|
||||
|
Loading…
Reference in New Issue
Block a user