From nobody Fri Apr 19 11:48:47 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 207.211.31.81 as permitted sender) client-ip=207.211.31.81; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-1.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 207.211.31.81 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1578652486; cv=none; d=zohomail.com; s=zohoarc; b=JEBst2N4nIuf9im7X2A5jZcv5QCWc2UlHwQ9D7NsXLNqRXuipqrCUa05dip5K+eeBKxahnujeLxVCxVV5ucqL2CaO2NZcOhUfwoL03Se6C4Scf/ITHxaEkUprAI+DnK12RzVYAXF0NVNbkXNYRzB4+2BhWD/C/XjOU8BAcF3A/E= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1578652486; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=ohJuil34jxNYJMZU3HoOjZNjjNYE0YGUSu1H2znC+ns=; b=Q3xE/UYnWHWf/zNPt0Sm6e8fEbYal2vEBxpcYK9p24TP5m9KdfW8Zd9novboXNIl5aG0IRGebr/8D34z2ny7t4atmgMZOPiht2tKuHfN05qorEGc4Ck1uydnxjB3iB6LCu4EzyLtPXg1Wnk70haOVYXWnSbA25I+n42p049Uboo= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 207.211.31.81 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-delivery-1.mimecast.com (us-smtp-1.mimecast.com [207.211.31.81]) by mx.zohomail.com with SMTPS id 1578652486602950.5565272845794; Fri, 10 Jan 2020 02:34:46 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-261-oviRjcS1OrmGojfAFGznOA-1; Fri, 10 Jan 2020 05:34:43 -0500 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 7087D184B1F8; Fri, 10 Jan 2020 10:34:38 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 4B7CB60E3E; Fri, 10 Jan 2020 10:34:38 +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 0426518089CD; Fri, 10 Jan 2020 10:34:37 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 00AAYbYJ001899 for ; Fri, 10 Jan 2020 05:34:37 -0500 Received: by smtp.corp.redhat.com (Postfix) id 1844386CCA; Fri, 10 Jan 2020 10:34:37 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-112-65.ams2.redhat.com [10.36.112.65]) by smtp.corp.redhat.com (Postfix) with ESMTP id CEAD184665; Fri, 10 Jan 2020 10:34:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1578652485; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=ohJuil34jxNYJMZU3HoOjZNjjNYE0YGUSu1H2znC+ns=; b=jDBjKqxK1vKA3OS/Dik16BnuyQMljiOHuRvnznq1uT7lN5omVGmqPXlXRfzQlwjCZaIH5D 64vsPbRe1aF841E0s4QLYcp2WZrmBN5aulSDY8DLcfrfcufDQaOMANkB9+ekYW8m6wGbPY kbnwPiQDm2tGbrJmfxBTDk3dMq38RkE= From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= To: libvir-list@redhat.com Date: Fri, 10 Jan 2020 10:34:25 +0000 Message-Id: <20200110103430.3564679-2-berrange@redhat.com> In-Reply-To: <20200110103430.3564679-1-berrange@redhat.com> References: <20200110103430.3564679-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH v4 1/6] util: add helper API for getting URI parameters 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: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-MC-Unique: oviRjcS1OrmGojfAFGznOA-1 X-Mimecast-Spam-Score: 0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) Signed-off-by: Daniel P. Berrang=C3=A9 Reviewed-by: Michal Privoznik --- src/libvirt_private.syms | 1 + src/util/viruri.c | 16 ++++++++++++++++ src/util/viruri.h | 2 ++ 3 files changed, 19 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index b97906b852..5ed6729e6c 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -3335,6 +3335,7 @@ virTypedParamsValidate; virURIFormat; virURIFormatParams; virURIFree; +virURIGetParam; virURIParse; virURIResolveAlias; =20 diff --git a/src/util/viruri.c b/src/util/viruri.c index 1b848bd336..f16ea16ac1 100644 --- a/src/util/viruri.c +++ b/src/util/viruri.c @@ -376,3 +376,19 @@ virURIResolveAlias(virConfPtr conf, const char *alias,= char **uri) =20 return ret; } + + +const char * +virURIGetParam(virURIPtr uri, const char *name) +{ + size_t i; + + for (i =3D 0; i < uri->paramsCount; i++) { + if (STREQ(uri->params[i].name, name)) + return uri->params[i].value; + } + + virReportError(VIR_ERR_INVALID_ARG, + _("Missing URI parameter '%s'"), name); + return NULL; +} diff --git a/src/util/viruri.h b/src/util/viruri.h index b7f845f41f..1735620a2f 100644 --- a/src/util/viruri.h +++ b/src/util/viruri.h @@ -62,4 +62,6 @@ void virURIFree(virURIPtr uri); G_DEFINE_AUTOPTR_CLEANUP_FUNC(virURI, virURIFree); int virURIResolveAlias(virConfPtr conf, const char *alias, char **uri); =20 +const char *virURIGetParam(virURIPtr uri, const char *name); + #define VIR_URI_SERVER(uri) ((uri) && (uri)->server ? (uri)->server : "loc= alhost") --=20 2.23.0 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Fri Apr 19 11:48:47 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 205.139.110.120 as permitted sender) client-ip=205.139.110.120; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-1.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 205.139.110.120 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1578652492; cv=none; d=zohomail.com; s=zohoarc; b=XLHObRxzRON2/xAXj4zbW7iwWbYlbDnWFu4wnrkklercepQ6WXdGR2L65QlCSliHiz3sRyPpxif8SNq44sfq8PG4GbmNcJzlcTF8fz7YWA+qQobbZLOg9IQvsTGFjf2h/sDCPffYYoycJmpq9Z/GOougQByQd3zxHaGLiwLa9o0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1578652492; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=ba6yaxSKUIlLcfUZMBXHewk23BiWbo9LcGVbzgpqToA=; b=c2stT/41ZWZDjuoztiTKRdTG8gJFGBwcXX2HGwcmaq1/FTY1YmZUGAXoh91sPH8yD1g+OcZ3J+Y+E1swTDAwk6H5wRZTAzb9HnuZaFJw5z3rlTSfGQvwNSuX+vrgz9tkpTbi5niYwaUsuhjhVe8HaCJRilfZvE7sPcRfzGMknmw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 205.139.110.120 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [205.139.110.120]) by mx.zohomail.com with SMTPS id 1578652492896805.4915974298551; Fri, 10 Jan 2020 02:34:52 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-278-G0xTQtlCP7alqg9ADz65LQ-1; Fri, 10 Jan 2020 05:34:49 -0500 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 mimecast-mx01.redhat.com (Postfix) with ESMTPS id 7A1D4800D50; Fri, 10 Jan 2020 10:34:44 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 555025C28C; Fri, 10 Jan 2020 10:34:44 +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 1BCA218089D6; Fri, 10 Jan 2020 10:34:44 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 00AAYcL1001912 for ; Fri, 10 Jan 2020 05:34:38 -0500 Received: by smtp.corp.redhat.com (Postfix) id DCE7B86CA0; Fri, 10 Jan 2020 10:34:38 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-112-65.ams2.redhat.com [10.36.112.65]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7E2FC858AB; Fri, 10 Jan 2020 10:34:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1578652491; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=ba6yaxSKUIlLcfUZMBXHewk23BiWbo9LcGVbzgpqToA=; b=aGEbawZxhgjJJ4626fyl/7x8Dm4GSgaaoQfcVGfne+aNeMLc1MzJkvD3zCZM3szSGr98Gq cGFSmReRXbGE4TrZPG7FhCUMJ55IgvOjZBVVgCuEK61b0snnmYr229hfXBVNXGtcESW+C5 51GUAg+HeohfZ1uWSSIAlwypXUG5wYQ= From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= To: libvir-list@redhat.com Date: Fri, 10 Jan 2020 10:34:26 +0000 Message-Id: <20200110103430.3564679-3-berrange@redhat.com> In-Reply-To: <20200110103430.3564679-1-berrange@redhat.com> References: <20200110103430.3564679-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-loop: libvir-list@redhat.com Cc: Michal Privoznik , Cole Robinson Subject: [libvirt] [PATCH v4 2/6] libvirt: pass a directory path into drivers for embedded usage 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: , 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-MC-Unique: G0xTQtlCP7alqg9ADz65LQ-1 X-Mimecast-Spam-Score: 0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) The intent here is to allow the virt drivers to be run directly embedded in an arbitrary process without interfering with libvirtd. To achieve this they need to store all their configuration & state in a separate directory tree from the main system or session libvirtd instances. This can be useful for doing testing of the virt drivers in "make check" without interfering with the user's own libvirtd instances. It can also be used for applications using KVM/QEMU as a piece of infrastructure to build an service, rather than for general purpose OS hosting. A long standing example is libguestfs, which would prefer if its temporary VMs did show up in the main libvirtd VM list, because this confuses apps such as OpenStack Nova. A more recent example would be Kata which is using KVM as a technology to build containers. Reviewed-by: Michal Privoznik Reviewed-by: Cole Robinson Signed-off-by: Daniel P. Berrang=C3=A9 --- src/driver-state.h | 1 + src/interface/interface_backend_netcf.c | 7 +++++++ src/interface/interface_backend_udev.c | 7 +++++++ src/libvirt.c | 21 +++++++++++++++++++++ src/libvirt_internal.h | 4 +++- src/libxl/libxl_driver.c | 7 +++++++ src/lxc/lxc_driver.c | 8 ++++++++ src/network/bridge_driver.c | 7 +++++++ src/node_device/node_device_hal.c | 7 +++++++ src/node_device/node_device_udev.c | 7 +++++++ src/nwfilter/nwfilter_driver.c | 7 +++++++ src/qemu/qemu_driver.c | 7 +++++++ src/remote/remote_daemon.c | 1 + src/remote/remote_driver.c | 1 + src/secret/secret_driver.c | 7 +++++++ src/storage/storage_driver.c | 7 +++++++ src/vz/vz_driver.c | 7 +++++++ 17 files changed, 112 insertions(+), 1 deletion(-) diff --git a/src/driver-state.h b/src/driver-state.h index 69e2678dfc..1e2f6ed247 100644 --- a/src/driver-state.h +++ b/src/driver-state.h @@ -32,6 +32,7 @@ typedef enum { =20 typedef virDrvStateInitResult (*virDrvStateInitialize)(bool privileged, + const char *root, virStateInhibitCallback callback, void *opaque); =20 diff --git a/src/interface/interface_backend_netcf.c b/src/interface/interf= ace_backend_netcf.c index 65cb7eae62..06eb1ace08 100644 --- a/src/interface/interface_backend_netcf.c +++ b/src/interface/interface_backend_netcf.c @@ -89,9 +89,16 @@ virNetcfDriverStateDispose(void *obj) =20 static int netcfStateInitialize(bool privileged, + const char *root, virStateInhibitCallback callback G_GNUC_UNUSED, void *opaque G_GNUC_UNUSED) { + if (root !=3D NULL) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("Driver does not support embedded mode")); + return -1; + } + if (virNetcfDriverStateInitialize() < 0) return VIR_DRV_STATE_INIT_ERROR; =20 diff --git a/src/interface/interface_backend_udev.c b/src/interface/interfa= ce_backend_udev.c index 7cc098eb33..e87b884c17 100644 --- a/src/interface/interface_backend_udev.c +++ b/src/interface/interface_backend_udev.c @@ -1145,11 +1145,18 @@ udevStateCleanup(void); =20 static int udevStateInitialize(bool privileged, + const char *root, virStateInhibitCallback callback G_GNUC_UNUSED, void *opaque G_GNUC_UNUSED) { int ret =3D VIR_DRV_STATE_INIT_ERROR; =20 + if (root !=3D NULL) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("Driver does not support embedded mode")); + return -1; + } + if (VIR_ALLOC(driver) < 0) goto cleanup; =20 diff --git a/src/libvirt.c b/src/libvirt.c index f1ffc97261..4de87cdecd 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -609,16 +609,36 @@ virRegisterStateDriver(virStateDriverPtr driver) * virStateInitialize: * @privileged: set to true if running with root privilege, false otherwise * @mandatory: set to true if all drivers must report success, not skipped + * @root: directory to use for embedded mode * @callback: callback to invoke to inhibit shutdown of the daemon * @opaque: data to pass to @callback * * Initialize all virtualization drivers. * + * Passing a non-NULL @root instructs the driver to run in embedded mode. + * Instead of using the compile time $prefix as the basis for directory + * paths, @root should be used instead. In addition any '/libvirt' + * component of the paths should be stripped. + * + * eg consider a build with prefix=3D/usr/local. A driver might use the + * locations + * + * /usr/local/etc/libvirt/$DRIVER/ + * /usr/local/var/lib/libvirt/$DRIVER/ + * /usr/local/run/libvirt/$DRIVER/ + * + * When run with @root, the locations should instead be + * + * @root/etc/$DRIVER/ + * @root/var/lib/$DRIVER/ + * @root/run/$DRIVER/ + * * Returns 0 if all succeed, -1 upon any failure. */ int virStateInitialize(bool privileged, bool mandatory, + const char *root, virStateInhibitCallback callback, void *opaque) { @@ -633,6 +653,7 @@ virStateInitialize(bool privileged, VIR_DEBUG("Running global init for %s state driver", virStateDriverTab[i]->name); ret =3D virStateDriverTab[i]->stateInitialize(privileged, + root, callback, opaque); VIR_DEBUG("State init result %d (mandatory=3D%d)", ret, mandat= ory); diff --git a/src/libvirt_internal.h b/src/libvirt_internal.h index 4a74dbc2af..00ef7aaf25 100644 --- a/src/libvirt_internal.h +++ b/src/libvirt_internal.h @@ -31,8 +31,10 @@ typedef void (*virStateInhibitCallback)(bool inhibit, =20 int virStateInitialize(bool privileged, bool mandatory, + const char *root, virStateInhibitCallback inhibit, - void *opaque); + void *opaque) + ATTRIBUTE_NONNULL(2); int virStateCleanup(void); int virStateReload(void); int virStateStop(void); diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index f021ec9c5d..85a1fc5de7 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -648,6 +648,7 @@ libxlAddDom0(libxlDriverPrivatePtr driver) =20 static int libxlStateInitialize(bool privileged, + const char *root, virStateInhibitCallback callback G_GNUC_UNUSED, void *opaque G_GNUC_UNUSED) { @@ -656,6 +657,12 @@ libxlStateInitialize(bool privileged, char ebuf[1024]; bool autostart =3D true; =20 + if (root !=3D NULL) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("Driver does not support embedded mode")); + return -1; + } + if (!libxlDriverShouldLoad(privileged)) return VIR_DRV_STATE_INIT_SKIPPED; =20 diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 780c6ed4a2..47175d92b8 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -85,6 +85,7 @@ VIR_LOG_INIT("lxc.lxc_driver"); =20 =20 static int lxcStateInitialize(bool privileged, + const char *root, virStateInhibitCallback callback, void *opaque); static int lxcStateCleanup(void); @@ -1526,12 +1527,19 @@ lxcSecurityInit(virLXCDriverConfigPtr cfg) =20 =20 static int lxcStateInitialize(bool privileged, + const char *root, virStateInhibitCallback callback G_GNUC_UNUS= ED, void *opaque G_GNUC_UNUSED) { virLXCDriverConfigPtr cfg =3D NULL; bool autostart =3D true; =20 + if (root !=3D NULL) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("Driver does not support embedded mode")); + return -1; + } + /* Check that the user is root, silently disable if not */ if (!privileged) { VIR_INFO("Not running privileged, disabling driver"); diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index c9c45df758..b66135f2d9 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -702,6 +702,7 @@ firewalld_dbus_filter_bridge(DBusConnection *connection= G_GNUC_UNUSED, */ static int networkStateInitialize(bool privileged, + const char *root, virStateInhibitCallback callback G_GNUC_UNUSED, void *opaque G_GNUC_UNUSED) { @@ -713,6 +714,12 @@ networkStateInitialize(bool privileged, DBusConnection *sysbus =3D NULL; #endif =20 + if (root !=3D NULL) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("Driver does not support embedded mode")); + return -1; + } + if (VIR_ALLOC(network_driver) < 0) goto error; =20 diff --git a/src/node_device/node_device_hal.c b/src/node_device/node_devic= e_hal.c index 4cef7c2c12..c3ca310bb7 100644 --- a/src/node_device/node_device_hal.c +++ b/src/node_device/node_device_hal.c @@ -580,6 +580,7 @@ device_prop_modified(LibHalContext *ctx G_GNUC_UNUSED, =20 static int nodeStateInitialize(bool privileged G_GNUC_UNUSED, + const char *root, virStateInhibitCallback callback G_GNUC_UNUSED, void *opaque G_GNUC_UNUSED) { @@ -591,6 +592,12 @@ nodeStateInitialize(bool privileged G_GNUC_UNUSED, DBusConnection *sysbus; DBusError err; =20 + if (root !=3D NULL) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("Driver does not support embedded mode")); + return -1; + } + /* Ensure caps_tbl is sorted by capability name */ qsort(caps_tbl, G_N_ELEMENTS(caps_tbl), sizeof(caps_tbl[0]), cmpstringp); diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_devi= ce_udev.c index 4b33dc25d8..396763fa29 100644 --- a/src/node_device/node_device_udev.c +++ b/src/node_device/node_device_udev.c @@ -1781,6 +1781,7 @@ udevPCITranslateInit(bool privileged G_GNUC_UNUSED) =20 static int nodeStateInitialize(bool privileged, + const char *root, virStateInhibitCallback callback G_GNUC_UNUSED, void *opaque G_GNUC_UNUSED) { @@ -1788,6 +1789,12 @@ nodeStateInitialize(bool privileged, struct udev *udev =3D NULL; virThread enumThread; =20 + if (root !=3D NULL) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("Driver does not support embedded mode")); + return -1; + } + if (VIR_ALLOC(driver) < 0) return VIR_DRV_STATE_INIT_ERROR; =20 diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c index cc3ce98cc5..1c407727db 100644 --- a/src/nwfilter/nwfilter_driver.c +++ b/src/nwfilter/nwfilter_driver.c @@ -177,11 +177,18 @@ virNWFilterTriggerRebuildImpl(void *opaque) */ static int nwfilterStateInitialize(bool privileged, + const char *root, virStateInhibitCallback callback G_GNUC_UNUSED, void *opaque G_GNUC_UNUSED) { DBusConnection *sysbus =3D NULL; =20 + if (root !=3D NULL) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("Driver does not support embedded mode")); + return -1; + } + if (virDBusHasSystemBus() && !(sysbus =3D virDBusGetSystemBus())) return VIR_DRV_STATE_INIT_ERROR; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 1fc662b3c8..56d420f608 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -631,6 +631,7 @@ qemuDomainFindMaxID(virDomainObjPtr vm, */ static int qemuStateInitialize(bool privileged, + const char *root, virStateInhibitCallback callback, void *opaque) { @@ -644,6 +645,12 @@ qemuStateInitialize(bool privileged, const char *defsecmodel =3D NULL; g_autofree virSecurityManagerPtr *sec_managers =3D NULL; =20 + if (root !=3D NULL) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("Driver does not support embedded mode")); + return -1; + } + if (VIR_ALLOC(qemu_driver) < 0) return VIR_DRV_STATE_INIT_ERROR; =20 diff --git a/src/remote/remote_daemon.c b/src/remote/remote_daemon.c index cd55b2c39e..34788fb9b5 100644 --- a/src/remote/remote_daemon.c +++ b/src/remote/remote_daemon.c @@ -834,6 +834,7 @@ static void daemonRunStateInit(void *opaque) * seriously delay OS bootup process */ if (virStateInitialize(virNetDaemonIsPrivileged(dmn), mandatory, + NULL, daemonInhibitCallback, dmn) < 0) { VIR_ERROR(_("Driver state initialization failed")); diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index c11f73ab4d..9b60cc5161 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -235,6 +235,7 @@ static int remoteSplitURIScheme(virURIPtr uri, =20 static int remoteStateInitialize(bool privileged G_GNUC_UNUSED, + const char *root G_GNUC_UNUSED, virStateInhibitCallback callback G_GNUC_UNUSED, void *opaque G_GNUC_UNUSED) { diff --git a/src/secret/secret_driver.c b/src/secret/secret_driver.c index c3c57a41c7..a31005c731 100644 --- a/src/secret/secret_driver.c +++ b/src/secret/secret_driver.c @@ -452,9 +452,16 @@ secretStateCleanup(void) =20 static int secretStateInitialize(bool privileged, + const char *root, virStateInhibitCallback callback G_GNUC_UNUSED, void *opaque G_GNUC_UNUSED) { + if (root !=3D NULL) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("Driver does not support embedded mode")); + return -1; + } + if (VIR_ALLOC(driver) < 0) return VIR_DRV_STATE_INIT_ERROR; =20 diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c index 0bb116cf08..2dd093a9da 100644 --- a/src/storage/storage_driver.c +++ b/src/storage/storage_driver.c @@ -250,6 +250,7 @@ storageDriverAutostart(void) */ static int storageStateInitialize(bool privileged, + const char *root, virStateInhibitCallback callback G_GNUC_UNUSED, void *opaque G_GNUC_UNUSED) { @@ -257,6 +258,12 @@ storageStateInitialize(bool privileged, g_autofree char *rundir =3D NULL; bool autostart =3D true; =20 + if (root !=3D NULL) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("Driver does not support embedded mode")); + return -1; + } + if (VIR_ALLOC(driver) < 0) return VIR_DRV_STATE_INIT_ERROR; =20 diff --git a/src/vz/vz_driver.c b/src/vz/vz_driver.c index bcdbb50404..e833f59235 100644 --- a/src/vz/vz_driver.c +++ b/src/vz/vz_driver.c @@ -4094,12 +4094,19 @@ vzStateCleanup(void) =20 static int vzStateInitialize(bool privileged, + const char *root, virStateInhibitCallback callback G_GNUC_UNUSED, void *opaque G_GNUC_UNUSED) { if (!privileged) return VIR_DRV_STATE_INIT_SKIPPED; =20 + if (root !=3D NULL) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("Driver does not support embedded mode")); + return -1; + } + vz_driver_privileged =3D privileged; =20 if (virFileMakePathWithMode(VZ_STATEDIR, S_IRWXU) < 0) { --=20 2.23.0 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Fri Apr 19 11:48:47 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 207.211.31.81 as permitted sender) client-ip=207.211.31.81; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-1.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 207.211.31.81 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1578652496; cv=none; d=zohomail.com; s=zohoarc; b=ITSaDC0U+KdNMBv8twcaP5LQXVKut1FwUimPmhLmD6ktFP7DI5IY4wEV6ZQnkESBLXrOc+acqOn+NjCfE5eyaxnAiKe8arS+6v6ImHVrJ4Oy0cnRxq49wFzmGQBcxmQarhyc1INqqpAxGvlC3WjRVsR59LTza0DDKDCHc7TsQ1o= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1578652496; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=G4ZVRv7WKlPc+jS9M/Lg61y9BL06fgjO4MO4lPX7L/U=; b=JeUS8ejjKcXoo2Nr/BBGRyyrYR4bVNGm+2jBjmrmn3UnGRldWT6ZT0bmv1iGhKY+G2EJWNsvlJFnHHu4g9wGQLUoz/QAObS/HLe5ulGQYDKv9nGdeN1OTKoFT6gv6IsbLHkAOpUeT2oZrMVEIgE7d42mkfB/K3ThoZcII6AEhBI= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 207.211.31.81 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-delivery-1.mimecast.com (us-smtp-1.mimecast.com [207.211.31.81]) by mx.zohomail.com with SMTPS id 1578652496310609.6597913260722; Fri, 10 Jan 2020 02:34:56 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-29-M8R9-O7POj2MlKq8gj1FFQ-1; Fri, 10 Jan 2020 05:34:53 -0500 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 58749107ACCC; Fri, 10 Jan 2020 10:34:48 +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 2F1A580629; Fri, 10 Jan 2020 10:34:48 +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 D9BCA503DC; Fri, 10 Jan 2020 10:34:47 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 00AAYe4F001921 for ; Fri, 10 Jan 2020 05:34:40 -0500 Received: by smtp.corp.redhat.com (Postfix) id 391BA86CA5; Fri, 10 Jan 2020 10:34:40 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-112-65.ams2.redhat.com [10.36.112.65]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3D76884665; Fri, 10 Jan 2020 10:34:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1578652495; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=G4ZVRv7WKlPc+jS9M/Lg61y9BL06fgjO4MO4lPX7L/U=; b=gmI4qN52/KwN6gb+dfBlFvkAs1tkeq1SC8EkwvXBpfMbSs8rUgZ0tZs5ieQy+tNDm0g4bz 0K1bq9CJ4o7wXwv3qiNug25nUUvjCVJV7XzS7YuliXGTSQKHXwa7U5yQWRpWyEF+8XReJZ fOq+kkORCZi/MZmPIi+iSOy4ijCCFuk= From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= To: libvir-list@redhat.com Date: Fri, 10 Jan 2020 10:34:27 +0000 Message-Id: <20200110103430.3564679-4-berrange@redhat.com> In-Reply-To: <20200110103430.3564679-1-berrange@redhat.com> References: <20200110103430.3564679-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-loop: libvir-list@redhat.com Cc: Michal Privoznik Subject: [libvirt] [PATCH v4 3/6] libvirt: support an "embed" URI path selector for opening drivers 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: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-MC-Unique: M8R9-O7POj2MlKq8gj1FFQ-1 X-Mimecast-Spam-Score: 0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) The driver URI scheme: "$drivername:///embed?root=3D/some/path" enables a new way to use the drivers by embedding them directly in the calling process. To use this the process must have a thread running the libvirt event loop. This URI will then cause libvirt to dynamically load the driver module and call its global initialization function. This syntax is applicable to any driver, but only those will have been modified to support a custom root directory and embed URI path will successfully open. The application can now make normal libvirt API calls which are all serviced in-process with no RPC layer involved. It is required to specify an explicit root directory, and locks will be acquired on this directory to avoid conflicting with another app that might accidentally pick the same directory. Use of '/' is not explicitly forbidden, but note that the file layout used underneath the embedded driver root does not match the file layout used by system/session mode drivers. So this cannot be used as a backdoor to interact with, or fake, the system/session mode drivers. Libvirt will create arbitrary files underneath this root directory. The root directory can be kept untouched across connection open attempts if the application needs persistence. The application is responsible for purging everything underneath this root directory when finally no longer required. Even when a virt driver is used in embedded mode, it is still possible for it to in turn use functionality that calls out to other secondary drivers in libvirtd. For example an embedded instance of QEMU can open the network, secret or storage drivers in the system libvirtd. That said, the application would typically want to at least open an embedded secret driver ("secret:///embed?root=3D/some/path"). Note that multiple different embedded drivers can use the same root prefix and co-operate just as they would inside a normal libvirtd daemon. A key thing to note is that for this to work, the application that links to libvirt *MUST* be built with -Wl,--export-dynamic to ensure that symbols from libvirt.so are exported & thus available to the dynamically loaded driver module. If libvirt.so itself was dynamically loaded then RTLD_GLOBAL must be passed to dlopen(). Reviewed-by: Michal Privoznik Signed-off-by: Daniel P. Berrang=C3=A9 --- src/driver-state.h | 1 + src/driver.h | 2 ++ src/libvirt.c | 72 ++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 73 insertions(+), 2 deletions(-) diff --git a/src/driver-state.h b/src/driver-state.h index 1e2f6ed247..6b3f501e05 100644 --- a/src/driver-state.h +++ b/src/driver-state.h @@ -50,6 +50,7 @@ typedef virStateDriver *virStateDriverPtr; =20 struct _virStateDriver { const char *name; + bool initialized; virDrvStateInitialize stateInitialize; virDrvStateCleanup stateCleanup; virDrvStateReload stateReload; diff --git a/src/driver.h b/src/driver.h index ca82ac974b..6278aa05b3 100644 --- a/src/driver.h +++ b/src/driver.h @@ -82,6 +82,8 @@ struct _virConnectDriver { bool localOnly; /* Whether driver needs a server in the URI */ bool remoteOnly; + /* Whether driver can be used in embedded mode */ + bool embeddable; /* * NULL terminated list of supported URI schemes. * - Single element { NULL } list indicates no supported schemes diff --git a/src/libvirt.c b/src/libvirt.c index 4de87cdecd..5599d5ff31 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -49,6 +49,7 @@ # include "rpc/virnettlscontext.h" #endif #include "vircommand.h" +#include "virevent.h" #include "virfile.h" #include "virrandom.h" #include "viruri.h" @@ -78,6 +79,7 @@ #ifdef WITH_BHYVE # include "bhyve/bhyve_driver.h" #endif +#include "access/viraccessmanager.h" =20 #define VIR_FROM_THIS VIR_FROM_NONE =20 @@ -648,10 +650,12 @@ virStateInitialize(bool privileged, return -1; =20 for (i =3D 0; i < virStateDriverTabCount; i++) { - if (virStateDriverTab[i]->stateInitialize) { + if (virStateDriverTab[i]->stateInitialize && + !virStateDriverTab[i]->initialized) { virDrvStateInitResult ret; VIR_DEBUG("Running global init for %s state driver", virStateDriverTab[i]->name); + virStateDriverTab[i]->initialized =3D true; ret =3D virStateDriverTab[i]->stateInitialize(privileged, root, callback, @@ -844,6 +848,7 @@ virConnectOpenInternal(const char *name, virConnectPtr ret; g_autoptr(virConf) conf =3D NULL; char *uristr =3D NULL; + bool embed =3D false; =20 ret =3D virGetConnect(); if (ret =3D=3D NULL) @@ -934,6 +939,52 @@ virConnectOpenInternal(const char *name, ret->uri) < 0) { goto failed; } + + if (STREQ(ret->uri->path, "/embed")) { + const char *root =3D NULL; + g_autofree char *regMethod =3D NULL; + VIR_DEBUG("URI path requests %s driver embedded mode", + ret->uri->scheme); + if (strspn(ret->uri->scheme, "abcdefghijklmnopqrstuvwxyz") != =3D + strlen(ret->uri->scheme)) { + virReportError(VIR_ERR_NO_CONNECT, + _("URI scheme '%s' for embedded driver is n= ot valid"), + ret->uri->scheme); + goto failed; + } + + for (i =3D 0; i < ret->uri->paramsCount; i++) { + virURIParamPtr var =3D &ret->uri->params[i]; + if (STREQ(var->name, "root")) + root =3D var->value; + } + + if (!root) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("root parameter required for embedded dri= ver")); + goto failed; + } + + if (virEventRequireImpl() < 0) + goto failed; + + regMethod =3D g_strdup_printf("%sRegister", ret->uri->scheme); + + if (virDriverLoadModule(ret->uri->scheme, regMethod, false) < = 0) + goto failed; + + if (virAccessManagerGetDefault() =3D=3D NULL) { + virAccessManagerPtr acl =3D virAccessManagerNew("none"); + if (!acl) + goto failed; + virAccessManagerSetDefault(acl); + } + + if (virStateInitialize(geteuid() =3D=3D 0, true, root, NULL, N= ULL) < 0) + goto failed; + + embed =3D true; + } } else { VIR_DEBUG("no name, allowing driver auto-select"); } @@ -987,6 +1038,12 @@ virConnectOpenInternal(const char *name, VIR_DEBUG("No URI, skipping driver with URI whitelist"); continue; } + if (embed && !virConnectDriverTab[i]->embeddable) { + VIR_DEBUG("Ignoring non-embeddable driver %s", + virConnectDriverTab[i]->hypervisorDriver->name); + continue; + } + VIR_DEBUG("Checking for supported URI schemes"); for (s =3D 0; virConnectDriverTab[i]->uriSchemes[s] !=3D NULL;= s++) { if (STREQ(ret->uri->scheme, virConnectDriverTab[i]->uriSch= emes[s])) { @@ -1000,9 +1057,20 @@ virConnectOpenInternal(const char *name, continue; } } else { - VIR_DEBUG("Matching any URI scheme for '%s'", ret->uri ? ret->= uri->scheme : ""); + if (embed) { + VIR_DEBUG("Skipping wildcard for embedded URI"); + continue; + } else { + VIR_DEBUG("Matching any URI scheme for '%s'", ret->uri ? r= et->uri->scheme : ""); + } } =20 + if (embed && !virConnectDriverTab[i]->embeddable) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Driver %s cannot be used in embedded mode"), + virConnectDriverTab[i]->hypervisorDriver->name); + goto failed; + } /* before starting the new connection, check if the driver only wo= rks * with a server, and so return an error if the server is missing = */ if (virConnectDriverTab[i]->remoteOnly && ret->uri && !ret->uri->s= erver) { --=20 2.23.0 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Fri Apr 19 11:48:47 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 207.211.31.120 as permitted sender) client-ip=207.211.31.120; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-1.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 207.211.31.120 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1578652494; cv=none; d=zohomail.com; s=zohoarc; b=es4LLgLvjotdmx/1tF7hjyvx0VtVslZYcbPeBJUdt3Nv7kqab1bJVPz2UgrwtG8JUENIs4wsEaGT3FWqfnM0ooVRc07ud6uHAkPoHN1KMA4YK1TLzaL9h+loQb24Suf6Iqx9G3QyXItFp3c4CpUcJPyLruakXzQqrsQGU482oj8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1578652494; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=JOH0f/bg4XR78U3XkV/YlvbaNgF6bZ90GQmrKF9Uvcw=; b=YMvA8O/pim2wXtt7gdBzOlTgicpMEVWiBIC9ZxQbuqsds18iLAfXwf7kDMTuppnAZefLQfVDRzD68a1qqBK6xnIswx9PsBw+ix3Z/7wCO7Y+0uKfl2rTO+PlRGpMS0usGDkb+hhq9W964gXGlzlEj/lsF0ChIiYJe7Aeli5AjCY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 207.211.31.120 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [207.211.31.120]) by mx.zohomail.com with SMTPS id 1578652494356942.123915322187; Fri, 10 Jan 2020 02:34:54 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-53-YOGUfuB0NX-ObStwIQ9CIQ-1; Fri, 10 Jan 2020 05:34:51 -0500 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 mimecast-mx01.redhat.com (Postfix) with ESMTPS id E25EC800EBF; Fri, 10 Jan 2020 10:34:45 +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 BCC3E5C28C; Fri, 10 Jan 2020 10:34:45 +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 78335503D4; Fri, 10 Jan 2020 10:34:45 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 00AAYfa0001931 for ; Fri, 10 Jan 2020 05:34:41 -0500 Received: by smtp.corp.redhat.com (Postfix) id 5DFF986CA0; Fri, 10 Jan 2020 10:34:41 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-112-65.ams2.redhat.com [10.36.112.65]) by smtp.corp.redhat.com (Postfix) with ESMTP id 87DDF84665; Fri, 10 Jan 2020 10:34:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1578652493; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=JOH0f/bg4XR78U3XkV/YlvbaNgF6bZ90GQmrKF9Uvcw=; b=P6GYmEnNTT1IjCi591pPBHCiNdQWpUUFgfKby8Fk9cAvJyOCZ+S01fRP0amDszypNikuc0 fCSQKgOU9f4ghBSfKXoI0j/GeAPesbTUo64TCvl+6yDkmHTdAJSYuYrKaxkhkNO4ZZ3O3d Dt21Us6JGq170m/nZuyJhWpiu0qYtMQ= From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= To: libvir-list@redhat.com Date: Fri, 10 Jan 2020 10:34:28 +0000 Message-Id: <20200110103430.3564679-5-berrange@redhat.com> In-Reply-To: <20200110103430.3564679-1-berrange@redhat.com> References: <20200110103430.3564679-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH v4 4/6] qemu: add support for running QEMU driver in embedded mode 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: , 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-MC-Unique: YOGUfuB0NX-ObStwIQ9CIQ-1 X-Mimecast-Spam-Score: 0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) This enables support for running QEMU embedded to the calling application process using a URI: qemu:///embed?root=3D/some/path Note that it is important to keep the path reasonably short to avoid risk of hitting the limit on UNIX socket path names which is 108 characters. When using the embedded mode with a root=3D/var/tmp/embed, the driver will use the following paths: logDir: /var/tmp/embed/log/qemu swtpmLogDir: /var/tmp/embed/log/swtpm configBaseDir: /var/tmp/embed/etc/qemu stateDir: /var/tmp/embed/run/qemu swtpmStateDir: /var/tmp/embed/run/swtpm cacheDir: /var/tmp/embed/cache/qemu libDir: /var/tmp/embed/lib/qemu swtpmStorageDir: /var/tmp/embed/lib/swtpm defaultTLSx509certdir: /var/tmp/embed/etc/pki/qemu These are identical whether the embedded driver is privileged or unprivileged. This compares with the system instance which uses logDir: /var/log/libvirt/qemu swtpmLogDir: /var/log/swtpm/libvirt/qemu configBaseDir: /etc/libvirt/qemu stateDir: /run/libvirt/qemu swtpmStateDir: /run/libvirt/qemu/swtpm cacheDir: /var/cache/libvirt/qemu libDir: /var/lib/libvirt/qemu swtpmStorageDir: /var/lib/libvirt/swtpm defaultTLSx509certdir: /etc/pki/qemu At this time all features present in the QEMU driver are available when running in embedded mode, availability matching whether the embedded driver is privileged or unprivileged. Signed-off-by: Daniel P. Berrang=C3=A9 Reviewed-by: Michal Privoznik --- docs/drvqemu.html.in | 99 +++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_conf.c | 45 +++++++++++++++++-- src/qemu/qemu_conf.h | 8 ++-- src/qemu/qemu_driver.c | 39 +++++++++++----- src/qemu/qemu_process.c | 15 +++++-- tests/domaincapstest.c | 2 +- tests/testutilsqemu.c | 3 +- 7 files changed, 186 insertions(+), 25 deletions(-) diff --git a/docs/drvqemu.html.in b/docs/drvqemu.html.in index 8beb28655c..f6abb45706 100644 --- a/docs/drvqemu.html.in +++ b/docs/drvqemu.html.in @@ -63,6 +63,105 @@ qemu+tcp://example.com/system (remote access, SA= Sl/Kerberos) qemu+ssh://root@example.com/system (remote access, SSH tunnelled) =20 +

