From 9d96f1ce906084e698c48e7fc9be4524632ebc01 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Fri, 21 Oct 2011 09:00:37 +0100 Subject: [PATCH] Introduce the virDomainOpenGraphics API The virDomainOpenGraphics API allows a libvirt client to pass in a file descriptor for an open socket pair, and get it connected to the graphics display of the guest. This is limited to working with local libvirt hypervisors connected over a UNIX domain socket, since it will use UNIX FD passing * include/libvirt/libvirt.h.in: Define virDomainOpenGraphics * src/driver.h: Define driver for virDomainOpenGraphics * src/libvirt_public.syms, src/libvirt.c: Entry point for virDomainOpenGraphics * src/libvirt_internal.h: VIR_DRV_FEATURE_FD_PASSING --- include/libvirt/libvirt.h.in | 9 ++++ src/driver.h | 6 +++ src/libvirt.c | 85 ++++++++++++++++++++++++++++++++++++ src/libvirt_internal.h | 5 +++ src/libvirt_public.syms | 1 + 5 files changed, 106 insertions(+) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 7102bce54e..917c64de10 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -3140,6 +3140,15 @@ int virDomainOpenConsole(virDomainPtr dom, virStreamPtr st, unsigned int flags); +typedef enum { + VIR_DOMAIN_OPEN_GRAPHICS_SKIPAUTH = (1 << 0), +} virDomainOpenGraphicsFlags; + +int virDomainOpenGraphics(virDomainPtr dom, + unsigned int idx, + int fd, + unsigned int flags); + int virDomainInjectNMI(virDomainPtr domain, unsigned int flags); diff --git a/src/driver.h b/src/driver.h index b899d0ea1f..4c14aaa8e9 100644 --- a/src/driver.h +++ b/src/driver.h @@ -632,6 +632,11 @@ typedef int const char *dev_name, virStreamPtr st, unsigned int flags); +typedef int + (*virDrvDomainOpenGraphics)(virDomainPtr dom, + unsigned int idx, + int fd, + unsigned int flags); typedef int (*virDrvDomainInjectNMI)(virDomainPtr dom, unsigned int flags); @@ -881,6 +886,7 @@ struct _virDriver { virDrvDomainQemuMonitorCommand qemuDomainMonitorCommand; virDrvDomainQemuAttach qemuDomainAttach; virDrvDomainOpenConsole domainOpenConsole; + virDrvDomainOpenGraphics domainOpenGraphics; virDrvDomainInjectNMI domainInjectNMI; virDrvDomainMigrateBegin3 domainMigrateBegin3; virDrvDomainMigratePrepare3 domainMigratePrepare3; diff --git a/src/libvirt.c b/src/libvirt.c index a6bcee69b4..e9d1a299f2 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -16964,3 +16964,88 @@ error: virDispatchError(dom->conn); return -1; } + + +/** + * virDomainOpenGraphics: + * @dom: pointer to domain object + * @idx: index of graphics config to open + * @fd: file descriptor to attach graphics to + * @flags: flags to control open operation + * + * This will attempt to connect the file descriptor @fd, to + * the graphics backend of @dom. If @dom has multiple graphics + * backends configured, then @idx will determine which one is + * opened, starting from @idx 0. + * + * To disable any authentication, pass the VIR_DOMAIN_OPEN_GRAPHICS_SKIPAUTH + * constant for @flags. + * + * The caller should use an anonymous socketpair to open + * @fd before invocation. + * + * This method can only be used when connected to a local + * libvirt hypervisor, over a UNIX domain socket. Attempts + * to use this method over a TCP connection will always fail + * + * Returns 0 on success, -1 on failure + */ +int virDomainOpenGraphics(virDomainPtr dom, + unsigned int idx, + int fd, + unsigned int flags) +{ + struct stat sb; + VIR_DOMAIN_DEBUG(dom, "idx=%u, fd=%d, flags=%x", + idx, fd, flags); + + virResetLastError(); + + if (!VIR_IS_DOMAIN(dom)) { + virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + + if (fd < 0) { + virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + if (fstat(fd, &sb) < 0) { + virReportSystemError(errno, + _("Unable to access file descriptor %d"), fd); + goto error; + } + + if (!S_ISSOCK(sb.st_mode)) { + virLibDomainError(VIR_ERR_INVALID_ARG, + _("File descriptor %d must be a socket"), fd); + goto error; + } + + if (dom->conn->flags & VIR_CONNECT_RO) { + virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + if (!VIR_DRV_SUPPORTS_FEATURE(dom->conn->driver, dom->conn, + VIR_DRV_FEATURE_FD_PASSING)) { + virLibDomainError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + goto error; + } + + if (dom->conn->driver->domainOpenGraphics) { + int ret; + ret = dom->conn->driver->domainOpenGraphics(dom, idx, fd, flags); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(dom->conn); + return -1; +} diff --git a/src/libvirt_internal.h b/src/libvirt_internal.h index 6e44341289..0117c5b1ca 100644 --- a/src/libvirt_internal.h +++ b/src/libvirt_internal.h @@ -79,6 +79,11 @@ enum { * to domain configuration, i.e., starting from Begin3 and not Perform3. */ VIR_DRV_FEATURE_MIGRATE_CHANGE_PROTECTION = 7, + + /* + * Support for file descriptor passing + */ + VIR_DRV_FEATURE_FD_PASSING = 8 }; diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 9762fc47b2..bcefb100f6 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -491,6 +491,7 @@ LIBVIRT_0.9.5 { LIBVIRT_0.9.7 { global: + virDomainOpenGraphics; virDomainReset; virDomainSnapshotGetParent; virDomainSnapshotListChildrenNames;