2008-11-19 16:58:23 +00:00
|
|
|
/*
|
|
|
|
* uml_driver.c: core driver methods for managing UML guests
|
|
|
|
*
|
2013-01-30 14:54:41 +00:00
|
|
|
* Copyright (C) 2006-2013 Red Hat, Inc.
|
2008-11-19 16:58:23 +00:00
|
|
|
* Copyright (C) 2006-2008 Daniel P. Berrange
|
|
|
|
*
|
|
|
|
* 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-21 10:06:23 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2008-11-19 16:58:23 +00:00
|
|
|
*
|
|
|
|
* Author: Daniel P. Berrange <berrange@redhat.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/poll.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <sys/utsname.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <paths.h>
|
|
|
|
#include <pwd.h>
|
|
|
|
#include <sys/wait.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <sys/inotify.h>
|
Move xen driver code into src/xen/ directory
* src/Makefile.am, src/proxy_internal.c, src/proxy_internal.h
src/sexpr.c, src/sexpr.h, src/xen_unified.c, src/xen_unified.h,
src/xen_internal.c, src/xen_internal.h, src/xen_inotify.c,
src/xen_inotify.h, src/xend_internal.c, src/xend_internal.h,
src/xm_internal.c, src/xm_internal.h, src/xs_internal.c,
src/xs_internal.h: Move to src/xen/ directory
* proxy/Makefile.am, proxy/libvirt_proxy.c, src/Makefile.am,
src/libvirt.c, tests/sexpr2xmltest.c, tests/statstest.c,
tests/xencapstest.c, tests/xmconfigtest.c, tests/xml2sexprtest.c:
Adapt to changed xen location
* src/stats_linux.h, src/stats_linux.c: Remove xen specific block
stats APIs
* src/qemu_driver.c, src/uml_driver.c: Add missing sys/un.h include
uncovered after change to stats_linux.h
* src/xen/block_stats.h, src/xen/block_stats.c: Add xen specific
block stats APIs
2009-09-15 15:38:33 +00:00
|
|
|
#include <sys/un.h>
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
#include "uml_driver.h"
|
|
|
|
#include "uml_conf.h"
|
2012-12-04 12:04:07 +00:00
|
|
|
#include "virbuffer.h"
|
2012-12-13 17:44:57 +00:00
|
|
|
#include "virutil.h"
|
2008-11-19 16:58:23 +00:00
|
|
|
#include "nodeinfo.h"
|
2012-12-13 15:14:15 +00:00
|
|
|
#include "virstatslinux.h"
|
2008-11-19 16:58:23 +00:00
|
|
|
#include "capabilities.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.h"
|
2012-12-13 18:01:25 +00:00
|
|
|
#include "viruuid.h"
|
2008-11-19 16:58:23 +00:00
|
|
|
#include "domain_conf.h"
|
2011-07-04 11:10:30 +00:00
|
|
|
#include "domain_audit.h"
|
2008-11-19 16:58:23 +00:00
|
|
|
#include "datatypes.h"
|
2012-12-12 17:59:27 +00:00
|
|
|
#include "virlog.h"
|
2010-09-07 08:19:56 +00:00
|
|
|
#include "domain_nwfilter.h"
|
2013-01-11 13:54:15 +00:00
|
|
|
#include "nwfilter_conf.h"
|
2011-07-19 18:32:58 +00:00
|
|
|
#include "virfile.h"
|
2010-10-22 13:40:26 +00:00
|
|
|
#include "fdstream.h"
|
2010-11-16 14:54:17 +00:00
|
|
|
#include "configmake.h"
|
Split bridge.h into three separate files
Following the renaming of the bridge management APIs, we can now
split the source file into 3 corresponding pieces
* src/util/virnetdev.c: APIs for any type of network interface
* src/util/virnetdevbridge.c: APIs for bridge interfaces
* src/util/virnetdevtap.c: APIs for TAP interfaces
* src/util/virnetdev.c, src/util/virnetdev.h,
src/util/virnetdevbridge.c, src/util/virnetdevbridge.h,
src/util/virnetdevtap.c, src/util/virnetdevtap.h: Copied
from bridge.{c,h}
* src/util/bridge.c, src/util/bridge.h: Split into 3 pieces
* src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/openvz/openvz_driver.c, src/qemu/qemu_command.c,
src/qemu/qemu_conf.h, src/uml/uml_conf.c, src/uml/uml_conf.h,
src/uml/uml_driver.c: Update #include directives
2011-11-02 13:41:58 +00:00
|
|
|
#include "virnetdevtap.h"
|
Implement the core API to suspend/resume the host
Add the core functions that implement the functionality of the API.
Suspend is done by using an asynchronous mechanism so that we can return
the status to the caller before the host gets suspended. This asynchronous
operation is achieved by suspending the host in a separate thread of
execution. However, returning the status to the caller is only best-effort,
but not guaranteed.
To resume the host, an RTC alarm is set up (based on how long we want to
suspend) before suspending the host. When this alarm fires, the host
gets woken up.
Suspend-to-RAM operation on a host running Linux can take upto more than 20
seconds, depending on the load of the system. (Freezing of tasks, an operation
preceding any suspend operation, is given up after a 20 second timeout).
And Suspend-to-Disk can take even more time, considering the time required
for compaction, creating the memory image and writing it to disk etc.
So, we do not allow the user to specify a suspend duration of less than 60
seconds, to be on the safer side, since we don't want to prematurely declare
failure when we only had to wait for some more time.
2011-11-29 09:07:38 +00:00
|
|
|
#include "virnodesuspend.h"
|
2012-09-24 16:54:51 +00:00
|
|
|
#include "virprocess.h"
|
2012-02-24 18:48:55 +00:00
|
|
|
#include "viruri.h"
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2009-01-20 17:13:33 +00:00
|
|
|
#define VIR_FROM_THIS VIR_FROM_UML
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
/* For storing short-lived temporary files. */
|
2010-11-16 14:54:17 +00:00
|
|
|
#define TEMPDIR LOCALSTATEDIR "/cache/libvirt"
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2009-11-26 17:55:12 +00:00
|
|
|
typedef struct _umlDomainObjPrivate umlDomainObjPrivate;
|
|
|
|
typedef umlDomainObjPrivate *umlDomainObjPrivatePtr;
|
|
|
|
struct _umlDomainObjPrivate {
|
|
|
|
int monitor;
|
|
|
|
int monitorWatch;
|
|
|
|
};
|
|
|
|
|
2011-07-13 11:21:54 +00:00
|
|
|
static int umlProcessAutoDestroyInit(struct uml_driver *driver);
|
|
|
|
static void umlProcessAutoDestroyRun(struct uml_driver *driver,
|
|
|
|
virConnectPtr conn);
|
|
|
|
static void umlProcessAutoDestroyShutdown(struct uml_driver *driver);
|
|
|
|
static int umlProcessAutoDestroyAdd(struct uml_driver *driver,
|
|
|
|
virDomainObjPtr vm,
|
|
|
|
virConnectPtr conn);
|
|
|
|
static int umlProcessAutoDestroyRemove(struct uml_driver *driver,
|
|
|
|
virDomainObjPtr vm);
|
|
|
|
|
2009-11-26 17:55:12 +00:00
|
|
|
|
2013-04-23 12:50:18 +00:00
|
|
|
static int umlStateCleanup(void);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2009-11-26 17:55:12 +00:00
|
|
|
static void *umlDomainObjPrivateAlloc(void)
|
|
|
|
{
|
|
|
|
umlDomainObjPrivatePtr priv;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(priv) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
priv->monitor = -1;
|
|
|
|
priv->monitorWatch = -1;
|
|
|
|
|
|
|
|
return priv;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void umlDomainObjPrivateFree(void *data)
|
|
|
|
{
|
|
|
|
umlDomainObjPrivatePtr priv = data;
|
|
|
|
|
|
|
|
VIR_FREE(priv);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
static void umlDriverLock(struct uml_driver *driver)
|
|
|
|
{
|
2009-01-15 19:56:05 +00:00
|
|
|
virMutexLock(&driver->lock);
|
2008-12-04 21:14:39 +00:00
|
|
|
}
|
|
|
|
static void umlDriverUnlock(struct uml_driver *driver)
|
|
|
|
{
|
2009-01-15 19:56:05 +00:00
|
|
|
virMutexUnlock(&driver->lock);
|
2008-12-04 21:14:39 +00:00
|
|
|
}
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2010-04-03 13:33:29 +00:00
|
|
|
static int umlOpenMonitor(struct uml_driver *driver,
|
2008-11-19 16:58:23 +00:00
|
|
|
virDomainObjPtr vm);
|
2010-02-04 20:02:58 +00:00
|
|
|
static int umlReadPidFile(struct uml_driver *driver,
|
2008-11-19 16:58:23 +00:00
|
|
|
virDomainObjPtr vm);
|
2009-07-06 15:06:11 +00:00
|
|
|
static void umlDomainEventQueue(struct uml_driver *driver,
|
|
|
|
virDomainEventPtr event);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
static int umlStartVMDaemon(virConnectPtr conn,
|
|
|
|
struct uml_driver *driver,
|
2011-07-13 11:21:54 +00:00
|
|
|
virDomainObjPtr vm,
|
|
|
|
bool autoDestroy);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2011-07-13 11:21:54 +00:00
|
|
|
static void umlShutdownVMDaemon(struct uml_driver *driver,
|
2011-05-04 09:07:01 +00:00
|
|
|
virDomainObjPtr vm,
|
|
|
|
virDomainShutoffReason reason);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
|
2010-04-03 13:33:29 +00:00
|
|
|
static int umlMonitorCommand(const struct uml_driver *driver,
|
|
|
|
const virDomainObjPtr vm,
|
|
|
|
const char *cmd,
|
|
|
|
char **reply);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
static struct uml_driver *uml_driver = NULL;
|
|
|
|
|
nwfilter: fix crash during filter define when lxc driver failed startup
The meat of this patch is just moving the calls to
virNWFilterRegisterCallbackDriver from each hypervisor's "register"
function into its "initialize" function. The rest is just code
movement to allow that, and a new virNWFilterUnRegisterCallbackDriver
function to undo what the register function does.
The long explanation:
There is an array in nwfilter called callbackDrvArray that has
pointers to a table of functions for each hypervisor driver that are
called by nwfilter. One of those function pointers is to a function
that will lock the hypervisor driver. Entries are added to the table
by calling each driver's "register" function, which happens quite
early in libvirtd's startup.
Sometime later, each driver's "initialize" function is called. This
function allocates a driver object and stores a pointer to it in a
static variable that was previously initialized to NULL. (and here's
the important part...) If the "initialize" function fails, the driver
object is freed, and that pointer set back to NULL (but the entry in
nwfilter's callbackDrvArray is still there).
When the "lock the driver" function mentioned above is called, it
assumes that the driver was successfully loaded, so it blindly tries
to call virMutexLock on "driver->lock".
BUT, if the initialize never happened, or if it failed, "driver" is
NULL. And it just happens that "lock" is always the first field in
driver so it is also NULL.
Boom.
To fix this, the call to virNWFilterRegisterCallbackDriver for each
driver shouldn't be called until the end of its (*already guaranteed
successful*) "initialize" function, not during its "register" function
(which is currently the case). This implies that there should also be
a virNWFilterUnregisterCallbackDriver() function that is called in a
driver's "shutdown" function (although in practice, that function is
currently never called).
2012-08-09 06:18:23 +00:00
|
|
|
static int
|
|
|
|
umlVMFilterRebuild(virConnectPtr conn ATTRIBUTE_UNUSED,
|
2013-01-11 13:54:15 +00:00
|
|
|
virDomainObjListIterator iter, void *data)
|
nwfilter: fix crash during filter define when lxc driver failed startup
The meat of this patch is just moving the calls to
virNWFilterRegisterCallbackDriver from each hypervisor's "register"
function into its "initialize" function. The rest is just code
movement to allow that, and a new virNWFilterUnRegisterCallbackDriver
function to undo what the register function does.
The long explanation:
There is an array in nwfilter called callbackDrvArray that has
pointers to a table of functions for each hypervisor driver that are
called by nwfilter. One of those function pointers is to a function
that will lock the hypervisor driver. Entries are added to the table
by calling each driver's "register" function, which happens quite
early in libvirtd's startup.
Sometime later, each driver's "initialize" function is called. This
function allocates a driver object and stores a pointer to it in a
static variable that was previously initialized to NULL. (and here's
the important part...) If the "initialize" function fails, the driver
object is freed, and that pointer set back to NULL (but the entry in
nwfilter's callbackDrvArray is still there).
When the "lock the driver" function mentioned above is called, it
assumes that the driver was successfully loaded, so it blindly tries
to call virMutexLock on "driver->lock".
BUT, if the initialize never happened, or if it failed, "driver" is
NULL. And it just happens that "lock" is always the first field in
driver so it is also NULL.
Boom.
To fix this, the call to virNWFilterRegisterCallbackDriver for each
driver shouldn't be called until the end of its (*already guaranteed
successful*) "initialize" function, not during its "register" function
(which is currently the case). This implies that there should also be
a virNWFilterUnregisterCallbackDriver() function that is called in a
driver's "shutdown" function (although in practice, that function is
currently never called).
2012-08-09 06:18:23 +00:00
|
|
|
{
|
2013-01-11 13:54:15 +00:00
|
|
|
return virDomainObjListForEach(uml_driver->domains, iter, data);
|
nwfilter: fix crash during filter define when lxc driver failed startup
The meat of this patch is just moving the calls to
virNWFilterRegisterCallbackDriver from each hypervisor's "register"
function into its "initialize" function. The rest is just code
movement to allow that, and a new virNWFilterUnRegisterCallbackDriver
function to undo what the register function does.
The long explanation:
There is an array in nwfilter called callbackDrvArray that has
pointers to a table of functions for each hypervisor driver that are
called by nwfilter. One of those function pointers is to a function
that will lock the hypervisor driver. Entries are added to the table
by calling each driver's "register" function, which happens quite
early in libvirtd's startup.
Sometime later, each driver's "initialize" function is called. This
function allocates a driver object and stores a pointer to it in a
static variable that was previously initialized to NULL. (and here's
the important part...) If the "initialize" function fails, the driver
object is freed, and that pointer set back to NULL (but the entry in
nwfilter's callbackDrvArray is still there).
When the "lock the driver" function mentioned above is called, it
assumes that the driver was successfully loaded, so it blindly tries
to call virMutexLock on "driver->lock".
BUT, if the initialize never happened, or if it failed, "driver" is
NULL. And it just happens that "lock" is always the first field in
driver so it is also NULL.
Boom.
To fix this, the call to virNWFilterRegisterCallbackDriver for each
driver shouldn't be called until the end of its (*already guaranteed
successful*) "initialize" function, not during its "register" function
(which is currently the case). This implies that there should also be
a virNWFilterUnregisterCallbackDriver() function that is called in a
driver's "shutdown" function (although in practice, that function is
currently never called).
2012-08-09 06:18:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
umlVMDriverLock(void)
|
|
|
|
{
|
|
|
|
umlDriverLock(uml_driver);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
umlVMDriverUnlock(void)
|
|
|
|
{
|
|
|
|
umlDriverUnlock(uml_driver);
|
|
|
|
}
|
|
|
|
|
|
|
|
static virNWFilterCallbackDriver umlCallbackDriver = {
|
|
|
|
.name = "UML",
|
|
|
|
.vmFilterRebuild = umlVMFilterRebuild,
|
|
|
|
.vmDriverLock = umlVMDriverLock,
|
|
|
|
.vmDriverUnlock = umlVMDriverUnlock,
|
|
|
|
};
|
|
|
|
|
Convert virDomainObjListPtr to use a hash of domain objects
The current virDomainObjListPtr object stores domain objects in
an array. This means that to find a particular objects requires
O(n) time, and more critically acquiring O(n) mutex locks.
The new impl replaces the array with a virHashTable, keyed off
UUID. Finding a object based on UUID is now O(1) time, and only
requires a single mutex lock. Finding by name/id is unchanged
in complexity.
In changing this, all code which iterates over the array had
to be updated to use a hash table iterator function callback.
Several of the functions which were identically duplicating
across all drivers were pulled into domain_conf.c
* src/conf/domain_conf.h, src/conf/domain_conf.c: Change
virDomainObjListPtr to use virHashTable. Add a initializer
method virDomainObjListInit, and rename virDomainObjListFree
to virDomainObjListDeinit, since its not actually freeing
the container, only its contents. Also add some convenient
methods virDomainObjListGetInactiveNames,
virDomainObjListGetActiveIDs and virDomainObjListNumOfDomains
which can be used to implement the correspondingly named
public API entry points in drivers
* src/libvirt_private.syms: Export new methods from domain_conf.h
* src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_conf.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c: Update all code
to deal with hash tables instead of arrays for domains
2009-10-09 11:33:51 +00:00
|
|
|
struct umlAutostartData {
|
|
|
|
struct uml_driver *driver;
|
|
|
|
virConnectPtr conn;
|
|
|
|
};
|
|
|
|
|
2013-01-11 13:54:15 +00:00
|
|
|
static int
|
|
|
|
umlAutostartDomain(virDomainObjPtr vm,
|
|
|
|
void *opaque)
|
Convert virDomainObjListPtr to use a hash of domain objects
The current virDomainObjListPtr object stores domain objects in
an array. This means that to find a particular objects requires
O(n) time, and more critically acquiring O(n) mutex locks.
The new impl replaces the array with a virHashTable, keyed off
UUID. Finding a object based on UUID is now O(1) time, and only
requires a single mutex lock. Finding by name/id is unchanged
in complexity.
In changing this, all code which iterates over the array had
to be updated to use a hash table iterator function callback.
Several of the functions which were identically duplicating
across all drivers were pulled into domain_conf.c
* src/conf/domain_conf.h, src/conf/domain_conf.c: Change
virDomainObjListPtr to use virHashTable. Add a initializer
method virDomainObjListInit, and rename virDomainObjListFree
to virDomainObjListDeinit, since its not actually freeing
the container, only its contents. Also add some convenient
methods virDomainObjListGetInactiveNames,
virDomainObjListGetActiveIDs and virDomainObjListNumOfDomains
which can be used to implement the correspondingly named
public API entry points in drivers
* src/libvirt_private.syms: Export new methods from domain_conf.h
* src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_conf.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c: Update all code
to deal with hash tables instead of arrays for domains
2009-10-09 11:33:51 +00:00
|
|
|
{
|
|
|
|
const struct umlAutostartData *data = opaque;
|
2013-01-11 13:54:15 +00:00
|
|
|
int ret = 0;
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectLock(vm);
|
Convert virDomainObjListPtr to use a hash of domain objects
The current virDomainObjListPtr object stores domain objects in
an array. This means that to find a particular objects requires
O(n) time, and more critically acquiring O(n) mutex locks.
The new impl replaces the array with a virHashTable, keyed off
UUID. Finding a object based on UUID is now O(1) time, and only
requires a single mutex lock. Finding by name/id is unchanged
in complexity.
In changing this, all code which iterates over the array had
to be updated to use a hash table iterator function callback.
Several of the functions which were identically duplicating
across all drivers were pulled into domain_conf.c
* src/conf/domain_conf.h, src/conf/domain_conf.c: Change
virDomainObjListPtr to use virHashTable. Add a initializer
method virDomainObjListInit, and rename virDomainObjListFree
to virDomainObjListDeinit, since its not actually freeing
the container, only its contents. Also add some convenient
methods virDomainObjListGetInactiveNames,
virDomainObjListGetActiveIDs and virDomainObjListNumOfDomains
which can be used to implement the correspondingly named
public API entry points in drivers
* src/libvirt_private.syms: Export new methods from domain_conf.h
* src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_conf.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c: Update all code
to deal with hash tables instead of arrays for domains
2009-10-09 11:33:51 +00:00
|
|
|
if (vm->autostart &&
|
Rename internal APis
Rename virDomainIsActive to virDomainObjIsActive, and
virInterfaceIsActive to virInterfaceObjIsActive and finally
virNetworkIsActive to virNetworkObjIsActive.
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/conf/interface_conf.h, src/conf/network_conf.c,
src/conf/network_conf.h, src/lxc/lxc_driver.c,
src/network/bridge_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_driver.c, src/qemu/qemu_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c: Update for
renamed APIs.
2009-10-20 14:51:03 +00:00
|
|
|
!virDomainObjIsActive(vm)) {
|
Convert virDomainObjListPtr to use a hash of domain objects
The current virDomainObjListPtr object stores domain objects in
an array. This means that to find a particular objects requires
O(n) time, and more critically acquiring O(n) mutex locks.
The new impl replaces the array with a virHashTable, keyed off
UUID. Finding a object based on UUID is now O(1) time, and only
requires a single mutex lock. Finding by name/id is unchanged
in complexity.
In changing this, all code which iterates over the array had
to be updated to use a hash table iterator function callback.
Several of the functions which were identically duplicating
across all drivers were pulled into domain_conf.c
* src/conf/domain_conf.h, src/conf/domain_conf.c: Change
virDomainObjListPtr to use virHashTable. Add a initializer
method virDomainObjListInit, and rename virDomainObjListFree
to virDomainObjListDeinit, since its not actually freeing
the container, only its contents. Also add some convenient
methods virDomainObjListGetInactiveNames,
virDomainObjListGetActiveIDs and virDomainObjListNumOfDomains
which can be used to implement the correspondingly named
public API entry points in drivers
* src/libvirt_private.syms: Export new methods from domain_conf.h
* src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_conf.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c: Update all code
to deal with hash tables instead of arrays for domains
2009-10-09 11:33:51 +00:00
|
|
|
virResetLastError();
|
2011-07-13 11:21:54 +00:00
|
|
|
ret = umlStartVMDaemon(data->conn, data->driver, vm, false);
|
2011-07-04 11:10:30 +00:00
|
|
|
virDomainAuditStart(vm, "booted", ret >= 0);
|
|
|
|
if (ret < 0) {
|
Convert virDomainObjListPtr to use a hash of domain objects
The current virDomainObjListPtr object stores domain objects in
an array. This means that to find a particular objects requires
O(n) time, and more critically acquiring O(n) mutex locks.
The new impl replaces the array with a virHashTable, keyed off
UUID. Finding a object based on UUID is now O(1) time, and only
requires a single mutex lock. Finding by name/id is unchanged
in complexity.
In changing this, all code which iterates over the array had
to be updated to use a hash table iterator function callback.
Several of the functions which were identically duplicating
across all drivers were pulled into domain_conf.c
* src/conf/domain_conf.h, src/conf/domain_conf.c: Change
virDomainObjListPtr to use virHashTable. Add a initializer
method virDomainObjListInit, and rename virDomainObjListFree
to virDomainObjListDeinit, since its not actually freeing
the container, only its contents. Also add some convenient
methods virDomainObjListGetInactiveNames,
virDomainObjListGetActiveIDs and virDomainObjListNumOfDomains
which can be used to implement the correspondingly named
public API entry points in drivers
* src/libvirt_private.syms: Export new methods from domain_conf.h
* src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_conf.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c: Update all code
to deal with hash tables instead of arrays for domains
2009-10-09 11:33:51 +00:00
|
|
|
virErrorPtr err = virGetLastError();
|
|
|
|
VIR_ERROR(_("Failed to autostart VM '%s': %s"),
|
2010-05-20 06:44:27 +00:00
|
|
|
vm->def->name, err ? err->message : _("unknown error"));
|
2009-07-06 15:06:11 +00:00
|
|
|
} else {
|
|
|
|
virDomainEventPtr event =
|
|
|
|
virDomainEventNewFromObj(vm,
|
|
|
|
VIR_DOMAIN_EVENT_STARTED,
|
|
|
|
VIR_DOMAIN_EVENT_STARTED_BOOTED);
|
|
|
|
if (event)
|
|
|
|
umlDomainEventQueue(data->driver, event);
|
Convert virDomainObjListPtr to use a hash of domain objects
The current virDomainObjListPtr object stores domain objects in
an array. This means that to find a particular objects requires
O(n) time, and more critically acquiring O(n) mutex locks.
The new impl replaces the array with a virHashTable, keyed off
UUID. Finding a object based on UUID is now O(1) time, and only
requires a single mutex lock. Finding by name/id is unchanged
in complexity.
In changing this, all code which iterates over the array had
to be updated to use a hash table iterator function callback.
Several of the functions which were identically duplicating
across all drivers were pulled into domain_conf.c
* src/conf/domain_conf.h, src/conf/domain_conf.c: Change
virDomainObjListPtr to use virHashTable. Add a initializer
method virDomainObjListInit, and rename virDomainObjListFree
to virDomainObjListDeinit, since its not actually freeing
the container, only its contents. Also add some convenient
methods virDomainObjListGetInactiveNames,
virDomainObjListGetActiveIDs and virDomainObjListNumOfDomains
which can be used to implement the correspondingly named
public API entry points in drivers
* src/libvirt_private.syms: Export new methods from domain_conf.h
* src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_conf.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c: Update all code
to deal with hash tables instead of arrays for domains
2009-10-09 11:33:51 +00:00
|
|
|
}
|
|
|
|
}
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(vm);
|
2013-01-11 13:54:15 +00:00
|
|
|
return ret;
|
Convert virDomainObjListPtr to use a hash of domain objects
The current virDomainObjListPtr object stores domain objects in
an array. This means that to find a particular objects requires
O(n) time, and more critically acquiring O(n) mutex locks.
The new impl replaces the array with a virHashTable, keyed off
UUID. Finding a object based on UUID is now O(1) time, and only
requires a single mutex lock. Finding by name/id is unchanged
in complexity.
In changing this, all code which iterates over the array had
to be updated to use a hash table iterator function callback.
Several of the functions which were identically duplicating
across all drivers were pulled into domain_conf.c
* src/conf/domain_conf.h, src/conf/domain_conf.c: Change
virDomainObjListPtr to use virHashTable. Add a initializer
method virDomainObjListInit, and rename virDomainObjListFree
to virDomainObjListDeinit, since its not actually freeing
the container, only its contents. Also add some convenient
methods virDomainObjListGetInactiveNames,
virDomainObjListGetActiveIDs and virDomainObjListNumOfDomains
which can be used to implement the correspondingly named
public API entry points in drivers
* src/libvirt_private.syms: Export new methods from domain_conf.h
* src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_conf.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c: Update all code
to deal with hash tables instead of arrays for domains
2009-10-09 11:33:51 +00:00
|
|
|
}
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
umlAutostartConfigs(struct uml_driver *driver) {
|
2008-12-08 11:18:47 +00:00
|
|
|
/* XXX: Figure out a better way todo this. The domain
|
|
|
|
* startup code needs a connection handle in order
|
|
|
|
* to lookup the bridge associated with a virtual
|
|
|
|
* network
|
|
|
|
*/
|
2009-06-12 13:20:13 +00:00
|
|
|
virConnectPtr conn = virConnectOpen(driver->privileged ?
|
|
|
|
"uml:///system" :
|
|
|
|
"uml:///session");
|
2008-12-08 11:18:47 +00:00
|
|
|
/* Ignoring NULL conn which is mostly harmless here */
|
2008-11-19 16:58:23 +00:00
|
|
|
|
Convert virDomainObjListPtr to use a hash of domain objects
The current virDomainObjListPtr object stores domain objects in
an array. This means that to find a particular objects requires
O(n) time, and more critically acquiring O(n) mutex locks.
The new impl replaces the array with a virHashTable, keyed off
UUID. Finding a object based on UUID is now O(1) time, and only
requires a single mutex lock. Finding by name/id is unchanged
in complexity.
In changing this, all code which iterates over the array had
to be updated to use a hash table iterator function callback.
Several of the functions which were identically duplicating
across all drivers were pulled into domain_conf.c
* src/conf/domain_conf.h, src/conf/domain_conf.c: Change
virDomainObjListPtr to use virHashTable. Add a initializer
method virDomainObjListInit, and rename virDomainObjListFree
to virDomainObjListDeinit, since its not actually freeing
the container, only its contents. Also add some convenient
methods virDomainObjListGetInactiveNames,
virDomainObjListGetActiveIDs and virDomainObjListNumOfDomains
which can be used to implement the correspondingly named
public API entry points in drivers
* src/libvirt_private.syms: Export new methods from domain_conf.h
* src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_conf.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c: Update all code
to deal with hash tables instead of arrays for domains
2009-10-09 11:33:51 +00:00
|
|
|
struct umlAutostartData data = { driver, conn };
|
|
|
|
|
2009-07-06 15:06:11 +00:00
|
|
|
umlDriverLock(driver);
|
2013-01-11 13:54:15 +00:00
|
|
|
virDomainObjListForEach(driver->domains, umlAutostartDomain, &data);
|
2009-07-06 15:06:11 +00:00
|
|
|
umlDriverUnlock(driver);
|
2008-12-08 11:18:47 +00:00
|
|
|
|
2009-03-16 10:30:04 +00:00
|
|
|
if (conn)
|
|
|
|
virConnectClose(conn);
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2010-02-04 18:19:08 +00:00
|
|
|
umlIdentifyOneChrPTY(struct uml_driver *driver,
|
2008-11-19 16:58:23 +00:00
|
|
|
virDomainObjPtr dom,
|
|
|
|
virDomainChrDefPtr def,
|
|
|
|
const char *dev)
|
|
|
|
{
|
|
|
|
char *cmd;
|
|
|
|
char *res = NULL;
|
|
|
|
int retries = 0;
|
2009-11-05 13:19:14 +00:00
|
|
|
if (virAsprintf(&cmd, "config %s%d", dev, def->target.port) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-11-19 16:58:23 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
requery:
|
2010-04-03 13:33:29 +00:00
|
|
|
if (umlMonitorCommand(driver, dom, cmd, &res) < 0)
|
2009-06-03 10:55:33 +00:00
|
|
|
return -1;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2009-06-03 10:55:33 +00:00
|
|
|
if (res && STRPREFIX(res, "pts:")) {
|
domain_conf: split source data out from ChrDef
This opens up the possibility of reusing the smaller ChrSourceDef
for both qemu monitor and a passthrough smartcard device.
* src/conf/domain_conf.h (_virDomainChrDef): Factor host
details...
(_virDomainChrSourceDef): ...into new struct.
(virDomainChrSourceDefFree): New prototype.
* src/conf/domain_conf.c (virDomainChrDefFree)
(virDomainChrDefParseXML, virDomainChrDefFormat): Split...
(virDomainChrSourceDefClear, virDomainChrSourceDefFree)
(virDomainChrSourceDefParseXML, virDomainChrSourceDefFormat):
...into new functions.
(virDomainChrDefParseTargetXML): Update clients to reflect type
split.
* src/vmx/vmx.c (virVMXParseSerial, virVMXParseParallel)
(virVMXFormatSerial, virVMXFormatParallel): Likewise.
* src/xen/xen_driver.c (xenUnifiedDomainOpenConsole): Likewise.
* src/xen/xend_internal.c (xenDaemonParseSxprChar)
(xenDaemonFormatSxprChr): Likewise.
* src/vbox/vbox_tmpl.c (vboxDomainDumpXML, vboxAttachSerial)
(vboxAttachParallel): Likewise.
* src/security/security_dac.c (virSecurityDACSetChardevLabel)
(virSecurityDACSetChardevCallback)
(virSecurityDACRestoreChardevLabel)
(virSecurityDACRestoreChardevCallback): Likewise.
* src/security/security_selinux.c (SELinuxSetSecurityChardevLabel)
(SELinuxSetSecurityChardevCallback)
(SELinuxRestoreSecurityChardevLabel)
(SELinuxSetSecurityChardevCallback): Likewise.
* src/security/virt-aa-helper.c (get_files): Likewise.
* src/lxc/lxc_driver.c (lxcVmStart, lxcDomainOpenConsole):
Likewise.
* src/uml/uml_conf.c (umlBuildCommandLineChr): Likewise.
* src/uml/uml_driver.c (umlIdentifyOneChrPTY, umlIdentifyChrPTY)
(umlDomainOpenConsole): Likewise.
* src/qemu/qemu_command.c (qemuBuildChrChardevStr)
(qemuBuildChrArgStr, qemuBuildCommandLine)
(qemuParseCommandLineChr): Likewise.
* src/qemu/qemu_domain.c (qemuDomainObjPrivateXMLFormat)
(qemuDomainObjPrivateXMLParse): Likewise.
* src/qemu/qemu_cgroup.c (qemuSetupChardevCgroup): Likewise.
* src/qemu/qemu_hotplug.c (qemuDomainAttachNetDevice): Likewise.
* src/qemu/qemu_driver.c (qemudFindCharDevicePTYsMonitor)
(qemudFindCharDevicePTYs, qemuPrepareChardevDevice)
(qemuPrepareMonitorChr, qemudShutdownVMDaemon)
(qemuDomainOpenConsole): Likewise.
* src/qemu/qemu_command.h (qemuBuildChrChardevStr)
(qemuBuildChrArgStr): Delete, now that they are static.
* src/libvirt_private.syms (domain_conf.h): New exports.
* cfg.mk (useless_free_options): Update list.
* tests/qemuxml2argvtest.c (testCompareXMLToArgvFiles): Update
tests.
2011-01-07 22:45:01 +00:00
|
|
|
VIR_FREE(def->source.data.file.path);
|
|
|
|
if ((def->source.data.file.path = strdup(res + 4)) == NULL) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-11-19 16:58:23 +00:00
|
|
|
VIR_FREE(res);
|
|
|
|
VIR_FREE(cmd);
|
|
|
|
return -1;
|
|
|
|
}
|
2009-06-03 10:55:33 +00:00
|
|
|
} else if (!res || STRPREFIX(res, "pts")) {
|
2008-11-19 16:58:23 +00:00
|
|
|
/* It can take a while to startup, so retry for
|
2012-10-11 16:31:20 +00:00
|
|
|
up to 5 seconds */
|
2008-11-19 16:58:23 +00:00
|
|
|
/* XXX should do this in a better non-blocking
|
|
|
|
way somehow ...perhaps register a timer */
|
|
|
|
if (retries++ < 50) {
|
2013-01-30 14:54:41 +00:00
|
|
|
VIR_FREE(res);
|
2008-11-19 16:58:23 +00:00
|
|
|
usleep(1000*10);
|
|
|
|
goto requery;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_FREE(cmd);
|
|
|
|
VIR_FREE(res);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2010-02-04 18:19:08 +00:00
|
|
|
umlIdentifyChrPTY(struct uml_driver *driver,
|
2008-11-19 16:58:23 +00:00
|
|
|
virDomainObjPtr dom)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2012-04-09 03:40:52 +00:00
|
|
|
for (i = 0 ; i < dom->def->nconsoles; i++)
|
Allow multiple consoles per virtual guest
While Xen only has a single paravirt console, UML, and
QEMU both support multiple paravirt consoles. The LXC
driver can also be trivially made to support multiple
consoles. This patch extends the XML to allow multiple
<console> elements in the XML. It also makes the UML
and QEMU drivers support this config.
* src/conf/domain_conf.c, src/conf/domain_conf.h: Allow
multiple <console> devices
* src/lxc/lxc_driver.c, src/xen/xen_driver.c,
src/xenxs/xen_sxpr.c, src/xenxs/xen_xm.c: Update for
internal API changes
* src/security/security_selinux.c, src/security/virt-aa-helper.c:
Only label consoles that aren't a copy of the serial device
* src/qemu/qemu_command.c, src/qemu/qemu_driver.c,
src/qemu/qemu_process.c, src/uml/uml_conf.c,
src/uml/uml_driver.c: Support multiple console devices
* tests/qemuxml2xmltest.c, tests/qemuxml2argvtest.c: Extra
tests for multiple virtio consoles. Set QEMU_CAPS_CHARDEV
for all console /channel tests
* tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-auto.args,
tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.args
tests/qemuxml2argvdata/qemuxml2argv-console-virtio.args: Update
for correct chardev syntax
* tests/qemuxml2argvdata/qemuxml2argv-console-virtio-many.args,
tests/qemuxml2argvdata/qemuxml2argv-console-virtio-many.xml: New
test file
2011-02-23 18:27:23 +00:00
|
|
|
if (dom->def->consoles[i]->source.type == VIR_DOMAIN_CHR_TYPE_PTY)
|
2010-02-04 18:19:08 +00:00
|
|
|
if (umlIdentifyOneChrPTY(driver, dom,
|
Allow multiple consoles per virtual guest
While Xen only has a single paravirt console, UML, and
QEMU both support multiple paravirt consoles. The LXC
driver can also be trivially made to support multiple
consoles. This patch extends the XML to allow multiple
<console> elements in the XML. It also makes the UML
and QEMU drivers support this config.
* src/conf/domain_conf.c, src/conf/domain_conf.h: Allow
multiple <console> devices
* src/lxc/lxc_driver.c, src/xen/xen_driver.c,
src/xenxs/xen_sxpr.c, src/xenxs/xen_xm.c: Update for
internal API changes
* src/security/security_selinux.c, src/security/virt-aa-helper.c:
Only label consoles that aren't a copy of the serial device
* src/qemu/qemu_command.c, src/qemu/qemu_driver.c,
src/qemu/qemu_process.c, src/uml/uml_conf.c,
src/uml/uml_driver.c: Support multiple console devices
* tests/qemuxml2xmltest.c, tests/qemuxml2argvtest.c: Extra
tests for multiple virtio consoles. Set QEMU_CAPS_CHARDEV
for all console /channel tests
* tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-auto.args,
tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.args
tests/qemuxml2argvdata/qemuxml2argv-console-virtio.args: Update
for correct chardev syntax
* tests/qemuxml2argvdata/qemuxml2argv-console-virtio-many.args,
tests/qemuxml2argvdata/qemuxml2argv-console-virtio-many.xml: New
test file
2011-02-23 18:27:23 +00:00
|
|
|
dom->def->consoles[i], "con") < 0)
|
2008-11-19 16:58:23 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
for (i = 0 ; i < dom->def->nserials; i++)
|
domain_conf: split source data out from ChrDef
This opens up the possibility of reusing the smaller ChrSourceDef
for both qemu monitor and a passthrough smartcard device.
* src/conf/domain_conf.h (_virDomainChrDef): Factor host
details...
(_virDomainChrSourceDef): ...into new struct.
(virDomainChrSourceDefFree): New prototype.
* src/conf/domain_conf.c (virDomainChrDefFree)
(virDomainChrDefParseXML, virDomainChrDefFormat): Split...
(virDomainChrSourceDefClear, virDomainChrSourceDefFree)
(virDomainChrSourceDefParseXML, virDomainChrSourceDefFormat):
...into new functions.
(virDomainChrDefParseTargetXML): Update clients to reflect type
split.
* src/vmx/vmx.c (virVMXParseSerial, virVMXParseParallel)
(virVMXFormatSerial, virVMXFormatParallel): Likewise.
* src/xen/xen_driver.c (xenUnifiedDomainOpenConsole): Likewise.
* src/xen/xend_internal.c (xenDaemonParseSxprChar)
(xenDaemonFormatSxprChr): Likewise.
* src/vbox/vbox_tmpl.c (vboxDomainDumpXML, vboxAttachSerial)
(vboxAttachParallel): Likewise.
* src/security/security_dac.c (virSecurityDACSetChardevLabel)
(virSecurityDACSetChardevCallback)
(virSecurityDACRestoreChardevLabel)
(virSecurityDACRestoreChardevCallback): Likewise.
* src/security/security_selinux.c (SELinuxSetSecurityChardevLabel)
(SELinuxSetSecurityChardevCallback)
(SELinuxRestoreSecurityChardevLabel)
(SELinuxSetSecurityChardevCallback): Likewise.
* src/security/virt-aa-helper.c (get_files): Likewise.
* src/lxc/lxc_driver.c (lxcVmStart, lxcDomainOpenConsole):
Likewise.
* src/uml/uml_conf.c (umlBuildCommandLineChr): Likewise.
* src/uml/uml_driver.c (umlIdentifyOneChrPTY, umlIdentifyChrPTY)
(umlDomainOpenConsole): Likewise.
* src/qemu/qemu_command.c (qemuBuildChrChardevStr)
(qemuBuildChrArgStr, qemuBuildCommandLine)
(qemuParseCommandLineChr): Likewise.
* src/qemu/qemu_domain.c (qemuDomainObjPrivateXMLFormat)
(qemuDomainObjPrivateXMLParse): Likewise.
* src/qemu/qemu_cgroup.c (qemuSetupChardevCgroup): Likewise.
* src/qemu/qemu_hotplug.c (qemuDomainAttachNetDevice): Likewise.
* src/qemu/qemu_driver.c (qemudFindCharDevicePTYsMonitor)
(qemudFindCharDevicePTYs, qemuPrepareChardevDevice)
(qemuPrepareMonitorChr, qemudShutdownVMDaemon)
(qemuDomainOpenConsole): Likewise.
* src/qemu/qemu_command.h (qemuBuildChrChardevStr)
(qemuBuildChrArgStr): Delete, now that they are static.
* src/libvirt_private.syms (domain_conf.h): New exports.
* cfg.mk (useless_free_options): Update list.
* tests/qemuxml2argvtest.c (testCompareXMLToArgvFiles): Update
tests.
2011-01-07 22:45:01 +00:00
|
|
|
if (dom->def->serials[i]->source.type == VIR_DOMAIN_CHR_TYPE_PTY &&
|
2010-02-04 18:19:08 +00:00
|
|
|
umlIdentifyOneChrPTY(driver, dom,
|
2008-11-19 16:58:23 +00:00
|
|
|
dom->def->serials[i], "ssl") < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
umlInotifyEvent(int watch,
|
|
|
|
int fd,
|
|
|
|
int events ATTRIBUTE_UNUSED,
|
|
|
|
void *data)
|
|
|
|
{
|
|
|
|
char buf[1024];
|
2013-04-03 13:33:56 +00:00
|
|
|
struct inotify_event e;
|
2008-11-19 16:58:23 +00:00
|
|
|
int got;
|
|
|
|
char *tmp, *name;
|
|
|
|
struct uml_driver *driver = data;
|
|
|
|
virDomainObjPtr dom;
|
2009-07-06 15:06:11 +00:00
|
|
|
virDomainEventPtr event = NULL;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2008-11-19 16:58:23 +00:00
|
|
|
if (watch != driver->inotifyWatch)
|
2008-12-04 21:14:39 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
reread:
|
|
|
|
got = read(fd, buf, sizeof(buf));
|
|
|
|
if (got == -1) {
|
|
|
|
if (errno == EINTR)
|
|
|
|
goto reread;
|
2008-12-04 21:14:39 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
tmp = buf;
|
|
|
|
while (got) {
|
2013-04-03 13:33:56 +00:00
|
|
|
if (got < sizeof(e))
|
2008-12-04 21:14:39 +00:00
|
|
|
goto cleanup; /* bad */
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2013-04-03 13:33:56 +00:00
|
|
|
memcpy(&e, tmp, sizeof(e));
|
|
|
|
tmp += sizeof(e);
|
|
|
|
got -= sizeof(e);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2013-04-03 13:33:56 +00:00
|
|
|
if (got < e.len)
|
2008-12-04 21:14:39 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2013-04-03 13:33:56 +00:00
|
|
|
tmp += e.len;
|
|
|
|
got -= e.len;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2013-04-03 13:33:56 +00:00
|
|
|
name = (char *)&(e.name);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2013-01-11 16:04:47 +00:00
|
|
|
dom = virDomainObjListFindByName(driver->domains, name);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
if (!dom) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2013-04-03 13:33:56 +00:00
|
|
|
if (e.mask & IN_DELETE) {
|
2009-06-03 10:55:33 +00:00
|
|
|
VIR_DEBUG("Got inotify domain shutdown '%s'", name);
|
Rename internal APis
Rename virDomainIsActive to virDomainObjIsActive, and
virInterfaceIsActive to virInterfaceObjIsActive and finally
virNetworkIsActive to virNetworkObjIsActive.
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/conf/interface_conf.h, src/conf/network_conf.c,
src/conf/network_conf.h, src/lxc/lxc_driver.c,
src/network/bridge_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_driver.c, src/qemu/qemu_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c: Update for
renamed APIs.
2009-10-20 14:51:03 +00:00
|
|
|
if (!virDomainObjIsActive(dom)) {
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(dom);
|
2008-11-19 16:58:23 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2011-07-13 11:21:54 +00:00
|
|
|
umlShutdownVMDaemon(driver, dom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
|
2011-07-04 11:10:30 +00:00
|
|
|
virDomainAuditStop(dom, "shutdown");
|
2009-07-06 15:06:11 +00:00
|
|
|
event = virDomainEventNewFromObj(dom,
|
|
|
|
VIR_DOMAIN_EVENT_STOPPED,
|
|
|
|
VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
|
2011-07-04 11:11:56 +00:00
|
|
|
if (!dom->persistent) {
|
2013-01-11 16:04:47 +00:00
|
|
|
virDomainObjListRemove(driver->domains,
|
|
|
|
dom);
|
2011-07-04 11:11:56 +00:00
|
|
|
dom = NULL;
|
|
|
|
}
|
2013-04-03 13:33:56 +00:00
|
|
|
} else if (e.mask & (IN_CREATE | IN_MODIFY)) {
|
2009-06-03 10:55:33 +00:00
|
|
|
VIR_DEBUG("Got inotify domain startup '%s'", name);
|
Rename internal APis
Rename virDomainIsActive to virDomainObjIsActive, and
virInterfaceIsActive to virInterfaceObjIsActive and finally
virNetworkIsActive to virNetworkObjIsActive.
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/conf/interface_conf.h, src/conf/network_conf.c,
src/conf/network_conf.h, src/lxc/lxc_driver.c,
src/network/bridge_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_driver.c, src/qemu/qemu_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c: Update for
renamed APIs.
2009-10-20 14:51:03 +00:00
|
|
|
if (virDomainObjIsActive(dom)) {
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(dom);
|
2008-11-19 16:58:23 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2010-02-04 20:02:58 +00:00
|
|
|
if (umlReadPidFile(driver, dom) < 0) {
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(dom);
|
2008-11-19 16:58:23 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
dom->def->id = driver->nextvmid++;
|
2012-10-31 19:03:55 +00:00
|
|
|
|
|
|
|
if (!driver->nactive && driver->inhibitCallback)
|
|
|
|
driver->inhibitCallback(true, driver->inhibitOpaque);
|
|
|
|
driver->nactive++;
|
|
|
|
|
2011-05-04 09:07:01 +00:00
|
|
|
virDomainObjSetState(dom, VIR_DOMAIN_RUNNING,
|
|
|
|
VIR_DOMAIN_RUNNING_BOOTED);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2010-04-03 13:33:29 +00:00
|
|
|
if (umlOpenMonitor(driver, dom) < 0) {
|
2011-05-09 09:24:09 +00:00
|
|
|
VIR_WARN("Could not open monitor for new domain");
|
2011-07-13 11:21:54 +00:00
|
|
|
umlShutdownVMDaemon(driver, dom,
|
2011-05-04 09:07:01 +00:00
|
|
|
VIR_DOMAIN_SHUTOFF_FAILED);
|
2011-07-04 11:10:30 +00:00
|
|
|
virDomainAuditStop(dom, "failed");
|
2009-07-06 15:06:11 +00:00
|
|
|
event = virDomainEventNewFromObj(dom,
|
|
|
|
VIR_DOMAIN_EVENT_STOPPED,
|
|
|
|
VIR_DOMAIN_EVENT_STOPPED_FAILED);
|
2011-07-04 11:11:56 +00:00
|
|
|
if (!dom->persistent) {
|
2013-01-11 16:04:47 +00:00
|
|
|
virDomainObjListRemove(driver->domains,
|
|
|
|
dom);
|
2011-07-04 11:11:56 +00:00
|
|
|
dom = NULL;
|
|
|
|
}
|
2010-02-04 18:19:08 +00:00
|
|
|
} else if (umlIdentifyChrPTY(driver, dom) < 0) {
|
2011-07-04 11:11:56 +00:00
|
|
|
VIR_WARN("Could not identify character devices for new domain");
|
2011-07-13 11:21:54 +00:00
|
|
|
umlShutdownVMDaemon(driver, dom,
|
2011-05-04 09:07:01 +00:00
|
|
|
VIR_DOMAIN_SHUTOFF_FAILED);
|
2011-07-04 11:10:30 +00:00
|
|
|
virDomainAuditStop(dom, "failed");
|
2009-07-06 15:06:11 +00:00
|
|
|
event = virDomainEventNewFromObj(dom,
|
|
|
|
VIR_DOMAIN_EVENT_STOPPED,
|
|
|
|
VIR_DOMAIN_EVENT_STOPPED_FAILED);
|
2011-07-04 11:11:56 +00:00
|
|
|
if (!dom->persistent) {
|
2013-01-11 16:04:47 +00:00
|
|
|
virDomainObjListRemove(driver->domains,
|
|
|
|
dom);
|
2011-07-04 11:11:56 +00:00
|
|
|
dom = NULL;
|
|
|
|
}
|
2009-06-03 10:55:33 +00:00
|
|
|
}
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
2011-07-04 11:11:56 +00:00
|
|
|
if (dom)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(dom);
|
2013-01-22 14:20:06 +00:00
|
|
|
if (event) {
|
|
|
|
umlDomainEventQueue(driver, event);
|
|
|
|
event = NULL;
|
|
|
|
}
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
2008-12-04 21:14:39 +00:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
umlDriverUnlock(driver);
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
2013-03-13 20:39:34 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
umlDomainDeviceDefPostParse(virDomainDeviceDefPtr dev,
|
|
|
|
virDomainDefPtr def ATTRIBUTE_UNUSED,
|
|
|
|
virCapsPtr caps ATTRIBUTE_UNUSED,
|
|
|
|
void *opaque ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
if (dev->type == VIR_DOMAIN_DEVICE_CHR &&
|
|
|
|
dev->data.chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
|
|
|
|
dev->data.chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_NONE)
|
|
|
|
dev->data.chr->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_UML;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
virDomainDefParserConfig umlDriverDomainDefParserConfig = {
|
|
|
|
.devicesPostParseCallback = umlDomainDeviceDefPostParse,
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
/**
|
|
|
|
* umlStartup:
|
|
|
|
*
|
|
|
|
* Initialization function for the Uml daemon
|
|
|
|
*/
|
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
umlStateInitialize(bool privileged,
|
|
|
|
virStateInhibitCallback callback,
|
|
|
|
void *opaque)
|
2011-01-15 16:38:57 +00:00
|
|
|
{
|
2008-11-19 16:58:23 +00:00
|
|
|
char *base = NULL;
|
2009-01-22 19:41:48 +00:00
|
|
|
char *userdir = NULL;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2013-03-05 15:17:24 +00:00
|
|
|
virDomainXMLPrivateDataCallbacks privcb = {
|
|
|
|
.alloc = umlDomainObjPrivateAlloc,
|
|
|
|
.free = umlDomainObjPrivateFree,
|
|
|
|
};
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
if (VIR_ALLOC(uml_driver) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2009-06-12 13:20:13 +00:00
|
|
|
uml_driver->privileged = privileged;
|
2012-10-31 19:03:55 +00:00
|
|
|
uml_driver->inhibitCallback = callback;
|
|
|
|
uml_driver->inhibitOpaque = opaque;
|
2009-06-12 13:20:13 +00:00
|
|
|
|
2009-01-15 19:56:05 +00:00
|
|
|
if (virMutexInit(¨_driver->lock) < 0) {
|
|
|
|
VIR_FREE(uml_driver);
|
|
|
|
return -1;
|
|
|
|
}
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(uml_driver);
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
/* Don't have a dom0 so start from 1 */
|
|
|
|
uml_driver->nextvmid = 1;
|
2009-01-29 17:50:00 +00:00
|
|
|
uml_driver->inotifyWatch = -1;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2013-01-11 16:04:47 +00:00
|
|
|
if (!(uml_driver->domains = virDomainObjListNew()))
|
Convert virDomainObjListPtr to use a hash of domain objects
The current virDomainObjListPtr object stores domain objects in
an array. This means that to find a particular objects requires
O(n) time, and more critically acquiring O(n) mutex locks.
The new impl replaces the array with a virHashTable, keyed off
UUID. Finding a object based on UUID is now O(1) time, and only
requires a single mutex lock. Finding by name/id is unchanged
in complexity.
In changing this, all code which iterates over the array had
to be updated to use a hash table iterator function callback.
Several of the functions which were identically duplicating
across all drivers were pulled into domain_conf.c
* src/conf/domain_conf.h, src/conf/domain_conf.c: Change
virDomainObjListPtr to use virHashTable. Add a initializer
method virDomainObjListInit, and rename virDomainObjListFree
to virDomainObjListDeinit, since its not actually freeing
the container, only its contents. Also add some convenient
methods virDomainObjListGetInactiveNames,
virDomainObjListGetActiveIDs and virDomainObjListNumOfDomains
which can be used to implement the correspondingly named
public API entry points in drivers
* src/libvirt_private.syms: Export new methods from domain_conf.h
* src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_conf.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c: Update all code
to deal with hash tables instead of arrays for domains
2009-10-09 11:33:51 +00:00
|
|
|
goto error;
|
|
|
|
|
2011-12-14 00:25:58 +00:00
|
|
|
uml_driver->domainEventState = virDomainEventStateNew();
|
2009-07-06 15:06:11 +00:00
|
|
|
if (!uml_driver->domainEventState)
|
|
|
|
goto error;
|
|
|
|
|
2012-05-24 12:29:42 +00:00
|
|
|
userdir = virGetUserDirectory();
|
2009-01-22 19:41:48 +00:00
|
|
|
if (!userdir)
|
2008-12-04 21:14:39 +00:00
|
|
|
goto error;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2009-06-12 13:20:13 +00:00
|
|
|
if (privileged) {
|
2008-12-23 13:03:29 +00:00
|
|
|
if (virAsprintf(¨_driver->logDir,
|
2010-11-16 14:54:17 +00:00
|
|
|
"%s/log/libvirt/uml", LOCALSTATEDIR) == -1)
|
2008-11-19 16:58:23 +00:00
|
|
|
goto out_of_memory;
|
|
|
|
|
2012-10-17 09:23:12 +00:00
|
|
|
if ((base = strdup(SYSCONFDIR "/libvirt")) == NULL)
|
2008-11-19 16:58:23 +00:00
|
|
|
goto out_of_memory;
|
2010-08-31 11:44:16 +00:00
|
|
|
|
|
|
|
if (virAsprintf(¨_driver->monitorDir,
|
2010-11-16 14:54:17 +00:00
|
|
|
"%s/run/libvirt/uml-guest", LOCALSTATEDIR) == -1)
|
2010-08-31 11:44:16 +00:00
|
|
|
goto out_of_memory;
|
2008-11-19 16:58:23 +00:00
|
|
|
} else {
|
2012-05-24 12:29:42 +00:00
|
|
|
base = virGetUserConfigDirectory();
|
2012-05-03 16:36:27 +00:00
|
|
|
if (!base)
|
|
|
|
goto error;
|
2009-01-22 19:41:48 +00:00
|
|
|
|
2008-12-23 13:03:29 +00:00
|
|
|
if (virAsprintf(¨_driver->logDir,
|
2012-05-03 16:36:27 +00:00
|
|
|
"%s/uml/log", base) == -1)
|
2008-11-19 16:58:23 +00:00
|
|
|
goto out_of_memory;
|
|
|
|
|
2010-08-31 11:44:16 +00:00
|
|
|
if (virAsprintf(¨_driver->monitorDir,
|
|
|
|
"%s/.uml", userdir) == -1)
|
|
|
|
goto out_of_memory;
|
|
|
|
}
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2012-05-03 16:36:27 +00:00
|
|
|
/* Configuration paths are either $XDG_CONFIG_HOME/libvirt/uml/... (session) or
|
2008-11-19 16:58:23 +00:00
|
|
|
* /etc/libvirt/uml/... (system).
|
|
|
|
*/
|
2008-12-23 13:03:29 +00:00
|
|
|
if (virAsprintf(¨_driver->configDir, "%s/uml", base) == -1)
|
2008-11-19 16:58:23 +00:00
|
|
|
goto out_of_memory;
|
|
|
|
|
2008-12-23 13:03:29 +00:00
|
|
|
if (virAsprintf(¨_driver->autostartDir, "%s/uml/autostart", base) == -1)
|
2008-11-19 16:58:23 +00:00
|
|
|
goto out_of_memory;
|
|
|
|
|
|
|
|
VIR_FREE(base);
|
|
|
|
|
|
|
|
if ((uml_driver->caps = umlCapsInit()) == NULL)
|
|
|
|
goto out_of_memory;
|
|
|
|
|
2013-03-13 20:39:34 +00:00
|
|
|
if (!(uml_driver->xmlopt = virDomainXMLOptionNew(¨DriverDomainDefParserConfig,
|
|
|
|
&privcb, NULL)))
|
2013-03-05 15:17:24 +00:00
|
|
|
goto error;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
if ((uml_driver->inotifyFD = inotify_init()) < 0) {
|
2011-05-09 09:24:09 +00:00
|
|
|
VIR_ERROR(_("cannot initialize inotify"));
|
2008-12-04 21:14:39 +00:00
|
|
|
goto error;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
2011-07-05 21:02:53 +00:00
|
|
|
if (virFileMakePath(uml_driver->monitorDir) < 0) {
|
2009-02-05 16:28:30 +00:00
|
|
|
char ebuf[1024];
|
2009-06-25 15:02:10 +00:00
|
|
|
VIR_ERROR(_("Failed to create monitor directory %s: %s"),
|
2012-12-09 01:40:43 +00:00
|
|
|
uml_driver->monitorDir,
|
|
|
|
virStrerror(errno, ebuf, sizeof(ebuf)));
|
2008-12-04 21:14:39 +00:00
|
|
|
goto error;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
2009-06-03 10:55:33 +00:00
|
|
|
VIR_INFO("Adding inotify watch on %s", uml_driver->monitorDir);
|
2008-12-02 11:23:27 +00:00
|
|
|
if (inotify_add_watch(uml_driver->inotifyFD,
|
|
|
|
uml_driver->monitorDir,
|
|
|
|
IN_CREATE | IN_MODIFY | IN_DELETE) < 0) {
|
2012-12-09 01:40:43 +00:00
|
|
|
char ebuf[1024];
|
|
|
|
VIR_ERROR(_("Failed to create inotify watch on %s: %s"),
|
|
|
|
uml_driver->monitorDir,
|
|
|
|
virStrerror(errno, ebuf, sizeof(ebuf)));
|
2008-12-04 21:14:39 +00:00
|
|
|
goto error;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
2008-12-02 11:23:27 +00:00
|
|
|
if ((uml_driver->inotifyWatch =
|
|
|
|
virEventAddHandle(uml_driver->inotifyFD, POLLIN,
|
2008-12-04 21:14:39 +00:00
|
|
|
umlInotifyEvent, uml_driver, NULL)) < 0)
|
|
|
|
goto error;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2011-07-13 11:21:54 +00:00
|
|
|
if (umlProcessAutoDestroyInit(uml_driver) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2013-01-11 16:04:47 +00:00
|
|
|
if (virDomainObjListLoadAllConfigs(uml_driver->domains,
|
2013-03-28 13:55:55 +00:00
|
|
|
uml_driver->configDir,
|
|
|
|
uml_driver->autostartDir, 0,
|
2013-01-11 16:04:47 +00:00
|
|
|
uml_driver->caps,
|
2013-03-31 18:03:42 +00:00
|
|
|
uml_driver->xmlopt,
|
2013-03-28 13:55:55 +00:00
|
|
|
1 << VIR_DOMAIN_VIRT_UML,
|
2013-01-11 16:04:47 +00:00
|
|
|
NULL, NULL) < 0)
|
2008-12-04 21:14:39 +00:00
|
|
|
goto error;
|
|
|
|
|
2009-07-06 15:06:11 +00:00
|
|
|
umlDriverUnlock(uml_driver);
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
umlAutostartConfigs(uml_driver);
|
|
|
|
|
2009-01-22 19:41:48 +00:00
|
|
|
VIR_FREE(userdir);
|
|
|
|
|
nwfilter: fix crash during filter define when lxc driver failed startup
The meat of this patch is just moving the calls to
virNWFilterRegisterCallbackDriver from each hypervisor's "register"
function into its "initialize" function. The rest is just code
movement to allow that, and a new virNWFilterUnRegisterCallbackDriver
function to undo what the register function does.
The long explanation:
There is an array in nwfilter called callbackDrvArray that has
pointers to a table of functions for each hypervisor driver that are
called by nwfilter. One of those function pointers is to a function
that will lock the hypervisor driver. Entries are added to the table
by calling each driver's "register" function, which happens quite
early in libvirtd's startup.
Sometime later, each driver's "initialize" function is called. This
function allocates a driver object and stores a pointer to it in a
static variable that was previously initialized to NULL. (and here's
the important part...) If the "initialize" function fails, the driver
object is freed, and that pointer set back to NULL (but the entry in
nwfilter's callbackDrvArray is still there).
When the "lock the driver" function mentioned above is called, it
assumes that the driver was successfully loaded, so it blindly tries
to call virMutexLock on "driver->lock".
BUT, if the initialize never happened, or if it failed, "driver" is
NULL. And it just happens that "lock" is always the first field in
driver so it is also NULL.
Boom.
To fix this, the call to virNWFilterRegisterCallbackDriver for each
driver shouldn't be called until the end of its (*already guaranteed
successful*) "initialize" function, not during its "register" function
(which is currently the case). This implies that there should also be
a virNWFilterUnregisterCallbackDriver() function that is called in a
driver's "shutdown" function (although in practice, that function is
currently never called).
2012-08-09 06:18:23 +00:00
|
|
|
virNWFilterRegisterCallbackDriver(¨CallbackDriver);
|
2008-11-19 16:58:23 +00:00
|
|
|
return 0;
|
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
out_of_memory:
|
2011-05-09 09:24:09 +00:00
|
|
|
VIR_ERROR(_("umlStartup: out of memory"));
|
2008-12-04 21:14:39 +00:00
|
|
|
|
|
|
|
error:
|
2009-01-22 19:41:48 +00:00
|
|
|
VIR_FREE(userdir);
|
2008-11-19 16:58:23 +00:00
|
|
|
VIR_FREE(base);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(uml_driver);
|
2013-04-23 12:50:18 +00:00
|
|
|
umlStateCleanup();
|
2008-11-19 16:58:23 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2009-07-06 15:06:11 +00:00
|
|
|
static void umlNotifyLoadDomain(virDomainObjPtr vm, int newVM, void *opaque)
|
|
|
|
{
|
|
|
|
struct uml_driver *driver = opaque;
|
|
|
|
|
|
|
|
if (newVM) {
|
|
|
|
virDomainEventPtr event =
|
|
|
|
virDomainEventNewFromObj(vm,
|
|
|
|
VIR_DOMAIN_EVENT_DEFINED,
|
|
|
|
VIR_DOMAIN_EVENT_DEFINED_ADDED);
|
|
|
|
if (event)
|
|
|
|
umlDomainEventQueue(driver, event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
/**
|
2013-04-23 12:50:18 +00:00
|
|
|
* umlStateReload:
|
2008-11-19 16:58:23 +00:00
|
|
|
*
|
|
|
|
* Function to restart the Uml daemon, it will recheck the configuration
|
|
|
|
* files and update its state and the networking
|
|
|
|
*/
|
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
umlStateReload(void) {
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!uml_driver)
|
|
|
|
return 0;
|
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(uml_driver);
|
2013-01-11 16:04:47 +00:00
|
|
|
virDomainObjListLoadAllConfigs(uml_driver->domains,
|
2013-03-28 13:55:55 +00:00
|
|
|
uml_driver->configDir,
|
|
|
|
uml_driver->autostartDir, 0,
|
2013-01-11 16:04:47 +00:00
|
|
|
uml_driver->caps,
|
2013-03-31 18:03:42 +00:00
|
|
|
uml_driver->xmlopt,
|
2013-03-28 13:55:55 +00:00
|
|
|
1 << VIR_DOMAIN_VIRT_UML,
|
2013-01-11 16:04:47 +00:00
|
|
|
umlNotifyLoadDomain, uml_driver);
|
2009-07-06 15:06:11 +00:00
|
|
|
umlDriverUnlock(uml_driver);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-01-11 13:54:15 +00:00
|
|
|
static int
|
|
|
|
umlShutdownOneVM(virDomainObjPtr dom, void *opaque)
|
Convert virDomainObjListPtr to use a hash of domain objects
The current virDomainObjListPtr object stores domain objects in
an array. This means that to find a particular objects requires
O(n) time, and more critically acquiring O(n) mutex locks.
The new impl replaces the array with a virHashTable, keyed off
UUID. Finding a object based on UUID is now O(1) time, and only
requires a single mutex lock. Finding by name/id is unchanged
in complexity.
In changing this, all code which iterates over the array had
to be updated to use a hash table iterator function callback.
Several of the functions which were identically duplicating
across all drivers were pulled into domain_conf.c
* src/conf/domain_conf.h, src/conf/domain_conf.c: Change
virDomainObjListPtr to use virHashTable. Add a initializer
method virDomainObjListInit, and rename virDomainObjListFree
to virDomainObjListDeinit, since its not actually freeing
the container, only its contents. Also add some convenient
methods virDomainObjListGetInactiveNames,
virDomainObjListGetActiveIDs and virDomainObjListNumOfDomains
which can be used to implement the correspondingly named
public API entry points in drivers
* src/libvirt_private.syms: Export new methods from domain_conf.h
* src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_conf.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c: Update all code
to deal with hash tables instead of arrays for domains
2009-10-09 11:33:51 +00:00
|
|
|
{
|
|
|
|
struct uml_driver *driver = opaque;
|
|
|
|
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectLock(dom);
|
2011-07-04 11:10:30 +00:00
|
|
|
if (virDomainObjIsActive(dom)) {
|
2011-07-13 11:21:54 +00:00
|
|
|
umlShutdownVMDaemon(driver, dom, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
|
2011-07-04 11:10:30 +00:00
|
|
|
virDomainAuditStop(dom, "shutdown");
|
|
|
|
}
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(dom);
|
2013-01-11 13:54:15 +00:00
|
|
|
return 0;
|
Convert virDomainObjListPtr to use a hash of domain objects
The current virDomainObjListPtr object stores domain objects in
an array. This means that to find a particular objects requires
O(n) time, and more critically acquiring O(n) mutex locks.
The new impl replaces the array with a virHashTable, keyed off
UUID. Finding a object based on UUID is now O(1) time, and only
requires a single mutex lock. Finding by name/id is unchanged
in complexity.
In changing this, all code which iterates over the array had
to be updated to use a hash table iterator function callback.
Several of the functions which were identically duplicating
across all drivers were pulled into domain_conf.c
* src/conf/domain_conf.h, src/conf/domain_conf.c: Change
virDomainObjListPtr to use virHashTable. Add a initializer
method virDomainObjListInit, and rename virDomainObjListFree
to virDomainObjListDeinit, since its not actually freeing
the container, only its contents. Also add some convenient
methods virDomainObjListGetInactiveNames,
virDomainObjListGetActiveIDs and virDomainObjListNumOfDomains
which can be used to implement the correspondingly named
public API entry points in drivers
* src/libvirt_private.syms: Export new methods from domain_conf.h
* src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_conf.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c: Update all code
to deal with hash tables instead of arrays for domains
2009-10-09 11:33:51 +00:00
|
|
|
}
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
/**
|
2013-04-23 12:50:18 +00:00
|
|
|
* umlStateCleanup:
|
2008-11-19 16:58:23 +00:00
|
|
|
*
|
|
|
|
* Shutdown the Uml daemon, it will stop all active domains and networks
|
|
|
|
*/
|
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
umlStateCleanup(void) {
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!uml_driver)
|
|
|
|
return -1;
|
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(uml_driver);
|
nwfilter: fix crash during filter define when lxc driver failed startup
The meat of this patch is just moving the calls to
virNWFilterRegisterCallbackDriver from each hypervisor's "register"
function into its "initialize" function. The rest is just code
movement to allow that, and a new virNWFilterUnRegisterCallbackDriver
function to undo what the register function does.
The long explanation:
There is an array in nwfilter called callbackDrvArray that has
pointers to a table of functions for each hypervisor driver that are
called by nwfilter. One of those function pointers is to a function
that will lock the hypervisor driver. Entries are added to the table
by calling each driver's "register" function, which happens quite
early in libvirtd's startup.
Sometime later, each driver's "initialize" function is called. This
function allocates a driver object and stores a pointer to it in a
static variable that was previously initialized to NULL. (and here's
the important part...) If the "initialize" function fails, the driver
object is freed, and that pointer set back to NULL (but the entry in
nwfilter's callbackDrvArray is still there).
When the "lock the driver" function mentioned above is called, it
assumes that the driver was successfully loaded, so it blindly tries
to call virMutexLock on "driver->lock".
BUT, if the initialize never happened, or if it failed, "driver" is
NULL. And it just happens that "lock" is always the first field in
driver so it is also NULL.
Boom.
To fix this, the call to virNWFilterRegisterCallbackDriver for each
driver shouldn't be called until the end of its (*already guaranteed
successful*) "initialize" function, not during its "register" function
(which is currently the case). This implies that there should also be
a virNWFilterUnregisterCallbackDriver() function that is called in a
driver's "shutdown" function (although in practice, that function is
currently never called).
2012-08-09 06:18:23 +00:00
|
|
|
virNWFilterRegisterCallbackDriver(¨CallbackDriver);
|
2009-01-29 17:50:00 +00:00
|
|
|
if (uml_driver->inotifyWatch != -1)
|
|
|
|
virEventRemoveHandle(uml_driver->inotifyWatch);
|
2010-11-09 20:48:48 +00:00
|
|
|
VIR_FORCE_CLOSE(uml_driver->inotifyFD);
|
2013-02-01 12:26:18 +00:00
|
|
|
virObjectUnref(uml_driver->caps);
|
2013-03-31 18:03:42 +00:00
|
|
|
virObjectUnref(uml_driver->xmlopt);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
Convert virDomainObjListPtr to use a hash of domain objects
The current virDomainObjListPtr object stores domain objects in
an array. This means that to find a particular objects requires
O(n) time, and more critically acquiring O(n) mutex locks.
The new impl replaces the array with a virHashTable, keyed off
UUID. Finding a object based on UUID is now O(1) time, and only
requires a single mutex lock. Finding by name/id is unchanged
in complexity.
In changing this, all code which iterates over the array had
to be updated to use a hash table iterator function callback.
Several of the functions which were identically duplicating
across all drivers were pulled into domain_conf.c
* src/conf/domain_conf.h, src/conf/domain_conf.c: Change
virDomainObjListPtr to use virHashTable. Add a initializer
method virDomainObjListInit, and rename virDomainObjListFree
to virDomainObjListDeinit, since its not actually freeing
the container, only its contents. Also add some convenient
methods virDomainObjListGetInactiveNames,
virDomainObjListGetActiveIDs and virDomainObjListNumOfDomains
which can be used to implement the correspondingly named
public API entry points in drivers
* src/libvirt_private.syms: Export new methods from domain_conf.h
* src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_conf.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c: Update all code
to deal with hash tables instead of arrays for domains
2009-10-09 11:33:51 +00:00
|
|
|
/* shutdown active VMs
|
|
|
|
* XXX allow them to stay around & reconnect */
|
2013-01-11 13:54:15 +00:00
|
|
|
virDomainObjListForEach(uml_driver->domains, umlShutdownOneVM, uml_driver);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2013-01-11 13:54:15 +00:00
|
|
|
virObjectUnref(uml_driver->domains);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2009-07-06 15:06:11 +00:00
|
|
|
virDomainEventStateFree(uml_driver->domainEventState);
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
VIR_FREE(uml_driver->logDir);
|
|
|
|
VIR_FREE(uml_driver->configDir);
|
|
|
|
VIR_FREE(uml_driver->autostartDir);
|
|
|
|
VIR_FREE(uml_driver->monitorDir);
|
|
|
|
|
2011-07-13 11:21:54 +00:00
|
|
|
umlProcessAutoDestroyShutdown(uml_driver);
|
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(uml_driver);
|
2009-01-15 19:56:05 +00:00
|
|
|
virMutexDestroy(¨_driver->lock);
|
2008-11-19 16:58:23 +00:00
|
|
|
VIR_FREE(uml_driver);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-07-13 11:21:54 +00:00
|
|
|
static int umlProcessAutoDestroyInit(struct uml_driver *driver)
|
|
|
|
{
|
|
|
|
if (!(driver->autodestroy = virHashCreate(5, NULL)))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct umlProcessAutoDestroyData {
|
|
|
|
struct uml_driver *driver;
|
|
|
|
virConnectPtr conn;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void umlProcessAutoDestroyDom(void *payload,
|
|
|
|
const void *name,
|
|
|
|
void *opaque)
|
|
|
|
{
|
|
|
|
struct umlProcessAutoDestroyData *data = opaque;
|
|
|
|
virConnectPtr conn = payload;
|
|
|
|
const char *uuidstr = name;
|
|
|
|
unsigned char uuid[VIR_UUID_BUFLEN];
|
|
|
|
virDomainObjPtr dom;
|
|
|
|
virDomainEventPtr event = NULL;
|
|
|
|
|
|
|
|
VIR_DEBUG("conn=%p uuidstr=%s thisconn=%p", conn, uuidstr, data->conn);
|
|
|
|
|
|
|
|
if (data->conn != conn)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (virUUIDParse(uuidstr, uuid) < 0) {
|
|
|
|
VIR_WARN("Failed to parse %s", uuidstr);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-01-11 16:04:47 +00:00
|
|
|
if (!(dom = virDomainObjListFindByUUID(data->driver->domains,
|
|
|
|
uuid))) {
|
2011-07-13 11:21:54 +00:00
|
|
|
VIR_DEBUG("No domain object to kill");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_DEBUG("Killing domain");
|
|
|
|
umlShutdownVMDaemon(data->driver, dom, VIR_DOMAIN_SHUTOFF_DESTROYED);
|
|
|
|
virDomainAuditStop(dom, "destroyed");
|
|
|
|
event = virDomainEventNewFromObj(dom,
|
|
|
|
VIR_DOMAIN_EVENT_STOPPED,
|
|
|
|
VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
|
|
|
|
|
|
|
|
if (dom && !dom->persistent)
|
2013-01-11 16:04:47 +00:00
|
|
|
virDomainObjListRemove(data->driver->domains, dom);
|
2011-07-13 11:21:54 +00:00
|
|
|
|
|
|
|
if (dom)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(dom);
|
2011-07-13 11:21:54 +00:00
|
|
|
if (event)
|
|
|
|
umlDomainEventQueue(data->driver, event);
|
|
|
|
virHashRemoveEntry(data->driver->autodestroy, uuidstr);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Precondition: driver is locked
|
|
|
|
*/
|
|
|
|
static void umlProcessAutoDestroyRun(struct uml_driver *driver, virConnectPtr conn)
|
|
|
|
{
|
|
|
|
struct umlProcessAutoDestroyData data = {
|
|
|
|
driver, conn
|
|
|
|
};
|
|
|
|
VIR_DEBUG("conn=%p", conn);
|
|
|
|
virHashForEach(driver->autodestroy, umlProcessAutoDestroyDom, &data);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void umlProcessAutoDestroyShutdown(struct uml_driver *driver)
|
|
|
|
{
|
|
|
|
virHashFree(driver->autodestroy);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int umlProcessAutoDestroyAdd(struct uml_driver *driver,
|
|
|
|
virDomainObjPtr vm,
|
|
|
|
virConnectPtr conn)
|
|
|
|
{
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(vm->def->uuid, uuidstr);
|
|
|
|
VIR_DEBUG("vm=%s uuid=%s conn=%p", vm->def->name, uuidstr, conn);
|
|
|
|
if (virHashAddEntry(driver->autodestroy, uuidstr, conn) < 0)
|
|
|
|
return -1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int umlProcessAutoDestroyRemove(struct uml_driver *driver,
|
|
|
|
virDomainObjPtr vm)
|
|
|
|
{
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(vm->def->uuid, uuidstr);
|
|
|
|
VIR_DEBUG("vm=%s uuid=%s", vm->def->name, uuidstr);
|
|
|
|
if (virHashRemoveEntry(driver->autodestroy, uuidstr) < 0)
|
|
|
|
return -1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-02-04 20:02:58 +00:00
|
|
|
static int umlReadPidFile(struct uml_driver *driver,
|
2008-11-19 16:58:23 +00:00
|
|
|
virDomainObjPtr vm)
|
|
|
|
{
|
|
|
|
int rc = -1;
|
|
|
|
FILE *file;
|
|
|
|
char *pidfile = NULL;
|
|
|
|
int retries = 0;
|
|
|
|
|
|
|
|
vm->pid = -1;
|
2008-12-23 13:03:29 +00:00
|
|
|
if (virAsprintf(&pidfile, "%s/%s/pid",
|
|
|
|
driver->monitorDir, vm->def->name) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-11-19 16:58:23 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
reopen:
|
|
|
|
if (!(file = fopen(pidfile, "r"))) {
|
|
|
|
if (errno == ENOENT &&
|
|
|
|
retries++ < 50) {
|
|
|
|
usleep(1000 * 100);
|
|
|
|
goto reopen;
|
|
|
|
}
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fscanf(file, "%d", &vm->pid) != 1) {
|
|
|
|
errno = EINVAL;
|
2010-11-17 02:13:29 +00:00
|
|
|
VIR_FORCE_FCLOSE(file);
|
2008-11-19 16:58:23 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2010-11-17 02:13:29 +00:00
|
|
|
if (VIR_FCLOSE(file) < 0)
|
2008-11-19 16:58:23 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
rc = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (rc != 0)
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("failed to read pid: %s"),
|
|
|
|
pidfile);
|
2008-11-19 16:58:23 +00:00
|
|
|
VIR_FREE(pidfile);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2010-04-03 13:33:29 +00:00
|
|
|
static int umlMonitorAddress(const struct uml_driver *driver,
|
2008-11-19 16:58:23 +00:00
|
|
|
virDomainObjPtr vm,
|
|
|
|
struct sockaddr_un *addr) {
|
|
|
|
char *sockname;
|
2009-08-03 12:37:44 +00:00
|
|
|
int retval = 0;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-23 13:03:29 +00:00
|
|
|
if (virAsprintf(&sockname, "%s/%s/mconsole",
|
|
|
|
driver->monitorDir, vm->def->name) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-11-19 16:58:23 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-03-29 09:52:04 +00:00
|
|
|
memset(addr, 0, sizeof(*addr));
|
2008-11-19 16:58:23 +00:00
|
|
|
addr->sun_family = AF_UNIX;
|
2009-08-03 12:37:44 +00:00
|
|
|
if (virStrcpyStatic(addr->sun_path, sockname) == NULL) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2009-08-03 12:37:44 +00:00
|
|
|
_("Unix path %s too long for destination"), sockname);
|
|
|
|
retval = -1;
|
|
|
|
}
|
2008-11-19 16:58:23 +00:00
|
|
|
VIR_FREE(sockname);
|
2009-08-03 12:37:44 +00:00
|
|
|
return retval;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
2010-04-03 13:33:29 +00:00
|
|
|
static int umlOpenMonitor(struct uml_driver *driver,
|
2008-11-19 16:58:23 +00:00
|
|
|
virDomainObjPtr vm) {
|
|
|
|
struct sockaddr_un addr;
|
|
|
|
struct stat sb;
|
|
|
|
int retries = 0;
|
2009-11-26 17:55:12 +00:00
|
|
|
umlDomainObjPrivatePtr priv = vm->privateData;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2010-04-03 13:33:29 +00:00
|
|
|
if (umlMonitorAddress(driver, vm, &addr) < 0)
|
2008-11-19 16:58:23 +00:00
|
|
|
return -1;
|
|
|
|
|
2009-06-03 10:55:33 +00:00
|
|
|
VIR_DEBUG("Dest address for monitor is '%s'", addr.sun_path);
|
2008-11-19 16:58:23 +00:00
|
|
|
restat:
|
|
|
|
if (stat(addr.sun_path, &sb) < 0) {
|
|
|
|
if (errno == ENOENT &&
|
2009-06-03 10:55:33 +00:00
|
|
|
retries++ < 50) {
|
2008-11-19 16:58:23 +00:00
|
|
|
usleep(1000 * 100);
|
|
|
|
goto restat;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2009-11-26 17:55:12 +00:00
|
|
|
if ((priv->monitor = socket(PF_UNIX, SOCK_DGRAM, 0)) < 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
"%s", _("cannot open socket"));
|
2008-11-19 16:58:23 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-03-29 09:52:04 +00:00
|
|
|
memset(addr.sun_path, 0, sizeof(addr.sun_path));
|
2010-08-18 23:31:39 +00:00
|
|
|
snprintf(addr.sun_path + 1, sizeof(addr.sun_path) - 1,
|
|
|
|
"libvirt-uml-%u", vm->pid);
|
2009-06-03 10:55:33 +00:00
|
|
|
VIR_DEBUG("Reply address for monitor is '%s'", addr.sun_path+1);
|
2012-03-29 09:52:04 +00:00
|
|
|
if (bind(priv->monitor, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
"%s", _("cannot bind socket"));
|
2010-11-09 20:48:48 +00:00
|
|
|
VIR_FORCE_CLOSE(priv->monitor);
|
2008-11-19 16:58:23 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define MONITOR_MAGIC 0xcafebabe
|
|
|
|
#define MONITOR_BUFLEN 512
|
|
|
|
#define MONITOR_VERSION 2
|
|
|
|
|
|
|
|
struct monitor_request {
|
|
|
|
uint32_t magic;
|
|
|
|
uint32_t version;
|
|
|
|
uint32_t length;
|
|
|
|
char data[MONITOR_BUFLEN];
|
|
|
|
};
|
|
|
|
|
|
|
|
struct monitor_response {
|
|
|
|
uint32_t error;
|
|
|
|
uint32_t extra;
|
|
|
|
uint32_t length;
|
|
|
|
char data[MONITOR_BUFLEN];
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2010-04-03 13:33:29 +00:00
|
|
|
static int umlMonitorCommand(const struct uml_driver *driver,
|
2008-11-19 16:58:23 +00:00
|
|
|
const virDomainObjPtr vm,
|
|
|
|
const char *cmd,
|
|
|
|
char **reply)
|
|
|
|
{
|
|
|
|
struct monitor_request req;
|
|
|
|
struct monitor_response res;
|
|
|
|
char *retdata = NULL;
|
|
|
|
int retlen = 0, ret = 0;
|
|
|
|
struct sockaddr_un addr;
|
|
|
|
unsigned int addrlen;
|
2009-11-26 17:55:12 +00:00
|
|
|
umlDomainObjPrivatePtr priv = vm->privateData;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2009-06-03 10:55:33 +00:00
|
|
|
VIR_DEBUG("Run command '%s'", cmd);
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
*reply = NULL;
|
|
|
|
|
2010-04-03 13:33:29 +00:00
|
|
|
if (umlMonitorAddress(driver, vm, &addr) < 0)
|
2008-11-19 16:58:23 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
|
|
req.magic = MONITOR_MAGIC;
|
|
|
|
req.version = MONITOR_VERSION;
|
|
|
|
req.length = strlen(cmd);
|
|
|
|
if (req.length > (MONITOR_BUFLEN-1)) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(EINVAL,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("cannot send too long command %s (%d bytes)"),
|
|
|
|
cmd, req.length);
|
2008-11-19 16:58:23 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2009-08-03 12:37:44 +00:00
|
|
|
if (virStrcpyStatic(req.data, cmd) == NULL) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2009-08-03 12:37:44 +00:00
|
|
|
_("Command %s too long for destination"), cmd);
|
|
|
|
return -1;
|
|
|
|
}
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2012-03-29 09:52:04 +00:00
|
|
|
if (sendto(priv->monitor, &req, sizeof(req), 0,
|
|
|
|
(struct sockaddr *)&addr, sizeof(addr)) != sizeof(req)) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("cannot send command %s"),
|
|
|
|
cmd);
|
2008-11-19 16:58:23 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
2010-03-03 00:16:05 +00:00
|
|
|
ssize_t nbytes;
|
2008-11-19 16:58:23 +00:00
|
|
|
addrlen = sizeof(addr);
|
2012-03-29 09:52:04 +00:00
|
|
|
nbytes = recvfrom(priv->monitor, &res, sizeof(res), 0,
|
2010-07-13 20:28:35 +00:00
|
|
|
(struct sockaddr *)&addr, &addrlen);
|
2010-03-03 00:16:05 +00:00
|
|
|
if (nbytes < 0) {
|
|
|
|
if (errno == EAGAIN || errno == EINTR)
|
|
|
|
continue;
|
2010-03-03 16:31:02 +00:00
|
|
|
virReportSystemError(errno, _("cannot read reply %s"), cmd);
|
2008-11-19 16:58:23 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2010-08-16 21:21:38 +00:00
|
|
|
/* Ensure res.length is safe to read before validating its value. */
|
|
|
|
if (nbytes < offsetof(struct monitor_request, data) ||
|
|
|
|
nbytes < offsetof(struct monitor_request, data) + res.length) {
|
2010-03-03 16:31:02 +00:00
|
|
|
virReportSystemError(0, _("incomplete reply %s"), cmd);
|
|
|
|
goto error;
|
|
|
|
}
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
if (VIR_REALLOC_N(retdata, retlen + res.length) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-11-19 16:58:23 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
memcpy(retdata + retlen, res.data, res.length);
|
|
|
|
retlen += res.length - 1;
|
|
|
|
retdata[retlen] = '\0';
|
|
|
|
|
|
|
|
if (res.error)
|
|
|
|
ret = -1;
|
|
|
|
|
|
|
|
} while (res.extra);
|
|
|
|
|
2009-06-03 10:55:33 +00:00
|
|
|
VIR_DEBUG("Command reply is '%s'", NULLSTR(retdata));
|
|
|
|
|
2010-02-15 18:22:38 +00:00
|
|
|
if (ret < 0)
|
|
|
|
VIR_FREE(retdata);
|
|
|
|
else
|
|
|
|
*reply = retdata;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
error:
|
|
|
|
VIR_FREE(retdata);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-02 12:00:28 +00:00
|
|
|
static void umlCleanupTapDevices(virDomainObjPtr vm) {
|
2009-06-03 11:13:33 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0 ; i < vm->def->nnets ; i++) {
|
|
|
|
virDomainNetDefPtr def = vm->def->nets[i];
|
|
|
|
|
|
|
|
if (def->type != VIR_DOMAIN_NET_TYPE_BRIDGE &&
|
|
|
|
def->type != VIR_DOMAIN_NET_TYPE_NETWORK)
|
|
|
|
continue;
|
|
|
|
|
2011-11-02 12:35:18 +00:00
|
|
|
ignore_value(virNetDevTapDelete(def->ifname));
|
2009-06-03 11:13:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
static int umlStartVMDaemon(virConnectPtr conn,
|
|
|
|
struct uml_driver *driver,
|
2011-07-13 11:21:54 +00:00
|
|
|
virDomainObjPtr vm,
|
|
|
|
bool autoDestroy) {
|
2011-10-20 13:57:10 +00:00
|
|
|
int ret = -1;
|
2008-11-19 16:58:23 +00:00
|
|
|
char *logfile;
|
|
|
|
int logfd = -1;
|
2009-11-26 17:55:12 +00:00
|
|
|
umlDomainObjPrivatePtr priv = vm->privateData;
|
2010-05-25 13:17:48 +00:00
|
|
|
virCommandPtr cmd = NULL;
|
2011-10-20 13:57:10 +00:00
|
|
|
size_t i;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
Rename internal APis
Rename virDomainIsActive to virDomainObjIsActive, and
virInterfaceIsActive to virInterfaceObjIsActive and finally
virNetworkIsActive to virNetworkObjIsActive.
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/conf/interface_conf.h, src/conf/network_conf.c,
src/conf/network_conf.h, src/lxc/lxc_driver.c,
src/network/bridge_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_driver.c, src/qemu/qemu_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c: Update for
renamed APIs.
2009-10-20 14:51:03 +00:00
|
|
|
if (virDomainObjIsActive(vm)) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
2010-04-03 13:33:29 +00:00
|
|
|
_("VM is already active"));
|
2008-11-19 16:58:23 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!vm->def->os.kernel) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
2010-04-03 13:33:29 +00:00
|
|
|
_("no kernel specified"));
|
2008-11-19 16:58:23 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
/* Make sure the binary we are about to try exec'ing exists.
|
|
|
|
* Technically we could catch the exec() failure, but that's
|
|
|
|
* in a sub-process so its hard to feed back a useful error
|
|
|
|
*/
|
2011-03-18 20:41:13 +00:00
|
|
|
if (!virFileIsExecutable(vm->def->os.kernel)) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("Cannot find UML kernel %s"),
|
|
|
|
vm->def->os.kernel);
|
2008-11-19 16:58:23 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-07-05 21:02:53 +00:00
|
|
|
if (virFileMakePath(driver->logDir) < 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("cannot create log directory %s"),
|
|
|
|
driver->logDir);
|
2008-11-19 16:58:23 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2008-12-23 13:03:29 +00:00
|
|
|
if (virAsprintf(&logfile, "%s/%s.log",
|
|
|
|
driver->logDir, vm->def->name) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-11-19 16:58:23 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((logfd = open(logfile, O_CREAT | O_TRUNC | O_WRONLY,
|
|
|
|
S_IRUSR | S_IWUSR)) < 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("failed to create logfile %s"),
|
|
|
|
logfile);
|
2008-11-19 16:58:23 +00:00
|
|
|
VIR_FREE(logfile);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
VIR_FREE(logfile);
|
|
|
|
|
2011-07-07 23:42:05 +00:00
|
|
|
if (virSetCloseExec(logfd) < 0) {
|
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("Unable to set VM logfile close-on-exec flag"));
|
2010-11-09 20:48:48 +00:00
|
|
|
VIR_FORCE_CLOSE(logfd);
|
2008-11-19 16:58:23 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-10-20 13:57:10 +00:00
|
|
|
/* Do this upfront, so any part of the startup process can add
|
|
|
|
* runtime state to vm->def that won't be persisted. This let's us
|
|
|
|
* report implicit runtime defaults in the XML, like vnc listen/socket
|
|
|
|
*/
|
|
|
|
VIR_DEBUG("Setting current domain def as transient");
|
2013-03-31 18:03:42 +00:00
|
|
|
if (virDomainObjSetDefTransient(driver->caps, driver->xmlopt,
|
2013-03-05 15:17:24 +00:00
|
|
|
vm, true) < 0) {
|
2011-10-20 13:57:10 +00:00
|
|
|
VIR_FORCE_CLOSE(logfd);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-11-30 05:57:10 +00:00
|
|
|
if (!(cmd = umlBuildCommandLine(conn, driver, vm)))
|
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2011-10-20 13:57:10 +00:00
|
|
|
for (i = 0 ; i < vm->def->nconsoles ; i++) {
|
|
|
|
VIR_FREE(vm->def->consoles[i]->info.alias);
|
|
|
|
if (virAsprintf(&vm->def->consoles[i]->info.alias, "console%zu", i) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-25 13:17:48 +00:00
|
|
|
virCommandWriteArgLog(cmd, logfd);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2009-11-26 17:55:12 +00:00
|
|
|
priv->monitor = -1;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2010-05-25 13:17:48 +00:00
|
|
|
virCommandClearCaps(cmd);
|
|
|
|
virCommandSetOutputFD(cmd, &logfd);
|
|
|
|
virCommandSetErrorFD(cmd, &logfd);
|
|
|
|
virCommandDaemonize(cmd);
|
|
|
|
|
|
|
|
ret = virCommandRun(cmd, NULL);
|
2010-11-19 18:36:29 +00:00
|
|
|
if (ret < 0)
|
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2011-07-13 11:21:54 +00:00
|
|
|
if (autoDestroy &&
|
2011-11-30 05:57:10 +00:00
|
|
|
(ret = umlProcessAutoDestroyAdd(driver, vm, conn)) < 0)
|
2011-07-13 11:21:54 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-03-31 18:03:42 +00:00
|
|
|
ret = virDomainObjSetDefTransient(driver->caps, driver->xmlopt, vm, false);
|
2010-11-19 18:36:29 +00:00
|
|
|
cleanup:
|
2011-11-30 05:57:10 +00:00
|
|
|
VIR_FORCE_CLOSE(logfd);
|
2010-05-25 13:17:48 +00:00
|
|
|
virCommandFree(cmd);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2010-09-07 08:19:56 +00:00
|
|
|
if (ret < 0) {
|
|
|
|
virDomainConfVMNWFilterTeardown(vm);
|
2011-07-13 11:21:54 +00:00
|
|
|
umlCleanupTapDevices(vm);
|
2011-10-20 13:57:10 +00:00
|
|
|
if (vm->newDef) {
|
|
|
|
virDomainDefFree(vm->def);
|
|
|
|
vm->def = vm->newDef;
|
|
|
|
vm->def->id = -1;
|
|
|
|
vm->newDef = NULL;
|
|
|
|
}
|
2010-09-07 08:19:56 +00:00
|
|
|
}
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
/* NB we don't mark it running here - we do that async
|
|
|
|
with inotify */
|
2009-06-03 11:13:33 +00:00
|
|
|
/* XXX what if someone else tries to start it again
|
|
|
|
before we get the inotification ? Sounds like
|
|
|
|
trouble.... */
|
2009-07-06 15:06:11 +00:00
|
|
|
/* XXX this is bad for events too. must fix this better */
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-07-13 11:21:54 +00:00
|
|
|
static void umlShutdownVMDaemon(struct uml_driver *driver,
|
2011-05-04 09:07:01 +00:00
|
|
|
virDomainObjPtr vm,
|
|
|
|
virDomainShutoffReason reason)
|
2008-11-19 16:58:23 +00:00
|
|
|
{
|
|
|
|
int ret;
|
2009-11-26 17:55:12 +00:00
|
|
|
umlDomainObjPrivatePtr priv = vm->privateData;
|
|
|
|
|
Rename internal APis
Rename virDomainIsActive to virDomainObjIsActive, and
virInterfaceIsActive to virInterfaceObjIsActive and finally
virNetworkIsActive to virNetworkObjIsActive.
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/conf/interface_conf.h, src/conf/network_conf.c,
src/conf/network_conf.h, src/lxc/lxc_driver.c,
src/network/bridge_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_driver.c, src/qemu/qemu_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c: Update for
renamed APIs.
2009-10-20 14:51:03 +00:00
|
|
|
if (!virDomainObjIsActive(vm))
|
2008-11-19 16:58:23 +00:00
|
|
|
return;
|
|
|
|
|
2012-09-24 15:29:20 +00:00
|
|
|
virProcessKill(vm->pid, SIGTERM);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2010-11-09 20:48:48 +00:00
|
|
|
VIR_FORCE_CLOSE(priv->monitor);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
if ((ret = waitpid(vm->pid, NULL, 0)) != vm->pid) {
|
2010-05-19 10:00:18 +00:00
|
|
|
VIR_WARN("Got unexpected pid %d != %d",
|
2008-11-19 16:58:23 +00:00
|
|
|
ret, vm->pid);
|
|
|
|
}
|
|
|
|
|
|
|
|
vm->pid = -1;
|
|
|
|
vm->def->id = -1;
|
2011-05-04 09:07:01 +00:00
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, reason);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2010-09-07 08:19:56 +00:00
|
|
|
virDomainConfVMNWFilterTeardown(vm);
|
2011-07-13 11:21:54 +00:00
|
|
|
umlCleanupTapDevices(vm);
|
|
|
|
|
|
|
|
/* Stop autodestroy in case guest is restarted */
|
|
|
|
umlProcessAutoDestroyRemove(driver, vm);
|
2009-06-03 11:13:33 +00:00
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
if (vm->newDef) {
|
|
|
|
virDomainDefFree(vm->def);
|
|
|
|
vm->def = vm->newDef;
|
|
|
|
vm->def->id = -1;
|
|
|
|
vm->newDef = NULL;
|
|
|
|
}
|
2012-10-31 19:03:55 +00:00
|
|
|
|
|
|
|
driver->nactive--;
|
|
|
|
if (!driver->nactive && driver->inhibitCallback)
|
|
|
|
driver->inhibitCallback(false, driver->inhibitOpaque);
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-04-23 12:50:18 +00:00
|
|
|
static virDrvOpenStatus umlConnectOpen(virConnectPtr conn,
|
|
|
|
virConnectAuthPtr auth ATTRIBUTE_UNUSED,
|
|
|
|
unsigned int flags)
|
2011-07-06 23:02:14 +00:00
|
|
|
{
|
|
|
|
virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
|
|
|
|
|
2009-06-12 12:06:15 +00:00
|
|
|
if (conn->uri == NULL) {
|
|
|
|
if (uml_driver == NULL)
|
|
|
|
return VIR_DRV_OPEN_DECLINED;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
Centralize error reporting for URI parsing/formatting problems
Move error reporting out of the callers, into virURIParse
and virURIFormat, to get consistency.
* include/libvirt/virterror.h, src/util/virterror.c: Add VIR_FROM_URI
* src/util/viruri.c, src/util/viruri.h: Add error reporting
* src/esx/esx_driver.c, src/libvirt.c, src/libxl/libxl_driver.c,
src/lxc/lxc_driver.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/qemu/qemu_migration.c,
src/remote/remote_driver.c, src/uml/uml_driver.c,
src/vbox/vbox_tmpl.c, src/vmx/vmx.c, src/xen/xen_driver.c,
src/xen/xend_internal.c, tests/viruritest.c: Remove error
reporting
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-03-20 12:16:54 +00:00
|
|
|
if (!(conn->uri = virURIParse(uml_driver->privileged ?
|
|
|
|
"uml:///system" :
|
|
|
|
"uml:///session")))
|
2009-06-12 12:06:15 +00:00
|
|
|
return VIR_DRV_OPEN_ERROR;
|
|
|
|
} else {
|
|
|
|
if (conn->uri->scheme == NULL ||
|
2012-10-17 09:23:12 +00:00
|
|
|
STRNEQ(conn->uri->scheme, "uml"))
|
2009-06-12 12:06:15 +00:00
|
|
|
return VIR_DRV_OPEN_DECLINED;
|
|
|
|
|
|
|
|
/* Allow remote driver to deal with URIs with hostname server */
|
|
|
|
if (conn->uri->server != NULL)
|
|
|
|
return VIR_DRV_OPEN_DECLINED;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
|
2009-06-12 12:06:15 +00:00
|
|
|
/* Check path and tell them correct path if they made a mistake */
|
2009-06-12 13:20:13 +00:00
|
|
|
if (uml_driver->privileged) {
|
2012-10-17 09:23:12 +00:00
|
|
|
if (STRNEQ(conn->uri->path, "/system") &&
|
|
|
|
STRNEQ(conn->uri->path, "/session")) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2009-06-12 12:06:15 +00:00
|
|
|
_("unexpected UML URI path '%s', try uml:///system"),
|
|
|
|
conn->uri->path);
|
|
|
|
return VIR_DRV_OPEN_ERROR;
|
|
|
|
}
|
|
|
|
} else {
|
2012-10-17 09:23:12 +00:00
|
|
|
if (STRNEQ(conn->uri->path, "/session")) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2009-06-12 12:06:15 +00:00
|
|
|
_("unexpected UML URI path '%s', try uml:///session"),
|
|
|
|
conn->uri->path);
|
|
|
|
return VIR_DRV_OPEN_ERROR;
|
|
|
|
}
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
2009-06-12 12:06:15 +00:00
|
|
|
|
|
|
|
/* URI was good, but driver isn't active */
|
|
|
|
if (uml_driver == NULL) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
2009-06-12 12:06:15 +00:00
|
|
|
_("uml state driver is not active"));
|
2008-11-19 16:58:23 +00:00
|
|
|
return VIR_DRV_OPEN_ERROR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
conn->privateData = uml_driver;
|
|
|
|
|
|
|
|
return VIR_DRV_OPEN_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2013-04-23 12:50:18 +00:00
|
|
|
static int umlConnectClose(virConnectPtr conn) {
|
2009-07-06 15:06:11 +00:00
|
|
|
struct uml_driver *driver = conn->privateData;
|
|
|
|
|
|
|
|
umlDriverLock(driver);
|
2011-07-13 11:21:54 +00:00
|
|
|
umlProcessAutoDestroyRun(driver, conn);
|
2009-07-06 15:06:11 +00:00
|
|
|
umlDriverUnlock(driver);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
conn->privateData = NULL;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-04-23 12:50:18 +00:00
|
|
|
static const char *umlConnectGetType(virConnectPtr conn ATTRIBUTE_UNUSED) {
|
2008-11-19 16:58:23 +00:00
|
|
|
return "UML";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-04-23 12:50:18 +00:00
|
|
|
static int umlConnectIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED)
|
Implmentation of new APIs to checking state/persistence of objects
This implements the virConnectIsSecure, virConnectIsEncrypted,
virDomainIsPersistent, virDomainIsActive, virNetworkIsActive,
virNetworkIsPersistent, virStoragePoolIsActive,
virStoragePoolIsPersistent, virInterfaceIsActive APIs in
(nearly) all drivers. Exceptions are:
phyp: missing domainIsActive/Persistent
esx: missing domainIsPersistent
opennebula: missing domainIsActive/Persistent
* src/remote/remote_protocol.x: Define remote wire ABI for newly
added APIs.
* daemon/remote_dispatch*.h: Re-generated from remote_protocol.x
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/opennebula/one_driver.c, src/openvz/openvz_conf.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/remote/remote_driver.c, src/storage/storage_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c, src/xen/xen_driver.h, src/xen/xen_inotify.c,
src/xen/xen_inotify.h: Implement all the new APIs where possible
2009-10-20 14:12:03 +00:00
|
|
|
{
|
|
|
|
/* Trivially secure, since always inside the daemon */
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-04-23 12:50:18 +00:00
|
|
|
static int umlConnectIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
|
Implmentation of new APIs to checking state/persistence of objects
This implements the virConnectIsSecure, virConnectIsEncrypted,
virDomainIsPersistent, virDomainIsActive, virNetworkIsActive,
virNetworkIsPersistent, virStoragePoolIsActive,
virStoragePoolIsPersistent, virInterfaceIsActive APIs in
(nearly) all drivers. Exceptions are:
phyp: missing domainIsActive/Persistent
esx: missing domainIsPersistent
opennebula: missing domainIsActive/Persistent
* src/remote/remote_protocol.x: Define remote wire ABI for newly
added APIs.
* daemon/remote_dispatch*.h: Re-generated from remote_protocol.x
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/opennebula/one_driver.c, src/openvz/openvz_conf.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/remote/remote_driver.c, src/storage/storage_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c, src/xen/xen_driver.h, src/xen/xen_inotify.c,
src/xen/xen_inotify.h: Implement all the new APIs where possible
2009-10-20 14:12:03 +00:00
|
|
|
{
|
|
|
|
/* Not encrypted, but remote driver takes care of that */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-04-23 12:50:18 +00:00
|
|
|
static int umlConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
|
2011-09-23 06:56:13 +00:00
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-04-23 12:50:18 +00:00
|
|
|
static char *umlConnectGetCapabilities(virConnectPtr conn) {
|
2008-11-19 16:58:23 +00:00
|
|
|
struct uml_driver *driver = (struct uml_driver *)conn->privateData;
|
|
|
|
char *xml;
|
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2008-12-04 21:13:58 +00:00
|
|
|
if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL)
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
return xml;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
build: use correct type for pid and similar types
No thanks to 64-bit windows, with 64-bit pid_t, we have to avoid
constructs like 'int pid'. Our API in libvirt-qemu cannot be
changed without breaking ABI; but then again, libvirt-qemu can
only be used on systems that support UNIX sockets, which rules
out Windows (even if qemu could be compiled there) - so for all
points on the call chain that interact with this API decision,
we require a different variable name to make it clear that we
audited the use for safety.
Adding a syntax-check rule only solves half the battle; anywhere
that uses printf on a pid_t still needs to be converted, but that
will be a separate patch.
* cfg.mk (sc_correct_id_types): New syntax check.
* src/libvirt-qemu.c (virDomainQemuAttach): Document why we didn't
use pid_t for pid, and validate for overflow.
* include/libvirt/libvirt-qemu.h (virDomainQemuAttach): Tweak name
for syntax check.
* src/vmware/vmware_conf.c (vmwareExtractPid): Likewise.
* src/driver.h (virDrvDomainQemuAttach): Likewise.
* tools/virsh.c (cmdQemuAttach): Likewise.
* src/remote/qemu_protocol.x (qemu_domain_attach_args): Likewise.
* src/qemu_protocol-structs (qemu_domain_attach_args): Likewise.
* src/util/cgroup.c (virCgroupPidCode, virCgroupKillInternal):
Likewise.
* src/qemu/qemu_command.c(qemuParseProcFileStrings): Likewise.
(qemuParseCommandLinePid): Use pid_t for pid.
* daemon/libvirtd.c (daemonForkIntoBackground): Likewise.
* src/conf/domain_conf.h (_virDomainObj): Likewise.
* src/probes.d (rpc_socket_new): Likewise.
* src/qemu/qemu_command.h (qemuParseCommandLinePid): Likewise.
* src/qemu/qemu_driver.c (qemudGetProcessInfo, qemuDomainAttach):
Likewise.
* src/qemu/qemu_process.c (qemuProcessAttach): Likewise.
* src/qemu/qemu_process.h (qemuProcessAttach): Likewise.
* src/uml/uml_driver.c (umlGetProcessInfo): Likewise.
* src/util/virnetdev.h (virNetDevSetNamespace): Likewise.
* src/util/virnetdev.c (virNetDevSetNamespace): Likewise.
* tests/testutils.c (virtTestCaptureProgramOutput): Likewise.
* src/conf/storage_conf.h (_virStoragePerms): Use mode_t, uid_t,
and gid_t rather than int.
* src/security/security_dac.c (virSecurityDACSetOwnership): Likewise.
* src/conf/storage_conf.c (virStorageDefParsePerms): Avoid
compiler warning.
2012-02-10 23:08:11 +00:00
|
|
|
static int umlGetProcessInfo(unsigned long long *cpuTime, pid_t pid)
|
2011-04-03 09:21:31 +00:00
|
|
|
{
|
|
|
|
char *proc;
|
2008-11-19 16:58:23 +00:00
|
|
|
FILE *pidinfo;
|
|
|
|
unsigned long long usertime, systime;
|
|
|
|
|
build: use correct type for pid and similar types
No thanks to 64-bit windows, with 64-bit pid_t, we have to avoid
constructs like 'int pid'. Our API in libvirt-qemu cannot be
changed without breaking ABI; but then again, libvirt-qemu can
only be used on systems that support UNIX sockets, which rules
out Windows (even if qemu could be compiled there) - so for all
points on the call chain that interact with this API decision,
we require a different variable name to make it clear that we
audited the use for safety.
Adding a syntax-check rule only solves half the battle; anywhere
that uses printf on a pid_t still needs to be converted, but that
will be a separate patch.
* cfg.mk (sc_correct_id_types): New syntax check.
* src/libvirt-qemu.c (virDomainQemuAttach): Document why we didn't
use pid_t for pid, and validate for overflow.
* include/libvirt/libvirt-qemu.h (virDomainQemuAttach): Tweak name
for syntax check.
* src/vmware/vmware_conf.c (vmwareExtractPid): Likewise.
* src/driver.h (virDrvDomainQemuAttach): Likewise.
* tools/virsh.c (cmdQemuAttach): Likewise.
* src/remote/qemu_protocol.x (qemu_domain_attach_args): Likewise.
* src/qemu_protocol-structs (qemu_domain_attach_args): Likewise.
* src/util/cgroup.c (virCgroupPidCode, virCgroupKillInternal):
Likewise.
* src/qemu/qemu_command.c(qemuParseProcFileStrings): Likewise.
(qemuParseCommandLinePid): Use pid_t for pid.
* daemon/libvirtd.c (daemonForkIntoBackground): Likewise.
* src/conf/domain_conf.h (_virDomainObj): Likewise.
* src/probes.d (rpc_socket_new): Likewise.
* src/qemu/qemu_command.h (qemuParseCommandLinePid): Likewise.
* src/qemu/qemu_driver.c (qemudGetProcessInfo, qemuDomainAttach):
Likewise.
* src/qemu/qemu_process.c (qemuProcessAttach): Likewise.
* src/qemu/qemu_process.h (qemuProcessAttach): Likewise.
* src/uml/uml_driver.c (umlGetProcessInfo): Likewise.
* src/util/virnetdev.h (virNetDevSetNamespace): Likewise.
* src/util/virnetdev.c (virNetDevSetNamespace): Likewise.
* tests/testutils.c (virtTestCaptureProgramOutput): Likewise.
* src/conf/storage_conf.h (_virStoragePerms): Use mode_t, uid_t,
and gid_t rather than int.
* src/security/security_dac.c (virSecurityDACSetOwnership): Likewise.
* src/conf/storage_conf.c (virStorageDefParsePerms): Avoid
compiler warning.
2012-02-10 23:08:11 +00:00
|
|
|
if (virAsprintf(&proc, "/proc/%lld/stat", (long long) pid) < 0) {
|
2008-11-19 16:58:23 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(pidinfo = fopen(proc, "r"))) {
|
|
|
|
/* VM probably shut down, so fake 0 */
|
|
|
|
*cpuTime = 0;
|
2011-04-03 09:21:31 +00:00
|
|
|
VIR_FREE(proc);
|
2008-11-19 16:58:23 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-04-03 09:21:31 +00:00
|
|
|
VIR_FREE(proc);
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
if (fscanf(pidinfo, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %llu %llu", &usertime, &systime) != 2) {
|
|
|
|
umlDebug("not enough arg");
|
2010-11-17 02:13:29 +00:00
|
|
|
VIR_FORCE_FCLOSE(pidinfo);
|
2008-11-19 16:58:23 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We got jiffies
|
|
|
|
* We want nanoseconds
|
|
|
|
* _SC_CLK_TCK is jiffies per second
|
|
|
|
* So calulate thus....
|
|
|
|
*/
|
|
|
|
*cpuTime = 1000ull * 1000ull * 1000ull * (usertime + systime) / (unsigned long long)sysconf(_SC_CLK_TCK);
|
|
|
|
|
|
|
|
umlDebug("Got %llu %llu %llu", usertime, systime, *cpuTime);
|
|
|
|
|
2010-11-17 02:13:29 +00:00
|
|
|
VIR_FORCE_FCLOSE(pidinfo);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static virDomainPtr umlDomainLookupByID(virConnectPtr conn,
|
|
|
|
int id) {
|
|
|
|
struct uml_driver *driver = (struct uml_driver *)conn->privateData;
|
2008-12-04 21:13:58 +00:00
|
|
|
virDomainObjPtr vm;
|
|
|
|
virDomainPtr dom = NULL;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2013-01-11 16:04:47 +00:00
|
|
|
vm = virDomainObjListFindByID(driver->domains, id);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!vm) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, NULL);
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
|
|
|
if (dom) dom->id = vm->def->id;
|
2008-12-04 21:13:58 +00:00
|
|
|
|
|
|
|
cleanup:
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(vm);
|
2008-11-19 16:58:23 +00:00
|
|
|
return dom;
|
|
|
|
}
|
2008-12-04 21:13:58 +00:00
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
static virDomainPtr umlDomainLookupByUUID(virConnectPtr conn,
|
|
|
|
const unsigned char *uuid) {
|
|
|
|
struct uml_driver *driver = (struct uml_driver *)conn->privateData;
|
2008-12-04 21:13:58 +00:00
|
|
|
virDomainObjPtr vm;
|
|
|
|
virDomainPtr dom = NULL;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2013-01-11 16:04:47 +00:00
|
|
|
vm = virDomainObjListFindByUUID(driver->domains, uuid);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!vm) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, NULL);
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
|
|
|
if (dom) dom->id = vm->def->id;
|
2008-12-04 21:13:58 +00:00
|
|
|
|
|
|
|
cleanup:
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(vm);
|
2008-11-19 16:58:23 +00:00
|
|
|
return dom;
|
|
|
|
}
|
2008-12-04 21:13:58 +00:00
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
static virDomainPtr umlDomainLookupByName(virConnectPtr conn,
|
|
|
|
const char *name) {
|
|
|
|
struct uml_driver *driver = (struct uml_driver *)conn->privateData;
|
2008-12-04 21:13:58 +00:00
|
|
|
virDomainObjPtr vm;
|
|
|
|
virDomainPtr dom = NULL;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2013-01-11 16:04:47 +00:00
|
|
|
vm = virDomainObjListFindByName(driver->domains, name);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!vm) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, NULL);
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
|
|
|
if (dom) dom->id = vm->def->id;
|
2008-12-04 21:13:58 +00:00
|
|
|
|
|
|
|
cleanup:
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(vm);
|
2008-11-19 16:58:23 +00:00
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
Implmentation of new APIs to checking state/persistence of objects
This implements the virConnectIsSecure, virConnectIsEncrypted,
virDomainIsPersistent, virDomainIsActive, virNetworkIsActive,
virNetworkIsPersistent, virStoragePoolIsActive,
virStoragePoolIsPersistent, virInterfaceIsActive APIs in
(nearly) all drivers. Exceptions are:
phyp: missing domainIsActive/Persistent
esx: missing domainIsPersistent
opennebula: missing domainIsActive/Persistent
* src/remote/remote_protocol.x: Define remote wire ABI for newly
added APIs.
* daemon/remote_dispatch*.h: Re-generated from remote_protocol.x
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/opennebula/one_driver.c, src/openvz/openvz_conf.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/remote/remote_driver.c, src/storage/storage_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c, src/xen/xen_driver.h, src/xen/xen_inotify.c,
src/xen/xen_inotify.h: Implement all the new APIs where possible
2009-10-20 14:12:03 +00:00
|
|
|
|
|
|
|
static int umlDomainIsActive(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr obj;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
umlDriverLock(driver);
|
2013-01-11 16:04:47 +00:00
|
|
|
obj = virDomainObjListFindByUUID(driver->domains, dom->uuid);
|
Implmentation of new APIs to checking state/persistence of objects
This implements the virConnectIsSecure, virConnectIsEncrypted,
virDomainIsPersistent, virDomainIsActive, virNetworkIsActive,
virNetworkIsPersistent, virStoragePoolIsActive,
virStoragePoolIsPersistent, virInterfaceIsActive APIs in
(nearly) all drivers. Exceptions are:
phyp: missing domainIsActive/Persistent
esx: missing domainIsPersistent
opennebula: missing domainIsActive/Persistent
* src/remote/remote_protocol.x: Define remote wire ABI for newly
added APIs.
* daemon/remote_dispatch*.h: Re-generated from remote_protocol.x
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/opennebula/one_driver.c, src/openvz/openvz_conf.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/remote/remote_driver.c, src/storage/storage_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c, src/xen/xen_driver.h, src/xen/xen_inotify.c,
src/xen/xen_inotify.h: Implement all the new APIs where possible
2009-10-20 14:12:03 +00:00
|
|
|
umlDriverUnlock(driver);
|
|
|
|
if (!obj) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, NULL);
|
Implmentation of new APIs to checking state/persistence of objects
This implements the virConnectIsSecure, virConnectIsEncrypted,
virDomainIsPersistent, virDomainIsActive, virNetworkIsActive,
virNetworkIsPersistent, virStoragePoolIsActive,
virStoragePoolIsPersistent, virInterfaceIsActive APIs in
(nearly) all drivers. Exceptions are:
phyp: missing domainIsActive/Persistent
esx: missing domainIsPersistent
opennebula: missing domainIsActive/Persistent
* src/remote/remote_protocol.x: Define remote wire ABI for newly
added APIs.
* daemon/remote_dispatch*.h: Re-generated from remote_protocol.x
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/opennebula/one_driver.c, src/openvz/openvz_conf.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/remote/remote_driver.c, src/storage/storage_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c, src/xen/xen_driver.h, src/xen/xen_inotify.c,
src/xen/xen_inotify.h: Implement all the new APIs where possible
2009-10-20 14:12:03 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
ret = virDomainObjIsActive(obj);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (obj)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(obj);
|
Implmentation of new APIs to checking state/persistence of objects
This implements the virConnectIsSecure, virConnectIsEncrypted,
virDomainIsPersistent, virDomainIsActive, virNetworkIsActive,
virNetworkIsPersistent, virStoragePoolIsActive,
virStoragePoolIsPersistent, virInterfaceIsActive APIs in
(nearly) all drivers. Exceptions are:
phyp: missing domainIsActive/Persistent
esx: missing domainIsPersistent
opennebula: missing domainIsActive/Persistent
* src/remote/remote_protocol.x: Define remote wire ABI for newly
added APIs.
* daemon/remote_dispatch*.h: Re-generated from remote_protocol.x
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/opennebula/one_driver.c, src/openvz/openvz_conf.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/remote/remote_driver.c, src/storage/storage_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c, src/xen/xen_driver.h, src/xen/xen_inotify.c,
src/xen/xen_inotify.h: Implement all the new APIs where possible
2009-10-20 14:12:03 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int umlDomainIsPersistent(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr obj;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
umlDriverLock(driver);
|
2013-01-11 16:04:47 +00:00
|
|
|
obj = virDomainObjListFindByUUID(driver->domains, dom->uuid);
|
Implmentation of new APIs to checking state/persistence of objects
This implements the virConnectIsSecure, virConnectIsEncrypted,
virDomainIsPersistent, virDomainIsActive, virNetworkIsActive,
virNetworkIsPersistent, virStoragePoolIsActive,
virStoragePoolIsPersistent, virInterfaceIsActive APIs in
(nearly) all drivers. Exceptions are:
phyp: missing domainIsActive/Persistent
esx: missing domainIsPersistent
opennebula: missing domainIsActive/Persistent
* src/remote/remote_protocol.x: Define remote wire ABI for newly
added APIs.
* daemon/remote_dispatch*.h: Re-generated from remote_protocol.x
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/opennebula/one_driver.c, src/openvz/openvz_conf.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/remote/remote_driver.c, src/storage/storage_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c, src/xen/xen_driver.h, src/xen/xen_inotify.c,
src/xen/xen_inotify.h: Implement all the new APIs where possible
2009-10-20 14:12:03 +00:00
|
|
|
umlDriverUnlock(driver);
|
|
|
|
if (!obj) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, NULL);
|
Implmentation of new APIs to checking state/persistence of objects
This implements the virConnectIsSecure, virConnectIsEncrypted,
virDomainIsPersistent, virDomainIsActive, virNetworkIsActive,
virNetworkIsPersistent, virStoragePoolIsActive,
virStoragePoolIsPersistent, virInterfaceIsActive APIs in
(nearly) all drivers. Exceptions are:
phyp: missing domainIsActive/Persistent
esx: missing domainIsPersistent
opennebula: missing domainIsActive/Persistent
* src/remote/remote_protocol.x: Define remote wire ABI for newly
added APIs.
* daemon/remote_dispatch*.h: Re-generated from remote_protocol.x
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/opennebula/one_driver.c, src/openvz/openvz_conf.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/remote/remote_driver.c, src/storage/storage_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c, src/xen/xen_driver.h, src/xen/xen_inotify.c,
src/xen/xen_inotify.h: Implement all the new APIs where possible
2009-10-20 14:12:03 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
ret = obj->persistent;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (obj)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(obj);
|
Implmentation of new APIs to checking state/persistence of objects
This implements the virConnectIsSecure, virConnectIsEncrypted,
virDomainIsPersistent, virDomainIsActive, virNetworkIsActive,
virNetworkIsPersistent, virStoragePoolIsActive,
virStoragePoolIsPersistent, virInterfaceIsActive APIs in
(nearly) all drivers. Exceptions are:
phyp: missing domainIsActive/Persistent
esx: missing domainIsPersistent
opennebula: missing domainIsActive/Persistent
* src/remote/remote_protocol.x: Define remote wire ABI for newly
added APIs.
* daemon/remote_dispatch*.h: Re-generated from remote_protocol.x
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/opennebula/one_driver.c, src/openvz/openvz_conf.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/remote/remote_driver.c, src/storage/storage_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c, src/xen/xen_driver.h, src/xen/xen_inotify.c,
src/xen/xen_inotify.h: Implement all the new APIs where possible
2009-10-20 14:12:03 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-11-24 07:43:15 +00:00
|
|
|
static int umlDomainIsUpdated(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr obj;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
umlDriverLock(driver);
|
2013-01-11 16:04:47 +00:00
|
|
|
obj = virDomainObjListFindByUUID(driver->domains, dom->uuid);
|
2010-11-24 07:43:15 +00:00
|
|
|
umlDriverUnlock(driver);
|
|
|
|
if (!obj) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, NULL);
|
2010-11-24 07:43:15 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
ret = obj->updated;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (obj)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(obj);
|
2010-11-24 07:43:15 +00:00
|
|
|
return ret;
|
|
|
|
}
|
Implmentation of new APIs to checking state/persistence of objects
This implements the virConnectIsSecure, virConnectIsEncrypted,
virDomainIsPersistent, virDomainIsActive, virNetworkIsActive,
virNetworkIsPersistent, virStoragePoolIsActive,
virStoragePoolIsPersistent, virInterfaceIsActive APIs in
(nearly) all drivers. Exceptions are:
phyp: missing domainIsActive/Persistent
esx: missing domainIsPersistent
opennebula: missing domainIsActive/Persistent
* src/remote/remote_protocol.x: Define remote wire ABI for newly
added APIs.
* daemon/remote_dispatch*.h: Re-generated from remote_protocol.x
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/opennebula/one_driver.c, src/openvz/openvz_conf.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/remote/remote_driver.c, src/storage/storage_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c, src/xen/xen_driver.h, src/xen/xen_inotify.c,
src/xen/xen_inotify.h: Implement all the new APIs where possible
2009-10-20 14:12:03 +00:00
|
|
|
|
2013-04-23 12:50:18 +00:00
|
|
|
static int umlConnectGetVersion(virConnectPtr conn, unsigned long *version) {
|
2008-12-04 21:14:39 +00:00
|
|
|
struct uml_driver *driver = conn->privateData;
|
2008-11-19 16:58:23 +00:00
|
|
|
struct utsname ut;
|
2008-12-04 21:14:39 +00:00
|
|
|
int ret = -1;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2010-03-30 14:15:13 +00:00
|
|
|
|
|
|
|
if (driver->umlVersion == 0) {
|
|
|
|
uname(&ut);
|
|
|
|
|
2011-07-01 13:23:02 +00:00
|
|
|
if (virParseVersionString(ut.release, &driver->umlVersion, true) < 0) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2010-03-30 14:15:13 +00:00
|
|
|
_("cannot parse version %s"), ut.release);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
*version = driver->umlVersion;
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
umlDriverUnlock(driver);
|
|
|
|
return ret;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
2013-04-23 12:50:18 +00:00
|
|
|
static int umlConnectListDomains(virConnectPtr conn, int *ids, int nids) {
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = conn->privateData;
|
Convert virDomainObjListPtr to use a hash of domain objects
The current virDomainObjListPtr object stores domain objects in
an array. This means that to find a particular objects requires
O(n) time, and more critically acquiring O(n) mutex locks.
The new impl replaces the array with a virHashTable, keyed off
UUID. Finding a object based on UUID is now O(1) time, and only
requires a single mutex lock. Finding by name/id is unchanged
in complexity.
In changing this, all code which iterates over the array had
to be updated to use a hash table iterator function callback.
Several of the functions which were identically duplicating
across all drivers were pulled into domain_conf.c
* src/conf/domain_conf.h, src/conf/domain_conf.c: Change
virDomainObjListPtr to use virHashTable. Add a initializer
method virDomainObjListInit, and rename virDomainObjListFree
to virDomainObjListDeinit, since its not actually freeing
the container, only its contents. Also add some convenient
methods virDomainObjListGetInactiveNames,
virDomainObjListGetActiveIDs and virDomainObjListNumOfDomains
which can be used to implement the correspondingly named
public API entry points in drivers
* src/libvirt_private.syms: Export new methods from domain_conf.h
* src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_conf.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c: Update all code
to deal with hash tables instead of arrays for domains
2009-10-09 11:33:51 +00:00
|
|
|
int n;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2013-01-11 16:04:47 +00:00
|
|
|
n = virDomainObjListGetActiveIDs(driver->domains, ids, nids);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
Convert virDomainObjListPtr to use a hash of domain objects
The current virDomainObjListPtr object stores domain objects in
an array. This means that to find a particular objects requires
O(n) time, and more critically acquiring O(n) mutex locks.
The new impl replaces the array with a virHashTable, keyed off
UUID. Finding a object based on UUID is now O(1) time, and only
requires a single mutex lock. Finding by name/id is unchanged
in complexity.
In changing this, all code which iterates over the array had
to be updated to use a hash table iterator function callback.
Several of the functions which were identically duplicating
across all drivers were pulled into domain_conf.c
* src/conf/domain_conf.h, src/conf/domain_conf.c: Change
virDomainObjListPtr to use virHashTable. Add a initializer
method virDomainObjListInit, and rename virDomainObjListFree
to virDomainObjListDeinit, since its not actually freeing
the container, only its contents. Also add some convenient
methods virDomainObjListGetInactiveNames,
virDomainObjListGetActiveIDs and virDomainObjListNumOfDomains
which can be used to implement the correspondingly named
public API entry points in drivers
* src/libvirt_private.syms: Export new methods from domain_conf.h
* src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_conf.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c: Update all code
to deal with hash tables instead of arrays for domains
2009-10-09 11:33:51 +00:00
|
|
|
return n;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
2013-04-23 12:50:18 +00:00
|
|
|
static int umlConnectNumOfDomains(virConnectPtr conn) {
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = conn->privateData;
|
Convert virDomainObjListPtr to use a hash of domain objects
The current virDomainObjListPtr object stores domain objects in
an array. This means that to find a particular objects requires
O(n) time, and more critically acquiring O(n) mutex locks.
The new impl replaces the array with a virHashTable, keyed off
UUID. Finding a object based on UUID is now O(1) time, and only
requires a single mutex lock. Finding by name/id is unchanged
in complexity.
In changing this, all code which iterates over the array had
to be updated to use a hash table iterator function callback.
Several of the functions which were identically duplicating
across all drivers were pulled into domain_conf.c
* src/conf/domain_conf.h, src/conf/domain_conf.c: Change
virDomainObjListPtr to use virHashTable. Add a initializer
method virDomainObjListInit, and rename virDomainObjListFree
to virDomainObjListDeinit, since its not actually freeing
the container, only its contents. Also add some convenient
methods virDomainObjListGetInactiveNames,
virDomainObjListGetActiveIDs and virDomainObjListNumOfDomains
which can be used to implement the correspondingly named
public API entry points in drivers
* src/libvirt_private.syms: Export new methods from domain_conf.h
* src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_conf.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c: Update all code
to deal with hash tables instead of arrays for domains
2009-10-09 11:33:51 +00:00
|
|
|
int n;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2013-01-11 16:04:47 +00:00
|
|
|
n = virDomainObjListNumOfDomains(driver->domains, 1);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
2013-04-23 12:50:18 +00:00
|
|
|
static virDomainPtr umlDomainCreateXML(virConnectPtr conn, const char *xml,
|
|
|
|
unsigned int flags) {
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = conn->privateData;
|
2008-11-19 16:58:23 +00:00
|
|
|
virDomainDefPtr def;
|
2008-12-04 21:14:39 +00:00
|
|
|
virDomainObjPtr vm = NULL;
|
2008-12-04 21:13:58 +00:00
|
|
|
virDomainPtr dom = NULL;
|
2009-07-06 15:06:11 +00:00
|
|
|
virDomainEventPtr event = NULL;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2011-07-13 11:21:54 +00:00
|
|
|
virCheckFlags(VIR_DOMAIN_START_AUTODESTROY, NULL);
|
2010-05-25 17:13:13 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2013-03-28 13:55:55 +00:00
|
|
|
if (!(def = virDomainDefParseString(xml, driver->caps, driver->xmlopt,
|
|
|
|
1 << VIR_DOMAIN_VIRT_UML,
|
2009-01-08 13:54:20 +00:00
|
|
|
VIR_DOMAIN_XML_INACTIVE)))
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2013-03-28 13:55:55 +00:00
|
|
|
if (!(vm = virDomainObjListAdd(driver->domains, def,
|
2013-03-31 18:03:42 +00:00
|
|
|
driver->xmlopt,
|
Merge virDomainObjListIsDuplicate into virDomainObjListAdd
The duplicate VM checking should be done atomically with
virDomainObjListAdd, so shoud not be a separate function.
Instead just use flags to indicate what kind of checks are
required.
This pair, used in virDomainCreateXML:
if (virDomainObjListIsDuplicate(privconn->domains, def, 1) < 0)
goto cleanup;
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def, false)))
goto cleanup;
Changes to
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def,
VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
NULL)))
goto cleanup;
This pair, used in virDomainRestoreFlags:
if (virDomainObjListIsDuplicate(privconn->domains, def, 1) < 0)
goto cleanup;
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def, true)))
goto cleanup;
Changes to
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def,
VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
NULL)))
goto cleanup;
This pair, used in virDomainDefineXML:
if (virDomainObjListIsDuplicate(privconn->domains, def, 0) < 0)
goto cleanup;
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def, false)))
goto cleanup;
Changes to
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def,
0, NULL)))
goto cleanup;
2013-01-14 14:46:58 +00:00
|
|
|
VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
|
|
|
|
NULL)))
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
|
|
|
def = NULL;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2011-07-13 11:21:54 +00:00
|
|
|
if (umlStartVMDaemon(conn, driver, vm,
|
|
|
|
(flags & VIR_DOMAIN_START_AUTODESTROY)) < 0) {
|
2011-07-04 11:10:30 +00:00
|
|
|
virDomainAuditStart(vm, "booted", false);
|
2013-01-11 16:04:47 +00:00
|
|
|
virDomainObjListRemove(driver->domains,
|
|
|
|
vm);
|
2008-12-04 21:13:58 +00:00
|
|
|
vm = NULL;
|
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
2011-07-04 11:10:30 +00:00
|
|
|
virDomainAuditStart(vm, "booted", true);
|
2009-07-06 15:06:11 +00:00
|
|
|
event = virDomainEventNewFromObj(vm,
|
|
|
|
VIR_DOMAIN_EVENT_STARTED,
|
|
|
|
VIR_DOMAIN_EVENT_STARTED_BOOTED);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
|
|
|
if (dom) dom->id = vm->def->id;
|
2008-12-04 21:13:58 +00:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virDomainDefFree(def);
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(vm);
|
2009-07-06 15:06:11 +00:00
|
|
|
if (event)
|
|
|
|
umlDomainEventQueue(driver, event);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
2008-11-19 16:58:23 +00:00
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-05 17:31:55 +00:00
|
|
|
static int umlDomainShutdownFlags(virDomainPtr dom,
|
|
|
|
unsigned int flags) {
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
2008-12-01 11:08:16 +00:00
|
|
|
char *info = NULL;
|
2008-12-04 21:13:58 +00:00
|
|
|
int ret = -1;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2011-10-05 17:31:55 +00:00
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2013-01-11 16:04:47 +00:00
|
|
|
vm = virDomainObjListFindByID(driver->domains, dom->id);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!vm) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
2010-04-03 13:33:29 +00:00
|
|
|
_("no domain with matching id %d"), dom->id);
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
if (umlMonitorCommand(driver, vm, "system_powerdown", &info) < 0) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
|
2010-04-03 13:33:29 +00:00
|
|
|
_("shutdown operation failed"));
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
2008-12-04 21:13:58 +00:00
|
|
|
ret = 0;
|
2008-11-19 16:58:23 +00:00
|
|
|
#endif
|
|
|
|
|
2008-12-04 21:13:58 +00:00
|
|
|
cleanup:
|
|
|
|
VIR_FREE(info);
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(vm);
|
2008-12-04 21:13:58 +00:00
|
|
|
return ret;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
2011-10-05 17:31:55 +00:00
|
|
|
static int
|
|
|
|
umlDomainShutdown(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
return umlDomainShutdownFlags(dom, 0);
|
|
|
|
}
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2011-07-21 07:54:28 +00:00
|
|
|
static int
|
|
|
|
umlDomainDestroyFlags(virDomainPtr dom,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
2009-07-06 15:06:11 +00:00
|
|
|
virDomainEventPtr event = NULL;
|
2008-12-04 21:13:58 +00:00
|
|
|
int ret = -1;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2011-07-21 07:54:28 +00:00
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2013-01-11 16:04:47 +00:00
|
|
|
vm = virDomainObjListFindByID(driver->domains, dom->id);
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!vm) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
2010-04-03 13:33:29 +00:00
|
|
|
_("no domain with matching id %d"), dom->id);
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
2011-07-13 11:21:54 +00:00
|
|
|
umlShutdownVMDaemon(driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED);
|
2011-07-04 11:10:30 +00:00
|
|
|
virDomainAuditStop(vm, "destroyed");
|
2009-07-06 15:06:11 +00:00
|
|
|
event = virDomainEventNewFromObj(vm,
|
|
|
|
VIR_DOMAIN_EVENT_STOPPED,
|
|
|
|
VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
|
2008-12-04 21:13:58 +00:00
|
|
|
if (!vm->persistent) {
|
2013-01-11 16:04:47 +00:00
|
|
|
virDomainObjListRemove(driver->domains,
|
|
|
|
vm);
|
2008-12-04 21:13:58 +00:00
|
|
|
vm = NULL;
|
|
|
|
}
|
|
|
|
ret = 0;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:13:58 +00:00
|
|
|
cleanup:
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(vm);
|
2009-07-06 15:06:11 +00:00
|
|
|
if (event)
|
|
|
|
umlDomainEventQueue(driver, event);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
2008-12-04 21:13:58 +00:00
|
|
|
return ret;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-07-21 07:54:28 +00:00
|
|
|
static int umlDomainDestroy(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
return umlDomainDestroyFlags(dom, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
static char *umlDomainGetOSType(virDomainPtr dom) {
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
char *type = NULL;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2013-01-11 16:04:47 +00:00
|
|
|
vm = virDomainObjListFindByUUID(driver->domains, dom->uuid);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!vm) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, "%s",
|
2010-04-03 13:33:29 +00:00
|
|
|
_("no domain with matching uuid"));
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
2008-12-04 21:13:58 +00:00
|
|
|
if (!(type = strdup(vm->def->os.type)))
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-12-04 21:13:58 +00:00
|
|
|
|
|
|
|
cleanup:
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(vm);
|
2008-11-19 16:58:23 +00:00
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Returns max memory in kb, 0 if error */
|
xml: use long long internally, to centralize overflow checks
On 64-bit platforms, unsigned long and unsigned long long are
identical, so we don't have to worry about overflow checks.
On 32-bit platforms, anywhere we narrow unsigned long long back
to unsigned long, we have to worry about overflow; it's easier
to do this in one place by having most of the code use the same
or wider types, and only doing the narrowing at the last minute.
Therefore, the memory set commands remain unsigned long, and
the memory get command now centralizes the overflow check into
libvirt.c, so that drivers don't have to repeat the work.
This also fixes a bug where xen returned the wrong value on
failure (most APIs return -1 on failure, but getMaxMemory
must return 0 on failure).
* src/driver.h (virDrvDomainGetMaxMemory): Use long long.
* src/libvirt.c (virDomainGetMaxMemory): Raise overflow.
* src/test/test_driver.c (testGetMaxMemory): Fix driver.
* src/rpc/gendispatch.pl (name_to_ProcName): Likewise.
* src/xen/xen_hypervisor.c (xenHypervisorGetMaxMemory): Likewise.
* src/xen/xen_driver.c (xenUnifiedDomainGetMaxMemory): Likewise.
* src/xen/xend_internal.c (xenDaemonDomainGetMaxMemory):
Likewise.
* src/xen/xend_internal.h (xenDaemonDomainGetMaxMemory):
Likewise.
* src/xen/xm_internal.c (xenXMDomainGetMaxMemory): Likewise.
* src/xen/xm_internal.h (xenXMDomainGetMaxMemory): Likewise.
* src/xen/xs_internal.c (xenStoreDomainGetMaxMemory): Likewise.
* src/xen/xs_internal.h (xenStoreDomainGetMaxMemory): Likewise.
* src/xenapi/xenapi_driver.c (xenapiDomainGetMaxMemory):
Likewise.
* src/esx/esx_driver.c (esxDomainGetMaxMemory): Likewise.
* src/libxl/libxl_driver.c (libxlDomainGetMaxMemory): Likewise.
* src/qemu/qemu_driver.c (qemudDomainGetMaxMemory): Likewise.
* src/lxc/lxc_driver.c (lxcDomainGetMaxMemory): Likewise.
* src/uml/uml_driver.c (umlDomainGetMaxMemory): Likewise.
2012-03-03 00:47:16 +00:00
|
|
|
static unsigned long long
|
|
|
|
umlDomainGetMaxMemory(virDomainPtr dom)
|
|
|
|
{
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
xml: use long long internally, to centralize overflow checks
On 64-bit platforms, unsigned long and unsigned long long are
identical, so we don't have to worry about overflow checks.
On 32-bit platforms, anywhere we narrow unsigned long long back
to unsigned long, we have to worry about overflow; it's easier
to do this in one place by having most of the code use the same
or wider types, and only doing the narrowing at the last minute.
Therefore, the memory set commands remain unsigned long, and
the memory get command now centralizes the overflow check into
libvirt.c, so that drivers don't have to repeat the work.
This also fixes a bug where xen returned the wrong value on
failure (most APIs return -1 on failure, but getMaxMemory
must return 0 on failure).
* src/driver.h (virDrvDomainGetMaxMemory): Use long long.
* src/libvirt.c (virDomainGetMaxMemory): Raise overflow.
* src/test/test_driver.c (testGetMaxMemory): Fix driver.
* src/rpc/gendispatch.pl (name_to_ProcName): Likewise.
* src/xen/xen_hypervisor.c (xenHypervisorGetMaxMemory): Likewise.
* src/xen/xen_driver.c (xenUnifiedDomainGetMaxMemory): Likewise.
* src/xen/xend_internal.c (xenDaemonDomainGetMaxMemory):
Likewise.
* src/xen/xend_internal.h (xenDaemonDomainGetMaxMemory):
Likewise.
* src/xen/xm_internal.c (xenXMDomainGetMaxMemory): Likewise.
* src/xen/xm_internal.h (xenXMDomainGetMaxMemory): Likewise.
* src/xen/xs_internal.c (xenStoreDomainGetMaxMemory): Likewise.
* src/xen/xs_internal.h (xenStoreDomainGetMaxMemory): Likewise.
* src/xenapi/xenapi_driver.c (xenapiDomainGetMaxMemory):
Likewise.
* src/esx/esx_driver.c (esxDomainGetMaxMemory): Likewise.
* src/libxl/libxl_driver.c (libxlDomainGetMaxMemory): Likewise.
* src/qemu/qemu_driver.c (qemudDomainGetMaxMemory): Likewise.
* src/lxc/lxc_driver.c (lxcDomainGetMaxMemory): Likewise.
* src/uml/uml_driver.c (umlDomainGetMaxMemory): Likewise.
2012-03-03 00:47:16 +00:00
|
|
|
unsigned long long ret = 0;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2013-01-11 16:04:47 +00:00
|
|
|
vm = virDomainObjListFindByUUID(driver->domains, dom->uuid);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
2008-12-04 21:13:58 +00:00
|
|
|
_("no domain with matching uuid '%s'"), uuidstr);
|
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
2010-10-12 14:43:39 +00:00
|
|
|
ret = vm->def->mem.max_balloon;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:13:58 +00:00
|
|
|
cleanup:
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(vm);
|
2008-12-04 21:13:58 +00:00
|
|
|
return ret;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int umlDomainSetMaxMemory(virDomainPtr dom, unsigned long newmax) {
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2013-01-11 16:04:47 +00:00
|
|
|
vm = virDomainObjListFindByUUID(driver->domains, dom->uuid);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
2010-04-03 13:33:29 +00:00
|
|
|
_("no domain with matching uuid '%s'"), uuidstr);
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
2010-10-12 14:43:39 +00:00
|
|
|
if (newmax < vm->def->mem.cur_balloon) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
2010-04-03 13:33:29 +00:00
|
|
|
_("cannot set max memory lower than current memory"));
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
2010-10-12 14:43:39 +00:00
|
|
|
vm->def->mem.max_balloon = newmax;
|
2008-12-04 21:13:58 +00:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(vm);
|
2008-12-04 21:13:58 +00:00
|
|
|
return ret;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int umlDomainSetMemory(virDomainPtr dom, unsigned long newmem) {
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2013-01-11 16:04:47 +00:00
|
|
|
vm = virDomainObjListFindByUUID(driver->domains, dom->uuid);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
2010-04-03 13:33:29 +00:00
|
|
|
_("no domain with matching uuid '%s'"), uuidstr);
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
Rename internal APis
Rename virDomainIsActive to virDomainObjIsActive, and
virInterfaceIsActive to virInterfaceObjIsActive and finally
virNetworkIsActive to virNetworkObjIsActive.
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/conf/interface_conf.h, src/conf/network_conf.c,
src/conf/network_conf.h, src/lxc/lxc_driver.c,
src/network/bridge_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_driver.c, src/qemu/qemu_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c: Update for
renamed APIs.
2009-10-20 14:51:03 +00:00
|
|
|
if (virDomainObjIsActive(vm)) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
2010-04-03 13:33:29 +00:00
|
|
|
_("cannot set memory of an active domain"));
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
2010-10-12 14:43:39 +00:00
|
|
|
if (newmem > vm->def->mem.max_balloon) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
2010-04-03 13:33:29 +00:00
|
|
|
_("cannot set memory higher than max memory"));
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
2010-10-12 14:43:39 +00:00
|
|
|
vm->def->mem.cur_balloon = newmem;
|
2008-12-04 21:13:58 +00:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(vm);
|
2008-12-04 21:13:58 +00:00
|
|
|
return ret;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int umlDomainGetInfo(virDomainPtr dom,
|
|
|
|
virDomainInfoPtr info) {
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2013-01-11 16:04:47 +00:00
|
|
|
vm = virDomainObjListFindByUUID(driver->domains, dom->uuid);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!vm) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, "%s",
|
2010-04-03 13:33:29 +00:00
|
|
|
_("no domain with matching uuid"));
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
2011-05-04 09:07:01 +00:00
|
|
|
info->state = virDomainObjGetState(vm, NULL);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
Rename internal APis
Rename virDomainIsActive to virDomainObjIsActive, and
virInterfaceIsActive to virInterfaceObjIsActive and finally
virNetworkIsActive to virNetworkObjIsActive.
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/conf/interface_conf.h, src/conf/network_conf.c,
src/conf/network_conf.h, src/lxc/lxc_driver.c,
src/network/bridge_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_driver.c, src/qemu/qemu_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c: Update for
renamed APIs.
2009-10-20 14:51:03 +00:00
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2008-11-19 16:58:23 +00:00
|
|
|
info->cpuTime = 0;
|
|
|
|
} else {
|
|
|
|
if (umlGetProcessInfo(&(info->cpuTime), vm->pid) < 0) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
|
2010-04-03 13:33:29 +00:00
|
|
|
_("cannot read cputime for domain"));
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-12 14:43:39 +00:00
|
|
|
info->maxMem = vm->def->mem.max_balloon;
|
|
|
|
info->memory = vm->def->mem.cur_balloon;
|
2008-11-19 16:58:23 +00:00
|
|
|
info->nrVirtCpu = vm->def->vcpus;
|
2008-12-04 21:13:58 +00:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(vm);
|
2008-12-04 21:13:58 +00:00
|
|
|
return ret;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-05-02 09:35:29 +00:00
|
|
|
static int
|
|
|
|
umlDomainGetState(virDomainPtr dom,
|
|
|
|
int *state,
|
|
|
|
int *reason,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
|
|
|
umlDriverLock(driver);
|
2013-01-11 16:04:47 +00:00
|
|
|
vm = virDomainObjListFindByUUID(driver->domains, dom->uuid);
|
2011-05-02 09:35:29 +00:00
|
|
|
umlDriverUnlock(driver);
|
|
|
|
|
|
|
|
if (!vm) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, "%s",
|
2011-05-02 09:35:29 +00:00
|
|
|
_("no domain with matching uuid"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-05-04 09:07:01 +00:00
|
|
|
*state = virDomainObjGetState(vm, reason);
|
2011-05-02 09:35:29 +00:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(vm);
|
2011-05-02 09:35:29 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-05-06 19:53:10 +00:00
|
|
|
static char *umlDomainGetXMLDesc(virDomainPtr dom,
|
2011-07-06 23:02:14 +00:00
|
|
|
unsigned int flags)
|
|
|
|
{
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
char *ret = NULL;
|
|
|
|
|
2011-07-13 22:24:38 +00:00
|
|
|
/* Flags checked by virDomainDefFormat */
|
2011-07-06 23:02:14 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2013-01-11 16:04:47 +00:00
|
|
|
vm = virDomainObjListFindByUUID(driver->domains, dom->uuid);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!vm) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, "%s",
|
2010-04-03 13:33:29 +00:00
|
|
|
_("no domain with matching uuid"));
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
2010-02-09 18:58:01 +00:00
|
|
|
ret = virDomainDefFormat((flags & VIR_DOMAIN_XML_INACTIVE) && vm->newDef ?
|
2008-12-04 21:13:58 +00:00
|
|
|
vm->newDef : vm->def,
|
|
|
|
flags);
|
|
|
|
|
|
|
|
cleanup:
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(vm);
|
2008-12-04 21:13:58 +00:00
|
|
|
return ret;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-04-23 12:50:18 +00:00
|
|
|
static int umlConnectListDefinedDomains(virConnectPtr conn,
|
|
|
|
char **const names, int nnames) {
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = conn->privateData;
|
Convert virDomainObjListPtr to use a hash of domain objects
The current virDomainObjListPtr object stores domain objects in
an array. This means that to find a particular objects requires
O(n) time, and more critically acquiring O(n) mutex locks.
The new impl replaces the array with a virHashTable, keyed off
UUID. Finding a object based on UUID is now O(1) time, and only
requires a single mutex lock. Finding by name/id is unchanged
in complexity.
In changing this, all code which iterates over the array had
to be updated to use a hash table iterator function callback.
Several of the functions which were identically duplicating
across all drivers were pulled into domain_conf.c
* src/conf/domain_conf.h, src/conf/domain_conf.c: Change
virDomainObjListPtr to use virHashTable. Add a initializer
method virDomainObjListInit, and rename virDomainObjListFree
to virDomainObjListDeinit, since its not actually freeing
the container, only its contents. Also add some convenient
methods virDomainObjListGetInactiveNames,
virDomainObjListGetActiveIDs and virDomainObjListNumOfDomains
which can be used to implement the correspondingly named
public API entry points in drivers
* src/libvirt_private.syms: Export new methods from domain_conf.h
* src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_conf.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c: Update all code
to deal with hash tables instead of arrays for domains
2009-10-09 11:33:51 +00:00
|
|
|
int n;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2013-01-11 16:04:47 +00:00
|
|
|
n = virDomainObjListGetInactiveNames(driver->domains, names, nnames);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
Convert virDomainObjListPtr to use a hash of domain objects
The current virDomainObjListPtr object stores domain objects in
an array. This means that to find a particular objects requires
O(n) time, and more critically acquiring O(n) mutex locks.
The new impl replaces the array with a virHashTable, keyed off
UUID. Finding a object based on UUID is now O(1) time, and only
requires a single mutex lock. Finding by name/id is unchanged
in complexity.
In changing this, all code which iterates over the array had
to be updated to use a hash table iterator function callback.
Several of the functions which were identically duplicating
across all drivers were pulled into domain_conf.c
* src/conf/domain_conf.h, src/conf/domain_conf.c: Change
virDomainObjListPtr to use virHashTable. Add a initializer
method virDomainObjListInit, and rename virDomainObjListFree
to virDomainObjListDeinit, since its not actually freeing
the container, only its contents. Also add some convenient
methods virDomainObjListGetInactiveNames,
virDomainObjListGetActiveIDs and virDomainObjListNumOfDomains
which can be used to implement the correspondingly named
public API entry points in drivers
* src/libvirt_private.syms: Export new methods from domain_conf.h
* src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_conf.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c: Update all code
to deal with hash tables instead of arrays for domains
2009-10-09 11:33:51 +00:00
|
|
|
return n;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
2013-04-23 12:50:18 +00:00
|
|
|
static int umlConnectNumOfDefinedDomains(virConnectPtr conn) {
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = conn->privateData;
|
Convert virDomainObjListPtr to use a hash of domain objects
The current virDomainObjListPtr object stores domain objects in
an array. This means that to find a particular objects requires
O(n) time, and more critically acquiring O(n) mutex locks.
The new impl replaces the array with a virHashTable, keyed off
UUID. Finding a object based on UUID is now O(1) time, and only
requires a single mutex lock. Finding by name/id is unchanged
in complexity.
In changing this, all code which iterates over the array had
to be updated to use a hash table iterator function callback.
Several of the functions which were identically duplicating
across all drivers were pulled into domain_conf.c
* src/conf/domain_conf.h, src/conf/domain_conf.c: Change
virDomainObjListPtr to use virHashTable. Add a initializer
method virDomainObjListInit, and rename virDomainObjListFree
to virDomainObjListDeinit, since its not actually freeing
the container, only its contents. Also add some convenient
methods virDomainObjListGetInactiveNames,
virDomainObjListGetActiveIDs and virDomainObjListNumOfDomains
which can be used to implement the correspondingly named
public API entry points in drivers
* src/libvirt_private.syms: Export new methods from domain_conf.h
* src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_conf.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c: Update all code
to deal with hash tables instead of arrays for domains
2009-10-09 11:33:51 +00:00
|
|
|
int n;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2013-01-11 16:04:47 +00:00
|
|
|
n = virDomainObjListNumOfDomains(driver->domains, 0);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-04-23 12:50:18 +00:00
|
|
|
static int umlDomainCreateWithFlags(virDomainPtr dom, unsigned int flags) {
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
2009-07-06 15:06:11 +00:00
|
|
|
virDomainEventPtr event = NULL;
|
2008-12-04 21:13:58 +00:00
|
|
|
int ret = -1;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2011-07-13 11:21:54 +00:00
|
|
|
virCheckFlags(VIR_DOMAIN_START_AUTODESTROY, -1);
|
2010-06-10 15:55:36 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2013-01-11 16:04:47 +00:00
|
|
|
vm = virDomainObjListFindByUUID(driver->domains, dom->uuid);
|
2008-12-04 21:14:39 +00:00
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!vm) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, "%s",
|
2010-04-03 13:33:29 +00:00
|
|
|
_("no domain with matching uuid"));
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
2011-07-13 11:21:54 +00:00
|
|
|
ret = umlStartVMDaemon(dom->conn, driver, vm,
|
|
|
|
(flags & VIR_DOMAIN_START_AUTODESTROY));
|
2011-07-04 11:10:30 +00:00
|
|
|
virDomainAuditStart(vm, "booted", ret >= 0);
|
2009-07-06 15:06:11 +00:00
|
|
|
if (ret == 0)
|
|
|
|
event = virDomainEventNewFromObj(vm,
|
|
|
|
VIR_DOMAIN_EVENT_STARTED,
|
|
|
|
VIR_DOMAIN_EVENT_STARTED_BOOTED);
|
2008-12-04 21:13:58 +00:00
|
|
|
|
|
|
|
cleanup:
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(vm);
|
2009-07-06 15:06:11 +00:00
|
|
|
if (event)
|
|
|
|
umlDomainEventQueue(driver, event);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
2008-12-04 21:13:58 +00:00
|
|
|
return ret;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
2013-04-23 12:50:18 +00:00
|
|
|
static int umlDomainCreate(virDomainPtr dom) {
|
|
|
|
return umlDomainCreateWithFlags(dom, 0);
|
2010-06-10 15:55:36 +00:00
|
|
|
}
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2013-04-23 12:50:18 +00:00
|
|
|
static virDomainPtr umlDomainDefineXML(virConnectPtr conn, const char *xml) {
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = conn->privateData;
|
2008-11-19 16:58:23 +00:00
|
|
|
virDomainDefPtr def;
|
2008-12-04 21:14:39 +00:00
|
|
|
virDomainObjPtr vm = NULL;
|
2008-12-04 21:13:58 +00:00
|
|
|
virDomainPtr dom = NULL;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2013-03-28 13:55:55 +00:00
|
|
|
if (!(def = virDomainDefParseString(xml, driver->caps, driver->xmlopt,
|
|
|
|
1 << VIR_DOMAIN_VIRT_UML,
|
2009-01-08 13:54:20 +00:00
|
|
|
VIR_DOMAIN_XML_INACTIVE)))
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2013-03-28 13:55:55 +00:00
|
|
|
if (!(vm = virDomainObjListAdd(driver->domains, def,
|
2013-03-31 18:03:42 +00:00
|
|
|
driver->xmlopt,
|
Merge virDomainObjListIsDuplicate into virDomainObjListAdd
The duplicate VM checking should be done atomically with
virDomainObjListAdd, so shoud not be a separate function.
Instead just use flags to indicate what kind of checks are
required.
This pair, used in virDomainCreateXML:
if (virDomainObjListIsDuplicate(privconn->domains, def, 1) < 0)
goto cleanup;
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def, false)))
goto cleanup;
Changes to
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def,
VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
NULL)))
goto cleanup;
This pair, used in virDomainRestoreFlags:
if (virDomainObjListIsDuplicate(privconn->domains, def, 1) < 0)
goto cleanup;
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def, true)))
goto cleanup;
Changes to
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def,
VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
NULL)))
goto cleanup;
This pair, used in virDomainDefineXML:
if (virDomainObjListIsDuplicate(privconn->domains, def, 0) < 0)
goto cleanup;
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def, false)))
goto cleanup;
Changes to
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def,
0, NULL)))
goto cleanup;
2013-01-14 14:46:58 +00:00
|
|
|
0, NULL)))
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
|
|
|
def = NULL;
|
2008-11-19 16:58:23 +00:00
|
|
|
vm->persistent = 1;
|
|
|
|
|
2010-02-09 18:58:01 +00:00
|
|
|
if (virDomainSaveConfig(driver->configDir,
|
2008-11-19 16:58:23 +00:00
|
|
|
vm->newDef ? vm->newDef : vm->def) < 0) {
|
2013-01-11 16:04:47 +00:00
|
|
|
virDomainObjListRemove(driver->domains,
|
|
|
|
vm);
|
2008-12-04 21:14:39 +00:00
|
|
|
vm = NULL;
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
|
|
|
if (dom) dom->id = vm->def->id;
|
2008-12-04 21:13:58 +00:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virDomainDefFree(def);
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(vm);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
2008-11-19 16:58:23 +00:00
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
2011-07-20 03:08:21 +00:00
|
|
|
static int umlDomainUndefineFlags(virDomainPtr dom,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2011-07-20 03:08:21 +00:00
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2013-01-11 16:04:47 +00:00
|
|
|
vm = virDomainObjListFindByUUID(driver->domains, dom->uuid);
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!vm) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, "%s",
|
2010-04-03 13:33:29 +00:00
|
|
|
_("no domain with matching uuid"));
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!vm->persistent) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
2010-04-03 13:33:29 +00:00
|
|
|
_("cannot undefine transient domain"));
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
2010-02-09 18:58:01 +00:00
|
|
|
if (virDomainDeleteConfig(driver->configDir, driver->autostartDir, vm) < 0)
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2011-08-19 13:51:42 +00:00
|
|
|
if (virDomainObjIsActive(vm)) {
|
|
|
|
vm->persistent = 0;
|
|
|
|
} else {
|
2013-01-11 16:04:47 +00:00
|
|
|
virDomainObjListRemove(driver->domains, vm);
|
2011-08-19 13:51:42 +00:00
|
|
|
vm = NULL;
|
|
|
|
}
|
|
|
|
|
2008-12-04 21:13:58 +00:00
|
|
|
ret = 0;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:13:58 +00:00
|
|
|
cleanup:
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(vm);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
2008-12-04 21:13:58 +00:00
|
|
|
return ret;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-07-20 03:08:21 +00:00
|
|
|
static int umlDomainUndefine(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
return umlDomainUndefineFlags(dom, 0);
|
|
|
|
}
|
|
|
|
|
2010-08-23 09:31:27 +00:00
|
|
|
static int umlDomainAttachUmlDisk(struct uml_driver *driver,
|
|
|
|
virDomainObjPtr vm,
|
|
|
|
virDomainDiskDefPtr disk)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
char *cmd = NULL;
|
|
|
|
char *reply = NULL;
|
|
|
|
|
|
|
|
for (i = 0 ; i < vm->def->ndisks ; i++) {
|
|
|
|
if (STREQ(vm->def->disks[i]->dst, disk->dst)) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
2010-08-23 09:31:27 +00:00
|
|
|
_("target %s already exists"), disk->dst);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!disk->src) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2010-08-23 09:31:27 +00:00
|
|
|
"%s", _("disk source path is missing"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virAsprintf(&cmd, "config %s=%s", disk->dst, disk->src) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (umlMonitorCommand(driver, vm, cmd, &reply) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainDiskInsertPreAlloced(vm->def, disk);
|
|
|
|
|
|
|
|
VIR_FREE(reply);
|
|
|
|
VIR_FREE(cmd);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
|
|
|
|
VIR_FREE(reply);
|
|
|
|
VIR_FREE(cmd);
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int umlDomainAttachDevice(virDomainPtr dom, const char *xml)
|
|
|
|
{
|
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
virDomainDeviceDefPtr dev = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
umlDriverLock(driver);
|
|
|
|
|
2013-01-11 16:04:47 +00:00
|
|
|
vm = virDomainObjListFindByUUID(driver->domains, dom->uuid);
|
2010-08-23 09:31:27 +00:00
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
2010-08-23 09:31:27 +00:00
|
|
|
_("no domain with matching uuid '%s'"), uuidstr);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
2010-08-23 09:31:27 +00:00
|
|
|
"%s", _("cannot attach device on inactive domain"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-03-28 13:55:55 +00:00
|
|
|
dev = virDomainDeviceDefParse(xml, vm->def, driver->caps, driver->xmlopt,
|
2010-08-23 09:31:27 +00:00
|
|
|
VIR_DOMAIN_XML_INACTIVE);
|
|
|
|
|
|
|
|
if (dev == NULL)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
|
|
|
|
if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_UML) {
|
|
|
|
ret = umlDomainAttachUmlDisk(driver, vm, dev->data.disk);
|
|
|
|
if (ret == 0)
|
|
|
|
dev->data.disk = NULL;
|
|
|
|
} else {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
2010-08-23 09:31:27 +00:00
|
|
|
_("disk bus '%s' cannot be hotplugged."),
|
|
|
|
virDomainDiskBusTypeToString(dev->data.disk->bus));
|
|
|
|
}
|
|
|
|
} else {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
2010-08-23 09:31:27 +00:00
|
|
|
_("device type '%s' cannot be attached"),
|
|
|
|
virDomainDeviceTypeToString(dev->type));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
|
|
|
|
virDomainDeviceDefFree(dev);
|
|
|
|
if (vm)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(vm);
|
2010-08-23 09:31:27 +00:00
|
|
|
umlDriverUnlock(driver);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-07-13 22:24:38 +00:00
|
|
|
static int
|
|
|
|
umlDomainAttachDeviceFlags(virDomainPtr dom,
|
|
|
|
const char *xml,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1);
|
|
|
|
|
2011-06-08 06:33:33 +00:00
|
|
|
if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
2010-08-23 09:31:27 +00:00
|
|
|
"%s", _("cannot modify the persistent configuration of a domain"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return umlDomainAttachDevice(dom, xml);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int umlDomainDetachUmlDisk(struct uml_driver *driver,
|
|
|
|
virDomainObjPtr vm,
|
|
|
|
virDomainDeviceDefPtr dev)
|
|
|
|
{
|
|
|
|
int i, ret = -1;
|
|
|
|
virDomainDiskDefPtr detach = NULL;
|
|
|
|
char *cmd;
|
|
|
|
char *reply;
|
|
|
|
|
|
|
|
for (i = 0 ; i < vm->def->ndisks ; i++) {
|
|
|
|
if (STREQ(vm->def->disks[i]->dst, dev->data.disk->dst)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i == vm->def->ndisks) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
2010-08-23 09:31:27 +00:00
|
|
|
_("disk %s not found"), dev->data.disk->dst);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
detach = vm->def->disks[i];
|
|
|
|
|
|
|
|
if (virAsprintf(&cmd, "remove %s", detach->dst) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (umlMonitorCommand(driver, vm, cmd, &reply) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
virDomainDiskRemove(vm->def, i);
|
|
|
|
|
|
|
|
virDomainDiskDefFree(detach);
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
VIR_FREE(reply);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(cmd);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int umlDomainDetachDevice(virDomainPtr dom, const char *xml) {
|
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
virDomainDeviceDefPtr dev = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
umlDriverLock(driver);
|
2013-01-11 16:04:47 +00:00
|
|
|
vm = virDomainObjListFindByUUID(driver->domains, dom->uuid);
|
2010-08-23 09:31:27 +00:00
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
2010-08-23 09:31:27 +00:00
|
|
|
_("no domain with matching uuid '%s'"), uuidstr);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
2010-08-23 09:31:27 +00:00
|
|
|
"%s", _("cannot detach device on inactive domain"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-03-28 13:55:55 +00:00
|
|
|
dev = virDomainDeviceDefParse(xml, vm->def, driver->caps, driver->xmlopt,
|
2010-08-23 09:31:27 +00:00
|
|
|
VIR_DOMAIN_XML_INACTIVE);
|
|
|
|
if (dev == NULL)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (dev->type == VIR_DOMAIN_DEVICE_DISK &&
|
|
|
|
dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
|
|
|
|
if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_UML)
|
|
|
|
ret = umlDomainDetachUmlDisk(driver, vm, dev);
|
|
|
|
else {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
2010-08-23 09:31:27 +00:00
|
|
|
_("This type of disk cannot be hot unplugged"));
|
|
|
|
}
|
|
|
|
} else {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
2010-08-23 09:31:27 +00:00
|
|
|
"%s", _("This type of device cannot be hot unplugged"));
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virDomainDeviceDefFree(dev);
|
|
|
|
if (vm)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(vm);
|
2010-08-23 09:31:27 +00:00
|
|
|
umlDriverUnlock(driver);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-07-13 22:24:38 +00:00
|
|
|
static int
|
|
|
|
umlDomainDetachDeviceFlags(virDomainPtr dom,
|
|
|
|
const char *xml,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1);
|
|
|
|
|
2011-06-08 06:33:33 +00:00
|
|
|
if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
2010-08-23 09:31:27 +00:00
|
|
|
"%s", _("cannot modify the persistent configuration of a domain"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return umlDomainDetachDevice(dom, xml);
|
|
|
|
}
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
static int umlDomainGetAutostart(virDomainPtr dom,
|
|
|
|
int *autostart) {
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2013-01-11 16:04:47 +00:00
|
|
|
vm = virDomainObjListFindByUUID(driver->domains, dom->uuid);
|
2008-12-04 21:14:39 +00:00
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!vm) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, "%s",
|
2010-04-03 13:33:29 +00:00
|
|
|
_("no domain with matching uuid"));
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
*autostart = vm->autostart;
|
2008-12-04 21:13:58 +00:00
|
|
|
ret = 0;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:13:58 +00:00
|
|
|
cleanup:
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(vm);
|
2009-05-19 11:06:25 +00:00
|
|
|
umlDriverUnlock(driver);
|
2008-12-04 21:13:58 +00:00
|
|
|
return ret;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int umlDomainSetAutostart(virDomainPtr dom,
|
|
|
|
int autostart) {
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
2008-12-04 21:14:39 +00:00
|
|
|
virDomainObjPtr vm;
|
2008-11-19 16:58:23 +00:00
|
|
|
char *configFile = NULL, *autostartLink = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2013-01-11 16:04:47 +00:00
|
|
|
vm = virDomainObjListFindByUUID(driver->domains, dom->uuid);
|
2008-12-04 21:14:39 +00:00
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!vm) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, "%s",
|
2010-04-03 13:33:29 +00:00
|
|
|
_("no domain with matching uuid"));
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!vm->persistent) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
2010-04-03 13:33:29 +00:00
|
|
|
_("cannot set autostart for transient domain"));
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
autostart = (autostart != 0);
|
|
|
|
|
2008-12-04 21:13:58 +00:00
|
|
|
if (vm->autostart != autostart) {
|
2010-02-09 18:58:01 +00:00
|
|
|
if ((configFile = virDomainConfigFile(driver->configDir, vm->def->name)) == NULL)
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2010-02-09 18:58:01 +00:00
|
|
|
if ((autostartLink = virDomainConfigFile(driver->autostartDir, vm->def->name)) == NULL)
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:13:58 +00:00
|
|
|
if (autostart) {
|
2011-07-05 21:02:53 +00:00
|
|
|
if (virFileMakePath(driver->autostartDir) < 0) {
|
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("cannot create autostart directory %s"),
|
|
|
|
driver->autostartDir);
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:13:58 +00:00
|
|
|
if (symlink(configFile, autostartLink) < 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("Failed to create symlink '%s to '%s'"),
|
|
|
|
autostartLink, configFile);
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("Failed to delete symlink '%s'"),
|
|
|
|
autostartLink);
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
2008-12-04 21:13:58 +00:00
|
|
|
vm->autostart = autostart;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(configFile);
|
|
|
|
VIR_FREE(autostartLink);
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(vm);
|
2009-05-19 11:06:25 +00:00
|
|
|
umlDriverUnlock(driver);
|
2008-11-19 16:58:23 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2010-10-22 13:40:26 +00:00
|
|
|
umlDomainBlockPeek(virDomainPtr dom,
|
|
|
|
const char *path,
|
|
|
|
unsigned long long offset, size_t size,
|
|
|
|
void *buffer,
|
2011-07-06 23:02:14 +00:00
|
|
|
unsigned int flags)
|
2008-11-19 16:58:23 +00:00
|
|
|
{
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
snapshot: also support disks by path
I got confused when 'virsh domblkinfo dom disk' required the
path to a disk (which can be ambiguous, since a single file
can back multiple disks), rather than the unambiguous target
device name that I was using in disk snapshots. So, in true
developer fashion, I went for the best of both worlds - all
interfaces that operate on a disk (aka block) now accept
either the target name or the unambiguous path to the backing
file used by the disk.
* src/conf/domain_conf.h (virDomainDiskIndexByName): Add
parameter.
(virDomainDiskPathByName): New prototype.
* src/libvirt_private.syms (domain_conf.h): Export it.
* src/conf/domain_conf.c (virDomainDiskIndexByName): Also allow
searching by path, and decide whether ambiguity is okay.
(virDomainDiskPathByName): New function.
(virDomainDiskRemoveByName, virDomainSnapshotAlignDisks): Update
callers.
* src/qemu/qemu_driver.c (qemudDomainBlockPeek)
(qemuDomainAttachDeviceConfig, qemuDomainUpdateDeviceConfig)
(qemuDomainGetBlockInfo, qemuDiskPathToAlias): Likewise.
* src/qemu/qemu_process.c (qemuProcessFindDomainDiskByPath):
Likewise.
* src/libxl/libxl_driver.c (libxlDomainAttachDeviceDiskLive)
(libxlDomainDetachDeviceDiskLive, libxlDomainAttachDeviceConfig)
(libxlDomainUpdateDeviceConfig): Likewise.
* src/uml/uml_driver.c (umlDomainBlockPeek): Likewise.
* src/xen/xend_internal.c (xenDaemonDomainBlockPeek): Likewise.
* docs/formatsnapshot.html.in: Update documentation.
* tools/virsh.pod (domblkstat, domblkinfo): Likewise.
* docs/schemas/domaincommon.rng (diskTarget): Tighten pattern on
disk targets.
* docs/schemas/domainsnapshot.rng (disksnapshot): Update to match.
* tests/domainsnapshotxml2xmlin/disk_snapshot.xml: Update test.
2011-08-20 02:38:36 +00:00
|
|
|
int fd = -1, ret = -1;
|
|
|
|
const char *actual;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2011-07-06 23:02:14 +00:00
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2013-01-11 16:04:47 +00:00
|
|
|
vm = virDomainObjListFindByUUID(driver->domains, dom->uuid);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!vm) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, "%s",
|
2010-04-03 13:33:29 +00:00
|
|
|
_("no domain with matching uuid"));
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!path || path[0] == '\0') {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
2010-04-03 13:33:29 +00:00
|
|
|
_("NULL or empty path"));
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Check the path belongs to this domain. */
|
snapshot: also support disks by path
I got confused when 'virsh domblkinfo dom disk' required the
path to a disk (which can be ambiguous, since a single file
can back multiple disks), rather than the unambiguous target
device name that I was using in disk snapshots. So, in true
developer fashion, I went for the best of both worlds - all
interfaces that operate on a disk (aka block) now accept
either the target name or the unambiguous path to the backing
file used by the disk.
* src/conf/domain_conf.h (virDomainDiskIndexByName): Add
parameter.
(virDomainDiskPathByName): New prototype.
* src/libvirt_private.syms (domain_conf.h): Export it.
* src/conf/domain_conf.c (virDomainDiskIndexByName): Also allow
searching by path, and decide whether ambiguity is okay.
(virDomainDiskPathByName): New function.
(virDomainDiskRemoveByName, virDomainSnapshotAlignDisks): Update
callers.
* src/qemu/qemu_driver.c (qemudDomainBlockPeek)
(qemuDomainAttachDeviceConfig, qemuDomainUpdateDeviceConfig)
(qemuDomainGetBlockInfo, qemuDiskPathToAlias): Likewise.
* src/qemu/qemu_process.c (qemuProcessFindDomainDiskByPath):
Likewise.
* src/libxl/libxl_driver.c (libxlDomainAttachDeviceDiskLive)
(libxlDomainDetachDeviceDiskLive, libxlDomainAttachDeviceConfig)
(libxlDomainUpdateDeviceConfig): Likewise.
* src/uml/uml_driver.c (umlDomainBlockPeek): Likewise.
* src/xen/xend_internal.c (xenDaemonDomainBlockPeek): Likewise.
* docs/formatsnapshot.html.in: Update documentation.
* tools/virsh.pod (domblkstat, domblkinfo): Likewise.
* docs/schemas/domaincommon.rng (diskTarget): Tighten pattern on
disk targets.
* docs/schemas/domainsnapshot.rng (disksnapshot): Update to match.
* tests/domainsnapshotxml2xmlin/disk_snapshot.xml: Update test.
2011-08-20 02:38:36 +00:00
|
|
|
if (!(actual = virDomainDiskPathByName(vm->def, path))) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
snapshot: also support disks by path
I got confused when 'virsh domblkinfo dom disk' required the
path to a disk (which can be ambiguous, since a single file
can back multiple disks), rather than the unambiguous target
device name that I was using in disk snapshots. So, in true
developer fashion, I went for the best of both worlds - all
interfaces that operate on a disk (aka block) now accept
either the target name or the unambiguous path to the backing
file used by the disk.
* src/conf/domain_conf.h (virDomainDiskIndexByName): Add
parameter.
(virDomainDiskPathByName): New prototype.
* src/libvirt_private.syms (domain_conf.h): Export it.
* src/conf/domain_conf.c (virDomainDiskIndexByName): Also allow
searching by path, and decide whether ambiguity is okay.
(virDomainDiskPathByName): New function.
(virDomainDiskRemoveByName, virDomainSnapshotAlignDisks): Update
callers.
* src/qemu/qemu_driver.c (qemudDomainBlockPeek)
(qemuDomainAttachDeviceConfig, qemuDomainUpdateDeviceConfig)
(qemuDomainGetBlockInfo, qemuDiskPathToAlias): Likewise.
* src/qemu/qemu_process.c (qemuProcessFindDomainDiskByPath):
Likewise.
* src/libxl/libxl_driver.c (libxlDomainAttachDeviceDiskLive)
(libxlDomainDetachDeviceDiskLive, libxlDomainAttachDeviceConfig)
(libxlDomainUpdateDeviceConfig): Likewise.
* src/uml/uml_driver.c (umlDomainBlockPeek): Likewise.
* src/xen/xend_internal.c (xenDaemonDomainBlockPeek): Likewise.
* docs/formatsnapshot.html.in: Update documentation.
* tools/virsh.pod (domblkstat, domblkinfo): Likewise.
* docs/schemas/domaincommon.rng (diskTarget): Tighten pattern on
disk targets.
* docs/schemas/domainsnapshot.rng (disksnapshot): Update to match.
* tests/domainsnapshotxml2xmlin/disk_snapshot.xml: Update test.
2011-08-20 02:38:36 +00:00
|
|
|
_("invalid path '%s'"), path);
|
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
snapshot: also support disks by path
I got confused when 'virsh domblkinfo dom disk' required the
path to a disk (which can be ambiguous, since a single file
can back multiple disks), rather than the unambiguous target
device name that I was using in disk snapshots. So, in true
developer fashion, I went for the best of both worlds - all
interfaces that operate on a disk (aka block) now accept
either the target name or the unambiguous path to the backing
file used by the disk.
* src/conf/domain_conf.h (virDomainDiskIndexByName): Add
parameter.
(virDomainDiskPathByName): New prototype.
* src/libvirt_private.syms (domain_conf.h): Export it.
* src/conf/domain_conf.c (virDomainDiskIndexByName): Also allow
searching by path, and decide whether ambiguity is okay.
(virDomainDiskPathByName): New function.
(virDomainDiskRemoveByName, virDomainSnapshotAlignDisks): Update
callers.
* src/qemu/qemu_driver.c (qemudDomainBlockPeek)
(qemuDomainAttachDeviceConfig, qemuDomainUpdateDeviceConfig)
(qemuDomainGetBlockInfo, qemuDiskPathToAlias): Likewise.
* src/qemu/qemu_process.c (qemuProcessFindDomainDiskByPath):
Likewise.
* src/libxl/libxl_driver.c (libxlDomainAttachDeviceDiskLive)
(libxlDomainDetachDeviceDiskLive, libxlDomainAttachDeviceConfig)
(libxlDomainUpdateDeviceConfig): Likewise.
* src/uml/uml_driver.c (umlDomainBlockPeek): Likewise.
* src/xen/xend_internal.c (xenDaemonDomainBlockPeek): Likewise.
* docs/formatsnapshot.html.in: Update documentation.
* tools/virsh.pod (domblkstat, domblkinfo): Likewise.
* docs/schemas/domaincommon.rng (diskTarget): Tighten pattern on
disk targets.
* docs/schemas/domainsnapshot.rng (disksnapshot): Update to match.
* tests/domainsnapshotxml2xmlin/disk_snapshot.xml: Update test.
2011-08-20 02:38:36 +00:00
|
|
|
path = actual;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
snapshot: also support disks by path
I got confused when 'virsh domblkinfo dom disk' required the
path to a disk (which can be ambiguous, since a single file
can back multiple disks), rather than the unambiguous target
device name that I was using in disk snapshots. So, in true
developer fashion, I went for the best of both worlds - all
interfaces that operate on a disk (aka block) now accept
either the target name or the unambiguous path to the backing
file used by the disk.
* src/conf/domain_conf.h (virDomainDiskIndexByName): Add
parameter.
(virDomainDiskPathByName): New prototype.
* src/libvirt_private.syms (domain_conf.h): Export it.
* src/conf/domain_conf.c (virDomainDiskIndexByName): Also allow
searching by path, and decide whether ambiguity is okay.
(virDomainDiskPathByName): New function.
(virDomainDiskRemoveByName, virDomainSnapshotAlignDisks): Update
callers.
* src/qemu/qemu_driver.c (qemudDomainBlockPeek)
(qemuDomainAttachDeviceConfig, qemuDomainUpdateDeviceConfig)
(qemuDomainGetBlockInfo, qemuDiskPathToAlias): Likewise.
* src/qemu/qemu_process.c (qemuProcessFindDomainDiskByPath):
Likewise.
* src/libxl/libxl_driver.c (libxlDomainAttachDeviceDiskLive)
(libxlDomainDetachDeviceDiskLive, libxlDomainAttachDeviceConfig)
(libxlDomainUpdateDeviceConfig): Likewise.
* src/uml/uml_driver.c (umlDomainBlockPeek): Likewise.
* src/xen/xend_internal.c (xenDaemonDomainBlockPeek): Likewise.
* docs/formatsnapshot.html.in: Update documentation.
* tools/virsh.pod (domblkstat, domblkinfo): Likewise.
* docs/schemas/domaincommon.rng (diskTarget): Tighten pattern on
disk targets.
* docs/schemas/domainsnapshot.rng (disksnapshot): Update to match.
* tests/domainsnapshotxml2xmlin/disk_snapshot.xml: Update test.
2011-08-20 02:38:36 +00:00
|
|
|
/* The path is correct, now try to open it and get its size. */
|
|
|
|
fd = open(path, O_RDONLY);
|
|
|
|
if (fd == -1) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("cannot open %s"), path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2008-12-04 21:13:58 +00:00
|
|
|
|
snapshot: also support disks by path
I got confused when 'virsh domblkinfo dom disk' required the
path to a disk (which can be ambiguous, since a single file
can back multiple disks), rather than the unambiguous target
device name that I was using in disk snapshots. So, in true
developer fashion, I went for the best of both worlds - all
interfaces that operate on a disk (aka block) now accept
either the target name or the unambiguous path to the backing
file used by the disk.
* src/conf/domain_conf.h (virDomainDiskIndexByName): Add
parameter.
(virDomainDiskPathByName): New prototype.
* src/libvirt_private.syms (domain_conf.h): Export it.
* src/conf/domain_conf.c (virDomainDiskIndexByName): Also allow
searching by path, and decide whether ambiguity is okay.
(virDomainDiskPathByName): New function.
(virDomainDiskRemoveByName, virDomainSnapshotAlignDisks): Update
callers.
* src/qemu/qemu_driver.c (qemudDomainBlockPeek)
(qemuDomainAttachDeviceConfig, qemuDomainUpdateDeviceConfig)
(qemuDomainGetBlockInfo, qemuDiskPathToAlias): Likewise.
* src/qemu/qemu_process.c (qemuProcessFindDomainDiskByPath):
Likewise.
* src/libxl/libxl_driver.c (libxlDomainAttachDeviceDiskLive)
(libxlDomainDetachDeviceDiskLive, libxlDomainAttachDeviceConfig)
(libxlDomainUpdateDeviceConfig): Likewise.
* src/uml/uml_driver.c (umlDomainBlockPeek): Likewise.
* src/xen/xend_internal.c (xenDaemonDomainBlockPeek): Likewise.
* docs/formatsnapshot.html.in: Update documentation.
* tools/virsh.pod (domblkstat, domblkinfo): Likewise.
* docs/schemas/domaincommon.rng (diskTarget): Tighten pattern on
disk targets.
* docs/schemas/domainsnapshot.rng (disksnapshot): Update to match.
* tests/domainsnapshotxml2xmlin/disk_snapshot.xml: Update test.
2011-08-20 02:38:36 +00:00
|
|
|
/* Seek and read. */
|
|
|
|
/* NB. Because we configure with AC_SYS_LARGEFILE, off_t should
|
|
|
|
* be 64 bits on all platforms.
|
|
|
|
*/
|
|
|
|
if (lseek(fd, offset, SEEK_SET) == (off_t) -1 ||
|
|
|
|
saferead(fd, buffer, size) == (ssize_t) -1) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("cannot read %s"), path);
|
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
snapshot: also support disks by path
I got confused when 'virsh domblkinfo dom disk' required the
path to a disk (which can be ambiguous, since a single file
can back multiple disks), rather than the unambiguous target
device name that I was using in disk snapshots. So, in true
developer fashion, I went for the best of both worlds - all
interfaces that operate on a disk (aka block) now accept
either the target name or the unambiguous path to the backing
file used by the disk.
* src/conf/domain_conf.h (virDomainDiskIndexByName): Add
parameter.
(virDomainDiskPathByName): New prototype.
* src/libvirt_private.syms (domain_conf.h): Export it.
* src/conf/domain_conf.c (virDomainDiskIndexByName): Also allow
searching by path, and decide whether ambiguity is okay.
(virDomainDiskPathByName): New function.
(virDomainDiskRemoveByName, virDomainSnapshotAlignDisks): Update
callers.
* src/qemu/qemu_driver.c (qemudDomainBlockPeek)
(qemuDomainAttachDeviceConfig, qemuDomainUpdateDeviceConfig)
(qemuDomainGetBlockInfo, qemuDiskPathToAlias): Likewise.
* src/qemu/qemu_process.c (qemuProcessFindDomainDiskByPath):
Likewise.
* src/libxl/libxl_driver.c (libxlDomainAttachDeviceDiskLive)
(libxlDomainDetachDeviceDiskLive, libxlDomainAttachDeviceConfig)
(libxlDomainUpdateDeviceConfig): Likewise.
* src/uml/uml_driver.c (umlDomainBlockPeek): Likewise.
* src/xen/xend_internal.c (xenDaemonDomainBlockPeek): Likewise.
* docs/formatsnapshot.html.in: Update documentation.
* tools/virsh.pod (domblkstat, domblkinfo): Likewise.
* docs/schemas/domaincommon.rng (diskTarget): Tighten pattern on
disk targets.
* docs/schemas/domainsnapshot.rng (disksnapshot): Update to match.
* tests/domainsnapshotxml2xmlin/disk_snapshot.xml: Update test.
2011-08-20 02:38:36 +00:00
|
|
|
ret = 0;
|
|
|
|
|
2008-12-04 21:13:58 +00:00
|
|
|
cleanup:
|
2010-11-09 20:48:48 +00:00
|
|
|
VIR_FORCE_CLOSE(fd);
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(vm);
|
2008-11-19 16:58:23 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-10-22 13:40:26 +00:00
|
|
|
static int
|
|
|
|
umlDomainOpenConsole(virDomainPtr dom,
|
2011-09-16 12:05:58 +00:00
|
|
|
const char *dev_name,
|
2010-10-22 13:40:26 +00:00
|
|
|
virStreamPtr st,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm = NULL;
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
int ret = -1;
|
|
|
|
virDomainChrDefPtr chr = NULL;
|
2011-10-20 13:57:10 +00:00
|
|
|
size_t i;
|
2010-10-22 13:40:26 +00:00
|
|
|
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
|
|
|
umlDriverLock(driver);
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2013-01-11 16:04:47 +00:00
|
|
|
vm = virDomainObjListFindByUUID(driver->domains, dom->uuid);
|
2010-10-22 13:40:26 +00:00
|
|
|
if (!vm) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
2010-10-22 13:40:26 +00:00
|
|
|
_("no domain with matching uuid '%s'"), uuidstr);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
2010-10-22 13:40:26 +00:00
|
|
|
"%s", _("domain is not running"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-09-16 12:05:58 +00:00
|
|
|
if (dev_name) {
|
2011-10-20 13:57:10 +00:00
|
|
|
for (i = 0 ; i < vm->def->nconsoles ; i++) {
|
|
|
|
if (vm->def->consoles[i]->info.alias &&
|
|
|
|
STREQ(vm->def->consoles[i]->info.alias, dev_name)) {
|
|
|
|
chr = vm->def->consoles[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2010-10-22 13:40:26 +00:00
|
|
|
} else {
|
Allow multiple consoles per virtual guest
While Xen only has a single paravirt console, UML, and
QEMU both support multiple paravirt consoles. The LXC
driver can also be trivially made to support multiple
consoles. This patch extends the XML to allow multiple
<console> elements in the XML. It also makes the UML
and QEMU drivers support this config.
* src/conf/domain_conf.c, src/conf/domain_conf.h: Allow
multiple <console> devices
* src/lxc/lxc_driver.c, src/xen/xen_driver.c,
src/xenxs/xen_sxpr.c, src/xenxs/xen_xm.c: Update for
internal API changes
* src/security/security_selinux.c, src/security/virt-aa-helper.c:
Only label consoles that aren't a copy of the serial device
* src/qemu/qemu_command.c, src/qemu/qemu_driver.c,
src/qemu/qemu_process.c, src/uml/uml_conf.c,
src/uml/uml_driver.c: Support multiple console devices
* tests/qemuxml2xmltest.c, tests/qemuxml2argvtest.c: Extra
tests for multiple virtio consoles. Set QEMU_CAPS_CHARDEV
for all console /channel tests
* tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-auto.args,
tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.args
tests/qemuxml2argvdata/qemuxml2argv-console-virtio.args: Update
for correct chardev syntax
* tests/qemuxml2argvdata/qemuxml2argv-console-virtio-many.args,
tests/qemuxml2argvdata/qemuxml2argv-console-virtio-many.xml: New
test file
2011-02-23 18:27:23 +00:00
|
|
|
if (vm->def->nconsoles)
|
|
|
|
chr = vm->def->consoles[0];
|
2010-10-22 13:40:26 +00:00
|
|
|
else if (vm->def->nserials)
|
|
|
|
chr = vm->def->serials[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!chr) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2011-10-20 13:57:10 +00:00
|
|
|
_("cannot find console device '%s'"),
|
|
|
|
dev_name ? dev_name : _("default"));
|
2010-10-22 13:40:26 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
domain_conf: split source data out from ChrDef
This opens up the possibility of reusing the smaller ChrSourceDef
for both qemu monitor and a passthrough smartcard device.
* src/conf/domain_conf.h (_virDomainChrDef): Factor host
details...
(_virDomainChrSourceDef): ...into new struct.
(virDomainChrSourceDefFree): New prototype.
* src/conf/domain_conf.c (virDomainChrDefFree)
(virDomainChrDefParseXML, virDomainChrDefFormat): Split...
(virDomainChrSourceDefClear, virDomainChrSourceDefFree)
(virDomainChrSourceDefParseXML, virDomainChrSourceDefFormat):
...into new functions.
(virDomainChrDefParseTargetXML): Update clients to reflect type
split.
* src/vmx/vmx.c (virVMXParseSerial, virVMXParseParallel)
(virVMXFormatSerial, virVMXFormatParallel): Likewise.
* src/xen/xen_driver.c (xenUnifiedDomainOpenConsole): Likewise.
* src/xen/xend_internal.c (xenDaemonParseSxprChar)
(xenDaemonFormatSxprChr): Likewise.
* src/vbox/vbox_tmpl.c (vboxDomainDumpXML, vboxAttachSerial)
(vboxAttachParallel): Likewise.
* src/security/security_dac.c (virSecurityDACSetChardevLabel)
(virSecurityDACSetChardevCallback)
(virSecurityDACRestoreChardevLabel)
(virSecurityDACRestoreChardevCallback): Likewise.
* src/security/security_selinux.c (SELinuxSetSecurityChardevLabel)
(SELinuxSetSecurityChardevCallback)
(SELinuxRestoreSecurityChardevLabel)
(SELinuxSetSecurityChardevCallback): Likewise.
* src/security/virt-aa-helper.c (get_files): Likewise.
* src/lxc/lxc_driver.c (lxcVmStart, lxcDomainOpenConsole):
Likewise.
* src/uml/uml_conf.c (umlBuildCommandLineChr): Likewise.
* src/uml/uml_driver.c (umlIdentifyOneChrPTY, umlIdentifyChrPTY)
(umlDomainOpenConsole): Likewise.
* src/qemu/qemu_command.c (qemuBuildChrChardevStr)
(qemuBuildChrArgStr, qemuBuildCommandLine)
(qemuParseCommandLineChr): Likewise.
* src/qemu/qemu_domain.c (qemuDomainObjPrivateXMLFormat)
(qemuDomainObjPrivateXMLParse): Likewise.
* src/qemu/qemu_cgroup.c (qemuSetupChardevCgroup): Likewise.
* src/qemu/qemu_hotplug.c (qemuDomainAttachNetDevice): Likewise.
* src/qemu/qemu_driver.c (qemudFindCharDevicePTYsMonitor)
(qemudFindCharDevicePTYs, qemuPrepareChardevDevice)
(qemuPrepareMonitorChr, qemudShutdownVMDaemon)
(qemuDomainOpenConsole): Likewise.
* src/qemu/qemu_command.h (qemuBuildChrChardevStr)
(qemuBuildChrArgStr): Delete, now that they are static.
* src/libvirt_private.syms (domain_conf.h): New exports.
* cfg.mk (useless_free_options): Update list.
* tests/qemuxml2argvtest.c (testCompareXMLToArgvFiles): Update
tests.
2011-01-07 22:45:01 +00:00
|
|
|
if (chr->source.type != VIR_DOMAIN_CHR_TYPE_PTY) {
|
2012-07-18 12:01:08 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2011-09-16 12:05:58 +00:00
|
|
|
_("character device %s is not using a PTY"), dev_name);
|
2010-10-22 13:40:26 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-04-05 10:27:35 +00:00
|
|
|
if (virFDStreamOpenFile(st, chr->source.data.file.path,
|
2011-08-02 17:19:53 +00:00
|
|
|
0, 0, O_RDWR) < 0)
|
2010-10-22 13:40:26 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(vm);
|
2010-10-22 13:40:26 +00:00
|
|
|
umlDriverUnlock(driver);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2009-07-06 15:06:11 +00:00
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
umlConnectDomainEventRegister(virConnectPtr conn,
|
|
|
|
virConnectDomainEventCallback callback,
|
|
|
|
void *opaque,
|
|
|
|
virFreeCallback freecb)
|
2009-07-06 15:06:11 +00:00
|
|
|
{
|
|
|
|
struct uml_driver *driver = conn->privateData;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
umlDriverLock(driver);
|
2011-12-13 11:14:46 +00:00
|
|
|
ret = virDomainEventStateRegister(conn,
|
|
|
|
driver->domainEventState,
|
|
|
|
callback, opaque, freecb);
|
2009-07-06 15:06:11 +00:00
|
|
|
umlDriverUnlock(driver);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
umlConnectDomainEventDeregister(virConnectPtr conn,
|
|
|
|
virConnectDomainEventCallback callback)
|
2009-07-06 15:06:11 +00:00
|
|
|
{
|
|
|
|
struct uml_driver *driver = conn->privateData;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
umlDriverLock(driver);
|
|
|
|
ret = virDomainEventStateDeregister(conn,
|
|
|
|
driver->domainEventState,
|
|
|
|
callback);
|
|
|
|
umlDriverUnlock(driver);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
umlConnectDomainEventRegisterAny(virConnectPtr conn,
|
|
|
|
virDomainPtr dom,
|
|
|
|
int eventID,
|
|
|
|
virConnectDomainEventGenericCallback callback,
|
|
|
|
void *opaque,
|
|
|
|
virFreeCallback freecb)
|
2009-07-06 15:06:11 +00:00
|
|
|
{
|
|
|
|
struct uml_driver *driver = conn->privateData;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
umlDriverLock(driver);
|
2011-12-13 11:14:46 +00:00
|
|
|
if (virDomainEventStateRegisterID(conn,
|
|
|
|
driver->domainEventState,
|
|
|
|
dom, eventID,
|
|
|
|
callback, opaque, freecb, &ret) < 0)
|
Return count of callbacks when registering callbacks
When registering a callback for a particular event some callers
need to know how many callbacks already exist for that event.
While it is possible to ask for a count, this is not free from
race conditions when threaded. Thus the API for registering
callbacks should return the count of callbacks. Also rename
virDomainEventStateDeregisterAny to virDomainEventStateDeregisterID
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Return count of callbacks when
registering callbacks
* src/libxl/libxl_driver.c, src/libxl/libxl_driver.c,
src/qemu/qemu_driver.c, src/remote/remote_driver.c,
src/remote/remote_driver.c, src/uml/uml_driver.c,
src/vbox/vbox_tmpl.c, src/xen/xen_driver.c: Update
for change in APIs
2011-12-13 23:38:54 +00:00
|
|
|
ret = -1;
|
2009-07-06 15:06:11 +00:00
|
|
|
umlDriverUnlock(driver);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2013-04-23 12:50:18 +00:00
|
|
|
umlConnectDomainEventDeregisterAny(virConnectPtr conn,
|
|
|
|
int callbackID)
|
2009-07-06 15:06:11 +00:00
|
|
|
{
|
|
|
|
struct uml_driver *driver = conn->privateData;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
umlDriverLock(driver);
|
Return count of callbacks when registering callbacks
When registering a callback for a particular event some callers
need to know how many callbacks already exist for that event.
While it is possible to ask for a count, this is not free from
race conditions when threaded. Thus the API for registering
callbacks should return the count of callbacks. Also rename
virDomainEventStateDeregisterAny to virDomainEventStateDeregisterID
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Return count of callbacks when
registering callbacks
* src/libxl/libxl_driver.c, src/libxl/libxl_driver.c,
src/qemu/qemu_driver.c, src/remote/remote_driver.c,
src/remote/remote_driver.c, src/uml/uml_driver.c,
src/vbox/vbox_tmpl.c, src/xen/xen_driver.c: Update
for change in APIs
2011-12-13 23:38:54 +00:00
|
|
|
ret = virDomainEventStateDeregisterID(conn,
|
|
|
|
driver->domainEventState,
|
|
|
|
callbackID);
|
2009-07-06 15:06:11 +00:00
|
|
|
umlDriverUnlock(driver);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* driver must be locked before calling */
|
|
|
|
static void umlDomainEventQueue(struct uml_driver *driver,
|
|
|
|
virDomainEventPtr event)
|
|
|
|
{
|
|
|
|
virDomainEventStateQueue(driver->domainEventState, event);
|
|
|
|
}
|
|
|
|
|
2013-04-23 12:50:18 +00:00
|
|
|
static int umlConnectListAllDomains(virConnectPtr conn,
|
|
|
|
virDomainPtr **domains,
|
|
|
|
unsigned int flags)
|
2012-06-11 09:04:57 +00:00
|
|
|
{
|
|
|
|
struct uml_driver *driver = conn->privateData;
|
|
|
|
int ret = -1;
|
|
|
|
|
2012-08-03 15:48:05 +00:00
|
|
|
virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
|
2012-06-11 09:04:57 +00:00
|
|
|
|
|
|
|
umlDriverLock(driver);
|
2013-01-11 16:04:47 +00:00
|
|
|
ret = virDomainObjListExport(driver->domains, conn, domains, flags);
|
2012-06-11 09:04:57 +00:00
|
|
|
umlDriverUnlock(driver);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2009-07-06 15:06:11 +00:00
|
|
|
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
static virDriver umlDriver = {
|
Convert all driver struct intializers to C99 style
Change all the driver struct initializers to use the
C99 style, leaving out unused fields. This will make
it possible to add new APIs without changing every
driver. eg change:
qemudDomainResume, /* domainResume */
qemudDomainShutdown, /* domainShutdown */
NULL, /* domainReboot */
qemudDomainDestroy, /* domainDestroy */
to
.domainResume = qemudDomainResume,
.domainShutdown = qemudDomainShutdown,
.domainDestroy = qemudDomainDestroy,
And get rid of any existing C99 style initializersr which
set NULL, eg change
.listPools = vboxStorageListPools,
.numOfDefinedPools = NULL,
.listDefinedPools = NULL,
.findPoolSources = NULL,
.poolLookupByName = vboxStoragePoolLookupByName,
to
.listPools = vboxStorageListPools,
.poolLookupByName = vboxStoragePoolLookupByName,
2011-05-13 10:16:31 +00:00
|
|
|
.no = VIR_DRV_UML,
|
|
|
|
.name = "UML",
|
2013-04-23 12:50:18 +00:00
|
|
|
.connectOpen = umlConnectOpen, /* 0.5.0 */
|
|
|
|
.connectClose = umlConnectClose, /* 0.5.0 */
|
|
|
|
.connectGetType = umlConnectGetType, /* 0.5.0 */
|
|
|
|
.connectGetVersion = umlConnectGetVersion, /* 0.5.0 */
|
2013-04-22 17:26:01 +00:00
|
|
|
.connectGetHostname = virGetHostname, /* 0.5.0 */
|
2011-05-13 13:35:01 +00:00
|
|
|
.nodeGetInfo = nodeGetInfo, /* 0.5.0 */
|
2013-04-23 12:50:18 +00:00
|
|
|
.connectGetCapabilities = umlConnectGetCapabilities, /* 0.5.0 */
|
|
|
|
.connectListDomains = umlConnectListDomains, /* 0.5.0 */
|
|
|
|
.connectNumOfDomains = umlConnectNumOfDomains, /* 0.5.0 */
|
|
|
|
.connectListAllDomains = umlConnectListAllDomains, /* 0.9.13 */
|
|
|
|
.domainCreateXML = umlDomainCreateXML, /* 0.5.0 */
|
2011-05-13 13:35:01 +00:00
|
|
|
.domainLookupByID = umlDomainLookupByID, /* 0.5.0 */
|
|
|
|
.domainLookupByUUID = umlDomainLookupByUUID, /* 0.5.0 */
|
|
|
|
.domainLookupByName = umlDomainLookupByName, /* 0.5.0 */
|
|
|
|
.domainShutdown = umlDomainShutdown, /* 0.5.0 */
|
2011-10-05 17:31:55 +00:00
|
|
|
.domainShutdownFlags = umlDomainShutdownFlags, /* 0.9.10 */
|
2011-05-13 13:35:01 +00:00
|
|
|
.domainDestroy = umlDomainDestroy, /* 0.5.0 */
|
2011-07-21 07:54:28 +00:00
|
|
|
.domainDestroyFlags = umlDomainDestroyFlags, /* 0.9.4 */
|
2011-05-13 13:35:01 +00:00
|
|
|
.domainGetOSType = umlDomainGetOSType, /* 0.5.0 */
|
|
|
|
.domainGetMaxMemory = umlDomainGetMaxMemory, /* 0.5.0 */
|
|
|
|
.domainSetMaxMemory = umlDomainSetMaxMemory, /* 0.5.0 */
|
|
|
|
.domainSetMemory = umlDomainSetMemory, /* 0.5.0 */
|
|
|
|
.domainGetInfo = umlDomainGetInfo, /* 0.5.0 */
|
|
|
|
.domainGetState = umlDomainGetState, /* 0.9.2 */
|
|
|
|
.domainGetXMLDesc = umlDomainGetXMLDesc, /* 0.5.0 */
|
2013-04-23 12:50:18 +00:00
|
|
|
.connectListDefinedDomains = umlConnectListDefinedDomains, /* 0.5.0 */
|
|
|
|
.connectNumOfDefinedDomains = umlConnectNumOfDefinedDomains, /* 0.5.0 */
|
|
|
|
.domainCreate = umlDomainCreate, /* 0.5.0 */
|
|
|
|
.domainCreateWithFlags = umlDomainCreateWithFlags, /* 0.8.2 */
|
|
|
|
.domainDefineXML = umlDomainDefineXML, /* 0.5.0 */
|
2011-05-13 13:35:01 +00:00
|
|
|
.domainUndefine = umlDomainUndefine, /* 0.5.0 */
|
2011-07-20 03:08:21 +00:00
|
|
|
.domainUndefineFlags = umlDomainUndefineFlags, /* 0.9.4 */
|
2011-05-13 13:35:01 +00:00
|
|
|
.domainAttachDevice = umlDomainAttachDevice, /* 0.8.4 */
|
|
|
|
.domainAttachDeviceFlags = umlDomainAttachDeviceFlags, /* 0.8.4 */
|
|
|
|
.domainDetachDevice = umlDomainDetachDevice, /* 0.8.4 */
|
|
|
|
.domainDetachDeviceFlags = umlDomainDetachDeviceFlags, /* 0.8.4 */
|
|
|
|
.domainGetAutostart = umlDomainGetAutostart, /* 0.5.0 */
|
|
|
|
.domainSetAutostart = umlDomainSetAutostart, /* 0.5.0 */
|
|
|
|
.domainBlockPeek = umlDomainBlockPeek, /* 0.5.0 */
|
2011-06-07 01:02:55 +00:00
|
|
|
.nodeGetCPUStats = nodeGetCPUStats, /* 0.9.3 */
|
2011-06-07 01:11:17 +00:00
|
|
|
.nodeGetMemoryStats = nodeGetMemoryStats, /* 0.9.3 */
|
2011-05-13 13:35:01 +00:00
|
|
|
.nodeGetCellsFreeMemory = nodeGetCellsFreeMemory, /* 0.5.0 */
|
|
|
|
.nodeGetFreeMemory = nodeGetFreeMemory, /* 0.5.0 */
|
2012-10-16 14:05:15 +00:00
|
|
|
.nodeGetCPUMap = nodeGetCPUMap, /* 1.0.0 */
|
2013-04-23 12:50:18 +00:00
|
|
|
.connectDomainEventRegister = umlConnectDomainEventRegister, /* 0.9.4 */
|
|
|
|
.connectDomainEventDeregister = umlConnectDomainEventDeregister, /* 0.9.4 */
|
|
|
|
.connectIsEncrypted = umlConnectIsEncrypted, /* 0.7.3 */
|
|
|
|
.connectIsSecure = umlConnectIsSecure, /* 0.7.3 */
|
2011-05-13 13:35:01 +00:00
|
|
|
.domainIsActive = umlDomainIsActive, /* 0.7.3 */
|
|
|
|
.domainIsPersistent = umlDomainIsPersistent, /* 0.7.3 */
|
|
|
|
.domainIsUpdated = umlDomainIsUpdated, /* 0.8.6 */
|
2013-04-23 12:50:18 +00:00
|
|
|
.connectDomainEventRegisterAny = umlConnectDomainEventRegisterAny, /* 0.9.4 */
|
|
|
|
.connectDomainEventDeregisterAny = umlConnectDomainEventDeregisterAny, /* 0.9.4 */
|
2011-05-13 13:35:01 +00:00
|
|
|
.domainOpenConsole = umlDomainOpenConsole, /* 0.8.6 */
|
2013-04-23 12:50:18 +00:00
|
|
|
.connectIsAlive = umlConnectIsAlive, /* 0.9.8 */
|
Implement the core API to suspend/resume the host
Add the core functions that implement the functionality of the API.
Suspend is done by using an asynchronous mechanism so that we can return
the status to the caller before the host gets suspended. This asynchronous
operation is achieved by suspending the host in a separate thread of
execution. However, returning the status to the caller is only best-effort,
but not guaranteed.
To resume the host, an RTC alarm is set up (based on how long we want to
suspend) before suspending the host. When this alarm fires, the host
gets woken up.
Suspend-to-RAM operation on a host running Linux can take upto more than 20
seconds, depending on the load of the system. (Freezing of tasks, an operation
preceding any suspend operation, is given up after a 20 second timeout).
And Suspend-to-Disk can take even more time, considering the time required
for compaction, creating the memory image and writing it to disk etc.
So, we do not allow the user to specify a suspend duration of less than 60
seconds, to be on the safer side, since we don't want to prematurely declare
failure when we only had to wait for some more time.
2011-11-29 09:07:38 +00:00
|
|
|
.nodeSuspendForDuration = nodeSuspendForDuration, /* 0.9.8 */
|
2012-09-14 14:42:17 +00:00
|
|
|
.nodeGetMemoryParameters = nodeGetMemoryParameters, /* 0.10.2 */
|
|
|
|
.nodeSetMemoryParameters = nodeSetMemoryParameters, /* 0.10.2 */
|
2008-11-19 16:58:23 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static virStateDriver umlStateDriver = {
|
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
|
|
|
.name = "UML",
|
2013-04-23 12:50:18 +00:00
|
|
|
.stateInitialize = umlStateInitialize,
|
|
|
|
.stateCleanup = umlStateCleanup,
|
|
|
|
.stateReload = umlStateReload,
|
2008-11-19 16:58:23 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
int umlRegister(void) {
|
|
|
|
virRegisterDriver(¨Driver);
|
|
|
|
virRegisterStateDriver(¨StateDriver);
|
|
|
|
return 0;
|
|
|
|
}
|