Embedded driver

+ +

+ Since 6.0.0 the QEMU driver has experimental support for operating + in an embedded mode. In this scenario, rather than connecting to + the libvirtd daemon, the QEMU driver runs in the client application + process directly. To use this the client application must have + registered & be running an instance of the event loop. To open + the driver in embedded mode the app use the new URI path and specify + a virtual root directory under which the driver will create content. +

+ +
+      qemu:///embed?root=3D/some/dir
+    
+ +

+ Broadly speaking the range of functionality is intended to be + on a par with that seen when using the traditional system or + session libvirt connections to QEMU. The features will of course + differ depending on whether the application using the embedded + driver is running privileged or unprivileged. For example PCI + device assignment or TAP based networking are only available + when running privileged. While the embedded mode is still classed + as experimental some features may change their default settings + between releases. +

+ +

+ By default if the application uses any APIs associated with + secondary drivers, these will result in a connection being + opened to the corresponding driver in libvirtd. For example, + this allows a virtual machine from the embedded QEMU to connect + its NIC to a virtual network or connect its disk to a storage + volume. Some of the secondary drivers will also be able to support + running in embedded mode. Currently this is supported by the + secrets driver, to allow for use of VMs with encrypted disks +

+ +

Directory tree

+ +

+ Under the specified root directory the following locations will + be used +

