From nobody Thu May 15 01:01:50 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1513788502965993.3614881791664; Wed, 20 Dec 2017 08:48:22 -0800 (PST) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id BE34F2C977D; Wed, 20 Dec 2017 16:48:20 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 8D2FE1755C; Wed, 20 Dec 2017 16:48:20 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 5A6213FA5B; Wed, 20 Dec 2017 16:48:20 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id vBKGmBap008493 for ; Wed, 20 Dec 2017 11:48:11 -0500 Received: by smtp.corp.redhat.com (Postfix) id DF17A18EC1; Wed, 20 Dec 2017 16:48:11 +0000 (UTC) Received: from localhost.localdomain.com (unknown [10.42.22.189]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9377E60C29; Wed, 20 Dec 2017 16:48:09 +0000 (UTC) From: "Daniel P. Berrange" To: libvir-list@redhat.com Date: Wed, 20 Dec 2017 16:47:50 +0000 Message-Id: <20171220164750.26419-6-berrange@redhat.com> In-Reply-To: <20171220164750.26419-1-berrange@redhat.com> References: <20171220164750.26419-1-berrange@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-loop: libvir-list@redhat.com Cc: Martin Kletzander , David Vossel , Fabian Deutsch Subject: [libvirt] [PATCH 5/5] qemu: implement the 'libvirt_qemu' shim for launching guests externally X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Wed, 20 Dec 2017 16:48:21 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" This introduces a new binary 'libvirt_qemu' which can be used to launch guests externally from libvirtd. eg libvirt_qemu -c qemu:///system /path/to/xml/file This will launch a guest from the requested XML file and then connect to qemu:///system to register it with libvirtd. At this point all normal libvirtd operations should generally work. NB, this impl has many flaws: - We don't generate a unique 'id', so all guests will get id=3D=3D1. Surprisingly this doesn't break the world. - Tracking of unique name + UUIDs is *not* race free. - No tracking/allocation of shared resource state (PCI devices, etc) Most other functionality works, but might have expected results. In terms of namespace support there's some restrictions - The mount namespace must share certain dirs /etc/libvirt /var/run/libvirt /var/lib/libvirt /var/cache/libvirt between the libvirtd and libvirt_qemu processes - The PID namespace must match libvirtd & libvirt_qemu though this will be addressed in another patch to come - The network namespace can be different - Hotplug/unplug will likely break if separate namespaces are used - The libvirt_qemu will exit if startup fails, however, it won't exit when QEMU later shuts down - you must listen for libvirtd events to detect that right now. We'll fix that - Killing the libvirt_qemu shim will not kill the QEMU process. You must kill via the libvirt API as normal. This won't change, because we need to be able to ultimately restart the libvirt_qemu shim in order to apply software updates to running instance. We might wire up a special signal though to let you kill libvirt_qemu & take out QEMU at same time eg SIGQUIT or something like that perhaps. Signed-off-by: Daniel P. Berrange --- po/POTFILES.in | 1 + src/Makefile.am | 49 ++++ src/qemu/qemu_conf.h | 2 +- src/qemu/qemu_controller.c | 551 +++++++++++++++++++++++++++++++++++++++++= ++++ src/qemu/qemu_domain.c | 2 +- src/qemu/qemu_driver.c | 2 +- 6 files changed, 604 insertions(+), 3 deletions(-) create mode 100644 src/qemu/qemu_controller.c diff --git a/po/POTFILES.in b/po/POTFILES.in index c1fa23427e..d97175b6d5 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -133,6 +133,7 @@ src/qemu/qemu_block.c src/qemu/qemu_capabilities.c src/qemu/qemu_cgroup.c src/qemu/qemu_command.c +src/qemu/qemu_controller.c src/qemu/qemu_conf.c src/qemu/qemu_domain.c src/qemu/qemu_domain_address.c diff --git a/src/Makefile.am b/src/Makefile.am index 4c022d1e44..7ca5ad4d3c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -922,6 +922,9 @@ QEMU_DRIVER_SOURCES =3D \ qemu/qemu_capspriv.h \ qemu/qemu_security.c qemu/qemu_security.h =20 +QEMU_CONTROLLER_SOURCES =3D \ + qemu/qemu_controller.c + XENAPI_DRIVER_SOURCES =3D \ xenapi/xenapi_driver.c xenapi/xenapi_driver.h \ xenapi/xenapi_driver_private.h \ @@ -3115,6 +3118,52 @@ endif WITH_LIBVIRTD endif WITH_LXC EXTRA_DIST +=3D $(LXC_CONTROLLER_SOURCES) =20 +if WITH_QEMU +if WITH_LIBVIRTD +libexec_PROGRAMS +=3D libvirt_qemu + +libvirt_qemu_SOURCES =3D \ + $(QEMU_CONTROLLER_SOURCES) \ + $(DATATYPES_SOURCES) +libvirt_qemu_LDFLAGS =3D \ + $(AM_LDFLAGS) \ + $(PIE_LDFLAGS) \ + $(NULL) +libvirt_qemu_LDADD =3D \ + libvirt.la \ + libvirt-qemu.la \ + libvirt_driver_qemu_impl.la +if WITH_NETWORK +libvirt_qemu_LDADD +=3D libvirt_driver_network_impl.la +endif WITH_NETWORK +if WITH_STORAGE +libvirt_qemu_LDADD +=3D libvirt_driver_storage_impl.la +endif WITH_STORAGE +libvirt_qemu_LDADD +=3D ../gnulib/lib/libgnu.la $(LIBSOCKET) +if WITH_DTRACE_PROBES +libvirt_qemu_LDADD +=3D libvirt_probes.lo libvirt_qemu_probes.lo +endif WITH_DTRACE_PROBES +libvirt_qemu_LDADD +=3D $(SECDRIVER_LIBS) +libvirt_qemu_CFLAGS =3D \ + -I$(srcdir)/access \ + -I$(srcdir)/conf \ + -I$(srcdir)/secret \ + $(AM_CFLAGS) \ + $(PIE_CFLAGS) \ + $(LIBNL_CFLAGS) \ + $(FUSE_CFLAGS) \ + $(DBUS_CFLAGS) \ + $(XDR_CFLAGS) \ + $(NULL) +if WITH_BLKID +libvirt_qemu_CFLAGS +=3D $(BLKID_CFLAGS) +libvirt_qemu_LDADD +=3D $(BLKID_LIBS) +endif WITH_BLKID +libvirt_qemu_CFLAGS +=3D $(SECDRIVER_CFLAGS) +endif WITH_LIBVIRTD +endif WITH_QEMU +EXTRA_DIST +=3D $(QEMU_CONTROLLER_SOURCES) + if WITH_SECDRIVER_APPARMOR if WITH_LIBVIRTD libexec_PROGRAMS +=3D virt-aa-helper diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index a553e30e2e..a19b199147 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -296,7 +296,7 @@ struct _qemuDomainCmdlineDef { char **env_value; }; =20 - +int qemuSecurityInit(virQEMUDriverPtr driver); =20 void qemuDomainCmdlineDefFree(qemuDomainCmdlineDefPtr def); =20 diff --git a/src/qemu/qemu_controller.c b/src/qemu/qemu_controller.c new file mode 100644 index 0000000000..320d9a99b6 --- /dev/null +++ b/src/qemu/qemu_controller.c @@ -0,0 +1,551 @@ +/* + * qemu_controller.c: QEMU process controller + * + * Copyright (C) 2006-2018 Red Hat, Inc. + * + * 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 + * . + * + */ + +#include + +#include +#include +#include +#include + +#include "virgettext.h" +#include "virthread.h" +#include "virlog.h" +#include "virfile.h" +#include "viralloc.h" +#include "virstring.h" +#include "dirname.h" +#include "driver.h" + +#include "qemu/qemu_conf.h" +#include "qemu/qemu_process.h" +#include "qemu/qemu_driver.h" +#include "libvirt_internal.h" + +static const char *argv0; + +#define VIR_FROM_THIS VIR_FROM_QEMU + +VIR_LOG_INIT("qemu.qemu_controller"); + +typedef struct virQEMUController virQEMUController; +typedef virQEMUController *virQEMUControllerPtr; +struct virQEMUController { + const char *uri; + bool privileged; + const char *xml; + virQEMUDriverPtr driver; + virConnectPtr conn; + virDomainObjPtr vm; +}; + +static void +virQEMUControllerDriverFree(virQEMUDriverPtr driver) +{ + if (!driver) + return; + + virObjectUnref(driver->config); + virObjectUnref(driver->hostdevMgr); + virHashFree(driver->sharedDevices); + virObjectUnref(driver->caps); + virObjectUnref(driver->qemuCapsCache); + + virObjectUnref(driver->domains); + virObjectUnref(driver->remotePorts); + virObjectUnref(driver->webSocketPorts); + virObjectUnref(driver->migrationPorts); + virObjectUnref(driver->migrationErrors); + + virObjectUnref(driver->xmlopt); + + virSysinfoDefFree(driver->hostsysinfo); + + virObjectUnref(driver->closeCallbacks); + + VIR_FREE(driver->qemuImgBinary); + + virObjectUnref(driver->securityManager); + + ebtablesContextFree(driver->ebtables); + + virLockManagerPluginUnref(driver->lockManager); + + virMutexDestroy(&driver->lock); + VIR_FREE(driver); +} + +static virQEMUDriverPtr virQEMUControllerNewDriver(bool privileged) +{ + virQEMUDriverPtr driver =3D NULL; + char *driverConf =3D NULL; + virConnectPtr conn =3D NULL; + virQEMUDriverConfigPtr cfg; + uid_t run_uid =3D -1; + gid_t run_gid =3D -1; + char *hugepagePath =3D NULL; + char *memoryBackingPath =3D NULL; + size_t i; + + if (VIR_ALLOC(driver) < 0) + return NULL; + + if (virMutexInit(&driver->lock) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot initialize mutex")); + VIR_FREE(driver); + return NULL; + } + + driver->privileged =3D privileged; + + /* read the host sysinfo */ + if (privileged) + driver->hostsysinfo =3D virSysinfoRead(); + + if (!(driver->config =3D cfg =3D virQEMUDriverConfigNew(privileged))) + goto error; + + if (virAsprintf(&driverConf, "%s/qemu.conf", cfg->configBaseDir) < 0) + goto error; + + if (virQEMUDriverConfigLoadFile(cfg, driverConf, privileged) < 0) + goto error; + VIR_FREE(driverConf); + + if (virQEMUDriverConfigValidate(cfg) < 0) + goto error; + + if (virFileMakePath(cfg->stateDir) < 0) { + virReportSystemError(errno, _("Failed to create state dir %s"), + cfg->stateDir); + goto error; + } + if (virFileMakePath(cfg->libDir) < 0) { + virReportSystemError(errno, _("Failed to create lib dir %s"), + cfg->libDir); + goto error; + } + if (virFileMakePath(cfg->cacheDir) < 0) { + virReportSystemError(errno, _("Failed to create cache dir %s"), + cfg->cacheDir); + goto error; + } + if (virFileMakePath(cfg->saveDir) < 0) { + virReportSystemError(errno, _("Failed to create save dir %s"), + cfg->saveDir); + goto error; + } + if (virFileMakePath(cfg->snapshotDir) < 0) { + virReportSystemError(errno, _("Failed to create save dir %s"), + cfg->snapshotDir); + goto error; + } + if (virFileMakePath(cfg->autoDumpPath) < 0) { + virReportSystemError(errno, _("Failed to create dump dir %s"), + cfg->autoDumpPath); + goto error; + } + if (virFileMakePath(cfg->channelTargetDir) < 0) { + virReportSystemError(errno, _("Failed to create channel target dir= %s"), + cfg->channelTargetDir); + goto error; + } + if (virFileMakePath(cfg->nvramDir) < 0) { + virReportSystemError(errno, _("Failed to create nvram dir %s"), + cfg->nvramDir); + goto error; + } + if (virFileMakePath(cfg->memoryBackingDir) < 0) { + virReportSystemError(errno, _("Failed to create memory backing dir= %s"), + cfg->memoryBackingDir); + goto error; + } + + driver->qemuImgBinary =3D virFindFileInPath("qemu-img"); + + if (!(driver->lockManager =3D + virLockManagerPluginNew(cfg->lockManagerName ? + cfg->lockManagerName : "nop", + "qemu", + cfg->configBaseDir, + 0))) + goto error; + + if (cfg->macFilter) { + if (!(driver->ebtables =3D ebtablesContextNew("qemu"))) { + virReportSystemError(errno, + _("failed to enable mac filter in '%s'"), + __FILE__); + goto error; + } + + if (ebtablesAddForwardPolicyReject(driver->ebtables) < 0) + goto error; + } + + /* Allocate bitmap for remote display port reservations. We cannot + * do this before the config is loaded properly, since the port + * numbers are configurable now */ + if ((driver->remotePorts =3D + virPortAllocatorNew(_("display"), + cfg->remotePortMin, + cfg->remotePortMax, + 0)) =3D=3D NULL) + goto error; + + if ((driver->webSocketPorts =3D + virPortAllocatorNew(_("webSocket"), + cfg->webSocketPortMin, + cfg->webSocketPortMax, + 0)) =3D=3D NULL) + goto error; + + if ((driver->migrationPorts =3D + virPortAllocatorNew(_("migration"), + cfg->migrationPortMin, + cfg->migrationPortMax, + 0)) =3D=3D NULL) + goto error; + + if (qemuSecurityInit(driver) < 0) + goto error; + + if (!(driver->hostdevMgr =3D virHostdevManagerGetDefault())) + goto error; + + if (!(driver->sharedDevices =3D virHashCreate(30, qemuSharedDeviceEntr= yFree))) + goto error; + + if (privileged) { + char *channeldir; + + if (chown(cfg->libDir, cfg->user, cfg->group) < 0) { + virReportSystemError(errno, + _("unable to set ownership of '%s' to use= r %d:%d"), + cfg->libDir, (int) cfg->user, + (int) cfg->group); + goto error; + } + if (chown(cfg->cacheDir, cfg->user, cfg->group) < 0) { + virReportSystemError(errno, + _("unable to set ownership of '%s' to %d:= %d"), + cfg->cacheDir, (int) cfg->user, + (int) cfg->group); + goto error; + } + if (chown(cfg->saveDir, cfg->user, cfg->group) < 0) { + virReportSystemError(errno, + _("unable to set ownership of '%s' to %d:= %d"), + cfg->saveDir, (int) cfg->user, + (int) cfg->group); + goto error; + } + if (chown(cfg->snapshotDir, cfg->user, cfg->group) < 0) { + virReportSystemError(errno, + _("unable to set ownership of '%s' to %d:= %d"), + cfg->snapshotDir, (int) cfg->user, + (int) cfg->group); + goto error; + } + if (chown(cfg->autoDumpPath, cfg->user, cfg->group) < 0) { + virReportSystemError(errno, + _("unable to set ownership of '%s' to %d:= %d"), + cfg->autoDumpPath, (int) cfg->user, + (int) cfg->group); + goto error; + } + if (!(channeldir =3D mdir_name(cfg->channelTargetDir))) { + virReportOOMError(); + goto error; + } + if (chown(channeldir, cfg->user, cfg->group) < 0) { + virReportSystemError(errno, + _("unable to set ownership of '%s' to %d:= %d"), + channeldir, (int) cfg->user, + (int) cfg->group); + VIR_FREE(channeldir); + goto error; + } + VIR_FREE(channeldir); + if (chown(cfg->channelTargetDir, cfg->user, cfg->group) < 0) { + virReportSystemError(errno, + _("unable to set ownership of '%s' to %d:= %d"), + cfg->channelTargetDir, (int) cfg->user, + (int) cfg->group); + goto error; + } + if (chown(cfg->nvramDir, cfg->user, cfg->group) < 0) { + virReportSystemError(errno, + _("unable to set ownership of '%s' to %d:= %d"), + cfg->nvramDir, (int) cfg->user, + (int) cfg->group); + goto error; + } + if (chown(cfg->memoryBackingDir, cfg->user, cfg->group) < 0) { + virReportSystemError(errno, + _("unable to set ownership of '%s' to %d:= %d"), + cfg->memoryBackingDir, (int) cfg->user, + (int) cfg->group); + goto error; + } + + run_uid =3D cfg->user; + run_gid =3D cfg->group; + } + + driver->qemuCapsCache =3D virQEMUCapsCacheNew(cfg->libDir, + cfg->cacheDir, + run_uid, + run_gid); + if (!driver->qemuCapsCache) + goto error; + + if ((driver->caps =3D virQEMUDriverCreateCapabilities(driver)) =3D=3D = NULL) + goto error; + + if (!(driver->xmlopt =3D virQEMUDriverCreateXMLConf(driver))) + goto error; + + /* If hugetlbfs is present, then we need to create a sub-directory wit= hin + * it, since we can't assume the root mount point has permissions that + * will let our spawned QEMU instances use it. */ + for (i =3D 0; i < cfg->nhugetlbfs; i++) { + hugepagePath =3D qemuGetBaseHugepagePath(&cfg->hugetlbfs[i]); + + if (!hugepagePath) + goto error; + + if (virFileMakePath(hugepagePath) < 0) { + virReportSystemError(errno, + _("unable to create hugepage path %s"), + hugepagePath); + goto error; + } + if (privileged && + virFileUpdatePerm(cfg->hugetlbfs[i].mnt_dir, + 0, S_IXGRP | S_IXOTH) < 0) + goto error; + VIR_FREE(hugepagePath); + } + + if (qemuGetMemoryBackingBasePath(cfg, &memoryBackingPath) < 0) + goto error; + + if (virFileMakePath(memoryBackingPath) < 0) { + virReportSystemError(errno, + _("unable to create memory backing path %s"), + memoryBackingPath); + goto error; + } + + if (privileged && + virFileUpdatePerm(memoryBackingPath, + 0, S_IXGRP | S_IXOTH) < 0) + goto error; + VIR_FREE(memoryBackingPath); + + if (!(driver->closeCallbacks =3D virCloseCallbacksNew())) + goto error; + + return driver; + + error: + virObjectUnref(conn); + VIR_FREE(driverConf); + VIR_FREE(hugepagePath); + VIR_FREE(memoryBackingPath); + virQEMUControllerDriverFree(driver); + return NULL; +} + +static void show_help(FILE *io) +{ + fprintf(io, "\n"); + fprintf(io, "syntax: %s [OPTIONS] PATH-TO-XML\n", argv0); + fprintf(io, "\n"); + fprintf(io, "Options\n"); + fprintf(io, "\n"); + fprintf(io, " -c URI, --connect URI\n"); + fprintf(io, " -h, --help\n"); + fprintf(io, "\n"); +} + +static void +virQEMUControllerMain(void *opaque) +{ + int ret =3D -1; + virQEMUControllerPtr ctrl =3D opaque; + virQEMUDriverConfigPtr cfg; + virDomainChrSourceDef monitor_chr =3D { 0 }; + qemuDomainObjPrivatePtr priv; + virDomainPtr dom; + + if (!(ctrl->conn =3D virConnectOpen(ctrl->uri))) { + fprintf(stderr, "Unable to connect to %s: %s", + ctrl->uri, virGetLastErrorMessage()); + goto cleanup; + } + + if (!(ctrl->driver =3D virQEMUControllerNewDriver(ctrl->privileged))) { + fprintf(stderr, "Unable to initialize driver: %s", + virGetLastErrorMessage()); + goto cleanup; + } + + cfg =3D virObjectRef(ctrl->driver->config); + + if (qemuProcessPrepareMonitorChr(&monitor_chr, cfg->libDir) < 0) { + fprintf(stderr, "Unable to prepare QEMU monitor: %s\n", + virGetLastErrorMessage()); + goto cleanup; + } + + if (!(ctrl->vm =3D virDomainObjNew(ctrl->driver->xmlopt))) { + fprintf(stderr, "Unable to allocate domain object: %s\n", + virGetLastErrorMessage()); + goto cleanup; + } + + if (!(ctrl->vm->def =3D virDomainDefParseFile(ctrl->xml, + ctrl->driver->caps, ctrl->= driver->xmlopt, + NULL, VIR_DOMAIN_DEF_PARSE= _INACTIVE))) { + fprintf(stderr, "Unable to parse domain config %s\n", + virGetLastErrorMessage()); + goto cleanup; + } + + if (qemuProcessStart(NULL, ctrl->driver, ctrl->vm, NULL, 0, NULL, -1, = NULL, NULL, 0, 0) < 0) { + fprintf(stderr, "Unable to start QEMU: %s\n", + virGetLastErrorMessage()); + goto cleanup; + } + + priv =3D ctrl->vm->privateData; + + /* Release the monitor & agent sockets, so main libvirtd can take over= */ + qemuMonitorClose(priv->mon); + if (priv->agent) + qemuAgentClose(priv->agent); + + dom =3D virDomainQemuReconnect(ctrl->conn, ctrl->vm->def->name, 0); + if (!dom) { + qemuProcessStop(ctrl->driver, ctrl->vm, 0, 0, 0); + fprintf(stderr, "Unable to reconnect with libvirtd: %s\n", + virGetLastErrorMessage()); + goto cleanup; + } + + virObjectUnref(dom); + + fprintf(stderr, "QEMU running and connected\n"); + ret =3D 0; + cleanup: + virConnectClose(ctrl->conn); + if (ret < 0) + exit(EXIT_FAILURE); +} + +int main(int argc, char **argv) +{ + int rc =3D 1; + virThread thr; + virQEMUControllerPtr ctrl; + const struct option options[] =3D { + { "connect", 1, NULL, 'c' }, + { "help", 0, NULL, 'h' }, + { 0, 0, 0, 0 }, + }; + + argv0 =3D argv[0]; + + if (virGettextInitialize() < 0 || + virThreadInitialize() < 0 || + virErrorInitialize() < 0) { + fprintf(stderr, _("%s: initialization failed\n"), argv0); + exit(EXIT_FAILURE); + } + + /* Initialize logging */ + virLogSetFromEnv(); + + virUpdateSelfLastChanged(argv[0]); + + virFileActivateDirOverride(argv[0]); + + if (VIR_ALLOC(ctrl) < 0) + goto cleanup; + + ctrl->privileged =3D geteuid() =3D=3D 0; + ctrl->uri =3D ctrl->privileged ? "qemu:///system" : "qemu:///session"; + + while (1) { + int c; + + c =3D getopt_long(argc, argv, "c:h", + options, NULL); + + if (c =3D=3D -1) + break; + + switch (c) { + case 'c': + ctrl->uri =3D optarg; + break; + + case 'h': + case '?': + show_help(stdout); + rc =3D 0; + goto cleanup; + } + } + + ctrl->xml =3D argv[optind]; + + if (ctrl->xml =3D=3D NULL) { + fprintf(stderr, "Missing XML file path\n"); + show_help(stderr); + goto cleanup; + } + + if (virEventRegisterDefaultImpl() < 0) { + fprintf(stderr, "Unable to initialize events: %s", + virGetLastErrorMessage()); + goto cleanup; + } + + if (virThreadCreate(&thr, false, virQEMUControllerMain, ctrl) < 0) + goto cleanup; + + for (;;) + virEventRunDefaultImpl(); + + rc =3D 0; + + cleanup: + virStateCleanup(); + if (ctrl->conn) + virConnectClose(ctrl->conn); + virObjectUnref(ctrl->vm); + VIR_FREE(ctrl); + return rc; +} diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 74b82450b4..8c8e9891c8 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -262,7 +262,7 @@ qemuDomainDisableNamespace(virDomainObjPtr vm, void qemuDomainEventQueue(virQEMUDriverPtr driver, virObjectEventPtr event) { - if (event) + if (event && driver->domainEventState) virObjectEventStateQueue(driver->domainEventState, event); } =20 diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index fea1f24250..a7252ea913 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -371,7 +371,7 @@ qemuSecurityChownCallback(const virStorageSource *src, } =20 =20 -static int +int qemuSecurityInit(virQEMUDriverPtr driver) { char **names; --=20 2.14.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list