2012-05-28 16:23:16 +00:00
|
|
|
/*
|
2006-02-09 17:45:11 +00:00
|
|
|
* libvirt.c: Main interfaces for the libvirt library to handle virtualization
|
2005-11-02 12:50:21 +00:00
|
|
|
* domains from a process running in domain 0
|
|
|
|
*
|
event: improve public API docs
Since libvirt 0.9.3, the entire virevent.c file has been a public
API, so improve the documentation in this file. Also, fix a
potential core dump - it could only be triggered by bogus use of
the API and would only affect the caller (not libvirtd), but we
might as well be nice.
* src/libvirt.c (virConnectSetKeepAlive)
(virConnectDomainEventRegister, virConnectDomainEventRegisterAny)
(virConnectNetworkEventRegisterAny): Document event loop requirement.
* src/util/virevent.c (virEventAddHandle, virEventRemoveHandle)
(virEventAddTimeout, virEventRemoveTimeout): Likewise.
(virEventUpdateHandle, virEventUpdateTimeout): Likewise, and avoid
core dump if caller didn't register handler.
(virEventRunDefaultImpl): Expand example, and set up code block in
html docs.
(virEventRegisterImpl, virEventRegisterDefaultImpl): Document more
on the use of the event loop.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-12-31 14:57:17 +00:00
|
|
|
* Copyright (C) 2005-2006, 2008-2014 Red Hat, Inc.
|
2005-11-02 12:50:21 +00:00
|
|
|
*
|
2012-07-27 09:39:53 +00:00
|
|
|
* 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
|
2012-09-20 22:30:55 +00:00
|
|
|
* License along with this library. If not, see
|
2012-07-27 09:39:53 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2005-11-02 12:50:21 +00:00
|
|
|
*/
|
|
|
|
|
2008-01-29 18:15:54 +00:00
|
|
|
#include <config.h>
|
2005-11-02 12:50:21 +00:00
|
|
|
|
2006-01-18 10:37:08 +00:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <unistd.h>
|
2009-01-22 20:27:01 +00:00
|
|
|
#include <time.h>
|
2019-12-23 15:37:14 +00:00
|
|
|
#include <gio/gnetworking.h>
|
2006-03-23 15:42:10 +00:00
|
|
|
|
2006-04-28 18:29:26 +00:00
|
|
|
#include <libxml/parser.h>
|
|
|
|
#include <libxml/xpath.h>
|
2007-12-07 14:56:37 +00:00
|
|
|
|
2013-01-08 21:09:09 +00:00
|
|
|
#ifdef WITH_CURL
|
2012-10-06 18:09:20 +00:00
|
|
|
# include <curl/curl.h>
|
|
|
|
#endif
|
|
|
|
|
2012-12-13 18:21:53 +00:00
|
|
|
#include "virerror.h"
|
2012-12-12 17:59:27 +00:00
|
|
|
#include "virlog.h"
|
2008-11-04 23:22:06 +00:00
|
|
|
#include "datatypes.h"
|
2006-03-20 17:49:28 +00:00
|
|
|
#include "driver.h"
|
2007-03-15 07:43:16 +00:00
|
|
|
|
2012-12-13 18:01:25 +00:00
|
|
|
#include "viruuid.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.h"
|
2010-11-16 14:54:17 +00:00
|
|
|
#include "configmake.h"
|
2012-12-12 16:35:35 +00:00
|
|
|
#include "virconf.h"
|
2020-01-22 16:21:35 +00:00
|
|
|
#include "rpc/virnettlscontext.h"
|
2012-12-12 16:27:01 +00:00
|
|
|
#include "vircommand.h"
|
libvirt: support an "embed" URI path selector for opening drivers
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@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
2019-05-17 11:42:04 +00:00
|
|
|
#include "virevent.h"
|
2013-05-09 18:59:04 +00:00
|
|
|
#include "virfile.h"
|
2012-01-25 15:17:46 +00:00
|
|
|
#include "virrandom.h"
|
2012-02-24 18:48:55 +00:00
|
|
|
#include "viruri.h"
|
2012-12-13 15:49:48 +00:00
|
|
|
#include "virthread.h"
|
2013-04-03 10:36:23 +00:00
|
|
|
#include "virstring.h"
|
2013-05-02 21:30:48 +00:00
|
|
|
#include "virutil.h"
|
2013-06-06 18:05:33 +00:00
|
|
|
#include "virtypedparam.h"
|
2008-08-20 20:48:35 +00:00
|
|
|
|
Only build server side drivers as modules
The driver modules all use symbols which are defined in libvirt.so.
Thus for loading of modules to work, the binary that libvirt.so
is linked to must export its symbols back to modules. If the
libvirt.so itself is dlopen()d then the RTLD_GLOBAL flag must
be set. Unfortunately few, if any, programming languages use
the RTLD_GLOBAL flag when loading modules :-( This means is it
not practical to use driver modules for any libvirt client side
drivers (OpenVZ, VMWare, Hyper-V, Remote client, test).
This patch changes the build process so only server side drivers
are built as modules (Xen, QEMU, LXC, UML)
* daemon/libvirtd.c: Add missing load of 'interface' driver
* src/Makefile.am: Only build server side drivers as modules
* src/libvirt.c: Don't load any driver modules
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2011-06-01 15:36:21 +00:00
|
|
|
#ifdef WITH_TEST
|
|
|
|
# include "test/test_driver.h"
|
|
|
|
#endif
|
|
|
|
#ifdef WITH_REMOTE
|
|
|
|
# include "remote/remote_driver.h"
|
|
|
|
#endif
|
|
|
|
#ifdef WITH_OPENVZ
|
|
|
|
# include "openvz/openvz_driver.h"
|
|
|
|
#endif
|
|
|
|
#ifdef WITH_VMWARE
|
|
|
|
# include "vmware/vmware_driver.h"
|
|
|
|
#endif
|
|
|
|
#ifdef WITH_ESX
|
|
|
|
# include "esx/esx_driver.h"
|
|
|
|
#endif
|
|
|
|
#ifdef WITH_HYPERV
|
|
|
|
# include "hyperv/hyperv_driver.h"
|
|
|
|
#endif
|
2014-02-18 10:08:10 +00:00
|
|
|
#ifdef WITH_BHYVE
|
|
|
|
# include "bhyve/bhyve_driver.h"
|
|
|
|
#endif
|
libvirt: support an "embed" URI path selector for opening drivers
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@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
2019-05-17 11:42:04 +00:00
|
|
|
#include "access/viraccessmanager.h"
|
2005-11-30 13:20:53 +00:00
|
|
|
|
2009-01-29 12:10:32 +00:00
|
|
|
#define VIR_FROM_THIS VIR_FROM_NONE
|
|
|
|
|
2014-02-28 12:16:17 +00:00
|
|
|
VIR_LOG_INIT("libvirt");
|
|
|
|
|
2005-11-02 12:50:21 +00:00
|
|
|
/*
|
|
|
|
* TODO:
|
|
|
|
* - use lock to protect against concurrent accesses ?
|
2008-04-04 07:58:29 +00:00
|
|
|
* - use reference counting to guarantee coherent pointer state ?
|
2005-11-02 12:50:21 +00:00
|
|
|
*/
|
|
|
|
|
2015-05-26 17:12:00 +00:00
|
|
|
#define MAX_DRIVERS 21
|
2008-11-04 23:22:06 +00:00
|
|
|
|
2015-01-20 16:16:26 +00:00
|
|
|
static virConnectDriverPtr virConnectDriverTab[MAX_DRIVERS];
|
|
|
|
static int virConnectDriverTabCount;
|
2007-06-26 22:56:14 +00:00
|
|
|
static virStateDriverPtr virStateDriverTab[MAX_DRIVERS];
|
2014-10-28 18:38:04 +00:00
|
|
|
static int virStateDriverTabCount;
|
2012-10-10 15:11:43 +00:00
|
|
|
|
2015-01-20 16:16:26 +00:00
|
|
|
static virNetworkDriverPtr virSharedNetworkDriver;
|
|
|
|
static virInterfaceDriverPtr virSharedInterfaceDriver;
|
|
|
|
static virStorageDriverPtr virSharedStorageDriver;
|
|
|
|
static virNodeDeviceDriverPtr virSharedNodeDeviceDriver;
|
|
|
|
static virSecretDriverPtr virSharedSecretDriver;
|
|
|
|
static virNWFilterDriverPtr virSharedNWFilterDriver;
|
|
|
|
|
2006-03-27 15:24:36 +00:00
|
|
|
|
2013-12-28 02:42:30 +00:00
|
|
|
static int
|
|
|
|
virConnectAuthCallbackDefault(virConnectCredentialPtr cred,
|
|
|
|
unsigned int ncred,
|
2019-10-14 12:45:33 +00:00
|
|
|
void *cbdata G_GNUC_UNUSED)
|
2013-12-28 02:42:30 +00:00
|
|
|
{
|
Convert 'int i' to 'size_t i' in src/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2007-12-05 18:55:04 +00:00
|
|
|
|
2013-05-21 08:08:42 +00:00
|
|
|
for (i = 0; i < ncred; i++) {
|
2007-12-05 18:55:04 +00:00
|
|
|
char buf[1024];
|
2020-03-05 15:42:53 +00:00
|
|
|
char *bufptr = NULL;
|
2008-01-21 14:09:51 +00:00
|
|
|
size_t len;
|
2007-12-05 18:55:04 +00:00
|
|
|
|
|
|
|
switch (cred[i].type) {
|
2008-02-20 16:54:35 +00:00
|
|
|
case VIR_CRED_EXTERNAL: {
|
|
|
|
if (STRNEQ(cred[i].challenge, "PolicyKit"))
|
|
|
|
return -1;
|
|
|
|
|
2008-04-04 15:09:19 +00:00
|
|
|
/*
|
|
|
|
* Ignore & carry on. Although we can't auth
|
|
|
|
* directly, the user may have authenticated
|
|
|
|
* themselves already outside context of libvirt
|
|
|
|
*/
|
2008-02-20 16:54:35 +00:00
|
|
|
break;
|
|
|
|
}
|
2008-04-04 15:09:19 +00:00
|
|
|
|
2007-12-05 18:55:04 +00:00
|
|
|
case VIR_CRED_USERNAME:
|
|
|
|
case VIR_CRED_AUTHNAME:
|
|
|
|
case VIR_CRED_ECHOPROMPT:
|
|
|
|
case VIR_CRED_REALM:
|
2010-02-24 19:19:28 +00:00
|
|
|
if (printf("%s: ", cred[i].prompt) < 0)
|
2008-02-20 16:54:35 +00:00
|
|
|
return -1;
|
|
|
|
if (fflush(stdout) != 0)
|
|
|
|
return -1;
|
|
|
|
|
2007-12-05 18:55:04 +00:00
|
|
|
if (!fgets(buf, sizeof(buf), stdin)) {
|
|
|
|
if (feof(stdin)) { /* Treat EOF as "" */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
2020-03-05 15:42:53 +00:00
|
|
|
|
2008-01-21 14:09:51 +00:00
|
|
|
len = strlen(buf);
|
|
|
|
if (len != 0 && buf[len-1] == '\n')
|
|
|
|
buf[len-1] = '\0';
|
2020-03-05 15:42:53 +00:00
|
|
|
bufptr = g_strdup(buf);
|
2007-12-05 18:55:04 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_CRED_PASSPHRASE:
|
|
|
|
case VIR_CRED_NOECHOPROMPT:
|
2010-02-24 19:19:28 +00:00
|
|
|
if (printf("%s: ", cred[i].prompt) < 0)
|
2008-02-20 16:54:35 +00:00
|
|
|
return -1;
|
|
|
|
if (fflush(stdout) != 0)
|
|
|
|
return -1;
|
|
|
|
|
2020-01-14 10:40:52 +00:00
|
|
|
bufptr = virGetPassword();
|
|
|
|
if (STREQ(bufptr, ""))
|
|
|
|
VIR_FREE(bufptr);
|
2007-12-05 18:55:04 +00:00
|
|
|
break;
|
2007-12-15 17:15:12 +00:00
|
|
|
|
|
|
|
default:
|
|
|
|
return -1;
|
2007-12-05 18:55:04 +00:00
|
|
|
}
|
|
|
|
|
2008-05-22 15:12:25 +00:00
|
|
|
if (cred[i].type != VIR_CRED_EXTERNAL) {
|
2020-01-14 10:40:52 +00:00
|
|
|
cred[i].result = bufptr ? bufptr : g_strdup(cred[i].defresult ? cred[i].defresult : "");
|
2008-05-22 15:12:25 +00:00
|
|
|
cred[i].resultlen = strlen(cred[i].result);
|
|
|
|
}
|
2007-12-05 18:55:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-12-28 02:42:30 +00:00
|
|
|
|
2007-12-05 18:55:04 +00:00
|
|
|
/* Don't typically want VIR_CRED_USERNAME. It enables you to authenticate
|
|
|
|
* as one user, and act as another. It just results in annoying
|
|
|
|
* prompts for the username twice & is very rarely what you want
|
|
|
|
*/
|
|
|
|
static int virConnectCredTypeDefault[] = {
|
|
|
|
VIR_CRED_AUTHNAME,
|
|
|
|
VIR_CRED_ECHOPROMPT,
|
|
|
|
VIR_CRED_REALM,
|
|
|
|
VIR_CRED_PASSPHRASE,
|
|
|
|
VIR_CRED_NOECHOPROMPT,
|
2008-02-20 16:54:35 +00:00
|
|
|
VIR_CRED_EXTERNAL,
|
2007-12-05 18:55:04 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static virConnectAuth virConnectAuthDefault = {
|
|
|
|
virConnectCredTypeDefault,
|
|
|
|
sizeof(virConnectCredTypeDefault)/sizeof(int),
|
|
|
|
virConnectAuthCallbackDefault,
|
|
|
|
NULL,
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* virConnectAuthPtrDefault
|
|
|
|
*
|
|
|
|
* A default implementation of the authentication callbacks. This
|
|
|
|
* implementation is suitable for command line based tools. It will
|
|
|
|
* prompt for username, passwords, realm and one time keys as needed.
|
|
|
|
* It will print on STDOUT, and read from STDIN. If this is not
|
|
|
|
* suitable for the application's needs an alternative implementation
|
|
|
|
* should be provided.
|
|
|
|
*/
|
|
|
|
virConnectAuthPtr virConnectAuthPtrDefault = &virConnectAuthDefault;
|
|
|
|
|
2014-10-28 18:38:04 +00:00
|
|
|
static bool virGlobalError;
|
2012-10-10 15:11:43 +00:00
|
|
|
static virOnceControl virGlobalOnce = VIR_ONCE_CONTROL_INITIALIZER;
|
2006-03-27 15:24:36 +00:00
|
|
|
|
2012-10-10 15:11:43 +00:00
|
|
|
static void
|
|
|
|
virGlobalInit(void)
|
|
|
|
{
|
maint: move debug statements first in public API
Most of our public APIs emit a debug log on entry, prior to anything
else. There were a few exceptions where obvious failures were not
logged, so fix those. When moving a debug earlier, this patch also
makes sure to avoid any NULL dereference during the log (the APIs
are supposed to gracefully fail if the user passes NULL for the object).
However, do NOT use VIR_DEBUG prior to virInitialize, since setting
up the error reporting can change where VIR_DEBUG output would be
routed. Instead add documentation to virGlobalInit, virInitialize,
and virGetVersion that better explains initialization.
* src/libvirt.c (virGetVersion, virConnectRef, virDomainRef)
(virNetworkRef, virInterfaceRef, virStoragePoolRef)
(virStorageVolRef, virNodeDeviceRef, virSecretRef, virStreamRef)
(virNWFilterRef, virDomainSnapshotRef): Debug on function entry.
* src/libvirt-lxc.c (virDomainLxcEnterNamespace)
(virDomainLxcEnterSecurityLabel): Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-12-27 21:16:56 +00:00
|
|
|
/* It would be nice if we could trace the use of this call, to
|
|
|
|
* help diagnose in log files if a user calls something other than
|
|
|
|
* virConnectOpen first. But we can't rely on VIR_DEBUG working
|
|
|
|
* until after initialization is complete, and since this is
|
|
|
|
* one-shot, we never get here again. */
|
2019-09-16 16:44:23 +00:00
|
|
|
if (virErrorInitialize() < 0)
|
2012-10-10 15:11:43 +00:00
|
|
|
goto error;
|
2009-01-15 19:56:05 +00:00
|
|
|
|
2019-08-29 10:52:08 +00:00
|
|
|
virFileActivateDirOverrideForLib();
|
|
|
|
|
2019-08-01 13:13:20 +00:00
|
|
|
if (getuid() != geteuid() ||
|
|
|
|
getgid() != getegid()) {
|
2013-10-10 16:45:14 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
2019-08-01 13:13:20 +00:00
|
|
|
_("libvirt.so is not safe to use from setuid/setgid programs"));
|
2013-10-10 16:45:14 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2009-08-06 13:55:07 +00:00
|
|
|
virLogSetFromEnv();
|
2008-01-19 18:36:01 +00:00
|
|
|
|
2011-08-24 14:16:45 +00:00
|
|
|
virNetTLSInit();
|
|
|
|
|
2013-01-08 21:09:09 +00:00
|
|
|
#if WITH_CURL
|
2012-10-06 18:09:20 +00:00
|
|
|
curl_global_init(CURL_GLOBAL_DEFAULT);
|
|
|
|
#endif
|
|
|
|
|
2011-05-09 09:24:09 +00:00
|
|
|
VIR_DEBUG("register drivers");
|
2008-01-19 18:36:01 +00:00
|
|
|
|
2019-12-23 15:37:14 +00:00
|
|
|
g_networking_init();
|
2007-12-07 14:56:37 +00:00
|
|
|
|
2018-04-03 15:39:17 +00:00
|
|
|
#ifdef HAVE_LIBINTL_H
|
2010-11-16 14:54:17 +00:00
|
|
|
if (!bindtextdomain(PACKAGE, LOCALEDIR))
|
2012-10-10 15:11:43 +00:00
|
|
|
goto error;
|
2018-04-03 15:39:17 +00:00
|
|
|
#endif /* HAVE_LIBINTL_H */
|
2006-09-21 15:24:37 +00:00
|
|
|
|
2006-03-27 15:24:36 +00:00
|
|
|
/*
|
2007-04-04 14:19:49 +00:00
|
|
|
* Note that the order is important: the first ones have a higher
|
|
|
|
* priority when calling virConnectOpen.
|
2006-03-27 15:24:36 +00:00
|
|
|
*/
|
2019-07-30 12:44:37 +00:00
|
|
|
#ifdef WITH_TEST
|
2012-10-10 15:11:43 +00:00
|
|
|
if (testRegister() == -1)
|
|
|
|
goto error;
|
2019-07-30 12:44:37 +00:00
|
|
|
#endif
|
|
|
|
#ifdef WITH_OPENVZ
|
2012-10-10 15:11:43 +00:00
|
|
|
if (openvzRegister() == -1)
|
|
|
|
goto error;
|
2019-07-30 12:44:37 +00:00
|
|
|
#endif
|
|
|
|
#ifdef WITH_VMWARE
|
2012-10-10 15:11:43 +00:00
|
|
|
if (vmwareRegister() == -1)
|
|
|
|
goto error;
|
2019-07-30 12:44:37 +00:00
|
|
|
#endif
|
|
|
|
#ifdef WITH_ESX
|
2012-10-10 15:11:43 +00:00
|
|
|
if (esxRegister() == -1)
|
|
|
|
goto error;
|
2019-07-30 12:44:37 +00:00
|
|
|
#endif
|
|
|
|
#ifdef WITH_HYPERV
|
2012-10-10 15:11:43 +00:00
|
|
|
if (hypervRegister() == -1)
|
|
|
|
goto error;
|
2019-07-30 12:44:37 +00:00
|
|
|
#endif
|
Only build server side drivers as modules
The driver modules all use symbols which are defined in libvirt.so.
Thus for loading of modules to work, the binary that libvirt.so
is linked to must export its symbols back to modules. If the
libvirt.so itself is dlopen()d then the RTLD_GLOBAL flag must
be set. Unfortunately few, if any, programming languages use
the RTLD_GLOBAL flag when loading modules :-( This means is it
not practical to use driver modules for any libvirt client side
drivers (OpenVZ, VMWare, Hyper-V, Remote client, test).
This patch changes the build process so only server side drivers
are built as modules (Xen, QEMU, LXC, UML)
* daemon/libvirtd.c: Add missing load of 'interface' driver
* src/Makefile.am: Only build server side drivers as modules
* src/libvirt.c: Don't load any driver modules
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2011-06-01 15:36:21 +00:00
|
|
|
#ifdef WITH_REMOTE
|
2012-10-17 09:23:12 +00:00
|
|
|
if (remoteRegister() == -1)
|
2012-10-10 15:11:43 +00:00
|
|
|
goto error;
|
2007-04-18 10:14:07 +00:00
|
|
|
#endif
|
2007-02-14 01:40:09 +00:00
|
|
|
|
2012-10-10 15:11:43 +00:00
|
|
|
return;
|
|
|
|
|
2014-03-25 06:49:02 +00:00
|
|
|
error:
|
2012-10-10 15:11:43 +00:00
|
|
|
virGlobalError = true;
|
|
|
|
}
|
|
|
|
|
2013-12-28 02:42:30 +00:00
|
|
|
|
2012-10-10 15:11:43 +00:00
|
|
|
/**
|
|
|
|
* virInitialize:
|
|
|
|
*
|
|
|
|
* Initialize the library.
|
|
|
|
*
|
maint: move debug statements first in public API
Most of our public APIs emit a debug log on entry, prior to anything
else. There were a few exceptions where obvious failures were not
logged, so fix those. When moving a debug earlier, this patch also
makes sure to avoid any NULL dereference during the log (the APIs
are supposed to gracefully fail if the user passes NULL for the object).
However, do NOT use VIR_DEBUG prior to virInitialize, since setting
up the error reporting can change where VIR_DEBUG output would be
routed. Instead add documentation to virGlobalInit, virInitialize,
and virGetVersion that better explains initialization.
* src/libvirt.c (virGetVersion, virConnectRef, virDomainRef)
(virNetworkRef, virInterfaceRef, virStoragePoolRef)
(virStorageVolRef, virNodeDeviceRef, virSecretRef, virStreamRef)
(virNWFilterRef, virDomainSnapshotRef): Debug on function entry.
* src/libvirt-lxc.c (virDomainLxcEnterNamespace)
(virDomainLxcEnterSecurityLabel): Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-12-27 21:16:56 +00:00
|
|
|
* This method is invoked automatically by any of the virConnectOpen() API
|
|
|
|
* calls, and by virGetVersion(). Since release 1.0.0, there is no need to
|
|
|
|
* call this method even in a multithreaded application, since
|
|
|
|
* initialization is performed in a thread safe manner; but applications
|
|
|
|
* using an older version of the library should manually call this before
|
|
|
|
* setting up competing threads that attempt virConnectOpen in parallel.
|
2012-10-10 15:11:43 +00:00
|
|
|
*
|
maint: move debug statements first in public API
Most of our public APIs emit a debug log on entry, prior to anything
else. There were a few exceptions where obvious failures were not
logged, so fix those. When moving a debug earlier, this patch also
makes sure to avoid any NULL dereference during the log (the APIs
are supposed to gracefully fail if the user passes NULL for the object).
However, do NOT use VIR_DEBUG prior to virInitialize, since setting
up the error reporting can change where VIR_DEBUG output would be
routed. Instead add documentation to virGlobalInit, virInitialize,
and virGetVersion that better explains initialization.
* src/libvirt.c (virGetVersion, virConnectRef, virDomainRef)
(virNetworkRef, virInterfaceRef, virStoragePoolRef)
(virStorageVolRef, virNodeDeviceRef, virSecretRef, virStreamRef)
(virNWFilterRef, virDomainSnapshotRef): Debug on function entry.
* src/libvirt-lxc.c (virDomainLxcEnterNamespace)
(virDomainLxcEnterSecurityLabel): Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-12-27 21:16:56 +00:00
|
|
|
* The only other time it would be necessary to call virInitialize is if the
|
|
|
|
* application did not invoke virConnectOpen as its first API call, such
|
|
|
|
* as when calling virEventRegisterImpl() before setting up connections,
|
|
|
|
* or when using virSetErrorFunc() to alter error reporting of the first
|
|
|
|
* connection attempt.
|
2012-10-10 15:11:43 +00:00
|
|
|
*
|
|
|
|
* Returns 0 in case of success, -1 in case of error
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virInitialize(void)
|
|
|
|
{
|
|
|
|
if (virOnce(&virGlobalOnce, virGlobalInit) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (virGlobalError)
|
|
|
|
return -1;
|
2011-01-07 17:39:43 +00:00
|
|
|
return 0;
|
2006-03-27 15:24:36 +00:00
|
|
|
}
|
|
|
|
|
2013-12-28 02:42:30 +00:00
|
|
|
|
2009-01-15 19:56:05 +00:00
|
|
|
#ifdef WIN32
|
|
|
|
BOOL WINAPI
|
2012-10-17 09:23:12 +00:00
|
|
|
DllMain(HINSTANCE instance, DWORD reason, LPVOID ignore);
|
2009-01-15 19:56:05 +00:00
|
|
|
|
|
|
|
BOOL WINAPI
|
2019-10-14 12:45:33 +00:00
|
|
|
DllMain(HINSTANCE instance G_GNUC_UNUSED,
|
2012-10-17 09:23:12 +00:00
|
|
|
DWORD reason,
|
2019-10-14 12:45:33 +00:00
|
|
|
LPVOID ignore G_GNUC_UNUSED)
|
2009-01-15 19:56:05 +00:00
|
|
|
{
|
|
|
|
switch (reason) {
|
|
|
|
case DLL_PROCESS_ATTACH:
|
|
|
|
virInitialize();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DLL_THREAD_ATTACH:
|
|
|
|
case DLL_THREAD_DETACH:
|
2019-09-16 16:44:23 +00:00
|
|
|
/* Nothing todo in libvirt yet */
|
2009-01-15 19:56:05 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
|
|
/* Don't bother releasing per-thread data
|
|
|
|
since (hopefully) windows cleans up
|
|
|
|
everything on process exit */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
#endif
|
2006-03-27 15:24:36 +00:00
|
|
|
|
2013-12-28 02:42:30 +00:00
|
|
|
|
2007-02-14 15:37:18 +00:00
|
|
|
/**
|
2015-01-20 16:16:26 +00:00
|
|
|
* virSetSharedNetworkDriver:
|
2007-02-14 15:37:18 +00:00
|
|
|
* @driver: pointer to a network driver block
|
|
|
|
*
|
|
|
|
* Register a network virtualization driver
|
|
|
|
*
|
2015-01-20 16:16:26 +00:00
|
|
|
* Returns 0 on success, or -1 in case of error.
|
2007-02-14 15:37:18 +00:00
|
|
|
*/
|
|
|
|
int
|
2015-01-20 16:16:26 +00:00
|
|
|
virSetSharedNetworkDriver(virNetworkDriverPtr driver)
|
2007-02-14 15:37:18 +00:00
|
|
|
{
|
Santize the reporting of VIR_ERR_INVALID_ERROR
To ensure consistent error reporting of invalid arguments,
provide a number of predefined helper methods & macros.
- An arg which must not be NULL:
virCheckNonNullArgReturn(argname, retvalue)
virCheckNonNullArgGoto(argname, label)
- An arg which must be NULL
virCheckNullArgGoto(argname, label)
- An arg which must be positive (ie 1 or greater)
virCheckPositiveArgGoto(argname, label)
- An arg which must not be 0
virCheckNonZeroArgGoto(argname, label)
- An arg which must be zero
virCheckZeroArgGoto(argname, label)
- An arg which must not be negative (ie 0 or greater)
virCheckNonNegativeArgGoto(argname, label)
* src/libvirt.c, src/libvirt-qemu.c,
src/nodeinfo.c, src/datatypes.c: Update to use
virCheckXXXX macros
* po/POTFILES.in: Add libvirt-qemu.c and virterror_internal.h
* src/internal.h: Define macros for checking invalid args
* src/util/virterror_internal.h: Define macros for reporting
invalid args
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-05-25 17:41:07 +00:00
|
|
|
virCheckNonNullArgReturn(driver, -1);
|
2007-03-08 14:53:41 +00:00
|
|
|
|
2015-01-20 16:16:26 +00:00
|
|
|
if (virSharedNetworkDriver) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("A network driver is already registered"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_DEBUG("registering %s as network driver", driver->name);
|
2008-11-21 12:16:08 +00:00
|
|
|
|
2015-01-20 16:16:26 +00:00
|
|
|
virSharedNetworkDriver = driver;
|
|
|
|
return 0;
|
2007-02-14 15:37:18 +00:00
|
|
|
}
|
|
|
|
|
2013-12-28 02:42:30 +00:00
|
|
|
|
2009-05-20 14:26:49 +00:00
|
|
|
/**
|
2015-01-20 16:16:26 +00:00
|
|
|
* virSetSharedInterfaceDriver:
|
2009-09-04 13:40:52 +00:00
|
|
|
* @driver: pointer to an interface driver block
|
2009-05-20 14:26:49 +00:00
|
|
|
*
|
2009-09-04 13:40:52 +00:00
|
|
|
* Register an interface virtualization driver
|
2009-05-20 14:26:49 +00:00
|
|
|
*
|
|
|
|
* Returns the driver priority or -1 in case of error.
|
|
|
|
*/
|
|
|
|
int
|
2015-01-20 16:16:26 +00:00
|
|
|
virSetSharedInterfaceDriver(virInterfaceDriverPtr driver)
|
2009-05-20 14:26:49 +00:00
|
|
|
{
|
Santize the reporting of VIR_ERR_INVALID_ERROR
To ensure consistent error reporting of invalid arguments,
provide a number of predefined helper methods & macros.
- An arg which must not be NULL:
virCheckNonNullArgReturn(argname, retvalue)
virCheckNonNullArgGoto(argname, label)
- An arg which must be NULL
virCheckNullArgGoto(argname, label)
- An arg which must be positive (ie 1 or greater)
virCheckPositiveArgGoto(argname, label)
- An arg which must not be 0
virCheckNonZeroArgGoto(argname, label)
- An arg which must be zero
virCheckZeroArgGoto(argname, label)
- An arg which must not be negative (ie 0 or greater)
virCheckNonNegativeArgGoto(argname, label)
* src/libvirt.c, src/libvirt-qemu.c,
src/nodeinfo.c, src/datatypes.c: Update to use
virCheckXXXX macros
* po/POTFILES.in: Add libvirt-qemu.c and virterror_internal.h
* src/internal.h: Define macros for checking invalid args
* src/util/virterror_internal.h: Define macros for reporting
invalid args
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-05-25 17:41:07 +00:00
|
|
|
virCheckNonNullArgReturn(driver, -1);
|
2009-05-20 14:26:49 +00:00
|
|
|
|
2015-01-20 16:16:26 +00:00
|
|
|
if (virSharedInterfaceDriver) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("A interface driver is already registered"));
|
|
|
|
return -1;
|
|
|
|
}
|
2009-05-20 14:26:49 +00:00
|
|
|
|
2015-01-20 16:16:26 +00:00
|
|
|
VIR_DEBUG("registering %s as interface driver", driver->name);
|
|
|
|
|
|
|
|
virSharedInterfaceDriver = driver;
|
|
|
|
return 0;
|
2009-05-20 14:26:49 +00:00
|
|
|
}
|
|
|
|
|
2013-12-28 02:42:30 +00:00
|
|
|
|
2008-02-20 15:06:53 +00:00
|
|
|
/**
|
2015-01-20 16:16:26 +00:00
|
|
|
* virSetSharedStorageDriver:
|
2008-02-20 15:06:53 +00:00
|
|
|
* @driver: pointer to a storage driver block
|
|
|
|
*
|
|
|
|
* Register a storage virtualization driver
|
|
|
|
*
|
|
|
|
* Returns the driver priority or -1 in case of error.
|
|
|
|
*/
|
|
|
|
int
|
2015-01-20 16:16:26 +00:00
|
|
|
virSetSharedStorageDriver(virStorageDriverPtr driver)
|
2008-02-20 15:06:53 +00:00
|
|
|
{
|
Santize the reporting of VIR_ERR_INVALID_ERROR
To ensure consistent error reporting of invalid arguments,
provide a number of predefined helper methods & macros.
- An arg which must not be NULL:
virCheckNonNullArgReturn(argname, retvalue)
virCheckNonNullArgGoto(argname, label)
- An arg which must be NULL
virCheckNullArgGoto(argname, label)
- An arg which must be positive (ie 1 or greater)
virCheckPositiveArgGoto(argname, label)
- An arg which must not be 0
virCheckNonZeroArgGoto(argname, label)
- An arg which must be zero
virCheckZeroArgGoto(argname, label)
- An arg which must not be negative (ie 0 or greater)
virCheckNonNegativeArgGoto(argname, label)
* src/libvirt.c, src/libvirt-qemu.c,
src/nodeinfo.c, src/datatypes.c: Update to use
virCheckXXXX macros
* po/POTFILES.in: Add libvirt-qemu.c and virterror_internal.h
* src/internal.h: Define macros for checking invalid args
* src/util/virterror_internal.h: Define macros for reporting
invalid args
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-05-25 17:41:07 +00:00
|
|
|
virCheckNonNullArgReturn(driver, -1);
|
2008-02-20 15:06:53 +00:00
|
|
|
|
2015-01-20 16:16:26 +00:00
|
|
|
if (virSharedStorageDriver) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("A storage driver is already registered"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_DEBUG("registering %s as storage driver", driver->name);
|
2008-11-21 12:16:08 +00:00
|
|
|
|
2015-01-20 16:16:26 +00:00
|
|
|
virSharedStorageDriver = driver;
|
|
|
|
return 0;
|
2008-02-20 15:06:53 +00:00
|
|
|
}
|
|
|
|
|
2013-12-28 02:42:30 +00:00
|
|
|
|
2008-11-21 12:19:22 +00:00
|
|
|
/**
|
2015-01-20 16:16:26 +00:00
|
|
|
* virSetSharedNodeDeviceDriver:
|
2008-11-21 12:19:22 +00:00
|
|
|
* @driver: pointer to a device monitor block
|
|
|
|
*
|
|
|
|
* Register a device monitor
|
|
|
|
*
|
|
|
|
* Returns the driver priority or -1 in case of error.
|
|
|
|
*/
|
|
|
|
int
|
2015-01-20 16:16:26 +00:00
|
|
|
virSetSharedNodeDeviceDriver(virNodeDeviceDriverPtr driver)
|
2008-11-21 12:19:22 +00:00
|
|
|
{
|
Santize the reporting of VIR_ERR_INVALID_ERROR
To ensure consistent error reporting of invalid arguments,
provide a number of predefined helper methods & macros.
- An arg which must not be NULL:
virCheckNonNullArgReturn(argname, retvalue)
virCheckNonNullArgGoto(argname, label)
- An arg which must be NULL
virCheckNullArgGoto(argname, label)
- An arg which must be positive (ie 1 or greater)
virCheckPositiveArgGoto(argname, label)
- An arg which must not be 0
virCheckNonZeroArgGoto(argname, label)
- An arg which must be zero
virCheckZeroArgGoto(argname, label)
- An arg which must not be negative (ie 0 or greater)
virCheckNonNegativeArgGoto(argname, label)
* src/libvirt.c, src/libvirt-qemu.c,
src/nodeinfo.c, src/datatypes.c: Update to use
virCheckXXXX macros
* po/POTFILES.in: Add libvirt-qemu.c and virterror_internal.h
* src/internal.h: Define macros for checking invalid args
* src/util/virterror_internal.h: Define macros for reporting
invalid args
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-05-25 17:41:07 +00:00
|
|
|
virCheckNonNullArgReturn(driver, -1);
|
2008-11-21 12:19:22 +00:00
|
|
|
|
2015-01-20 16:16:26 +00:00
|
|
|
if (virSharedNodeDeviceDriver) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("A node device driver is already registered"));
|
|
|
|
return -1;
|
|
|
|
}
|
2008-11-21 12:46:39 +00:00
|
|
|
|
2015-01-20 16:16:26 +00:00
|
|
|
VIR_DEBUG("registering %s as device driver", driver->name);
|
|
|
|
|
|
|
|
virSharedNodeDeviceDriver = driver;
|
|
|
|
return 0;
|
2008-11-21 12:19:22 +00:00
|
|
|
}
|
|
|
|
|
2013-12-28 02:42:30 +00:00
|
|
|
|
2009-08-14 19:42:19 +00:00
|
|
|
/**
|
2015-01-20 16:16:26 +00:00
|
|
|
* virSetSharedSecretDriver:
|
2009-08-14 19:42:19 +00:00
|
|
|
* @driver: pointer to a secret driver block
|
|
|
|
*
|
|
|
|
* Register a secret driver
|
|
|
|
*
|
|
|
|
* Returns the driver priority or -1 in case of error.
|
|
|
|
*/
|
|
|
|
int
|
2015-01-20 16:16:26 +00:00
|
|
|
virSetSharedSecretDriver(virSecretDriverPtr driver)
|
2009-08-14 19:42:19 +00:00
|
|
|
{
|
Santize the reporting of VIR_ERR_INVALID_ERROR
To ensure consistent error reporting of invalid arguments,
provide a number of predefined helper methods & macros.
- An arg which must not be NULL:
virCheckNonNullArgReturn(argname, retvalue)
virCheckNonNullArgGoto(argname, label)
- An arg which must be NULL
virCheckNullArgGoto(argname, label)
- An arg which must be positive (ie 1 or greater)
virCheckPositiveArgGoto(argname, label)
- An arg which must not be 0
virCheckNonZeroArgGoto(argname, label)
- An arg which must be zero
virCheckZeroArgGoto(argname, label)
- An arg which must not be negative (ie 0 or greater)
virCheckNonNegativeArgGoto(argname, label)
* src/libvirt.c, src/libvirt-qemu.c,
src/nodeinfo.c, src/datatypes.c: Update to use
virCheckXXXX macros
* po/POTFILES.in: Add libvirt-qemu.c and virterror_internal.h
* src/internal.h: Define macros for checking invalid args
* src/util/virterror_internal.h: Define macros for reporting
invalid args
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-05-25 17:41:07 +00:00
|
|
|
virCheckNonNullArgReturn(driver, -1);
|
2009-08-14 19:42:19 +00:00
|
|
|
|
2015-01-20 16:16:26 +00:00
|
|
|
if (virSharedSecretDriver) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("A secret driver is already registered"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_DEBUG("registering %s as secret driver", driver->name);
|
2009-08-14 19:42:19 +00:00
|
|
|
|
2015-01-20 16:16:26 +00:00
|
|
|
virSharedSecretDriver = driver;
|
|
|
|
return 0;
|
2009-08-14 19:42:19 +00:00
|
|
|
}
|
|
|
|
|
2013-12-28 02:42:30 +00:00
|
|
|
|
2010-03-25 17:46:02 +00:00
|
|
|
/**
|
2015-01-20 16:16:26 +00:00
|
|
|
* virSetSharedNWFilterDriver:
|
2010-03-25 17:46:02 +00:00
|
|
|
* @driver: pointer to a network filter driver block
|
|
|
|
*
|
|
|
|
* Register a network filter virtualization driver
|
|
|
|
*
|
|
|
|
* Returns the driver priority or -1 in case of error.
|
|
|
|
*/
|
|
|
|
int
|
2015-01-20 16:16:26 +00:00
|
|
|
virSetSharedNWFilterDriver(virNWFilterDriverPtr driver)
|
2010-03-25 17:46:02 +00:00
|
|
|
{
|
Santize the reporting of VIR_ERR_INVALID_ERROR
To ensure consistent error reporting of invalid arguments,
provide a number of predefined helper methods & macros.
- An arg which must not be NULL:
virCheckNonNullArgReturn(argname, retvalue)
virCheckNonNullArgGoto(argname, label)
- An arg which must be NULL
virCheckNullArgGoto(argname, label)
- An arg which must be positive (ie 1 or greater)
virCheckPositiveArgGoto(argname, label)
- An arg which must not be 0
virCheckNonZeroArgGoto(argname, label)
- An arg which must be zero
virCheckZeroArgGoto(argname, label)
- An arg which must not be negative (ie 0 or greater)
virCheckNonNegativeArgGoto(argname, label)
* src/libvirt.c, src/libvirt-qemu.c,
src/nodeinfo.c, src/datatypes.c: Update to use
virCheckXXXX macros
* po/POTFILES.in: Add libvirt-qemu.c and virterror_internal.h
* src/internal.h: Define macros for checking invalid args
* src/util/virterror_internal.h: Define macros for reporting
invalid args
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-05-25 17:41:07 +00:00
|
|
|
virCheckNonNullArgReturn(driver, -1);
|
2010-03-25 17:46:02 +00:00
|
|
|
|
2015-01-20 16:16:26 +00:00
|
|
|
if (virSharedNWFilterDriver) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("A network filter driver is already registered"));
|
|
|
|
return -1;
|
|
|
|
}
|
2010-03-25 17:46:02 +00:00
|
|
|
|
2015-01-20 16:16:26 +00:00
|
|
|
VIR_DEBUG("registering %s as network filter driver", driver->name);
|
|
|
|
|
|
|
|
virSharedNWFilterDriver = driver;
|
|
|
|
return 0;
|
2010-03-25 17:46:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-02-14 15:37:18 +00:00
|
|
|
/**
|
2015-01-20 16:16:26 +00:00
|
|
|
* virRegisterConnectDriver:
|
2007-02-14 15:37:18 +00:00
|
|
|
* @driver: pointer to a driver block
|
2015-01-20 16:16:26 +00:00
|
|
|
* @setSharedDrivers: populate shared drivers
|
2007-02-14 15:37:18 +00:00
|
|
|
*
|
2015-01-20 16:16:26 +00:00
|
|
|
* Register a virtualization driver, optionally filling in
|
|
|
|
* any empty pointers for shared secondary drivers
|
2007-02-14 15:37:18 +00:00
|
|
|
*
|
|
|
|
* Returns the driver priority or -1 in case of error.
|
|
|
|
*/
|
|
|
|
int
|
2015-01-20 16:16:26 +00:00
|
|
|
virRegisterConnectDriver(virConnectDriverPtr driver,
|
|
|
|
bool setSharedDrivers)
|
2007-02-14 15:37:18 +00:00
|
|
|
{
|
2014-01-14 21:20:59 +00:00
|
|
|
VIR_DEBUG("driver=%p name=%s", driver,
|
2015-01-20 16:16:26 +00:00
|
|
|
driver ? NULLSTR(driver->hypervisorDriver->name) : "(null)");
|
2011-01-07 17:31:36 +00:00
|
|
|
|
Santize the reporting of VIR_ERR_INVALID_ERROR
To ensure consistent error reporting of invalid arguments,
provide a number of predefined helper methods & macros.
- An arg which must not be NULL:
virCheckNonNullArgReturn(argname, retvalue)
virCheckNonNullArgGoto(argname, label)
- An arg which must be NULL
virCheckNullArgGoto(argname, label)
- An arg which must be positive (ie 1 or greater)
virCheckPositiveArgGoto(argname, label)
- An arg which must not be 0
virCheckNonZeroArgGoto(argname, label)
- An arg which must be zero
virCheckZeroArgGoto(argname, label)
- An arg which must not be negative (ie 0 or greater)
virCheckNonNegativeArgGoto(argname, label)
* src/libvirt.c, src/libvirt-qemu.c,
src/nodeinfo.c, src/datatypes.c: Update to use
virCheckXXXX macros
* po/POTFILES.in: Add libvirt-qemu.c and virterror_internal.h
* src/internal.h: Define macros for checking invalid args
* src/util/virterror_internal.h: Define macros for reporting
invalid args
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-05-25 17:41:07 +00:00
|
|
|
virCheckNonNullArgReturn(driver, -1);
|
2015-01-20 16:16:26 +00:00
|
|
|
if (virConnectDriverTabCount >= MAX_DRIVERS) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Too many drivers, cannot register %s"),
|
|
|
|
driver->hypervisorDriver->name);
|
|
|
|
return -1;
|
|
|
|
}
|
2007-03-08 14:53:41 +00:00
|
|
|
|
2012-10-17 09:23:12 +00:00
|
|
|
VIR_DEBUG("registering %s as driver %d",
|
2015-01-20 16:16:26 +00:00
|
|
|
driver->hypervisorDriver->name, virConnectDriverTabCount);
|
|
|
|
|
|
|
|
if (setSharedDrivers) {
|
|
|
|
if (driver->interfaceDriver == NULL)
|
|
|
|
driver->interfaceDriver = virSharedInterfaceDriver;
|
|
|
|
if (driver->networkDriver == NULL)
|
|
|
|
driver->networkDriver = virSharedNetworkDriver;
|
|
|
|
if (driver->nodeDeviceDriver == NULL)
|
|
|
|
driver->nodeDeviceDriver = virSharedNodeDeviceDriver;
|
|
|
|
if (driver->nwfilterDriver == NULL)
|
|
|
|
driver->nwfilterDriver = virSharedNWFilterDriver;
|
|
|
|
if (driver->secretDriver == NULL)
|
|
|
|
driver->secretDriver = virSharedSecretDriver;
|
|
|
|
if (driver->storageDriver == NULL)
|
|
|
|
driver->storageDriver = virSharedStorageDriver;
|
|
|
|
}
|
2008-10-15 10:33:01 +00:00
|
|
|
|
2015-01-20 16:16:26 +00:00
|
|
|
virConnectDriverTab[virConnectDriverTabCount] = driver;
|
|
|
|
return virConnectDriverTabCount++;
|
2007-02-14 15:37:18 +00:00
|
|
|
}
|
|
|
|
|
2013-12-28 02:42:30 +00:00
|
|
|
|
remote: enable connecting to the per-driver daemons
Historically URIs handled by the remote driver will always connect to
the libvirtd UNIX socket. There will now be one daemon per driver, and
each of these has its own UNIX sockets to connect to.
It will still be possible to run the traditional monolithic libvirtd
though, which will have the original UNIX socket path.
In addition there is a virproxyd daemon that doesn't run any drivers,
but provides proxying for clients accessing libvirt over IP sockets, or
tunnelling to the legacy libvirtd UNIX socket path.
Finally when running inside a daemon, the remote driver must not reject
connections unconditionally. For example, the QEMU driver needs to be
able to connect to the network driver. The remote driver must thus be
willing to handle connections even when inside the daemon, provided no
local driver is registered.
This refactoring enables the remote driver to be able to connect to the
per-driver daemons. The URI parameter "mode" accepts the values "auto",
"direct" and "legacy" to control which daemons are connected to.
The client side libvirt.conf config file also supports a "remote_mode"
setting which is used if the URI parameter is not set.
If neither the config file or URI parameter set a mode, then "auto"
is used, whereby the client looks to see which sockets actually exist
right now.
The remote driver will only ever spawn the per-driver daemons, or
the legacy libvirtd. It won't ever try to spawn virtproxyd, as
that is only there for IP based connectivity, or for access from
legacy remote clients.
If connecting to a remote host over any kind of ssh tunnel, for now we
must assume only the legacy socket exists. A future patch will introduce
a netcat replacement that is tailored for libvirt to make remote
tunnelling easier.
The configure arg '--with-remote-default-mode=legacy|direct' allows
packagers to set a default at build time. If not given, it will default
to legacy mode.
Eventually the default will switch to direct mode. Distros can choose
to do the switch earlier if desired. The main blocker is testing and
suitable SELinux/AppArmor policies.
Reviewed-by: Andrea Bolognani <abologna@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
2019-07-04 08:41:34 +00:00
|
|
|
/**
|
|
|
|
* virHasDriverForURIScheme:
|
|
|
|
* @scheme: the URI scheme
|
|
|
|
*
|
|
|
|
* Determine if there is a driver registered that explicitly
|
|
|
|
* handles URIs with the scheme @scheme.
|
|
|
|
*
|
|
|
|
* Returns: true if a driver is registered
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
virHasDriverForURIScheme(const char *scheme)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
size_t j;
|
|
|
|
|
|
|
|
for (i = 0; i < virConnectDriverTabCount; i++) {
|
|
|
|
if (!virConnectDriverTab[i]->uriSchemes)
|
|
|
|
continue;
|
|
|
|
for (j = 0; virConnectDriverTab[i]->uriSchemes[j]; j++) {
|
|
|
|
if (STREQ(virConnectDriverTab[i]->uriSchemes[j], scheme))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2007-06-26 22:56:14 +00:00
|
|
|
/**
|
|
|
|
* virRegisterStateDriver:
|
|
|
|
* @driver: pointer to a driver block
|
|
|
|
*
|
|
|
|
* Register a virtualization driver
|
|
|
|
*
|
|
|
|
* Returns the driver priority or -1 in case of error.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virRegisterStateDriver(virStateDriverPtr driver)
|
|
|
|
{
|
Santize the reporting of VIR_ERR_INVALID_ERROR
To ensure consistent error reporting of invalid arguments,
provide a number of predefined helper methods & macros.
- An arg which must not be NULL:
virCheckNonNullArgReturn(argname, retvalue)
virCheckNonNullArgGoto(argname, label)
- An arg which must be NULL
virCheckNullArgGoto(argname, label)
- An arg which must be positive (ie 1 or greater)
virCheckPositiveArgGoto(argname, label)
- An arg which must not be 0
virCheckNonZeroArgGoto(argname, label)
- An arg which must be zero
virCheckZeroArgGoto(argname, label)
- An arg which must not be negative (ie 0 or greater)
virCheckNonNegativeArgGoto(argname, label)
* src/libvirt.c, src/libvirt-qemu.c,
src/nodeinfo.c, src/datatypes.c: Update to use
virCheckXXXX macros
* po/POTFILES.in: Add libvirt-qemu.c and virterror_internal.h
* src/internal.h: Define macros for checking invalid args
* src/util/virterror_internal.h: Define macros for reporting
invalid args
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-05-25 17:41:07 +00:00
|
|
|
virCheckNonNullArgReturn(driver, -1);
|
2015-01-20 16:16:26 +00:00
|
|
|
|
|
|
|
if (virStateDriverTabCount >= MAX_DRIVERS) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Too many drivers, cannot register %s"),
|
|
|
|
driver->name);
|
|
|
|
return -1;
|
|
|
|
}
|
2007-06-26 22:56:14 +00:00
|
|
|
|
|
|
|
virStateDriverTab[virStateDriverTabCount] = driver;
|
|
|
|
return virStateDriverTabCount++;
|
|
|
|
}
|
|
|
|
|
2013-12-28 02:42:30 +00:00
|
|
|
|
2008-11-25 10:31:52 +00:00
|
|
|
/**
|
|
|
|
* virStateInitialize:
|
2012-10-31 19:03:54 +00:00
|
|
|
* @privileged: set to true if running with root privilege, false otherwise
|
2019-07-23 12:05:18 +00:00
|
|
|
* @mandatory: set to true if all drivers must report success, not skipped
|
2019-05-17 11:30:45 +00:00
|
|
|
* @root: directory to use for embedded mode
|
2012-10-31 19:03:55 +00:00
|
|
|
* @callback: callback to invoke to inhibit shutdown of the daemon
|
|
|
|
* @opaque: data to pass to @callback
|
2008-11-25 10:31:52 +00:00
|
|
|
*
|
2019-03-01 14:22:40 +00:00
|
|
|
* Initialize all virtualization drivers.
|
2008-11-25 10:31:52 +00:00
|
|
|
*
|
2019-05-17 11:30:45 +00:00
|
|
|
* 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=/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/
|
|
|
|
*
|
2009-09-25 12:24:40 +00:00
|
|
|
* Returns 0 if all succeed, -1 upon any failure.
|
2008-11-25 10:31:52 +00:00
|
|
|
*/
|
2013-12-28 02:42:30 +00:00
|
|
|
int
|
|
|
|
virStateInitialize(bool privileged,
|
2019-07-23 12:05:18 +00:00
|
|
|
bool mandatory,
|
2019-05-17 11:30:45 +00:00
|
|
|
const char *root,
|
2013-12-28 02:42:30 +00:00
|
|
|
virStateInhibitCallback callback,
|
|
|
|
void *opaque)
|
2012-10-31 19:03:55 +00:00
|
|
|
{
|
Convert 'int i' to 'size_t i' in src/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2007-06-26 22:56:14 +00:00
|
|
|
|
|
|
|
if (virInitialize() < 0)
|
|
|
|
return -1;
|
|
|
|
|
2013-05-21 08:08:42 +00:00
|
|
|
for (i = 0; i < virStateDriverTabCount; i++) {
|
libvirt: support an "embed" URI path selector for opening drivers
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@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
2019-05-17 11:42:04 +00:00
|
|
|
if (virStateDriverTab[i]->stateInitialize &&
|
|
|
|
!virStateDriverTab[i]->initialized) {
|
2019-07-23 12:05:18 +00:00
|
|
|
virDrvStateInitResult ret;
|
2012-06-15 12:48:34 +00:00
|
|
|
VIR_DEBUG("Running global init for %s state driver",
|
Fix return value in virStateInitialize impl for LXC
The LXC driver was mistakenly returning -1 for lxcStartup()
in scenarios that are not an error. This caused the libvirtd
to quit for unprivileged users. This fixes the return code
of LXC driver, and also adds a "name" field to the virStateDriver
struct and logging to make it easier to find these problems
in the future
* src/driver.h: Add a 'name' field to state driver to allow
easy identification during failures
* src/libvirt.c: Log name of failed driver for virStateInit
failures
* src/lxc/lxc_driver.c: Don't return a failure code for
lxcStartup() if LXC is not available on this host, simply
disable the driver.
* src/network/bridge_driver.c, src/node_device/node_device_devkit.c,
src/node_device/node_device_hal.c, src/opennebula/one_driver.c,
src/qemu/qemu_driver.c, src/remote/remote_driver.c,
src/secret/secret_driver.c, src/storage/storage_driver.c,
src/uml/uml_driver.c, src/xen/xen_driver.c: Fill in name
field in virStateDriver struct
2009-11-02 23:18:19 +00:00
|
|
|
virStateDriverTab[i]->name);
|
libvirt: support an "embed" URI path selector for opening drivers
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@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
2019-05-17 11:42:04 +00:00
|
|
|
virStateDriverTab[i]->initialized = true;
|
2019-07-23 12:05:18 +00:00
|
|
|
ret = virStateDriverTab[i]->stateInitialize(privileged,
|
2019-05-17 11:30:45 +00:00
|
|
|
root,
|
2019-07-23 12:05:18 +00:00
|
|
|
callback,
|
|
|
|
opaque);
|
|
|
|
VIR_DEBUG("State init result %d (mandatory=%d)", ret, mandatory);
|
|
|
|
if (ret == VIR_DRV_STATE_INIT_ERROR) {
|
2012-01-20 18:02:55 +00:00
|
|
|
VIR_ERROR(_("Initialization of %s state driver failed: %s"),
|
|
|
|
virStateDriverTab[i]->name,
|
2016-05-19 19:10:19 +00:00
|
|
|
virGetLastErrorMessage());
|
2012-06-15 12:48:34 +00:00
|
|
|
return -1;
|
2019-07-23 12:05:18 +00:00
|
|
|
} else if (ret == VIR_DRV_STATE_INIT_SKIPPED && mandatory) {
|
|
|
|
VIR_ERROR(_("Initialization of mandatory %s state driver skipped"),
|
|
|
|
virStateDriverTab[i]->name);
|
|
|
|
return -1;
|
2012-06-15 12:48:34 +00:00
|
|
|
}
|
Fix return value in virStateInitialize impl for LXC
The LXC driver was mistakenly returning -1 for lxcStartup()
in scenarios that are not an error. This caused the libvirtd
to quit for unprivileged users. This fixes the return code
of LXC driver, and also adds a "name" field to the virStateDriver
struct and logging to make it easier to find these problems
in the future
* src/driver.h: Add a 'name' field to state driver to allow
easy identification during failures
* src/libvirt.c: Log name of failed driver for virStateInit
failures
* src/lxc/lxc_driver.c: Don't return a failure code for
lxcStartup() if LXC is not available on this host, simply
disable the driver.
* src/network/bridge_driver.c, src/node_device/node_device_devkit.c,
src/node_device/node_device_hal.c, src/opennebula/one_driver.c,
src/qemu/qemu_driver.c, src/remote/remote_driver.c,
src/secret/secret_driver.c, src/storage/storage_driver.c,
src/uml/uml_driver.c, src/xen/xen_driver.c: Fill in name
field in virStateDriver struct
2009-11-02 23:18:19 +00:00
|
|
|
}
|
2007-06-26 22:56:14 +00:00
|
|
|
}
|
2012-06-15 12:48:34 +00:00
|
|
|
return 0;
|
2007-06-26 22:56:14 +00:00
|
|
|
}
|
|
|
|
|
2013-12-28 02:42:30 +00:00
|
|
|
|
2008-11-25 10:31:52 +00:00
|
|
|
/**
|
|
|
|
* virStateCleanup:
|
|
|
|
*
|
|
|
|
* Run each virtualization driver's cleanup method.
|
|
|
|
*
|
2009-09-25 12:24:40 +00:00
|
|
|
* Returns 0 if all succeed, -1 upon any failure.
|
2008-11-25 10:31:52 +00:00
|
|
|
*/
|
2013-12-28 02:42:30 +00:00
|
|
|
int
|
|
|
|
virStateCleanup(void)
|
|
|
|
{
|
2016-05-17 11:44:46 +00:00
|
|
|
int r;
|
Convert 'int i' to 'size_t i' in src/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
int ret = 0;
|
2007-06-26 22:56:14 +00:00
|
|
|
|
2016-05-17 11:44:46 +00:00
|
|
|
for (r = virStateDriverTabCount - 1; r >= 0; r--) {
|
|
|
|
if (virStateDriverTab[r]->stateCleanup &&
|
|
|
|
virStateDriverTab[r]->stateCleanup() < 0)
|
2007-06-26 22:56:14 +00:00
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-12-28 02:42:30 +00:00
|
|
|
|
2008-11-25 10:31:52 +00:00
|
|
|
/**
|
|
|
|
* virStateReload:
|
|
|
|
*
|
|
|
|
* Run each virtualization driver's reload method.
|
|
|
|
*
|
2009-09-25 12:24:40 +00:00
|
|
|
* Returns 0 if all succeed, -1 upon any failure.
|
2008-11-25 10:31:52 +00:00
|
|
|
*/
|
2013-12-28 02:42:30 +00:00
|
|
|
int
|
|
|
|
virStateReload(void)
|
|
|
|
{
|
Convert 'int i' to 'size_t i' in src/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
|
|
|
int ret = 0;
|
2007-06-26 22:56:14 +00:00
|
|
|
|
2013-05-21 08:08:42 +00:00
|
|
|
for (i = 0; i < virStateDriverTabCount; i++) {
|
2013-04-22 17:26:01 +00:00
|
|
|
if (virStateDriverTab[i]->stateReload &&
|
|
|
|
virStateDriverTab[i]->stateReload() < 0)
|
2007-06-26 22:56:14 +00:00
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-12-28 02:42:30 +00:00
|
|
|
|
2012-10-31 19:03:52 +00:00
|
|
|
/**
|
|
|
|
* virStateStop:
|
|
|
|
*
|
|
|
|
* Run each virtualization driver's "stop" method.
|
|
|
|
*
|
|
|
|
* Returns 0 if successful, -1 on failure
|
|
|
|
*/
|
2013-12-28 02:42:30 +00:00
|
|
|
int
|
|
|
|
virStateStop(void)
|
|
|
|
{
|
Convert 'int i' to 'size_t i' in src/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
|
|
|
int ret = 0;
|
2012-10-31 19:03:52 +00:00
|
|
|
|
2013-05-21 08:08:42 +00:00
|
|
|
for (i = 0; i < virStateDriverTabCount; i++) {
|
2013-04-22 17:26:01 +00:00
|
|
|
if (virStateDriverTab[i]->stateStop &&
|
|
|
|
virStateDriverTab[i]->stateStop())
|
2012-10-31 19:03:52 +00:00
|
|
|
ret = 1;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
2007-06-26 22:56:14 +00:00
|
|
|
|
|
|
|
|
2005-12-08 15:08:46 +00:00
|
|
|
/**
|
|
|
|
* virGetVersion:
|
|
|
|
* @libVer: return value for the library version (OUT)
|
2011-06-01 08:29:13 +00:00
|
|
|
* @type: ignored; pass NULL
|
|
|
|
* @typeVer: pass NULL; for historical purposes duplicates @libVer if
|
|
|
|
* non-NULL
|
|
|
|
*
|
|
|
|
* Provides version information. @libVer is the version of the
|
|
|
|
* library and will always be set unless an error occurs, in which case
|
|
|
|
* an error code will be returned. @typeVer exists for historical
|
|
|
|
* compatibility; if it is not NULL it will duplicate @libVer (it was
|
|
|
|
* originally intended to return hypervisor information based on @type,
|
|
|
|
* but due to the design of remote clients this is not reliable). To
|
maint: move debug statements first in public API
Most of our public APIs emit a debug log on entry, prior to anything
else. There were a few exceptions where obvious failures were not
logged, so fix those. When moving a debug earlier, this patch also
makes sure to avoid any NULL dereference during the log (the APIs
are supposed to gracefully fail if the user passes NULL for the object).
However, do NOT use VIR_DEBUG prior to virInitialize, since setting
up the error reporting can change where VIR_DEBUG output would be
routed. Instead add documentation to virGlobalInit, virInitialize,
and virGetVersion that better explains initialization.
* src/libvirt.c (virGetVersion, virConnectRef, virDomainRef)
(virNetworkRef, virInterfaceRef, virStoragePoolRef)
(virStorageVolRef, virNodeDeviceRef, virSecretRef, virStreamRef)
(virNWFilterRef, virDomainSnapshotRef): Debug on function entry.
* src/libvirt-lxc.c (virDomainLxcEnterNamespace)
(virDomainLxcEnterSecurityLabel): Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-12-27 21:16:56 +00:00
|
|
|
* get the version of the running hypervisor use the virConnectGetVersion()
|
2011-06-01 08:29:13 +00:00
|
|
|
* function instead. To get the libvirt library version used by a
|
maint: move debug statements first in public API
Most of our public APIs emit a debug log on entry, prior to anything
else. There were a few exceptions where obvious failures were not
logged, so fix those. When moving a debug earlier, this patch also
makes sure to avoid any NULL dereference during the log (the APIs
are supposed to gracefully fail if the user passes NULL for the object).
However, do NOT use VIR_DEBUG prior to virInitialize, since setting
up the error reporting can change where VIR_DEBUG output would be
routed. Instead add documentation to virGlobalInit, virInitialize,
and virGetVersion that better explains initialization.
* src/libvirt.c (virGetVersion, virConnectRef, virDomainRef)
(virNetworkRef, virInterfaceRef, virStoragePoolRef)
(virStorageVolRef, virNodeDeviceRef, virSecretRef, virStreamRef)
(virNWFilterRef, virDomainSnapshotRef): Debug on function entry.
* src/libvirt-lxc.c (virDomainLxcEnterNamespace)
(virDomainLxcEnterSecurityLabel): Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-12-27 21:16:56 +00:00
|
|
|
* connection use the virConnectGetLibVersion() instead.
|
|
|
|
*
|
|
|
|
* This function includes a call to virInitialize() when necessary.
|
2005-12-08 15:08:46 +00:00
|
|
|
*
|
|
|
|
* Returns -1 in case of failure, 0 otherwise, and values for @libVer and
|
|
|
|
* @typeVer have the format major * 1,000,000 + minor * 1,000 + release.
|
|
|
|
*/
|
|
|
|
int
|
2019-10-14 12:45:33 +00:00
|
|
|
virGetVersion(unsigned long *libVer, const char *type G_GNUC_UNUSED,
|
2006-03-15 12:13:25 +00:00
|
|
|
unsigned long *typeVer)
|
|
|
|
{
|
2012-10-10 15:11:43 +00:00
|
|
|
if (virInitialize() < 0)
|
|
|
|
goto error;
|
maint: move debug statements first in public API
Most of our public APIs emit a debug log on entry, prior to anything
else. There were a few exceptions where obvious failures were not
logged, so fix those. When moving a debug earlier, this patch also
makes sure to avoid any NULL dereference during the log (the APIs
are supposed to gracefully fail if the user passes NULL for the object).
However, do NOT use VIR_DEBUG prior to virInitialize, since setting
up the error reporting can change where VIR_DEBUG output would be
routed. Instead add documentation to virGlobalInit, virInitialize,
and virGetVersion that better explains initialization.
* src/libvirt.c (virGetVersion, virConnectRef, virDomainRef)
(virNetworkRef, virInterfaceRef, virStoragePoolRef)
(virStorageVolRef, virNodeDeviceRef, virSecretRef, virStreamRef)
(virNWFilterRef, virDomainSnapshotRef): Debug on function entry.
* src/libvirt-lxc.c (virDomainLxcEnterNamespace)
(virDomainLxcEnterSecurityLabel): Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-12-27 21:16:56 +00:00
|
|
|
VIR_DEBUG("libVir=%p, type=%s, typeVer=%p", libVer, type, typeVer);
|
2006-03-28 14:41:04 +00:00
|
|
|
|
maint: reset error on entrance to public API
We document that calling any public API wipes out all prior
libvirt errors in the same thread; but weren't obeying this
style in a few functions.
There are a couple of nested uses of virConnectRef (in lxc
and qemu reboot paths), but they should not be affected by
this change in semantics since there should not be any
previous error getting nuked (a later patch will clean up
the nested calls, along with abuse of virConnectClose on
cleanup paths which DOES nuke errors).
* src/libvirt.c (virGetVersion, virConnectRef, virDomainRef)
(virDomainGetSecurityLabel, virDomainGetSecurityLabelList)
(virDomainSetMetadata, virDomainGetMetadata)
(virNodeGetSecurityModel, virNetworkRef, virInterfaceRef)
(virStoragePoolRef, virStorageVolRef, virNodeDeviceGetName)
(virNodeDeviceRef, virSecretRef, virStreamRef, virNWFilterRef)
(virDomainSnapshotRef): Reset error on entrance.
(do_open): Drop redundant error reset.
* src/libvirt-qemu.c (virDomainQemuAgentCommand): Likewise.
* src/libvirt-lxc.c (virDomainLxcEnterNamespace)
(virDomainLxcEnterSecurityLabel): Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-12-27 21:54:34 +00:00
|
|
|
virResetLastError();
|
2005-12-08 15:08:46 +00:00
|
|
|
if (libVer == NULL)
|
2009-09-30 15:11:47 +00:00
|
|
|
goto error;
|
2005-12-08 15:08:46 +00:00
|
|
|
*libVer = LIBVIR_VERSION_NUMBER;
|
|
|
|
|
2011-06-01 08:29:13 +00:00
|
|
|
if (typeVer != NULL)
|
2009-02-17 10:33:41 +00:00
|
|
|
*typeVer = LIBVIR_VERSION_NUMBER;
|
|
|
|
|
2011-01-07 17:39:43 +00:00
|
|
|
return 0;
|
2009-09-30 15:11:47 +00:00
|
|
|
|
2014-03-25 06:49:02 +00:00
|
|
|
error:
|
2009-09-30 15:11:47 +00:00
|
|
|
virDispatchError(NULL);
|
|
|
|
return -1;
|
2005-12-08 15:08:46 +00:00
|
|
|
}
|
|
|
|
|
2012-03-14 12:30:52 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
virConnectGetDefaultURI(virConfPtr conf,
|
2016-07-08 10:38:17 +00:00
|
|
|
char **name)
|
2012-03-14 12:30:52 +00:00
|
|
|
{
|
2019-08-01 12:35:56 +00:00
|
|
|
const char *defname = getenv("LIBVIRT_DEFAULT_URI");
|
2012-03-14 12:30:52 +00:00
|
|
|
if (defname && *defname) {
|
|
|
|
VIR_DEBUG("Using LIBVIRT_DEFAULT_URI '%s'", defname);
|
2019-10-20 11:49:46 +00:00
|
|
|
*name = g_strdup(defname);
|
2016-07-08 10:38:17 +00:00
|
|
|
} else {
|
|
|
|
if (virConfGetValueString(conf, "uri_default", name) < 0)
|
2019-10-21 18:19:05 +00:00
|
|
|
return -1;
|
2016-07-08 10:38:17 +00:00
|
|
|
|
|
|
|
if (*name)
|
|
|
|
VIR_DEBUG("Using config file uri '%s'", *name);
|
2012-03-14 12:30:52 +00:00
|
|
|
}
|
|
|
|
|
2019-10-21 18:19:05 +00:00
|
|
|
return 0;
|
2011-10-13 10:49:45 +00:00
|
|
|
}
|
|
|
|
|
2013-12-28 02:42:30 +00:00
|
|
|
|
2016-04-16 12:59:08 +00:00
|
|
|
/*
|
|
|
|
* Check to see if an invalid URI like qemu://system (missing /) was passed,
|
|
|
|
* offer the suggested fix.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
virConnectCheckURIMissingSlash(const char *uristr, virURIPtr uri)
|
|
|
|
{
|
2018-04-09 15:33:22 +00:00
|
|
|
if (!uri->path || !uri->server)
|
2016-04-20 17:25:07 +00:00
|
|
|
return 0;
|
|
|
|
|
2016-04-16 12:59:08 +00:00
|
|
|
/* To avoid false positives, only check drivers that mandate
|
|
|
|
a path component in the URI, like /system or /session */
|
|
|
|
if (STRNEQ(uri->scheme, "qemu") &&
|
|
|
|
STRNEQ(uri->scheme, "vbox") &&
|
|
|
|
STRNEQ(uri->scheme, "vz"))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (STREQ(uri->server, "session") ||
|
|
|
|
STREQ(uri->server, "system")) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("invalid URI %s (maybe you want %s:///%s)"),
|
|
|
|
uristr, uri->scheme, uri->server);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-04-04 14:19:49 +00:00
|
|
|
static virConnectPtr
|
2016-04-19 16:18:40 +00:00
|
|
|
virConnectOpenInternal(const char *name,
|
|
|
|
virConnectAuthPtr auth,
|
|
|
|
unsigned int flags)
|
2006-03-15 12:13:25 +00:00
|
|
|
{
|
Convert 'int i' to 'size_t i' in src/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
|
|
|
int res;
|
2008-11-17 11:44:51 +00:00
|
|
|
virConnectPtr ret;
|
2019-10-15 12:47:50 +00:00
|
|
|
g_autoptr(virConf) conf = NULL;
|
2016-07-08 10:38:17 +00:00
|
|
|
char *uristr = NULL;
|
libvirt: support an "embed" URI path selector for opening drivers
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@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
2019-05-17 11:42:04 +00:00
|
|
|
bool embed = false;
|
2008-11-17 11:44:51 +00:00
|
|
|
|
|
|
|
ret = virGetConnect();
|
|
|
|
if (ret == NULL)
|
|
|
|
return NULL;
|
2005-11-30 13:20:53 +00:00
|
|
|
|
2016-07-26 12:06:13 +00:00
|
|
|
if (virConfLoadConfig(&conf, "libvirt.conf") < 0)
|
2012-03-14 12:30:52 +00:00
|
|
|
goto failed;
|
|
|
|
|
|
|
|
if (name && name[0] == '\0')
|
|
|
|
name = NULL;
|
|
|
|
|
2018-03-27 13:32:07 +00:00
|
|
|
/* Convert xen -> xen:///system for back compat */
|
2016-07-08 10:38:17 +00:00
|
|
|
if (name && STRCASEEQ(name, "xen"))
|
2018-03-27 13:32:07 +00:00
|
|
|
name = "xen:///system";
|
2016-07-08 10:38:17 +00:00
|
|
|
|
2018-03-27 13:32:07 +00:00
|
|
|
/* Convert xen:// -> xen:///system because xmlParseURI cannot parse the
|
2016-07-08 10:38:17 +00:00
|
|
|
* former. This allows URIs such as xen://localhost to work.
|
|
|
|
*/
|
|
|
|
if (name && STREQ(name, "xen://"))
|
2018-03-27 13:32:07 +00:00
|
|
|
name = "xen:///system";
|
2016-07-08 10:38:17 +00:00
|
|
|
|
2008-02-26 07:05:18 +00:00
|
|
|
/*
|
2013-12-28 18:10:06 +00:00
|
|
|
* If no URI is passed, then check for an environment string if not
|
|
|
|
* available probe the compiled in drivers to find a default hypervisor
|
|
|
|
* if detectable.
|
2008-02-26 07:05:18 +00:00
|
|
|
*/
|
2008-11-17 11:44:51 +00:00
|
|
|
if (name) {
|
2019-10-20 11:49:46 +00:00
|
|
|
uristr = g_strdup(name);
|
2016-07-08 10:38:17 +00:00
|
|
|
} else {
|
|
|
|
if (virConnectGetDefaultURI(conf, &uristr) < 0)
|
|
|
|
goto failed;
|
2018-03-27 16:24:44 +00:00
|
|
|
|
|
|
|
if (uristr == NULL) {
|
|
|
|
VIR_DEBUG("Trying to probe for default URI");
|
|
|
|
for (i = 0; i < virConnectDriverTabCount && uristr == NULL; i++) {
|
|
|
|
if (virConnectDriverTab[i]->hypervisorDriver->connectURIProbe) {
|
|
|
|
if (virConnectDriverTab[i]->hypervisorDriver->connectURIProbe(&uristr) < 0)
|
|
|
|
goto failed;
|
|
|
|
VIR_DEBUG("%s driver URI probe returned '%s'",
|
|
|
|
virConnectDriverTab[i]->hypervisorDriver->name,
|
2019-07-23 10:06:33 +00:00
|
|
|
NULLSTR(uristr));
|
2018-03-27 16:24:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-07-08 10:38:17 +00:00
|
|
|
}
|
2008-11-17 11:44:51 +00:00
|
|
|
|
2016-07-08 10:38:17 +00:00
|
|
|
if (uristr) {
|
|
|
|
char *alias = NULL;
|
2008-11-17 11:44:51 +00:00
|
|
|
|
2011-10-13 10:49:45 +00:00
|
|
|
if (!(flags & VIR_CONNECT_NO_ALIASES) &&
|
2016-07-08 10:38:17 +00:00
|
|
|
virURIResolveAlias(conf, uristr, &alias) < 0)
|
2011-10-13 10:49:45 +00:00
|
|
|
goto failed;
|
|
|
|
|
2016-07-08 10:38:17 +00:00
|
|
|
if (alias) {
|
|
|
|
VIR_FREE(uristr);
|
|
|
|
uristr = alias;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(ret->uri = virURIParse(uristr))) {
|
2011-10-13 10:49:45 +00:00
|
|
|
VIR_FREE(alias);
|
2008-11-17 11:44:51 +00:00
|
|
|
goto failed;
|
|
|
|
}
|
2006-03-20 17:49:28 +00:00
|
|
|
|
2018-03-28 13:25:23 +00:00
|
|
|
/* Avoid need for drivers to worry about NULLs, as
|
|
|
|
* no one needs to distinguish "" vs NULL */
|
2019-10-20 11:49:46 +00:00
|
|
|
if (ret->uri->path == NULL)
|
|
|
|
ret->uri->path = g_strdup("");
|
2018-03-28 13:25:23 +00:00
|
|
|
|
2016-07-08 10:38:17 +00:00
|
|
|
VIR_DEBUG("Split \"%s\" to URI components:\n"
|
2011-10-13 10:49:45 +00:00
|
|
|
" scheme %s\n"
|
|
|
|
" server %s\n"
|
|
|
|
" user %s\n"
|
|
|
|
" port %d\n"
|
2015-10-27 18:14:01 +00:00
|
|
|
" path %s",
|
2016-07-08 10:38:17 +00:00
|
|
|
uristr,
|
2012-03-20 13:33:41 +00:00
|
|
|
NULLSTR(ret->uri->scheme), NULLSTR(ret->uri->server),
|
2011-10-13 10:49:45 +00:00
|
|
|
NULLSTR(ret->uri->user), ret->uri->port,
|
2018-03-28 13:25:23 +00:00
|
|
|
ret->uri->path);
|
2011-10-13 10:49:45 +00:00
|
|
|
|
2018-04-09 15:33:22 +00:00
|
|
|
if (ret->uri->scheme == NULL) {
|
|
|
|
virReportError(VIR_ERR_NO_CONNECT,
|
|
|
|
_("URI '%s' does not include a driver name"),
|
|
|
|
name);
|
|
|
|
goto failed;
|
|
|
|
}
|
|
|
|
|
2016-07-08 10:38:17 +00:00
|
|
|
if (virConnectCheckURIMissingSlash(uristr,
|
2016-04-16 12:59:08 +00:00
|
|
|
ret->uri) < 0) {
|
|
|
|
goto failed;
|
|
|
|
}
|
libvirt: support an "embed" URI path selector for opening drivers
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@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
2019-05-17 11:42:04 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
root = virURIGetParam(ret->uri, "root");
|
|
|
|
if (!root)
|
|
|
|
goto failed;
|
|
|
|
|
|
|
|
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) {
|
|
|
|
virAccessManagerPtr acl;
|
|
|
|
|
|
|
|
virResetLastError();
|
|
|
|
|
|
|
|
if (!(acl = virAccessManagerNew("none")))
|
|
|
|
goto failed;
|
|
|
|
virAccessManagerSetDefault(acl);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virStateInitialize(geteuid() == 0, true, root, NULL, NULL) < 0)
|
|
|
|
goto failed;
|
|
|
|
|
|
|
|
embed = true;
|
|
|
|
}
|
2008-11-17 11:44:51 +00:00
|
|
|
} else {
|
2011-05-09 09:24:09 +00:00
|
|
|
VIR_DEBUG("no name, allowing driver auto-select");
|
2007-11-14 11:40:57 +00:00
|
|
|
}
|
|
|
|
|
2008-02-20 16:54:35 +00:00
|
|
|
/* Cleansing flags */
|
|
|
|
ret->flags = flags & VIR_CONNECT_RO;
|
|
|
|
|
2015-01-20 16:16:26 +00:00
|
|
|
for (i = 0; i < virConnectDriverTabCount; i++) {
|
2010-06-09 22:52:05 +00:00
|
|
|
/* We're going to probe the remote driver next. So we have already
|
|
|
|
* probed all other client-side-only driver before, but none of them
|
|
|
|
* accepted the URI.
|
|
|
|
* If the scheme corresponds to a known but disabled client-side-only
|
|
|
|
* driver then report a useful error, instead of a cryptic one about
|
|
|
|
* not being able to connect to libvirtd or not being able to find
|
|
|
|
* certificates. */
|
2015-01-20 16:16:26 +00:00
|
|
|
if (STREQ(virConnectDriverTab[i]->hypervisorDriver->name, "remote") &&
|
2018-04-09 15:33:22 +00:00
|
|
|
ret->uri != NULL &&
|
2010-06-09 22:52:05 +00:00
|
|
|
(
|
|
|
|
#ifndef WITH_ESX
|
2010-07-18 15:27:05 +00:00
|
|
|
STRCASEEQ(ret->uri->scheme, "vpx") ||
|
2010-06-09 22:52:05 +00:00
|
|
|
STRCASEEQ(ret->uri->scheme, "esx") ||
|
|
|
|
STRCASEEQ(ret->uri->scheme, "gsx") ||
|
2011-07-13 14:47:01 +00:00
|
|
|
#endif
|
|
|
|
#ifndef WITH_HYPERV
|
|
|
|
STRCASEEQ(ret->uri->scheme, "hyperv") ||
|
2012-07-31 18:56:05 +00:00
|
|
|
#endif
|
2015-06-10 07:50:00 +00:00
|
|
|
#ifndef WITH_VZ
|
2012-07-31 18:56:05 +00:00
|
|
|
STRCASEEQ(ret->uri->scheme, "parallels") ||
|
2010-06-09 22:52:05 +00:00
|
|
|
#endif
|
|
|
|
false)) {
|
Santize the reporting of VIR_ERR_INVALID_ERROR
To ensure consistent error reporting of invalid arguments,
provide a number of predefined helper methods & macros.
- An arg which must not be NULL:
virCheckNonNullArgReturn(argname, retvalue)
virCheckNonNullArgGoto(argname, label)
- An arg which must be NULL
virCheckNullArgGoto(argname, label)
- An arg which must be positive (ie 1 or greater)
virCheckPositiveArgGoto(argname, label)
- An arg which must not be 0
virCheckNonZeroArgGoto(argname, label)
- An arg which must be zero
virCheckZeroArgGoto(argname, label)
- An arg which must not be negative (ie 0 or greater)
virCheckNonNegativeArgGoto(argname, label)
* src/libvirt.c, src/libvirt-qemu.c,
src/nodeinfo.c, src/datatypes.c: Update to use
virCheckXXXX macros
* po/POTFILES.in: Add libvirt-qemu.c and virterror_internal.h
* src/internal.h: Define macros for checking invalid args
* src/util/virterror_internal.h: Define macros for reporting
invalid args
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-05-25 17:41:07 +00:00
|
|
|
virReportErrorHelper(VIR_FROM_NONE, VIR_ERR_CONFIG_UNSUPPORTED,
|
2010-06-09 22:52:05 +00:00
|
|
|
__FILE__, __FUNCTION__, __LINE__,
|
|
|
|
_("libvirt was built without the '%s' driver"),
|
|
|
|
ret->uri->scheme);
|
|
|
|
goto failed;
|
|
|
|
}
|
|
|
|
|
2015-01-20 16:16:26 +00:00
|
|
|
VIR_DEBUG("trying driver %zu (%s) ...",
|
|
|
|
i, virConnectDriverTab[i]->hypervisorDriver->name);
|
|
|
|
|
2018-03-28 09:53:31 +00:00
|
|
|
if (virConnectDriverTab[i]->localOnly && ret->uri && ret->uri->server) {
|
|
|
|
VIR_DEBUG("Server present, skipping local only driver");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2018-03-27 14:51:45 +00:00
|
|
|
/* Filter drivers based on declared URI schemes */
|
2018-03-28 11:49:29 +00:00
|
|
|
if (virConnectDriverTab[i]->uriSchemes) {
|
2018-03-27 14:51:45 +00:00
|
|
|
bool matchScheme = false;
|
|
|
|
size_t s;
|
2018-03-28 11:49:29 +00:00
|
|
|
if (!ret->uri) {
|
|
|
|
VIR_DEBUG("No URI, skipping driver with URI whitelist");
|
|
|
|
continue;
|
|
|
|
}
|
libvirt: support an "embed" URI path selector for opening drivers
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@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
2019-05-17 11:42:04 +00:00
|
|
|
if (embed && !virConnectDriverTab[i]->embeddable) {
|
|
|
|
VIR_DEBUG("Ignoring non-embeddable driver %s",
|
|
|
|
virConnectDriverTab[i]->hypervisorDriver->name);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2018-03-27 14:51:45 +00:00
|
|
|
VIR_DEBUG("Checking for supported URI schemes");
|
|
|
|
for (s = 0; virConnectDriverTab[i]->uriSchemes[s] != NULL; s++) {
|
|
|
|
if (STREQ(ret->uri->scheme, virConnectDriverTab[i]->uriSchemes[s])) {
|
|
|
|
VIR_DEBUG("Matched URI scheme '%s'", ret->uri->scheme);
|
|
|
|
matchScheme = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!matchScheme) {
|
|
|
|
VIR_DEBUG("No matching URI scheme");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
} else {
|
libvirt: support an "embed" URI path selector for opening drivers
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@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
2019-05-17 11:42:04 +00:00
|
|
|
if (embed) {
|
|
|
|
VIR_DEBUG("Skipping wildcard for embedded URI");
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
VIR_DEBUG("Matching any URI scheme for '%s'", ret->uri ? ret->uri->scheme : "");
|
|
|
|
}
|
2018-03-27 14:51:45 +00:00
|
|
|
}
|
|
|
|
|
libvirt: support an "embed" URI path selector for opening drivers
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@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
2019-05-17 11:42:04 +00:00
|
|
|
if (embed && !virConnectDriverTab[i]->embeddable) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("Driver %s cannot be used in embedded mode"),
|
|
|
|
virConnectDriverTab[i]->hypervisorDriver->name);
|
|
|
|
goto failed;
|
|
|
|
}
|
2018-07-10 23:30:59 +00:00
|
|
|
/* before starting the new connection, check if the driver only works
|
|
|
|
* with a server, and so return an error if the server is missing */
|
|
|
|
if (virConnectDriverTab[i]->remoteOnly && ret->uri && !ret->uri->server) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s", _("URI is missing the server part"));
|
|
|
|
goto failed;
|
|
|
|
}
|
|
|
|
|
2015-01-20 16:16:26 +00:00
|
|
|
ret->driver = virConnectDriverTab[i]->hypervisorDriver;
|
|
|
|
ret->interfaceDriver = virConnectDriverTab[i]->interfaceDriver;
|
|
|
|
ret->networkDriver = virConnectDriverTab[i]->networkDriver;
|
|
|
|
ret->nodeDeviceDriver = virConnectDriverTab[i]->nodeDeviceDriver;
|
|
|
|
ret->nwfilterDriver = virConnectDriverTab[i]->nwfilterDriver;
|
|
|
|
ret->secretDriver = virConnectDriverTab[i]->secretDriver;
|
|
|
|
ret->storageDriver = virConnectDriverTab[i]->storageDriver;
|
|
|
|
|
2016-06-03 17:01:27 +00:00
|
|
|
res = virConnectDriverTab[i]->hypervisorDriver->connectOpen(ret, auth, conf, flags);
|
Convert 'int i' to 'size_t i' in src/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
VIR_DEBUG("driver %zu %s returned %s",
|
2015-01-20 16:16:26 +00:00
|
|
|
i, virConnectDriverTab[i]->hypervisorDriver->name,
|
2012-12-03 08:41:45 +00:00
|
|
|
res == VIR_DRV_OPEN_SUCCESS ? "SUCCESS" :
|
|
|
|
(res == VIR_DRV_OPEN_DECLINED ? "DECLINED" :
|
|
|
|
(res == VIR_DRV_OPEN_ERROR ? "ERROR" : "unknown status")));
|
|
|
|
|
|
|
|
if (res == VIR_DRV_OPEN_SUCCESS) {
|
2007-04-04 14:19:49 +00:00
|
|
|
break;
|
2013-05-02 15:55:52 +00:00
|
|
|
} else {
|
|
|
|
ret->driver = NULL;
|
2015-01-20 16:16:26 +00:00
|
|
|
ret->interfaceDriver = NULL;
|
|
|
|
ret->networkDriver = NULL;
|
|
|
|
ret->nodeDeviceDriver = NULL;
|
|
|
|
ret->nwfilterDriver = NULL;
|
|
|
|
ret->secretDriver = NULL;
|
|
|
|
ret->storageDriver = NULL;
|
|
|
|
|
|
|
|
if (res == VIR_DRV_OPEN_ERROR)
|
|
|
|
goto failed;
|
2007-04-04 14:19:49 +00:00
|
|
|
}
|
2006-03-29 12:46:03 +00:00
|
|
|
}
|
|
|
|
|
2007-04-04 14:19:49 +00:00
|
|
|
if (!ret->driver) {
|
2007-06-20 17:25:39 +00:00
|
|
|
/* If we reach here, then all drivers declined the connection. */
|
2014-01-14 21:31:41 +00:00
|
|
|
virReportError(VIR_ERR_NO_CONNECT, "%s", NULLSTR(name));
|
2007-04-04 14:19:49 +00:00
|
|
|
goto failed;
|
2007-02-14 15:37:18 +00:00
|
|
|
}
|
|
|
|
|
2016-07-08 10:38:17 +00:00
|
|
|
VIR_FREE(uristr);
|
2012-03-14 12:30:52 +00:00
|
|
|
|
2007-04-04 14:19:49 +00:00
|
|
|
return ret;
|
2006-03-23 15:42:10 +00:00
|
|
|
|
2014-03-25 06:49:02 +00:00
|
|
|
failed:
|
2016-07-08 10:38:17 +00:00
|
|
|
VIR_FREE(uristr);
|
Convert public datatypes to inherit from virObject
This converts the following public API datatypes to use the
virObject infrastructure:
virConnectPtr
virDomainPtr
virDomainSnapshotPtr
virInterfacePtr
virNetworkPtr
virNodeDevicePtr
virNWFilterPtr
virSecretPtr
virStreamPtr
virStorageVolPtr
virStoragePoolPtr
The code is significantly simplified, since the mutex in the
virConnectPtr object now only needs to be held when accessing
the per-connection virError object instance. All other operations
are completely lock free.
* src/datatypes.c, src/datatypes.h, src/libvirt.c: Convert
public datatypes to use virObject
* src/conf/domain_event.c, src/phyp/phyp_driver.c,
src/qemu/qemu_command.c, src/qemu/qemu_migration.c,
src/qemu/qemu_process.c, src/storage/storage_driver.c,
src/vbox/vbox_tmpl.c, src/xen/xend_internal.c,
tests/qemuxml2argvtest.c, tests/qemuxmlnstest.c,
tests/sexpr2xmltest.c, tests/xmconfigtest.c: Convert
to use virObjectUnref/virObjectRef
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-31 16:55:36 +00:00
|
|
|
virObjectUnref(ret);
|
2008-08-21 10:12:32 +00:00
|
|
|
|
2007-11-14 11:40:57 +00:00
|
|
|
return NULL;
|
2005-12-01 16:35:42 +00:00
|
|
|
}
|
|
|
|
|
2013-12-28 02:42:30 +00:00
|
|
|
|
2007-04-04 14:19:49 +00:00
|
|
|
/**
|
|
|
|
* virConnectOpen:
|
2013-03-25 15:50:27 +00:00
|
|
|
* @name: (optional) URI of the hypervisor
|
2007-04-04 14:19:49 +00:00
|
|
|
*
|
2008-02-05 19:27:37 +00:00
|
|
|
* This function should be called first to get a connection to the
|
2007-04-04 14:19:49 +00:00
|
|
|
* Hypervisor and xen store
|
|
|
|
*
|
2012-03-14 12:30:52 +00:00
|
|
|
* If @name is NULL, if the LIBVIRT_DEFAULT_URI environment variable is set,
|
|
|
|
* then it will be used. Otherwise if the client configuration file
|
|
|
|
* has the "uri_default" parameter set, then it will be used. Finally
|
|
|
|
* probing will be done to determine a suitable default driver to activate.
|
|
|
|
* This involves trying each hypervisor in turn until one successfully opens.
|
2009-07-06 17:43:21 +00:00
|
|
|
*
|
|
|
|
* If connecting to an unprivileged hypervisor driver which requires
|
|
|
|
* the libvirtd daemon to be active, it will automatically be launched
|
|
|
|
* if not already running. This can be prevented by setting the
|
|
|
|
* environment variable LIBVIRT_AUTOSTART=0
|
|
|
|
*
|
2018-06-13 08:35:47 +00:00
|
|
|
* URIs are documented at https://libvirt.org/uri.html
|
2014-01-01 06:17:16 +00:00
|
|
|
*
|
2014-07-08 15:58:11 +00:00
|
|
|
* virConnectClose should be used to release the resources after the connection
|
|
|
|
* is no longer needed.
|
|
|
|
*
|
2014-01-01 06:17:16 +00:00
|
|
|
* Returns a pointer to the hypervisor connection or NULL in case of error
|
2007-04-04 14:19:49 +00:00
|
|
|
*/
|
|
|
|
virConnectPtr
|
2012-10-17 09:23:12 +00:00
|
|
|
virConnectOpen(const char *name)
|
2007-04-04 14:19:49 +00:00
|
|
|
{
|
2009-09-30 15:11:47 +00:00
|
|
|
virConnectPtr ret = NULL;
|
2012-10-10 15:11:43 +00:00
|
|
|
|
|
|
|
if (virInitialize() < 0)
|
|
|
|
goto error;
|
2008-02-20 16:54:35 +00:00
|
|
|
|
2013-03-25 15:50:27 +00:00
|
|
|
VIR_DEBUG("name=%s", NULLSTR(name));
|
2012-09-10 15:47:15 +00:00
|
|
|
virResetLastError();
|
2016-04-19 16:18:40 +00:00
|
|
|
ret = virConnectOpenInternal(name, NULL, 0);
|
2009-09-30 15:11:47 +00:00
|
|
|
if (!ret)
|
|
|
|
goto error;
|
|
|
|
return ret;
|
|
|
|
|
2014-03-25 06:49:02 +00:00
|
|
|
error:
|
2009-09-30 15:11:47 +00:00
|
|
|
virDispatchError(NULL);
|
|
|
|
return NULL;
|
2007-04-04 14:19:49 +00:00
|
|
|
}
|
|
|
|
|
2013-12-28 02:42:30 +00:00
|
|
|
|
2005-12-01 16:35:42 +00:00
|
|
|
/**
|
2005-12-05 11:16:07 +00:00
|
|
|
* virConnectOpenReadOnly:
|
2013-03-25 15:50:27 +00:00
|
|
|
* @name: (optional) URI of the hypervisor
|
2005-12-01 16:35:42 +00:00
|
|
|
*
|
2008-02-05 19:27:37 +00:00
|
|
|
* This function should be called first to get a restricted connection to the
|
2008-04-04 07:58:29 +00:00
|
|
|
* library functionalities. The set of APIs usable are then restricted
|
2006-01-19 10:23:15 +00:00
|
|
|
* on the available methods to control the domains.
|
2005-12-01 16:35:42 +00:00
|
|
|
*
|
2009-07-06 17:43:21 +00:00
|
|
|
* See virConnectOpen for notes about environment variables which can
|
2014-07-08 15:58:11 +00:00
|
|
|
* have an effect on opening drivers and freeing the connection resources
|
2009-07-06 17:43:21 +00:00
|
|
|
*
|
2017-10-13 15:30:41 +00:00
|
|
|
* URIs are documented at https://libvirt.org/uri.html
|
2014-01-01 06:17:16 +00:00
|
|
|
*
|
|
|
|
* Returns a pointer to the hypervisor connection or NULL in case of error
|
2005-12-01 16:35:42 +00:00
|
|
|
*/
|
2005-12-05 11:16:07 +00:00
|
|
|
virConnectPtr
|
2006-03-15 12:13:25 +00:00
|
|
|
virConnectOpenReadOnly(const char *name)
|
|
|
|
{
|
2009-09-30 15:11:47 +00:00
|
|
|
virConnectPtr ret = NULL;
|
2012-10-10 15:11:43 +00:00
|
|
|
|
|
|
|
if (virInitialize() < 0)
|
|
|
|
goto error;
|
2008-02-20 16:54:35 +00:00
|
|
|
|
2013-03-25 15:50:27 +00:00
|
|
|
VIR_DEBUG("name=%s", NULLSTR(name));
|
2012-09-10 15:47:15 +00:00
|
|
|
virResetLastError();
|
2016-04-19 16:18:40 +00:00
|
|
|
ret = virConnectOpenInternal(name, NULL, VIR_CONNECT_RO);
|
2009-09-30 15:11:47 +00:00
|
|
|
if (!ret)
|
|
|
|
goto error;
|
|
|
|
return ret;
|
|
|
|
|
2014-03-25 06:49:02 +00:00
|
|
|
error:
|
2009-09-30 15:11:47 +00:00
|
|
|
virDispatchError(NULL);
|
|
|
|
return NULL;
|
2007-12-05 18:28:05 +00:00
|
|
|
}
|
|
|
|
|
2013-12-28 02:42:30 +00:00
|
|
|
|
2007-12-05 18:28:05 +00:00
|
|
|
/**
|
|
|
|
* virConnectOpenAuth:
|
2013-03-25 15:50:27 +00:00
|
|
|
* @name: (optional) URI of the hypervisor
|
2007-12-05 18:28:05 +00:00
|
|
|
* @auth: Authenticate callback parameters
|
2012-01-09 20:56:42 +00:00
|
|
|
* @flags: bitwise-OR of virConnectFlags
|
2007-12-05 18:28:05 +00:00
|
|
|
*
|
2008-02-05 19:27:37 +00:00
|
|
|
* This function should be called first to get a connection to the
|
2008-03-17 10:27:31 +00:00
|
|
|
* Hypervisor. If necessary, authentication will be performed fetching
|
2007-12-05 18:28:05 +00:00
|
|
|
* credentials via the callback
|
|
|
|
*
|
2009-07-06 17:43:21 +00:00
|
|
|
* See virConnectOpen for notes about environment variables which can
|
2014-07-08 15:58:11 +00:00
|
|
|
* have an effect on opening drivers and freeing the connection resources
|
2009-07-06 17:43:21 +00:00
|
|
|
*
|
2017-10-13 15:30:41 +00:00
|
|
|
* URIs are documented at https://libvirt.org/uri.html
|
2014-01-01 06:17:16 +00:00
|
|
|
*
|
|
|
|
* Returns a pointer to the hypervisor connection or NULL in case of error
|
2007-12-05 18:28:05 +00:00
|
|
|
*/
|
|
|
|
virConnectPtr
|
|
|
|
virConnectOpenAuth(const char *name,
|
|
|
|
virConnectAuthPtr auth,
|
public API: prefer unsigned int for flags
Most APIs use 'unsigned int flags'; but a few stragglers were using
a signed value. In particular, the vir*GetXMLDesc APIs were
split-brain, with inconsistent choice of types. Although it is
an API break to use 'int' instead of 'unsigned int', it is ABI
compatible (pre-compiled apps will have no difference in behavior),
and generally apps can be recompiled without any issue (only rare
apps that compiled with extremely high warning levels, or which
pass libvirt API around as typed function pointers, would have to
make any code changes to deal with the change).
The migrate APIs use 'unsigned long flags', which can't be changed,
due to ABI constraints.
This patch intentionally touches only the public API, to prove the
claim that most existing code (including driver callbacks and virsh)
still compiles just fine in spite of the type change.
* include/libvirt/libvirt.h.in (virConnectOpenAuth)
(virDomainCoreDump, virDomainGetXMLDesc, virNetworkGetXMLDesc)
(virNWFilterGetXMLDesc): Use unsigned int for flags.
(virDomainHasCurrentSnapshot): Use consistent spelling.
* src/libvirt.c (virConnectOpenAuth, virDomainCoreDump)
(virDomainGetXMLDesc, virNetworkGetXMLDesc)
(virNWFilterGetXMLDesc, do_open): Update accordingly.
2011-07-06 19:55:47 +00:00
|
|
|
unsigned int flags)
|
2007-12-05 18:28:05 +00:00
|
|
|
{
|
2009-09-30 15:11:47 +00:00
|
|
|
virConnectPtr ret = NULL;
|
2012-10-10 15:11:43 +00:00
|
|
|
|
|
|
|
if (virInitialize() < 0)
|
|
|
|
goto error;
|
2008-02-20 16:54:35 +00:00
|
|
|
|
2017-09-25 10:43:33 +00:00
|
|
|
VIR_DEBUG("name=%s, auth=%p, flags=0x%x", NULLSTR(name), auth, flags);
|
2012-09-10 15:47:15 +00:00
|
|
|
virResetLastError();
|
2016-04-19 16:18:40 +00:00
|
|
|
ret = virConnectOpenInternal(name, auth, flags);
|
2009-09-30 15:11:47 +00:00
|
|
|
if (!ret)
|
|
|
|
goto error;
|
|
|
|
return ret;
|
|
|
|
|
2014-03-25 06:49:02 +00:00
|
|
|
error:
|
2009-09-30 15:11:47 +00:00
|
|
|
virDispatchError(NULL);
|
|
|
|
return NULL;
|
2005-11-02 12:50:21 +00:00
|
|
|
}
|
|
|
|
|
2013-12-28 02:42:30 +00:00
|
|
|
|
2014-11-22 01:27:25 +00:00
|
|
|
|
2005-11-02 12:50:21 +00:00
|
|
|
/**
|
2005-12-05 11:16:07 +00:00
|
|
|
* virConnectClose:
|
2005-11-02 12:50:21 +00:00
|
|
|
* @conn: pointer to the hypervisor connection
|
|
|
|
*
|
|
|
|
* This function closes the connection to the Hypervisor. This should
|
|
|
|
* not be called if further interaction with the Hypervisor are needed
|
|
|
|
* especially if there is running domain which need further monitoring by
|
|
|
|
* the application.
|
|
|
|
*
|
2011-06-22 16:17:04 +00:00
|
|
|
* Connections are reference counted; the count is explicitly
|
|
|
|
* increased by the initial open (virConnectOpen, virConnectOpenAuth,
|
|
|
|
* and the like) as well as virConnectRef; it is also temporarily
|
|
|
|
* increased by other API that depend on the connection remaining
|
|
|
|
* alive. The open and every virConnectRef call should have a
|
|
|
|
* matching virConnectClose, and all other references will be released
|
|
|
|
* after the corresponding operation completes.
|
|
|
|
*
|
Convert public datatypes to inherit from virObject
This converts the following public API datatypes to use the
virObject infrastructure:
virConnectPtr
virDomainPtr
virDomainSnapshotPtr
virInterfacePtr
virNetworkPtr
virNodeDevicePtr
virNWFilterPtr
virSecretPtr
virStreamPtr
virStorageVolPtr
virStoragePoolPtr
The code is significantly simplified, since the mutex in the
virConnectPtr object now only needs to be held when accessing
the per-connection virError object instance. All other operations
are completely lock free.
* src/datatypes.c, src/datatypes.h, src/libvirt.c: Convert
public datatypes to use virObject
* src/conf/domain_event.c, src/phyp/phyp_driver.c,
src/qemu/qemu_command.c, src/qemu/qemu_migration.c,
src/qemu/qemu_process.c, src/storage/storage_driver.c,
src/vbox/vbox_tmpl.c, src/xen/xend_internal.c,
tests/qemuxml2argvtest.c, tests/qemuxmlnstest.c,
tests/sexpr2xmltest.c, tests/xmconfigtest.c: Convert
to use virObjectUnref/virObjectRef
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-31 16:55:36 +00:00
|
|
|
* Returns a positive number if at least 1 reference remains on
|
|
|
|
* success. The returned value should not be assumed to be the total
|
|
|
|
* reference count. A return of 0 implies no references remain and
|
|
|
|
* the connection is closed and memory has been freed. A return of -1
|
|
|
|
* implies a failure.
|
|
|
|
*
|
|
|
|
* It is possible for the last virConnectClose to return a positive
|
|
|
|
* value if some other object still has a temporary reference to the
|
|
|
|
* connection, but the application should not try to further use a
|
|
|
|
* connection after the virConnectClose that matches the initial open.
|
2005-11-02 12:50:21 +00:00
|
|
|
*/
|
|
|
|
int
|
2006-03-15 12:13:25 +00:00
|
|
|
virConnectClose(virConnectPtr conn)
|
|
|
|
{
|
2011-02-16 23:37:57 +00:00
|
|
|
VIR_DEBUG("conn=%p", conn);
|
2007-07-12 08:34:51 +00:00
|
|
|
|
2009-01-20 12:01:45 +00:00
|
|
|
virResetLastError();
|
|
|
|
|
2013-12-28 03:31:17 +00:00
|
|
|
virCheckConnectReturn(conn, -1);
|
2007-04-04 14:19:49 +00:00
|
|
|
|
Convert public datatypes to inherit from virObject
This converts the following public API datatypes to use the
virObject infrastructure:
virConnectPtr
virDomainPtr
virDomainSnapshotPtr
virInterfacePtr
virNetworkPtr
virNodeDevicePtr
virNWFilterPtr
virSecretPtr
virStreamPtr
virStorageVolPtr
virStoragePoolPtr
The code is significantly simplified, since the mutex in the
virConnectPtr object now only needs to be held when accessing
the per-connection virError object instance. All other operations
are completely lock free.
* src/datatypes.c, src/datatypes.h, src/libvirt.c: Convert
public datatypes to use virObject
* src/conf/domain_event.c, src/phyp/phyp_driver.c,
src/qemu/qemu_command.c, src/qemu/qemu_migration.c,
src/qemu/qemu_process.c, src/storage/storage_driver.c,
src/vbox/vbox_tmpl.c, src/xen/xend_internal.c,
tests/qemuxml2argvtest.c, tests/qemuxmlnstest.c,
tests/sexpr2xmltest.c, tests/xmconfigtest.c: Convert
to use virObjectUnref/virObjectRef
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-07-31 16:55:36 +00:00
|
|
|
if (!virObjectUnref(conn))
|
|
|
|
return 0;
|
|
|
|
return 1;
|
2005-11-02 12:50:21 +00:00
|
|
|
}
|
|
|
|
|
2013-12-28 02:42:30 +00:00
|
|
|
|
2014-10-22 15:29:09 +00:00
|
|
|
/* Helper function called to validate incoming client array on any
|
|
|
|
* interface that sets typed parameters in the hypervisor. */
|
|
|
|
int
|
|
|
|
virTypedParameterValidateSet(virConnectPtr conn,
|
|
|
|
virTypedParameterPtr params,
|
|
|
|
int nparams)
|
|
|
|
{
|
|
|
|
bool string_okay;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
string_okay = VIR_DRV_SUPPORTS_FEATURE(conn->driver,
|
|
|
|
conn,
|
|
|
|
VIR_DRV_FEATURE_TYPED_PARAM_STRING);
|
|
|
|
for (i = 0; i < nparams; i++) {
|
|
|
|
if (strnlen(params[i].field, VIR_TYPED_PARAM_FIELD_LENGTH) ==
|
|
|
|
VIR_TYPED_PARAM_FIELD_LENGTH) {
|
|
|
|
virReportInvalidArg(params,
|
|
|
|
_("string parameter name '%.*s' too long"),
|
|
|
|
VIR_TYPED_PARAM_FIELD_LENGTH,
|
|
|
|
params[i].field);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (params[i].type == VIR_TYPED_PARAM_STRING) {
|
|
|
|
if (string_okay) {
|
|
|
|
if (!params[i].value.s) {
|
|
|
|
virReportInvalidArg(params,
|
|
|
|
_("NULL string parameter '%s'"),
|
|
|
|
params[i].field);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
virReportInvalidArg(params,
|
|
|
|
_("string parameter '%s' unsupported"),
|
|
|
|
params[i].field);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|