
On Wed, Jan 29, 2025 at 05:40:39PM +0400, marcandre.lureau@redhat.com wrote:
From: Marc-André Lureau <marcandre.lureau@redhat.com>
Helpers to start the qemu-rdp server and set it up.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- po/POTFILES | 1 + src/qemu/meson.build | 1 + src/qemu/qemu_domain.c | 1 + src/qemu/qemu_domain.h | 2 + src/qemu/qemu_rdp.c | 427 +++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_rdp.h | 71 +++++++ 6 files changed, 503 insertions(+) create mode 100644 src/qemu/qemu_rdp.c create mode 100644 src/qemu/qemu_rdp.h
snip
+ logpath = qemuRdpCreateLogFilename(cfg, vm->def); + + if (cfg->stdioLogD) { + g_autoptr(virLogManager) logManager = virLogManagerNew(driver->privileged); + + if (!logManager) + goto error; + + if ((logfd = virLogManagerDomainOpenLogFile(logManager, + "qemu", + vm->def->uuid, + vm->def->name, + logpath, + 0, + NULL, NULL)) < 0) + goto error; + } else { + if ((logfd = open(logpath, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR)) < 0) { + virReportSystemError(errno, _("failed to create logfile %1$s"), + logpath); + goto error; + } + if (virSetCloseExec(logfd) < 0) { + virReportSystemError(errno, _("failed to set close-on-exec flag on %1$s"), + logpath); + goto error; + } + }
These 30 lines are repeated in the dbus helper, and likewise the virtiofs helper. This ought to be spun out to a helper API we can call like: if (!(logfd = qemuHelperOpenLogFile(driver, vm, "rdp")) goto error
+ + cmd = virCommandNew(cfg->qemuRdpName); + virCommandClearCaps(cmd); + virCommandSetPidFile(cmd, pidfile); + virCommandSetOutputFD(cmd, &logfd); + virCommandSetErrorFD(cmd, &logfd); + virCommandDaemonize(cmd); + if (dbus_addr) {
If 'dbus_addr' is NULL, AFAICT an error has been reported and we should be propagating that as a fatal error scenario.
+ if (!qemuRdpHasFeature(rdp, QEMU_RDP_FEATURE_DBUS_ADDRESS)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("qemu-rdp doesn't support custom D-Bus address"));
Missing 'return -1', but...
+ }
...this ought be checked when we're probing capabilities for RDP support probably.
+ virCommandAddArgPair(cmd, "--dbus-address", dbus_addr); + } + virCommandAddArg(cmd, "serve"); + + virCommandAddArg(cmd, "--bind-address"); + virCommandAddArgBuffer(cmd, &bind_addr); + + certpath = g_build_filename(cfg->rdpTLSx509certdir, "server-cert.pem", NULL); + keypath = g_build_filename(cfg->rdpTLSx509certdir, "server-key.pem", NULL); + virCommandAddArgPair(cmd, "--cert", certpath); + virCommandAddArgPair(cmd, "--key", keypath); + + if (qemuExtDeviceLogCommand(driver, vm, cmd, "qemu-rdp") < 0) + return -1; + + rdp->name_watch = g_bus_watch_name_on_connection(priv->dbusConnection, + ORG_QEMUDISPLAY_RDP, + G_BUS_NAME_WATCHER_FLAGS_NONE, + name_appeared_cb, + name_vanished_cb, + rdp, + NULL); + + if (qemuSecurityCommandRun(driver, vm, cmd, -1, -1, false, NULL) < 0) + goto error; + + if (virPidFileReadPath(pidfile, &pid) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to read qemu-rdp pidfile '%1$s'"), + pidfile); + goto error; + } + + if (virProcessKill(pid, 0) != 0) { + virReportSystemError(errno, "%s", + _("qemu-rdp died unexpectedly")); + goto error; + } + + rdp->pid = pid; + + return 0; + + error: + g_clear_handle_id(&rdp->name_watch, g_bus_unwatch_name); + qemuRdpStop(vm, gfx); + return -1; +} + + +int +qemuRdpSetCredentials(virDomainObj *vm, + const char *username, + const char *password, + const char *domain) +{ + qemuDomainObjPrivate *priv = vm->privateData; + g_autoptr(GVariant) args = NULL; + + args = g_variant_new("(sss)", username, password, domain); + + return virGDBusCallMethod(priv->dbusConnection, + NULL, + G_VARIANT_TYPE("()"), + NULL, + ORG_QEMUDISPLAY_RDP, + ORG_QEMUDISPLAY_RDP_PATH, + ORG_QEMUDISPLAY_RDP_IFACE, + "SetCredentials", + args); +} diff --git a/src/qemu/qemu_rdp.h b/src/qemu/qemu_rdp.h new file mode 100644 index 0000000000..6af90b06d2 --- /dev/null +++ b/src/qemu/qemu_rdp.h @@ -0,0 +1,71 @@ +/* + * qemu_rdp.h: QEMU RDP support + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include "qemu_conf.h" +#include "virbitmap.h" +#include "virenum.h" + +typedef enum { + QEMU_RDP_FEATURE_NONE = 0, + + QEMU_RDP_FEATURE_DBUS_ADDRESS, + QEMU_RDP_FEATURE_REMOTEFX, + QEMU_RDP_FEATURE_LAST, +} qemuRdpFeature; + +VIR_ENUM_DECL(qemuRdpFeature); + +typedef struct _qemuRdp qemuRdp; +struct _qemuRdp { + int fd[2]; + virBitmap *features; + pid_t pid; + guint name_watch; + bool name_appeared; + guint leaving_id; +}; + +qemuRdp *qemuRdpNew(void); + +qemuRdp *qemuRdpNewForHelper(const char *helper); + +void qemuRdpFree(qemuRdp *rdp); + +void qemuRdpSetFeature(qemuRdp *rdp, + qemuRdpFeature feature); + +bool qemuRdpHasFeature(const qemuRdp *rdp, + qemuRdpFeature feature); + +int qemuRdpStart(virDomainObj *vm, + virDomainGraphicsDef *gfx); + +void qemuRdpStop(virDomainObj *vm, + virDomainGraphicsDef *gfx); + +int qemuRdpSetupCgroup(qemuRdp *rdp, + virCgroup *cgroup); + +int qemuRdpSetCredentials(virDomainObj *vm, + const char *username, + const char *password, + const char *domain); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(qemuRdp, qemuRdpFree); -- 2.47.0
With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|