+ +
+/some/dir
+  |
+  +- log
+  |   |
+  |   +- qemu
+  |   +- swtpm
+  |
+  +- etc
+  |   |
+  |   +- qemu
+  |   +- pki
+  |       |
+  |       +- qemu
+  |
+  +- run
+  |   |
+  |   +- qemu
+  |   +- swtpm
+  |
+  +- cache
+  |   |
+  |   +- qemu
+  |
+  +- lib
+      |
+      +- qemu
+      +- swtpm
+    
+ +

+ Note that UNIX domain sockets used for QEMU virtual machines had + a maximum filename length of 108 characters. Bear this in mind + when picking a root directory to avoid risk of exhausting the + filename space. The application is responsible for recursively + purging the contents of this directory tree once they no longer + require a connection, though it can also be left intact for reuse + when opening a future connection. +

+ +

API usage with event loop>

+ +

+ To use the QEMU driver in embedded mode the application must + register an event loop with libvirt. Many of the QEMU driver + API calls will rely on the event loop processing data. With this + in mind, applications must NEVER invoke API + calls from the event loop thread itself, only other threads. + Not following this rule will lead to deadlocks in the API. + This restriction is intended to be lifted in a future release + of libvirt, once QMP processing moves to a dedicated thread. +

+

Driver security architecture

