[libvirt] [PATCH v4 3/6] libvirt: support an "embed" URI path selector for opening drivers
Michal Prívozník
mprivozn at redhat.com
Sat Jan 25 15:07:12 UTC 2020
On 1/10/20 11:34 AM, Daniel P. Berrangé wrote:
> The driver URI scheme:
>
> "$drivername:///embed?root=/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=/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 <mprivozn at redhat.com>
> Signed-off-by: Daniel P. Berrangé <berrange at redhat.com>
> ---
> src/driver-state.h | 1 +
> src/driver.h | 2 ++
> src/libvirt.c | 72 ++++++++++++++++++++++++++++++++++++++++++++--
> 3 files changed, 73 insertions(+), 2 deletions(-)
>
> diff --git a/src/libvirt.c b/src/libvirt.c
> index 4de87cdecd..5599d5ff31 100644
> --- a/src/libvirt.c
> +++ b/src/libvirt.c
> @@ -934,6 +939,52 @@ virConnectOpenInternal(const char *name,
> ret->uri) < 0) {
> goto failed;
> }
> +
> + if (STREQ(ret->uri->path, "/embed")) {
> + const char *root = NULL;
> + g_autofree char *regMethod = NULL;
> + VIR_DEBUG("URI path requests %s driver embedded mode",
> + ret->uri->scheme);
> + if (strspn(ret->uri->scheme, "abcdefghijklmnopqrstuvwxyz") !=
> + strlen(ret->uri->scheme)) {
> + virReportError(VIR_ERR_NO_CONNECT,
> + _("URI scheme '%s' for embedded driver is not valid"),
> + ret->uri->scheme);
> + goto failed;
> + }
> +
> + for (i = 0; i < ret->uri->paramsCount; i++) {
> + virURIParamPtr var = &ret->uri->params[i];
> + if (STREQ(var->name, "root"))
> + root = var->value;
> + }
> +
> + if (!root) {
> + virReportError(VIR_ERR_INVALID_ARG, "%s",
> + _("root parameter required for embedded driver"));
> + goto failed;
> + }
Or use virURIGetParam() you've introduced two patches ago.
> +
> + if (virEventRequireImpl() < 0)
> + goto failed;
> +
> + regMethod = g_strdup_printf("%sRegister", ret->uri->scheme);
> +
> + if (virDriverLoadModule(ret->uri->scheme, regMethod, false) < 0)
> + goto failed;
> +
> + if (virAccessManagerGetDefault() == NULL) {
If this is true, then an error is reported. Should we reset the error then?
> + virAccessManagerPtr acl = virAccessManagerNew("none");
> + if (!acl)
> + goto failed;
> + virAccessManagerSetDefault(acl);
> + }
> +
> + if (virStateInitialize(geteuid() == 0, true, root, NULL, NULL) < 0)
> + goto failed;
> +
> + embed = true;
> + }
> } else {
> VIR_DEBUG("no name, allowing driver auto-select");
> }
Michal
More information about the libvir-list
mailing list