[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