=20

diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index b62dd1df52..fc42c2820e 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -104,7 +104,8 @@ qemuDriverUnlock(virQEMUDriverPtr driver) #endif =20 =20 -virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool privileged) +virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool privileged, + const char *root) { g_autoptr(virQEMUDriverConfig) cfg =3D NULL; =20 @@ -114,7 +115,11 @@ virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool pri= vileged) if (!(cfg =3D virObjectNew(virQEMUDriverConfigClass))) return NULL; =20 - cfg->uri =3D privileged ? "qemu:///system" : "qemu:///session"; + if (root) { + cfg->uri =3D g_strdup_printf("qemu:///embed?root=3D%s", root); + } else { + cfg->uri =3D g_strdup(privileged ? "qemu:///system" : "qemu:///ses= sion"); + } =20 if (privileged) { if (virGetUserID(QEMU_USER, &cfg->user) < 0) @@ -130,7 +135,24 @@ virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool pri= vileged) =20 cfg->cgroupControllers =3D -1; /* -1 =3D=3D auto-detect */ =20 - if (privileged) { + if (root !=3D NULL) { + cfg->logDir =3D g_strdup_printf("%s/log/qemu", root); + cfg->swtpmLogDir =3D g_strdup_printf("%s/log/swtpm", root); + cfg->configBaseDir =3D g_strdup_printf("%s/etc", root); + cfg->stateDir =3D g_strdup_printf("%s/run/qemu", root); + cfg->swtpmStateDir =3D g_strdup_printf("%s/run/swtpm", root); + cfg->cacheDir =3D g_strdup_printf("%s/cache/qemu", root); + cfg->libDir =3D g_strdup_printf("%s/lib/qemu", root); + cfg->swtpmStorageDir =3D g_strdup_printf("%s/lib/swtpm", root); + + cfg->saveDir =3D g_strdup_printf("%s/save", cfg->libDir); + cfg->snapshotDir =3D g_strdup_printf("%s/snapshot", cfg->libDir); + cfg->checkpointDir =3D g_strdup_printf("%s/checkpoint", cfg->libDi= r); + cfg->autoDumpPath =3D g_strdup_printf("%s/dump", cfg->libDir); + cfg->channelTargetDir =3D g_strdup_printf("%s/channel/target", cfg= ->libDir); + cfg->nvramDir =3D g_strdup_printf("%s/nvram", cfg->libDir); + cfg->memoryBackingDir =3D g_strdup_printf("%s/ram", cfg->libDir); + } else if (privileged) { cfg->logDir =3D g_strdup_printf("%s/log/libvirt/qemu", LOCALSTATED= IR); =20 cfg->swtpmLogDir =3D g_strdup_printf("%s/log/swtpm/libvirt/qemu", @@ -189,6 +211,16 @@ virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool pri= vileged) cfg->memoryBackingDir =3D g_strdup_printf("%s/qemu/ram", cfg->conf= igBaseDir); cfg->swtpmStorageDir =3D g_strdup_printf("%s/qemu/swtpm", cfg->configBaseDir); + } + + if (privileged) { + if (!virDoesUserExist("tss") || + virGetUserID("tss", &cfg->swtpm_user) < 0) + cfg->swtpm_user =3D 0; /* fall back to root */ + if (!virDoesGroupExist("tss") || + virGetGroupID("tss", &cfg->swtpm_group) < 0) + cfg->swtpm_group =3D 0; /* fall back to root */ + } else { cfg->swtpm_user =3D (uid_t)-1; cfg->swtpm_group =3D (gid_t)-1; } @@ -201,7 +233,11 @@ virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool pri= vileged) * This will then be used as a fallback if the service specific * directory doesn't exist (although we don't check if this exists). */ - cfg->defaultTLSx509certdir =3D g_strdup(SYSCONFDIR "/pki/qemu"); + if (root =3D=3D NULL) { + cfg->defaultTLSx509certdir =3D g_strdup(SYSCONFDIR "pki/qemu"); + } else { + cfg->defaultTLSx509certdir =3D g_strdup_printf("%s/etc/pki/qemu", = root); + } =20 cfg->vncListen =3D g_strdup(VIR_LOOPBACK_IPV4_ADDR); cfg->spiceListen =3D g_strdup(VIR_LOOPBACK_IPV4_ADDR); @@ -264,6 +300,7 @@ static void virQEMUDriverConfigDispose(void *obj) virBitmapFree(cfg->namespaces); =20 virStringListFree(cfg->cgroupDeviceACL); + VIR_FREE(cfg->uri); =20 VIR_FREE(cfg->configBaseDir); VIR_FREE(cfg->configDir); diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index b9401635d7..4ab1999568 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -75,7 +75,7 @@ typedef virQEMUDriverConfig *virQEMUDriverConfigPtr; struct _virQEMUDriverConfig { virObject parent; =20 - const char *uri; + char *uri; =20 uid_t user; gid_t group; @@ -240,8 +240,9 @@ struct _virQEMUDriver { /* Atomic inc/dec only */ unsigned int nactive; =20 - /* Immutable value */ + /* Immutable values */ bool privileged; + char *embeddedRoot; =20 /* Immutable pointers. Caller must provide locking */ virStateInhibitCallback inhibitCallback; @@ -313,7 +314,8 @@ struct _virQEMUDriver { virHashAtomicPtr migrationErrors; }; =20 -virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool privileged); +virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool privileged, + const char *root); =20 int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg, const char *filename, diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 56d420f608..5088a1573c 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -645,12 +645,6 @@ qemuStateInitialize(bool privileged, const char *defsecmodel =3D NULL; g_autofree virSecurityManagerPtr *sec_managers =3D NULL; =20 - if (root !=3D NULL) { - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("Driver does not support embedded mode")); - return -1; - } - if (VIR_ALLOC(qemu_driver) < 0) return VIR_DRV_STATE_INIT_ERROR; =20 @@ -668,6 +662,8 @@ qemuStateInitialize(bool privileged, =20 qemu_driver->privileged =3D privileged; qemu_driver->hostarch =3D virArchFromHost(); + if (root !=3D NULL) + qemu_driver->embeddedRoot =3D g_strdup(root); =20 if (!(qemu_driver->domains =3D virDomainObjListNew())) goto error; @@ -681,7 +677,7 @@ qemuStateInitialize(bool privileged, if (privileged) qemu_driver->hostsysinfo =3D virSysinfoRead(); =20 - if (!(qemu_driver->config =3D cfg =3D virQEMUDriverConfigNew(privilege= d))) + if (!(qemu_driver->config =3D cfg =3D virQEMUDriverConfigNew(privilege= d, root))) goto error; =20 if (!(driverConf =3D g_strdup_printf("%s/qemu.conf", cfg->configBaseDi= r))) @@ -1185,10 +1181,30 @@ static virDrvOpenStatus qemuConnectOpen(virConnectP= tr conn, return VIR_DRV_OPEN_ERROR; } =20 - if (!virConnectValidateURIPath(conn->uri->path, - "qemu", - virQEMUDriverIsPrivileged(qemu_driver))) - return VIR_DRV_OPEN_ERROR; + if (qemu_driver->embeddedRoot) { + const char *root =3D virURIGetParam(conn->uri, "root"); + if (!root) + return VIR_DRV_OPEN_ERROR; + + if (STRNEQ(conn->uri->path, "/embed")) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("URI must be qemu:///embed")); + return VIR_DRV_OPEN_ERROR; + } + + if (STRNEQ(root, qemu_driver->embeddedRoot)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Cannot open embedded driver at path '%s', " + "already open with path '%s'"), + root, qemu_driver->embeddedRoot); + return VIR_DRV_OPEN_ERROR; + } + } else { + if (!virConnectValidateURIPath(conn->uri->path, + "qemu", + virQEMUDriverIsPrivileged(qemu_driv= er))) + return VIR_DRV_OPEN_ERROR; + } =20 if (virConnectOpenEnsureACL(conn) < 0) return VIR_DRV_OPEN_ERROR; @@ -23239,6 +23255,7 @@ static virHypervisorDriver qemuHypervisorDriver =3D= { static virConnectDriver qemuConnectDriver =3D { .localOnly =3D true, .uriSchemes =3D (const char *[]){ "qemu", NULL }, + .embeddable =3D true, .hypervisorDriver =3D &qemuHypervisorDriver, }; =20 diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 4195042194..1374f2fbc6 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -6682,10 +6682,17 @@ qemuProcessLaunch(virConnectPtr conn, =20 cfg =3D virQEMUDriverGetConfig(driver); =20 - if ((flags & VIR_QEMU_PROCESS_START_AUTODESTROY) && !conn) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Domain autodestroy requires a connection handle"= )); - return -1; + if (flags & VIR_QEMU_PROCESS_START_AUTODESTROY) { + if (!conn) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Domain autodestroy requires a connection han= dle")); + return -1; + } + if (driver->embeddedRoot) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Domain autodestroy not supported for embedde= d drivers yet")); + return -1; + } } =20 hookData.vm =3D vm; diff --git a/tests/domaincapstest.c b/tests/domaincapstest.c index 9f5eab3230..fb803eaa47 100644 --- a/tests/domaincapstest.c +++ b/tests/domaincapstest.c @@ -369,7 +369,7 @@ mymain(void) #endif =20 #if WITH_QEMU - virQEMUDriverConfigPtr cfg =3D virQEMUDriverConfigNew(false); + virQEMUDriverConfigPtr cfg =3D virQEMUDriverConfigNew(false, ""); =20 if (!cfg) return EXIT_FAILURE; diff --git a/tests/testutilsqemu.c b/tests/testutilsqemu.c index 9db0cb44c6..39544c548f 100644 --- a/tests/testutilsqemu.c +++ b/tests/testutilsqemu.c @@ -380,8 +380,7 @@ int qemuTestDriverInit(virQEMUDriver *driver) return -1; =20 driver->hostarch =3D virArchFromHost(); - - driver->config =3D virQEMUDriverConfigNew(false); + driver->config =3D virQEMUDriverConfigNew(false, ""); if (!driver->config) goto error; =20 --=20 2.23.0 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Fri Apr 19 11:48:47 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 205.139.110.120 as permitted sender) client-ip=205.139.110.120; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-1.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 205.139.110.120 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1578652494; cv=none; d=zohomail.com; s=zohoarc; b=dFu+5LDKj4Olih3rfOKhtk8o4rXA0fsvCf4r2b0LAFikXuYA2w2a5t+3jCjcR8Gt2FjiCjjLKd3zShgE85F5rRYvLzGlmHlCOzpqlVPOPCPKJyzLzPGBsPOJS4+zrqmi9HFcLRoDfEi9JPuTTaHo5g9J7HRK3YP9FRkk/qtx8yY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1578652494; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=lbue7CyFrx451fBj/qhTyeQHOfPJaIMd2d85SEaMc3o=; b=jdtXciDopdbMM72zgKrpPY8x4ODNoIboCHynhJ6IO3d4PX3+8FV0rErjH8BFZO0/PYav0jUV8VjEdKhSCEsP1rx92ibxNW2Bx05P9r9/1sYS0hLsvTWlsDx6Ubj6FZtbVOGP/LdGvYsWGZkH+IrhrsgvvDH8hvJQpm0Xtxqhpsk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 205.139.110.120 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [205.139.110.120]) by mx.zohomail.com with SMTPS id 1578652494302601.7655904458046; Fri, 10 Jan 2020 02:34:54 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-48-6yDZSsJjNZqBStkTFjaq7A-1; Fri, 10 Jan 2020 05:34:49 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 7CA52593A1; Fri, 10 Jan 2020 10:34:44 +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 598F75DA66; Fri, 10 Jan 2020 10:34:44 +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 19685503D6; Fri, 10 Jan 2020 10:34:44 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 00AAYg32001939 for ; Fri, 10 Jan 2020 05:34:42 -0500 Received: by smtp.corp.redhat.com (Postfix) id 8050E84665; Fri, 10 Jan 2020 10:34:42 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-112-65.ams2.redhat.com [10.36.112.65]) by smtp.corp.redhat.com (Postfix) with ESMTP id B71C6858AB; Fri, 10 Jan 2020 10:34:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1578652491; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=lbue7CyFrx451fBj/qhTyeQHOfPJaIMd2d85SEaMc3o=; b=MOfGLq8eVUdbWRiVGgN1f34SP7P/JIWgoPF1r2CbD87mhcQ0WaDUsMM++8pWP3d5P9gZN2 qXDj6R04bOjYx84Qj1yM+5ny9UPltfjFv5+7SbkhqWMgNOKZZot7bZUizjnI8jq6RzaZdQ Kdr7d3ts3gUK1rS9AMVP6oeFbMI+acs= From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= To: libvir-list@redhat.com Date: Fri, 10 Jan 2020 10:34:29 +0000 Message-Id: <20200110103430.3564679-6-berrange@redhat.com> In-Reply-To: <20200110103430.3564679-1-berrange@redhat.com> References: <20200110103430.3564679-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH v4 5/6] secrets: add support for running secret driver in embedded mode 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: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-MC-Unique: 6yDZSsJjNZqBStkTFjaq7A-1 X-Mimecast-Spam-Score: 0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) This enables support for running the secret driver embedded to the calling application process using a URI: secret:///embed?root=3D/some/path When using the embedded mode with a root=3D/var/tmp/embed, the driver will use the following paths: configDir: /var/tmp/embed/etc/secrets stateDir: /var/tmp/embed/run/secrets These are identical whether the embedded driver is privileged or unprivileged. This compares with the system instance which uses configDir: /etc/libvirt/secrets stateDir: /var/lib/libvirt/secrets When an embedded instance of the secret driver is open, any other embedded drivers will automatically use the embedded secret driver. Signed-off-by: Daniel P. Berrang=C3=A9 Reviewed-by: Michal Privoznik --- docs/drivers.html.in | 1 + docs/drvsecret.html.in | 82 ++++++++++++++++++++++++++++++++++++++ src/secret/secret_driver.c | 58 ++++++++++++++++++++++----- 3 files changed, 130 insertions(+), 11 deletions(-) create mode 100644 docs/drvsecret.html.in diff --git a/docs/drivers.html.in b/docs/drivers.html.in index 8743301ebd..34f98f60b6 100644 --- a/docs/drivers.html.in +++ b/docs/drivers.html.in @@ -8,6 +8,7 @@

  • Hypervisor drivers
  • Storage drivers
  • Node device driver
  • +
  • Secret driver
  • =20

    diff --git a/docs/drvsecret.html.in b/docs/drvsecret.html.in new file mode 100644 index 0000000000..9a05fe1f09 --- /dev/null +++ b/docs/drvsecret.html.in @@ -0,0 +1,82 @@ + + + + +

    Secret information management

    + +

    + The secrets driver in libvirt provides a simple interface for + storing and retrieving secret information. +

    + +

    Connections to SECRET driver

    + +

    + The libvirt SECRET driver is a multi-instance driver, providing a sing= le + system wide privileged driver (the "system" instance), and per-user + unprivileged drivers (the "session" instance). A connection to the sec= ret + driver is automatically available when opening a connection to one of = the + stateful primary hypervisor drivers. It is none the less also possible= to + explicitly open just the secret driver, using the URI protocol "secret" + Some example connection URIs for the driver are: +

    + +
    +secret:///session                      (local access to per-user instance)
    +secret+unix:///session                 (local access to per-user instance)
    +
    +secret:///system                       (local access to system instance)
    +secret+unix:///system                  (local access to system instance)
    +secret://example.com/system            (remote access, TLS/x509)
    +secret+tcp://example.com/system        (remote access, SASl/Kerberos)
    +secret+ssh://root@example.com/system   (remote access, SSH tunnelled)
    +
    + +

    Embedded driver

    + +

    + Since 6.0.0 the secret driver has experimental support for operating + in an embedded mode. In this scenario, rather than connecting to + the libvirtd daemon, the secret driver runs in the client application + process directly. To open the driver in embedded mode the app use the + new URI path and specify a virtual root directory under which the + driver will create content. +

    + +
    +      secret:///embed?root=3D/some/dir
    +    
    + +

    + Under the specified root directory the following locations will + be used +

    + +
    +/some/dir
    +  |
    +  +- etc
    +  |   |
    +  |   +- secrets
    +  |
    +  +- run
    +      |
    +      +- secrets
    +    
    + +

    + The application is responsible for recursively purging the contents + of this directory tree once they no longer require a connection, + though it can also be left intact for reuse when opening a future + connection. +

    + +

    + The range of functionality is intended to be on a par with that + seen when using the traditional system or session libvirt connections + to QEMU. Normal practice would be to open the secret driver in embed= ded + mode any time one of the other drivers is opened in embedded mode so + that the two drivers can interact in-process. +

    + + diff --git a/src/secret/secret_driver.c b/src/secret/secret_driver.c index a31005c731..210a16c3d3 100644 --- a/src/secret/secret_driver.c +++ b/src/secret/secret_driver.c @@ -55,6 +55,8 @@ typedef virSecretDriverState *virSecretDriverStatePtr; struct _virSecretDriverState { virMutex lock; bool privileged; /* readonly */ + char *embeddedRoot; /* readonly */ + int embeddedRefs; virSecretObjListPtr secrets; char *stateDir; char *configDir; @@ -456,12 +458,6 @@ secretStateInitialize(bool privileged, virStateInhibitCallback callback G_GNUC_UNUSED, void *opaque G_GNUC_UNUSED) { - if (root !=3D NULL) { - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("Driver does not support embedded mode")); - return -1; - } - if (VIR_ALLOC(driver) < 0) return VIR_DRV_STATE_INIT_ERROR; =20 @@ -475,7 +471,11 @@ secretStateInitialize(bool privileged, driver->secretEventState =3D virObjectEventStateNew(); driver->privileged =3D privileged; =20 - if (privileged) { + if (root) { + driver->embeddedRoot =3D g_strdup(root); + driver->configDir =3D g_strdup_printf("%s/etc/secrets", root); + driver->stateDir =3D g_strdup_printf("%s/run/secrets", root); + } else if (privileged) { driver->configDir =3D g_strdup_printf("%s/libvirt/secrets", SYSCON= FDIR); driver->stateDir =3D g_strdup_printf("%s/libvirt/secrets", RUNSTAT= EDIR); } else { @@ -550,19 +550,54 @@ secretConnectOpen(virConnectPtr conn, return VIR_DRV_OPEN_ERROR; } =20 - if (!virConnectValidateURIPath(conn->uri->path, - "secret", - driver->privileged)) - return VIR_DRV_OPEN_ERROR; + if (driver->embeddedRoot) { + const char *root =3D virURIGetParam(conn->uri, "root"); + if (!root) + return VIR_DRV_OPEN_ERROR; + + if (STRNEQ(conn->uri->path, "/embed")) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("URI must be secret:///embed")); + return VIR_DRV_OPEN_ERROR; + } + + if (STRNEQ(root, driver->embeddedRoot)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Cannot open embedded driver at path '%s', " + "already open with path '%s'"), + root, driver->embeddedRoot); + return VIR_DRV_OPEN_ERROR; + } + } else { + if (!virConnectValidateURIPath(conn->uri->path, + "secret", + driver->privileged)) + return VIR_DRV_OPEN_ERROR; + } =20 if (virConnectOpenEnsureACL(conn) < 0) return VIR_DRV_OPEN_ERROR; =20 + if (driver->embeddedRoot) { + secretDriverLock(); + if (driver->embeddedRefs =3D=3D 0) + virSetConnectSecret(conn); + driver->embeddedRefs++; + secretDriverUnlock(); + } + return VIR_DRV_OPEN_SUCCESS; } =20 static int secretConnectClose(virConnectPtr conn G_GNUC_UNUSED) { + if (driver->embeddedRoot) { + secretDriverLock(); + driver->embeddedRefs--; + if (driver->embeddedRefs =3D=3D 0) + virSetConnectSecret(NULL); + secretDriverUnlock(); + } return 0; } =20 @@ -655,6 +690,7 @@ static virHypervisorDriver secretHypervisorDriver =3D { static virConnectDriver secretConnectDriver =3D { .localOnly =3D true, .uriSchemes =3D (const char *[]){ "secret", NULL }, + .embeddable =3D true, .hypervisorDriver =3D &secretHypervisorDriver, .secretDriver =3D &secretDriver, }; --=20 2.23.0 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Fri Apr 19 11:48:47 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 207.211.31.81 as permitted sender) client-ip=207.211.31.81; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-1.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 207.211.31.81 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1578652502; cv=none; d=zohomail.com; s=zohoarc; b=i+jDshfa1aGwthXQIgSXE20J1VxnhltHUIlvZgCQfQ9E6Qd88YcpwF5dVFmc1VTH3ndNb2V9tEmHMqWmMKXVMLebLf2fJDagW7LYgnFM3ieZYSrwZ9fLunR5iJPqrhM1wCnTvzHdm3G+lsrWQ3YjdlCkKqUBbkWaMroyp7p43GQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1578652502; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=eHpnz6P+OuRTYMroaUZxyapx8R1DEKAMw0EN9hjQOhg=; b=QyApLDjvYYuvyhuNyeCKELXfCd0lx0J8R79MWHa2cqym78ENFlJ1vs+bbkaye42RnIF60Nnftc9/nENiTPcXfDVVqGZtXiNpATAS3qqO3RG7DeKKHR7PasYSGmUgu77aoMKIlrecSiuHp+9Tdd4VjyrTvR8vwFnNpY9VpnaxGNA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 207.211.31.81 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-delivery-1.mimecast.com (us-smtp-1.mimecast.com [207.211.31.81]) by mx.zohomail.com with SMTPS id 157865250275272.49130142461593; Fri, 10 Jan 2020 02:35:02 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-135-IEHK8IOQMYu68BNMiJCNXQ-1; Fri, 10 Jan 2020 05:34:59 -0500 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id E47231800D78; Fri, 10 Jan 2020 10:34:52 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id AC34E271AF; Fri, 10 Jan 2020 10:34:52 +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 5D56318089D7; Fri, 10 Jan 2020 10:34:52 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 00AAYp1p001960 for ; Fri, 10 Jan 2020 05:34:51 -0500 Received: by smtp.corp.redhat.com (Postfix) id 3839786CD3; Fri, 10 Jan 2020 10:34:51 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-112-65.ams2.redhat.com [10.36.112.65]) by smtp.corp.redhat.com (Postfix) with ESMTP id 49F1984665; Fri, 10 Jan 2020 10:34:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1578652501; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=eHpnz6P+OuRTYMroaUZxyapx8R1DEKAMw0EN9hjQOhg=; b=St+fWS4nQ4FpkoLsqTTfopklvy8kyvi0LGddQgq0G6M1R8o7INbKT0pkpzjEeRxQ/fH7Ns mqPxT4vgnHiVDNzwyDRXQMnDLVSxhM6ndRAKWvkpKQ3s+irocgCcCyGHviYuLPmS/cRo60 9xn9iH8QewAx6bYyQQr0LcopA3a9bqA= From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= To: libvir-list@redhat.com Date: Fri, 10 Jan 2020 10:34:30 +0000 Message-Id: <20200110103430.3564679-7-berrange@redhat.com> In-Reply-To: <20200110103430.3564679-1-berrange@redhat.com> References: <20200110103430.3564679-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-loop: libvir-list@redhat.com Cc: Michal Privoznik Subject: [libvirt] [PATCH v4 6/6] qemu: introduce a new "virt-qemu-run" program 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: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-MC-Unique: IEHK8IOQMYu68BNMiJCNXQ-1 X-Mimecast-Spam-Score: 0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) The previous "QEMU shim" proof of concept was taking an approach of only caring about initial spawning of the QEMU process. It was then registered with the libvirtd daemon who took over management of it. The intent was that later libvirtd would be refactored so that the shim retained control over the QEMU monitor and libvirt just forwarded APIs to each shim as needed. This forwarding of APIs would require quite alot of significant refactoring of libvirtd to achieve. This impl thus takes a quite different approach, explicitly deciding to keep the VMs completely separate from those seen & managed by libvirtd. Instead it uses the new "qemu:///embed" URI scheme to embed the entire QEMU driver in the shim, running with a custom root directory. Once the driver is initialization, the shim starts a VM and then waits to shutdown automatically when QEMU shuts down, or should kill QEMU if it is terminated itself. This ought to use the AUTO_DESTROY feature but that is not yet available in embedded mode, so we rely on installing a few signal handlers to gracefully kill QEMU. This isn't reliable if we crash of course, but you can restart with the same root dir. Note this program does not expose any way to manage the QEMU process, since there's no RPC interface enabled. It merely starts the VM and cleans up when the guest shuts down at the end. This program is installed to /usr/bin/virt-qemu-run enabling direct use by end users. Most use cases will probably want to integrate the concept directly into their respective application codebases. This standalone binary serves as a nice demo though, and also provides a way to measure performance of the startup process quite simply. Reviewed-by: Michal Privoznik Signed-off-by: Daniel P. Berrang=C3=A9 --- build-aux/syntax-check.mk | 2 +- docs/Makefile.am | 5 + docs/manpages/index.rst | 1 + docs/manpages/virt-qemu-run.rst | 114 +++++++++++ libvirt.spec.in | 2 + src/Makefile.am | 1 + src/qemu/Makefile.inc.am | 13 ++ src/qemu/qemu_shim.c | 322 ++++++++++++++++++++++++++++++++ 8 files changed, 459 insertions(+), 1 deletion(-) create mode 100644 docs/manpages/virt-qemu-run.rst create mode 100644 src/qemu/qemu_shim.c diff --git a/build-aux/syntax-check.mk b/build-aux/syntax-check.mk index 7e7c59c3df..df57d81251 100644 --- a/build-aux/syntax-check.mk +++ b/build-aux/syntax-check.mk @@ -2335,7 +2335,7 @@ exclude_file_name_regexp--sc_prohibit_devname =3D \ ^(tools/virsh.pod|build-aux/syntax-check\.mk|docs/.*)$$ =20 exclude_file_name_regexp--sc_prohibit_virXXXFree =3D \ - ^(docs/|tests/|examples/|tools/|build-aux/syntax-check\.mk|src/test/test= _driver.c|src/libvirt_public.syms|include/libvirt/libvirt-(domain|network|n= odedev|storage|stream|secret|nwfilter|interface|domain-snapshot).h|src/libv= irt-(domain|qemu|network|nodedev|storage|stream|secret|nwfilter|interface|d= omain-snapshot).c$$) + ^(docs/|tests/|examples/|tools/|build-aux/syntax-check\.mk|src/test/test= _driver.c|src/libvirt_public.syms|include/libvirt/libvirt-(domain|network|n= odedev|storage|stream|secret|nwfilter|interface|domain-snapshot).h|src/libv= irt-(domain|qemu|network|nodedev|storage|stream|secret|nwfilter|interface|d= omain-snapshot).c|src/qemu/qemu_shim.c$$) =20 exclude_file_name_regexp--sc_prohibit_sysconf_pagesize =3D \ ^(build-aux/syntax-check\.mk|src/util/virutil\.c)$$ diff --git a/docs/Makefile.am b/docs/Makefile.am index 6e4dc68a7b..94ae5079dd 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -248,6 +248,11 @@ if WITH_SANLOCK else ! WITH_SANLOCK manpages_rst +=3D manpages/virt-sanlock-cleanup.rst endif ! WITH_SANLOCK +if WITH_QEMU + manpages1_rst +=3D manpages/virt-qemu-run.rst +else ! WITH_QEMU + manpages_rst +=3D manpages/virt-qemu-run.rst +endif ! WITH_QEMU manpages_rst_html_in =3D \ $(manpages_rst:%.rst=3D%.html.in) manpages_html =3D \ diff --git a/docs/manpages/index.rst b/docs/manpages/index.rst index 4945ad59e2..2e71f81962 100644 --- a/docs/manpages/index.rst +++ b/docs/manpages/index.rst @@ -19,6 +19,7 @@ Tools * `virt-login-shell(1) `__ - tool to execute a shel= l within a container * `virt-admin(1) `__ - daemon administration interface * `virsh(1) `__ - management user interface +* `virt-qemu-run(1) `_ + +#. the bug tracker + + `https://libvirt.org/bugs.html `_ + +Alternatively, you may report bugs to your software distributor / vendor. + + +COPYRIGHT +=3D=3D=3D=3D=3D=3D=3D=3D=3D + +Copyright (C) 2019 by Red Hat, Inc. + + +LICENSE +=3D=3D=3D=3D=3D=3D=3D + +``virt-run-qemu`` is distributed under the terms of the GNU LGPL v2+. +This is free software; see the source for copying conditions. There +is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE + +SEE ALSO +=3D=3D=3D=3D=3D=3D=3D=3D + +virsh(1), `https://libvirt.org/ `_ diff --git a/libvirt.spec.in b/libvirt.spec.in index 5055750d2d..bbf9748582 100644 --- a/libvirt.spec.in +++ b/libvirt.spec.in @@ -1749,6 +1749,8 @@ exit 0 %{_libdir}/%{name}/connection-driver/libvirt_driver_qemu.so %dir %attr(0711, root, root) %{_localstatedir}/lib/libvirt/swtpm/ %dir %attr(0711, root, root) %{_localstatedir}/log/swtpm/libvirt/qemu/ +%{_bindir}/virt-qemu-run +%{_mandir}/man1/virt-qemu-run.1* %endif =20 %if %{with_lxc} diff --git a/src/Makefile.am b/src/Makefile.am index c9b5eeba47..d4042cf7ba 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -87,6 +87,7 @@ OPENRC_INIT_FILES_IN =3D OPENRC_CONF_FILES =3D SYSCONF_FILES =3D sbin_PROGRAMS =3D +bin_PROGRAMS =3D DRIVER_SOURCES =3D =20 COMMON_UNIT_VARS =3D \ diff --git a/src/qemu/Makefile.inc.am b/src/qemu/Makefile.inc.am index 967f6e75a2..c6b04c3217 100644 --- a/src/qemu/Makefile.inc.am +++ b/src/qemu/Makefile.inc.am @@ -243,3 +243,16 @@ EXTRA_DIST +=3D \ qemu/THREADS.txt \ libvirt_qemu_probes.d \ $(NULL) + +QEMU_SHIM_SOURCES =3D qemu/qemu_shim.c + +EXTRA_DIST +=3D $(QEMU_SHIM_SOURCES) + +if WITH_QEMU +bin_PROGRAMS +=3D virt-qemu-run + +virt_qemu_run_SOURCES =3D $(QEMU_SHIM_SOURCES) + +virt_qemu_run_LDADD =3D libvirt.la +virt_qemu_run_LDFLAGS =3D -Wl,--export-dynamic +endif WITH_QEMU diff --git a/src/qemu/qemu_shim.c b/src/qemu/qemu_shim.c new file mode 100644 index 0000000000..b10d95c996 --- /dev/null +++ b/src/qemu/qemu_shim.c @@ -0,0 +1,322 @@ +/* + * qemu_shim.c: standalone binary for running QEMU instances + * + * Copyright (C) 2019 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 "virfile.h" +#include "virstring.h" +#include "virgettext.h" + +#define VIR_FROM_THIS VIR_FROM_QEMU + +static bool eventQuitFlag; +static int eventQuitFD =3D -1; +static virDomainPtr dom; + +static void * +qemuShimEventLoop(void *opaque G_GNUC_UNUSED) +{ + while (!eventQuitFlag) + virEventRunDefaultImpl(); + + return NULL; +} + +/* Runs in event loop thread context */ +static void +qemuShimEventLoopStop(int watch G_GNUC_UNUSED, + int fd G_GNUC_UNUSED, + int event G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + char c; + ignore_value(read(fd, &c, 1)); + eventQuitFlag =3D true; +} + +/* Runs in event loop thread context */ +static int +qemuShimDomShutdown(virConnectPtr econn G_GNUC_UNUSED, + virDomainPtr edom G_GNUC_UNUSED, + int event, + int detail G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + if (event =3D=3D VIR_DOMAIN_EVENT_STOPPED) + eventQuitFlag =3D true; + + return 0; +} + +/* Runs in unknown thread context */ +static void +qemuShimSigShutdown(int sig G_GNUC_UNUSED) +{ + if (dom) + virDomainDestroy(dom); + ignore_value(safewrite(eventQuitFD, "c", 1)); +} + +static void +qemuShimQuench(void *userData G_GNUC_UNUSED, + virErrorPtr error G_GNUC_UNUSED) +{ +} + +int main(int argc, char **argv) +{ + GThread *eventLoopThread =3D NULL; + virConnectPtr conn =3D NULL; + virConnectPtr sconn =3D NULL; + g_autofree char *xml =3D NULL; + g_autofree char *uri =3D NULL; + g_autofree char *suri =3D NULL; + char *root =3D NULL; + bool tmproot =3D false; + int ret =3D 1; + g_autoptr(GError) error =3D NULL; + g_auto(GStrv) secrets =3D NULL; + gboolean verbose =3D false; + gboolean debug =3D false; + GStrv tmpsecrets; + GOptionContext *ctx; + GOptionEntry entries[] =3D { + { "secret", 's', 0, G_OPTION_ARG_STRING_ARRAY, &secrets, "Load sec= ret file", "SECRET-XML-FILE,SECRET-VALUE-FILE" }, + { "root", 'r', 0, G_OPTION_ARG_STRING, &root, "Root directory", "D= IR"}, + { "debug", 'd', 0, G_OPTION_ARG_NONE, &debug, "Debug output", NULL= }, + { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Verbose output"= , NULL }, + { NULL } + }; + int quitfd[2] =3D {-1, -1}; + long long start =3D g_get_monotonic_time(); + +#define deltams() ((long long)g_get_monotonic_time() - start) + + ctx =3D g_option_context_new("- run a standalone QEMU process"); + g_option_context_add_main_entries(ctx, entries, PACKAGE); + if (!g_option_context_parse(ctx, &argc, &argv, &error)) { + g_printerr("%s: option parsing failed: %s\n", + argv[0], error->message); + return 1; + } + + if (argc !=3D 2) { + g_autofree char *help =3D g_option_context_get_help(ctx, TRUE, NUL= L); + g_printerr("%s", help); + return 1; + } + + if (verbose) + g_printerr("%s: %lld: initializing libvirt\n", + argv[0], deltams()); + + if (virInitialize() < 0) { + g_printerr("%s: cannot initialize libvirt\n", argv[0]); + return 1; + } + if (virGettextInitialize() < 0) { + g_printerr("%s: cannot initialize libvirt translations\n", argv[0]= ); + return 1; + } + + virSetErrorFunc(NULL, qemuShimQuench); + + if (verbose) + g_printerr("%s: %lld: initializing signal handlers\n", + argv[0], deltams()); + + signal(SIGTERM, qemuShimSigShutdown); + signal(SIGINT, qemuShimSigShutdown); + signal(SIGQUIT, qemuShimSigShutdown); + signal(SIGHUP, qemuShimSigShutdown); + + if (root =3D=3D NULL) { + if (!(root =3D g_dir_make_tmp("libvirt-qemu-shim-XXXXXX", &error))= ) { + g_printerr("%s: cannot create temporary dir: %s\n", + argv[0], error->message); + return 1; + } + tmproot =3D true; + } + + virFileActivateDirOverrideForProg(argv[0]); + + if (verbose) + g_printerr("%s: %lld: preparing event loop thread\n", + argv[0], deltams()); + virEventRegisterDefaultImpl(); + + if (pipe(quitfd) < 0) { + g_printerr("%s: cannot create event loop pipe: %s", + argv[0], g_strerror(errno)); + goto cleanup; + } + + if (virEventAddHandle(quitfd[0], VIR_EVENT_HANDLE_READABLE, qemuShimEv= entLoopStop, NULL, NULL) < 0) { + VIR_FORCE_CLOSE(quitfd[0]); + VIR_FORCE_CLOSE(quitfd[1]); + quitfd[0] =3D quitfd[1] =3D -1; + g_printerr("%s: cannot register event loop handle: %s", + argv[0], virGetLastErrorMessage()); + goto cleanup; + } + eventQuitFD =3D quitfd[1]; + + eventLoopThread =3D g_thread_new("event-loop", qemuShimEventLoop, NULL= ); + + if (secrets && *secrets) { + suri =3D g_strdup_printf("secret:///embed?root=3D%s", root); + + if (verbose) + g_printerr("%s: %lld: opening %s\n", + argv[0], deltams(), suri); + + sconn =3D virConnectOpen(suri); + if (!sconn) { + g_printerr("%s: cannot open %s: %s\n", + argv[0], suri, virGetLastErrorMessage()); + goto cleanup; + } + + tmpsecrets =3D secrets; + while (tmpsecrets && *tmpsecrets) { + g_auto(GStrv) bits =3D g_strsplit(*tmpsecrets, ",", 2); + g_autofree char *sxml =3D NULL; + g_autofree char *value =3D NULL; + virSecretPtr sec; + size_t nvalue; + + if (!bits || bits[0] =3D=3D NULL || bits[1] =3D=3D NULL) { + g_printerr("%s: expected a pair of filenames for --secret = argument\n", + argv[0]); + goto cleanup; + } + + if (verbose) + g_printerr("%s: %lld: loading secret %s and %s\n", + argv[0], deltams(), bits[0], bits[1]); + + if (!g_file_get_contents(bits[0], &sxml, NULL, &error)) { + g_printerr("%s: cannot read secret XML %s: %s\n", + argv[0], bits[0], error->message); + goto cleanup; + } + + if (!g_file_get_contents(bits[1], &value, &nvalue, &error)) { + g_printerr("%s: cannot read secret value %s: %s\n", + argv[0], bits[1], error->message); + goto cleanup; + } + + if (!(sec =3D virSecretDefineXML(sconn, sxml, 0))) { + g_printerr("%s: cannot define secret %s: %s\n", + argv[0], bits[0], virGetLastErrorMessage()); + goto cleanup; + } + + if (virSecretSetValue(sec, (unsigned char *)value, nvalue, 0) = < 0) { + virSecretFree(sec); + g_printerr("%s: cannot set value for secret %s: %s\n", + argv[0], bits[0], virGetLastErrorMessage()); + goto cleanup; + } + virSecretFree(sec); + + tmpsecrets++; + } + } + + uri =3D g_strdup_printf("qemu:///embed?root=3D%s", root); + + if (verbose) + g_printerr("%s: %lld: opening %s\n", + argv[0], deltams(), uri); + + conn =3D virConnectOpen(uri); + if (!conn) { + g_printerr("%s: cannot open %s: %s\n", + argv[0], uri, virGetLastErrorMessage()); + goto cleanup; + } + + if (virConnectDomainEventRegisterAny( + conn, dom, VIR_DOMAIN_EVENT_ID_LIFECYCLE, + VIR_DOMAIN_EVENT_CALLBACK(qemuShimDomShutdown), + NULL, NULL) < 0) { + g_printerr("%s: cannot regiser for lifecycle events: %s\n", + argv[0], virGetLastErrorMessage()); + goto cleanup; + } + + if (verbose) + g_printerr("%s: %lld: starting guest %s\n", + argv[0], deltams(), argv[1]); + + if (!g_file_get_contents(argv[1], &xml, NULL, &error)) { + g_printerr("%s: cannot read %s: %s\n", + argv[0], argv[1], error->message); + goto cleanup; + } + + dom =3D virDomainCreateXML(conn, xml, 0); + if (!dom) { + g_printerr("%s: cannot start VM: %s\n", + argv[0], virGetLastErrorMessage()); + goto cleanup; + } + if (verbose) + g_printerr("%s: %lld: guest running, Ctrl-C to stop nowbbbb\n", + argv[0], deltams()); + + if (debug) { + g_autofree char *newxml =3D NULL; + newxml =3D virDomainGetXMLDesc(dom, 0); + g_printerr("%s: XML: %s\n", argv[0], newxml); + } + + ret =3D 0; + + cleanup: + if (ret !=3D 0 && eventQuitFD !=3D -1) + ignore_value(safewrite(eventQuitFD, "c", 1)); + + if (eventLoopThread !=3D NULL && (ret =3D=3D 0 || eventQuitFD !=3D -1)) + g_thread_join(eventLoopThread); + + VIR_FORCE_CLOSE(quitfd[0]); + VIR_FORCE_CLOSE(quitfd[1]); + + if (dom !=3D NULL) + virDomainFree(dom); + if (sconn !=3D NULL) + virConnectClose(sconn); + if (conn !=3D NULL) + virConnectClose(conn); + if (tmproot) + virFileDeleteTree(root); + + if (verbose) + g_printerr("%s: %lld: cleaned up, exiting\n", + argv[0], deltams()); + return ret; +} --=20 2.23.0 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list