2008-03-21 15:03:37 +00:00
|
|
|
/*
|
2012-01-07 12:36:46 +00:00
|
|
|
* Copyright (C) 2010-2012 Red Hat, Inc.
|
2008-03-21 15:03:37 +00:00
|
|
|
* Copyright IBM Corp. 2008
|
|
|
|
*
|
|
|
|
* lxc_driver.c: linux container driver functions
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* David L. Leskovec <dlesko at linux.vnet.ibm.com>
|
|
|
|
*
|
|
|
|
* 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-07-21 10:06:23 +00:00
|
|
|
* License along with this library; If not, see
|
|
|
|
* <http://www.gnu.org/licenses/>.
|
2008-03-21 15:03:37 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
2008-04-10 07:30:52 +00:00
|
|
|
#include <fcntl.h>
|
2008-03-21 15:03:37 +00:00
|
|
|
#include <sched.h>
|
|
|
|
#include <sys/utsname.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/types.h>
|
2008-08-13 10:52:15 +00:00
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/un.h>
|
|
|
|
#include <sys/poll.h>
|
2008-03-21 15:03:37 +00:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <wait.h>
|
|
|
|
|
2008-11-04 22:30:33 +00:00
|
|
|
#include "virterror_internal.h"
|
2008-11-06 16:36:07 +00:00
|
|
|
#include "logging.h"
|
2008-11-04 23:22:06 +00:00
|
|
|
#include "datatypes.h"
|
2008-03-21 15:03:37 +00:00
|
|
|
#include "lxc_conf.h"
|
2008-04-10 07:30:52 +00:00
|
|
|
#include "lxc_container.h"
|
2012-07-13 10:16:23 +00:00
|
|
|
#include "lxc_domain.h"
|
2008-03-21 15:03:37 +00:00
|
|
|
#include "lxc_driver.h"
|
2012-07-13 11:39:29 +00:00
|
|
|
#include "lxc_process.h"
|
2008-06-09 22:51:32 +00:00
|
|
|
#include "memory.h"
|
2008-04-10 07:30:52 +00:00
|
|
|
#include "util.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 "virnetdevbridge.h"
|
2011-11-02 16:03:09 +00:00
|
|
|
#include "virnetdevveth.h"
|
2009-06-03 13:29:23 +00:00
|
|
|
#include "nodeinfo.h"
|
2009-07-06 15:05:32 +00:00
|
|
|
#include "uuid.h"
|
2009-11-12 13:55:44 +00:00
|
|
|
#include "stats_linux.h"
|
2010-03-26 15:02:05 +00:00
|
|
|
#include "hooks.h"
|
2011-07-19 18:32:58 +00:00
|
|
|
#include "virfile.h"
|
2011-08-05 13:13:12 +00:00
|
|
|
#include "virpidfile.h"
|
2010-10-22 13:40:26 +00:00
|
|
|
#include "fdstream.h"
|
2011-07-04 11:06:14 +00:00
|
|
|
#include "domain_audit.h"
|
2011-06-07 13:29:08 +00:00
|
|
|
#include "domain_nwfilter.h"
|
2011-10-04 12:47:26 +00:00
|
|
|
#include "network/bridge_driver.h"
|
2011-11-02 15:53:39 +00:00
|
|
|
#include "virnetdev.h"
|
2012-02-10 21:09:00 +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"
|
2011-11-29 12:33:23 +00:00
|
|
|
#include "virtime.h"
|
2012-01-07 12:47:43 +00:00
|
|
|
#include "virtypedparam.h"
|
2012-02-24 18:48:55 +00:00
|
|
|
#include "viruri.h"
|
2008-03-21 15:03:37 +00:00
|
|
|
|
2009-01-20 17:13:33 +00:00
|
|
|
#define VIR_FROM_THIS VIR_FROM_LXC
|
|
|
|
|
2011-05-05 20:35:00 +00:00
|
|
|
|
2010-10-12 16:39:05 +00:00
|
|
|
#define LXC_NB_MEM_PARAM 3
|
|
|
|
|
2009-06-12 13:20:13 +00:00
|
|
|
static int lxcStartup(int privileged);
|
2008-03-27 09:34:06 +00:00
|
|
|
static int lxcShutdown(void);
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr lxc_driver = NULL;
|
2008-03-21 15:03:37 +00:00
|
|
|
|
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
|
|
|
/* callbacks for nwfilter */
|
|
|
|
static int
|
|
|
|
lxcVMFilterRebuild(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|
|
|
virHashIterator iter, void *data)
|
|
|
|
{
|
|
|
|
virHashForEach(lxc_driver->domains.objs, iter, data);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
lxcVMDriverLock(void)
|
|
|
|
{
|
|
|
|
lxcDriverLock(lxc_driver);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
lxcVMDriverUnlock(void)
|
|
|
|
{
|
|
|
|
lxcDriverUnlock(lxc_driver);
|
|
|
|
}
|
|
|
|
|
|
|
|
static virNWFilterCallbackDriver lxcCallbackDriver = {
|
|
|
|
.name = "LXC",
|
|
|
|
.vmFilterRebuild = lxcVMFilterRebuild,
|
|
|
|
.vmDriverLock = lxcVMDriverLock,
|
|
|
|
.vmDriverUnlock = lxcVMDriverUnlock,
|
|
|
|
};
|
|
|
|
|
2008-03-21 15:03:37 +00:00
|
|
|
/* Functions */
|
|
|
|
|
|
|
|
static virDrvOpenStatus lxcOpen(virConnectPtr conn,
|
|
|
|
virConnectAuthPtr auth ATTRIBUTE_UNUSED,
|
2011-07-06 22:33:53 +00:00
|
|
|
unsigned int flags)
|
2008-03-21 15:03:37 +00:00
|
|
|
{
|
2011-07-06 22:33:53 +00:00
|
|
|
virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
|
|
|
|
|
2008-03-21 15:03:37 +00:00
|
|
|
/* Verify uri was specified */
|
2008-11-17 11:44:51 +00:00
|
|
|
if (conn->uri == NULL) {
|
2009-06-12 12:06:15 +00:00
|
|
|
if (lxc_driver == NULL)
|
|
|
|
return VIR_DRV_OPEN_DECLINED;
|
2009-01-30 16:51:33 +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("lxc:///")))
|
2008-11-17 11:44:51 +00:00
|
|
|
return VIR_DRV_OPEN_ERROR;
|
2009-06-12 12:06:15 +00:00
|
|
|
} else {
|
|
|
|
if (conn->uri->scheme == NULL ||
|
|
|
|
STRNEQ(conn->uri->scheme, "lxc"))
|
|
|
|
return VIR_DRV_OPEN_DECLINED;
|
|
|
|
|
|
|
|
/* Leave for remote driver */
|
|
|
|
if (conn->uri->server != NULL)
|
|
|
|
return VIR_DRV_OPEN_DECLINED;
|
|
|
|
|
|
|
|
/* If path isn't '/' then they typoed, tell them correct path */
|
2010-02-11 15:00:25 +00:00
|
|
|
if (conn->uri->path != NULL &&
|
|
|
|
STRNEQ(conn->uri->path, "/")) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unexpected LXC URI path '%s', try lxc:///"),
|
|
|
|
conn->uri->path);
|
2009-06-12 12:06:15 +00:00
|
|
|
return VIR_DRV_OPEN_ERROR;
|
|
|
|
}
|
2008-03-21 15:03:37 +00:00
|
|
|
|
2009-06-12 12:06:15 +00:00
|
|
|
/* URI was good, but driver isn't active */
|
|
|
|
if (lxc_driver == NULL) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("lxc state driver is not active"));
|
2009-06-12 12:06:15 +00:00
|
|
|
return VIR_DRV_OPEN_ERROR;
|
|
|
|
}
|
|
|
|
}
|
2009-01-30 16:51:33 +00:00
|
|
|
|
2008-03-27 09:34:06 +00:00
|
|
|
conn->privateData = lxc_driver;
|
2008-03-21 15:03:37 +00:00
|
|
|
|
|
|
|
return VIR_DRV_OPEN_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int lxcClose(virConnectPtr conn)
|
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = conn->privateData;
|
2009-07-06 15:04:36 +00:00
|
|
|
|
|
|
|
lxcDriverLock(driver);
|
2012-07-13 11:49:24 +00:00
|
|
|
virLXCProcessAutoDestroyRun(driver, conn);
|
2009-07-06 15:04:36 +00:00
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
|
2008-03-27 09:34:06 +00:00
|
|
|
conn->privateData = NULL;
|
|
|
|
return 0;
|
2008-03-21 15:03:37 +00:00
|
|
|
}
|
|
|
|
|
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 lxcIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
/* Trivially secure, since always inside the daemon */
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int lxcIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
/* Not encrypted, but remote driver takes care of that */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-09-23 06:56:13 +00:00
|
|
|
static int lxcIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-06-03 13:29:23 +00:00
|
|
|
static char *lxcGetCapabilities(virConnectPtr conn) {
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = conn->privateData;
|
2009-06-03 13:29:23 +00:00
|
|
|
char *xml;
|
|
|
|
|
|
|
|
lxcDriverLock(driver);
|
|
|
|
if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL)
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-06-03 13:29:23 +00:00
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
|
|
|
|
return xml;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-03-21 15:03:37 +00:00
|
|
|
static virDomainPtr lxcDomainLookupByID(virConnectPtr conn,
|
|
|
|
int id)
|
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = conn->privateData;
|
2008-12-04 21:11:41 +00:00
|
|
|
virDomainObjPtr vm;
|
|
|
|
virDomainPtr dom = NULL;
|
2008-03-21 15:03:37 +00:00
|
|
|
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverLock(driver);
|
2008-12-04 21:11:41 +00:00
|
|
|
vm = virDomainFindByID(&driver->domains, id);
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
|
2008-03-21 15:03:37 +00:00
|
|
|
if (!vm) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching id %d"), id);
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
2008-03-21 15:03:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
2008-12-04 21:11:41 +00:00
|
|
|
if (dom)
|
2008-03-21 15:03:37 +00:00
|
|
|
dom->id = vm->def->id;
|
|
|
|
|
2008-12-04 21:11:41 +00:00
|
|
|
cleanup:
|
2008-12-04 21:12:41 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
2008-03-21 15:03:37 +00:00
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
|
|
|
static virDomainPtr lxcDomainLookupByUUID(virConnectPtr conn,
|
|
|
|
const unsigned char *uuid)
|
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = conn->privateData;
|
2008-12-04 21:11:41 +00:00
|
|
|
virDomainObjPtr vm;
|
|
|
|
virDomainPtr dom = NULL;
|
2008-03-21 15:03:37 +00:00
|
|
|
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverLock(driver);
|
2008-12-04 21:11:41 +00:00
|
|
|
vm = virDomainFindByUUID(&driver->domains, uuid);
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
|
2008-03-21 15:03:37 +00:00
|
|
|
if (!vm) {
|
2010-05-03 11:59:03 +00:00
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(uuid, uuidstr);
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
2008-03-21 15:03:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
2008-12-04 21:11:41 +00:00
|
|
|
if (dom)
|
2008-03-21 15:03:37 +00:00
|
|
|
dom->id = vm->def->id;
|
|
|
|
|
2008-12-04 21:11:41 +00:00
|
|
|
cleanup:
|
2008-12-04 21:12:41 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
2008-03-21 15:03:37 +00:00
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
|
|
|
static virDomainPtr lxcDomainLookupByName(virConnectPtr conn,
|
|
|
|
const char *name)
|
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = conn->privateData;
|
2008-12-04 21:11:41 +00:00
|
|
|
virDomainObjPtr vm;
|
|
|
|
virDomainPtr dom = NULL;
|
2008-03-21 15:03:37 +00:00
|
|
|
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverLock(driver);
|
2008-12-04 21:11:41 +00:00
|
|
|
vm = virDomainFindByName(&driver->domains, name);
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverUnlock(driver);
|
2008-03-21 15:03:37 +00:00
|
|
|
if (!vm) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching name '%s'"), name);
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
2008-03-21 15:03:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
2008-12-04 21:11:41 +00:00
|
|
|
if (dom)
|
2008-03-21 15:03:37 +00:00
|
|
|
dom->id = vm->def->id;
|
|
|
|
|
2008-12-04 21:11:41 +00:00
|
|
|
cleanup:
|
2008-12-04 21:12:41 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
2008-03-21 15:03:37 +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 lxcDomainIsActive(virDomainPtr dom)
|
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = dom->conn->privateData;
|
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
|
|
|
virDomainObjPtr obj;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
lxcDriverLock(driver);
|
|
|
|
obj = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
if (!obj) {
|
2010-05-03 11:59:03 +00:00
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
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)
|
|
|
|
virDomainObjUnlock(obj);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int lxcDomainIsPersistent(virDomainPtr dom)
|
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = dom->conn->privateData;
|
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
|
|
|
virDomainObjPtr obj;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
lxcDriverLock(driver);
|
|
|
|
obj = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
if (!obj) {
|
2010-05-03 11:59:03 +00:00
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
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)
|
|
|
|
virDomainObjUnlock(obj);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-11-24 07:43:15 +00:00
|
|
|
static int lxcDomainIsUpdated(virDomainPtr dom)
|
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = dom->conn->privateData;
|
2010-11-24 07:43:15 +00:00
|
|
|
virDomainObjPtr obj;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
lxcDriverLock(driver);
|
|
|
|
obj = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
if (!obj) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
2010-11-24 07:43:15 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
ret = obj->updated;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (obj)
|
|
|
|
virDomainObjUnlock(obj);
|
|
|
|
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
|
|
|
|
2008-08-13 12:50:55 +00:00
|
|
|
static int lxcListDomains(virConnectPtr conn, int *ids, int nids) {
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr 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-10-10 14:20:37 +00:00
|
|
|
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverLock(driver);
|
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
|
|
|
n = virDomainObjListGetActiveIDs(&driver->domains, ids, nids);
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverUnlock(driver);
|
2008-10-10 14:20:37 +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-03-21 15:03:37 +00:00
|
|
|
}
|
2008-12-04 21:11:41 +00:00
|
|
|
|
2008-08-13 12:50:55 +00:00
|
|
|
static int lxcNumDomains(virConnectPtr conn) {
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr 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-10-10 14:20:37 +00:00
|
|
|
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverLock(driver);
|
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
|
|
|
n = virDomainObjListNumOfDomains(&driver->domains, 1);
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverUnlock(driver);
|
2008-10-10 14:20:37 +00:00
|
|
|
|
2008-08-13 12:50:55 +00:00
|
|
|
return n;
|
2008-03-21 15:03:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int lxcListDefinedDomains(virConnectPtr conn,
|
2008-08-13 12:50:55 +00:00
|
|
|
char **const names, int nnames) {
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr 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-10-10 14:20:37 +00:00
|
|
|
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverLock(driver);
|
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
|
|
|
n = virDomainObjListGetInactiveNames(&driver->domains, names, nnames);
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverUnlock(driver);
|
2008-10-10 14:20:37 +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-03-21 15:03:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-08-13 12:50:55 +00:00
|
|
|
static int lxcNumDefinedDomains(virConnectPtr conn) {
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr 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-10-10 14:20:37 +00:00
|
|
|
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverLock(driver);
|
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
|
|
|
n = virDomainObjListNumOfDomains(&driver->domains, 0);
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverUnlock(driver);
|
2008-10-10 14:20:37 +00:00
|
|
|
|
2008-08-13 12:50:55 +00:00
|
|
|
return n;
|
2008-03-21 15:03:37 +00:00
|
|
|
}
|
|
|
|
|
2008-08-13 12:50:55 +00:00
|
|
|
|
|
|
|
|
2008-03-21 15:03:37 +00:00
|
|
|
static virDomainPtr lxcDomainDefine(virConnectPtr conn, const char *xml)
|
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = conn->privateData;
|
2008-12-04 21:11:41 +00:00
|
|
|
virDomainDefPtr def = NULL;
|
2008-12-04 21:12:41 +00:00
|
|
|
virDomainObjPtr vm = NULL;
|
2008-12-04 21:11:41 +00:00
|
|
|
virDomainPtr dom = NULL;
|
2009-07-06 15:04:36 +00:00
|
|
|
virDomainEventPtr event = NULL;
|
2009-11-02 18:37:38 +00:00
|
|
|
int dupVM;
|
2008-03-21 15:03:37 +00:00
|
|
|
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverLock(driver);
|
2010-02-09 18:58:01 +00:00
|
|
|
if (!(def = virDomainDefParseString(driver->caps, xml,
|
2011-07-11 17:29:09 +00:00
|
|
|
1 << VIR_DOMAIN_VIRT_LXC,
|
2009-01-08 13:54:20 +00:00
|
|
|
VIR_DOMAIN_XML_INACTIVE)))
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
2008-03-21 15:03:37 +00:00
|
|
|
|
2012-01-25 14:12:53 +00:00
|
|
|
if (virSecurityManagerVerify(driver->securityManager, def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-07-11 17:29:09 +00:00
|
|
|
if ((dupVM = virDomainObjIsDuplicate(&driver->domains, def, 0)) < 0)
|
2009-11-02 18:37:38 +00:00
|
|
|
goto cleanup;
|
2009-07-31 14:25:03 +00:00
|
|
|
|
2008-06-26 16:08:59 +00:00
|
|
|
if ((def->nets != NULL) && !(driver->have_netns)) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("System lacks NETNS support"));
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
2008-06-26 16:08:59 +00:00
|
|
|
}
|
|
|
|
|
2010-02-09 18:58:01 +00:00
|
|
|
if (!(vm = virDomainAssignDef(driver->caps,
|
2010-03-24 14:31:21 +00:00
|
|
|
&driver->domains, def, false)))
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
|
|
|
def = NULL;
|
2008-08-20 19:42:36 +00:00
|
|
|
vm->persistent = 1;
|
2008-03-21 15:03:37 +00:00
|
|
|
|
2010-02-09 18:58:01 +00:00
|
|
|
if (virDomainSaveConfig(driver->configDir,
|
2008-08-20 19:42:36 +00:00
|
|
|
vm->newDef ? vm->newDef : vm->def) < 0) {
|
2008-08-13 12:50:55 +00:00
|
|
|
virDomainRemoveInactive(&driver->domains, vm);
|
2008-12-04 21:12:41 +00:00
|
|
|
vm = NULL;
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
2008-03-21 15:03:37 +00:00
|
|
|
}
|
|
|
|
|
2009-07-06 15:04:36 +00:00
|
|
|
event = virDomainEventNewFromObj(vm,
|
|
|
|
VIR_DOMAIN_EVENT_DEFINED,
|
2009-11-02 18:37:38 +00:00
|
|
|
!dupVM ?
|
2009-07-06 15:04:36 +00:00
|
|
|
VIR_DOMAIN_EVENT_DEFINED_ADDED :
|
|
|
|
VIR_DOMAIN_EVENT_DEFINED_UPDATED);
|
|
|
|
|
2008-03-21 15:03:37 +00:00
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
2008-12-04 21:11:41 +00:00
|
|
|
if (dom)
|
2008-03-21 15:03:37 +00:00
|
|
|
dom->id = vm->def->id;
|
|
|
|
|
2008-12-04 21:11:41 +00:00
|
|
|
cleanup:
|
|
|
|
virDomainDefFree(def);
|
2008-12-04 21:12:41 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
2009-07-06 15:04:36 +00:00
|
|
|
if (event)
|
2012-07-13 11:39:29 +00:00
|
|
|
virDomainEventStateQueue(driver->domainEventState, event);
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverUnlock(driver);
|
2008-03-21 15:03:37 +00:00
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
2011-07-20 03:08:21 +00:00
|
|
|
static int lxcDomainUndefineFlags(virDomainPtr dom,
|
|
|
|
unsigned int flags)
|
2008-03-21 15:03:37 +00:00
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = dom->conn->privateData;
|
2008-12-04 21:11:41 +00:00
|
|
|
virDomainObjPtr vm;
|
2009-07-06 15:04:36 +00:00
|
|
|
virDomainEventPtr event = NULL;
|
2008-12-04 21:11:41 +00:00
|
|
|
int ret = -1;
|
2008-03-21 15:03:37 +00:00
|
|
|
|
2011-07-20 03:08:21 +00:00
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverLock(driver);
|
2008-12-04 21:11:41 +00:00
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
2008-03-21 15:03:37 +00:00
|
|
|
if (!vm) {
|
2010-05-03 11:59:03 +00:00
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
2008-03-21 15:03:37 +00:00
|
|
|
}
|
|
|
|
|
2008-08-20 19:42:36 +00:00
|
|
|
if (!vm->persistent) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("Cannot undefine transient domain"));
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
2008-08-20 19:42:36 +00:00
|
|
|
}
|
2008-03-21 15:03:37 +00:00
|
|
|
|
2010-02-09 18:58:01 +00:00
|
|
|
if (virDomainDeleteConfig(driver->configDir,
|
2008-08-20 19:42:36 +00:00
|
|
|
driver->autostartDir,
|
2008-12-04 21:11:41 +00:00
|
|
|
vm) < 0)
|
|
|
|
goto cleanup;
|
2008-03-21 15:03:37 +00:00
|
|
|
|
2009-07-06 15:04:36 +00:00
|
|
|
event = virDomainEventNewFromObj(vm,
|
|
|
|
VIR_DOMAIN_EVENT_UNDEFINED,
|
|
|
|
VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
|
|
|
|
|
2011-08-19 13:47:33 +00:00
|
|
|
if (virDomainObjIsActive(vm)) {
|
|
|
|
vm->persistent = 0;
|
|
|
|
} else {
|
|
|
|
virDomainRemoveInactive(&driver->domains, vm);
|
|
|
|
vm = NULL;
|
|
|
|
}
|
|
|
|
|
2008-12-04 21:11:41 +00:00
|
|
|
ret = 0;
|
2008-03-21 15:03:37 +00:00
|
|
|
|
2008-12-04 21:11:41 +00:00
|
|
|
cleanup:
|
2008-12-04 21:12:41 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
2009-07-06 15:04:36 +00:00
|
|
|
if (event)
|
2012-07-13 11:39:29 +00:00
|
|
|
virDomainEventStateQueue(driver->domainEventState, event);
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverUnlock(driver);
|
2008-12-04 21:11:41 +00:00
|
|
|
return ret;
|
2008-03-21 15:03:37 +00:00
|
|
|
}
|
|
|
|
|
2011-07-20 03:08:21 +00:00
|
|
|
static int lxcDomainUndefine(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
return lxcDomainUndefineFlags(dom, 0);
|
|
|
|
}
|
|
|
|
|
2008-03-21 15:03:37 +00:00
|
|
|
static int lxcDomainGetInfo(virDomainPtr dom,
|
|
|
|
virDomainInfoPtr info)
|
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = dom->conn->privateData;
|
2008-12-04 21:11:41 +00:00
|
|
|
virDomainObjPtr vm;
|
2009-03-06 14:44:04 +00:00
|
|
|
virCgroupPtr cgroup = NULL;
|
2010-10-15 08:01:38 +00:00
|
|
|
int ret = -1, rc;
|
2008-03-21 15:03:37 +00:00
|
|
|
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverLock(driver);
|
2008-12-04 21:11:41 +00:00
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
2008-12-04 21:12:41 +00:00
|
|
|
|
2008-03-21 15:03:37 +00:00
|
|
|
if (!vm) {
|
2010-05-03 11:59:03 +00:00
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
2008-03-21 15:03:37 +00:00
|
|
|
}
|
|
|
|
|
2011-05-04 09:07:01 +00:00
|
|
|
info->state = virDomainObjGetState(vm, NULL);
|
2008-03-21 15:03:37 +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) || driver->cgroup == NULL) {
|
2008-03-21 15:03:37 +00:00
|
|
|
info->cpuTime = 0;
|
2010-10-12 14:43:39 +00:00
|
|
|
info->memory = vm->def->mem.cur_balloon;
|
2008-03-21 15:03:37 +00:00
|
|
|
} else {
|
2009-07-10 10:40:04 +00:00
|
|
|
if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) != 0) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unable to get cgroup for %s"), vm->def->name);
|
2009-03-06 14:44:04 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virCgroupGetCpuacctUsage(cgroup, &(info->cpuTime)) < 0) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
"%s", _("Cannot read cputime for domain"));
|
2009-10-07 13:26:23 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2010-10-15 08:01:38 +00:00
|
|
|
if ((rc = virCgroupGetMemoryUsage(cgroup, &(info->memory))) < 0) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
"%s", _("Cannot read memory usage for domain"));
|
2010-10-15 08:01:38 +00:00
|
|
|
if (rc == -ENOENT) {
|
|
|
|
/* Don't fail if we can't read memory usage due to a lack of
|
|
|
|
* kernel support */
|
|
|
|
info->memory = 0;
|
|
|
|
} else
|
|
|
|
goto cleanup;
|
2009-03-06 14:44:04 +00:00
|
|
|
}
|
2008-03-21 15:03:37 +00:00
|
|
|
}
|
|
|
|
|
2010-10-12 14:43:39 +00:00
|
|
|
info->maxMem = vm->def->mem.max_balloon;
|
2012-05-29 07:12:32 +00:00
|
|
|
info->nrVirtCpu = vm->def->vcpus;
|
2008-12-04 21:11:41 +00:00
|
|
|
ret = 0;
|
2008-03-21 15:03:37 +00:00
|
|
|
|
2008-12-04 21:11:41 +00:00
|
|
|
cleanup:
|
2009-09-02 13:02:06 +00:00
|
|
|
lxcDriverUnlock(driver);
|
2009-03-06 14:44:04 +00:00
|
|
|
if (cgroup)
|
|
|
|
virCgroupFree(&cgroup);
|
2008-12-04 21:12:41 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
2008-12-04 21:11:41 +00:00
|
|
|
return ret;
|
2008-03-21 15:03:37 +00:00
|
|
|
}
|
|
|
|
|
2011-05-02 09:35:29 +00:00
|
|
|
static int
|
|
|
|
lxcDomainGetState(virDomainPtr dom,
|
|
|
|
int *state,
|
|
|
|
int *reason,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = dom->conn->privateData;
|
2011-05-02 09:35:29 +00:00
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
|
|
|
lxcDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
|
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
2011-05-02 09:35:29 +00:00
|
|
|
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)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2008-08-13 12:50:55 +00:00
|
|
|
static char *lxcGetOSType(virDomainPtr dom)
|
2008-03-21 15:03:37 +00:00
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = dom->conn->privateData;
|
2008-12-04 21:11:41 +00:00
|
|
|
virDomainObjPtr vm;
|
|
|
|
char *ret = NULL;
|
2008-08-13 12:50:55 +00:00
|
|
|
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverLock(driver);
|
2008-12-04 21:11:41 +00:00
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
|
2008-08-13 12:50:55 +00:00
|
|
|
if (!vm) {
|
2010-05-03 11:59:03 +00:00
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
2008-08-13 12:50:55 +00:00
|
|
|
}
|
|
|
|
|
2008-12-04 21:11:41 +00:00
|
|
|
ret = strdup(vm->def->os.type);
|
|
|
|
|
2009-11-08 21:08:54 +00:00
|
|
|
if (ret == NULL)
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-11-08 21:08:54 +00:00
|
|
|
|
2008-12-04 21:11:41 +00:00
|
|
|
cleanup:
|
2008-12-04 21:12:41 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
2008-12-04 21:11:41 +00:00
|
|
|
return ret;
|
2008-03-21 15:03:37 +00:00
|
|
|
}
|
|
|
|
|
2009-10-07 13:26:23 +00:00
|
|
|
/* 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
|
|
|
|
lxcDomainGetMaxMemory(virDomainPtr dom)
|
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = dom->conn->privateData;
|
2009-10-07 13:26:23 +00:00
|
|
|
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;
|
2009-10-07 13:26:23 +00:00
|
|
|
|
|
|
|
lxcDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
|
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
2009-10-07 13:26:23 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2010-10-12 14:43:39 +00:00
|
|
|
ret = vm->def->mem.max_balloon;
|
2009-10-07 13:26:23 +00:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int lxcDomainSetMaxMemory(virDomainPtr dom, unsigned long newmax) {
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = dom->conn->privateData;
|
2009-10-07 13:26:23 +00:00
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
lxcDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
|
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
2009-10-07 13:26:23 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2010-10-12 14:43:39 +00:00
|
|
|
if (newmax < vm->def->mem.cur_balloon) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
"%s", _("Cannot set max memory lower than current memory"));
|
2009-10-07 13:26:23 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2010-10-12 14:43:39 +00:00
|
|
|
vm->def->mem.max_balloon = newmax;
|
2009-10-07 13:26:23 +00:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int lxcDomainSetMemory(virDomainPtr dom, unsigned long newmem) {
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = dom->conn->privateData;
|
2009-10-07 13:26:23 +00:00
|
|
|
virDomainObjPtr vm;
|
|
|
|
virCgroupPtr cgroup = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
lxcDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
2009-10-07 13:26:23 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2010-10-12 14:43:39 +00:00
|
|
|
if (newmem > vm->def->mem.max_balloon) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
"%s", _("Cannot set memory higher than max memory"));
|
2009-10-07 13:26:23 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2010-05-03 12:02:56 +00:00
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("Domain is not running"));
|
2010-05-03 12:02:56 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2010-03-22 15:42:14 +00:00
|
|
|
|
2010-05-03 12:02:56 +00:00
|
|
|
if (driver->cgroup == NULL) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("cgroups must be configured on the host"));
|
2010-05-03 12:02:56 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2009-10-07 13:26:23 +00:00
|
|
|
|
2010-05-03 12:02:56 +00:00
|
|
|
if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) != 0) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unable to get cgroup for %s"), vm->def->name);
|
2010-05-03 12:02:56 +00:00
|
|
|
goto cleanup;
|
2009-10-07 13:26:23 +00:00
|
|
|
}
|
2010-05-03 12:02:56 +00:00
|
|
|
|
|
|
|
if (virCgroupSetMemory(cgroup, newmem) < 0) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
"%s", _("Failed to set memory for domain"));
|
2010-05-03 12:02:56 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2009-10-07 13:26:23 +00:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
if (cgroup)
|
|
|
|
virCgroupFree(&cgroup);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-01-07 12:47:43 +00:00
|
|
|
static int
|
|
|
|
lxcDomainSetMemoryParameters(virDomainPtr dom,
|
|
|
|
virTypedParameterPtr params,
|
|
|
|
int nparams,
|
|
|
|
unsigned int flags)
|
2010-10-12 16:31:19 +00:00
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = dom->conn->privateData;
|
2010-10-12 16:31:19 +00:00
|
|
|
int i;
|
|
|
|
virCgroupPtr cgroup = NULL;
|
|
|
|
virDomainObjPtr vm = NULL;
|
|
|
|
int ret = -1;
|
2012-01-07 12:47:43 +00:00
|
|
|
int rc;
|
2010-10-12 16:31:19 +00:00
|
|
|
|
2011-07-06 22:33:53 +00:00
|
|
|
virCheckFlags(0, -1);
|
2012-01-07 12:47:43 +00:00
|
|
|
if (virTypedParameterArrayValidate(params, nparams,
|
|
|
|
VIR_DOMAIN_MEMORY_HARD_LIMIT,
|
|
|
|
VIR_TYPED_PARAM_ULLONG,
|
|
|
|
VIR_DOMAIN_MEMORY_SOFT_LIMIT,
|
|
|
|
VIR_TYPED_PARAM_ULLONG,
|
|
|
|
VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT,
|
|
|
|
VIR_TYPED_PARAM_ULLONG,
|
|
|
|
NULL) < 0)
|
|
|
|
return -1;
|
2011-07-06 22:33:53 +00:00
|
|
|
|
2010-10-12 16:31:19 +00:00
|
|
|
lxcDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
|
|
|
|
if (vm == NULL) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
2010-10-12 16:31:19 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) != 0) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("cannot find cgroup for domain %s"), vm->def->name);
|
2010-10-12 16:31:19 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
for (i = 0; i < nparams; i++) {
|
2011-05-26 17:39:04 +00:00
|
|
|
virTypedParameterPtr param = ¶ms[i];
|
2010-10-12 16:31:19 +00:00
|
|
|
|
|
|
|
if (STREQ(param->field, VIR_DOMAIN_MEMORY_HARD_LIMIT)) {
|
|
|
|
rc = virCgroupSetMemoryHardLimit(cgroup, params[i].value.ul);
|
|
|
|
if (rc != 0) {
|
|
|
|
virReportSystemError(-rc, "%s",
|
|
|
|
_("unable to set memory hard_limit tunable"));
|
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
} else if (STREQ(param->field, VIR_DOMAIN_MEMORY_SOFT_LIMIT)) {
|
|
|
|
rc = virCgroupSetMemorySoftLimit(cgroup, params[i].value.ul);
|
|
|
|
if (rc != 0) {
|
|
|
|
virReportSystemError(-rc, "%s",
|
|
|
|
_("unable to set memory soft_limit tunable"));
|
|
|
|
ret = -1;
|
|
|
|
}
|
2010-10-20 11:52:48 +00:00
|
|
|
} else if (STREQ(param->field, VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT)) {
|
2011-03-16 05:07:12 +00:00
|
|
|
rc = virCgroupSetMemSwapHardLimit(cgroup, params[i].value.ul);
|
2010-10-12 16:31:19 +00:00
|
|
|
if (rc != 0) {
|
|
|
|
virReportSystemError(-rc, "%s",
|
|
|
|
_("unable to set swap_hard_limit tunable"));
|
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (cgroup)
|
|
|
|
virCgroupFree(&cgroup);
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-01-07 12:47:43 +00:00
|
|
|
static int
|
|
|
|
lxcDomainGetMemoryParameters(virDomainPtr dom,
|
|
|
|
virTypedParameterPtr params,
|
|
|
|
int *nparams,
|
|
|
|
unsigned int flags)
|
2010-10-12 16:39:05 +00:00
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = dom->conn->privateData;
|
2010-10-12 16:39:05 +00:00
|
|
|
int i;
|
|
|
|
virCgroupPtr cgroup = NULL;
|
|
|
|
virDomainObjPtr vm = NULL;
|
2011-01-13 09:18:11 +00:00
|
|
|
unsigned long long val;
|
2010-10-12 16:39:05 +00:00
|
|
|
int ret = -1;
|
|
|
|
int rc;
|
|
|
|
|
2011-07-06 22:33:53 +00:00
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2010-10-12 16:39:05 +00:00
|
|
|
lxcDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
|
|
|
|
if (vm == NULL) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
2010-10-12 16:39:05 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((*nparams) == 0) {
|
|
|
|
/* Current number of memory parameters supported by cgroups */
|
|
|
|
*nparams = LXC_NB_MEM_PARAM;
|
|
|
|
ret = 0;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) != 0) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unable to get cgroup for %s"), vm->def->name);
|
2010-10-12 16:39:05 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-11-02 17:50:08 +00:00
|
|
|
for (i = 0; i < LXC_NB_MEM_PARAM && i < *nparams; i++) {
|
2011-05-26 17:39:04 +00:00
|
|
|
virTypedParameterPtr param = ¶ms[i];
|
2010-10-12 16:39:05 +00:00
|
|
|
val = 0;
|
|
|
|
|
|
|
|
switch(i) {
|
|
|
|
case 0: /* fill memory hard limit here */
|
|
|
|
rc = virCgroupGetMemoryHardLimit(cgroup, &val);
|
|
|
|
if (rc != 0) {
|
|
|
|
virReportSystemError(-rc, "%s",
|
|
|
|
_("unable to get memory hard limit"));
|
2010-11-06 17:52:00 +00:00
|
|
|
goto cleanup;
|
2010-10-12 16:39:05 +00:00
|
|
|
}
|
2012-01-07 12:47:43 +00:00
|
|
|
if (virTypedParameterAssign(param, VIR_DOMAIN_MEMORY_HARD_LIMIT,
|
|
|
|
VIR_TYPED_PARAM_ULLONG, val) < 0)
|
2010-11-06 17:52:00 +00:00
|
|
|
goto cleanup;
|
2010-10-12 16:39:05 +00:00
|
|
|
break;
|
|
|
|
case 1: /* fill memory soft limit here */
|
|
|
|
rc = virCgroupGetMemorySoftLimit(cgroup, &val);
|
|
|
|
if (rc != 0) {
|
|
|
|
virReportSystemError(-rc, "%s",
|
|
|
|
_("unable to get memory soft limit"));
|
2010-11-06 17:52:00 +00:00
|
|
|
goto cleanup;
|
2010-10-12 16:39:05 +00:00
|
|
|
}
|
2012-01-07 12:47:43 +00:00
|
|
|
if (virTypedParameterAssign(param, VIR_DOMAIN_MEMORY_SOFT_LIMIT,
|
|
|
|
VIR_TYPED_PARAM_ULLONG, val) < 0)
|
2010-11-06 17:52:00 +00:00
|
|
|
goto cleanup;
|
2010-10-12 16:39:05 +00:00
|
|
|
break;
|
|
|
|
case 2: /* fill swap hard limit here */
|
2011-03-16 05:07:12 +00:00
|
|
|
rc = virCgroupGetMemSwapHardLimit(cgroup, &val);
|
2010-10-12 16:39:05 +00:00
|
|
|
if (rc != 0) {
|
|
|
|
virReportSystemError(-rc, "%s",
|
|
|
|
_("unable to get swap hard limit"));
|
2010-11-06 17:52:00 +00:00
|
|
|
goto cleanup;
|
2010-10-12 16:39:05 +00:00
|
|
|
}
|
2012-01-07 12:47:43 +00:00
|
|
|
if (virTypedParameterAssign(param,
|
|
|
|
VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT,
|
|
|
|
VIR_TYPED_PARAM_ULLONG, val) < 0)
|
2010-11-06 17:52:00 +00:00
|
|
|
goto cleanup;
|
2010-10-12 16:39:05 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
/* should not hit here */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-02 17:50:08 +00:00
|
|
|
if (*nparams > LXC_NB_MEM_PARAM)
|
|
|
|
*nparams = LXC_NB_MEM_PARAM;
|
2010-11-06 17:52:00 +00:00
|
|
|
ret = 0;
|
|
|
|
|
2010-10-12 16:39:05 +00:00
|
|
|
cleanup:
|
|
|
|
if (cgroup)
|
|
|
|
virCgroupFree(&cgroup);
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-05-06 19:53:10 +00:00
|
|
|
static char *lxcDomainGetXMLDesc(virDomainPtr dom,
|
2011-07-06 20:40:19 +00:00
|
|
|
unsigned int flags)
|
2008-03-21 15:03:37 +00:00
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = dom->conn->privateData;
|
2008-12-04 21:11:41 +00:00
|
|
|
virDomainObjPtr vm;
|
|
|
|
char *ret = NULL;
|
2008-03-21 15:03:37 +00:00
|
|
|
|
2011-07-13 22:24:38 +00:00
|
|
|
/* Flags checked by virDomainDefFormat */
|
|
|
|
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverLock(driver);
|
2008-12-04 21:11:41 +00:00
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
|
2008-03-21 15:03:37 +00:00
|
|
|
if (!vm) {
|
2010-05-03 11:59:03 +00:00
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
2008-03-21 15:03:37 +00:00
|
|
|
}
|
|
|
|
|
2010-02-09 18:58:01 +00:00
|
|
|
ret = virDomainDefFormat((flags & VIR_DOMAIN_XML_INACTIVE) &&
|
2008-12-04 21:11:41 +00:00
|
|
|
vm->newDef ? vm->newDef : vm->def,
|
|
|
|
flags);
|
|
|
|
|
|
|
|
cleanup:
|
2008-12-04 21:12:41 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
2008-12-04 21:11:41 +00:00
|
|
|
return ret;
|
2008-03-21 15:03:37 +00:00
|
|
|
}
|
|
|
|
|
2008-08-13 10:52:15 +00:00
|
|
|
|
2008-04-10 07:30:52 +00:00
|
|
|
/**
|
2010-06-10 15:55:36 +00:00
|
|
|
* lxcDomainStartWithFlags:
|
2008-04-10 07:30:52 +00:00
|
|
|
* @dom: domain to start
|
2010-06-10 15:55:36 +00:00
|
|
|
* @flags: Must be 0 for now
|
2008-04-10 07:30:52 +00:00
|
|
|
*
|
|
|
|
* Looks up domain and starts it.
|
|
|
|
*
|
|
|
|
* Returns 0 on success or -1 in case of error
|
|
|
|
*/
|
2010-06-10 15:55:36 +00:00
|
|
|
static int lxcDomainStartWithFlags(virDomainPtr dom, unsigned int flags)
|
2008-04-10 07:30:52 +00:00
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = dom->conn->privateData;
|
2008-12-04 21:11:41 +00:00
|
|
|
virDomainObjPtr vm;
|
2009-07-06 15:04:36 +00:00
|
|
|
virDomainEventPtr event = NULL;
|
2008-12-04 21:11:41 +00:00
|
|
|
int ret = -1;
|
2008-04-10 07:30:52 +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:12:41 +00:00
|
|
|
lxcDriverLock(driver);
|
2010-05-03 11:59:03 +00:00
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
2008-04-10 07:30:52 +00:00
|
|
|
if (!vm) {
|
2010-05-03 11:59:03 +00:00
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
2008-04-10 07:30:52 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2008-08-13 12:50:55 +00:00
|
|
|
if ((vm->def->nets != NULL) && !(driver->have_netns)) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("System lacks NETNS support"));
|
2008-08-13 12:50:55 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2010-05-03 12:04:44 +00:00
|
|
|
if (virDomainObjIsActive(vm)) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("Domain is already running"));
|
2010-05-03 12:04:44 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2012-07-13 11:49:24 +00:00
|
|
|
ret = virLXCProcessStart(dom->conn, driver, vm,
|
|
|
|
(flags & VIR_DOMAIN_START_AUTODESTROY),
|
|
|
|
VIR_DOMAIN_RUNNING_BOOTED);
|
2008-04-10 07:30:52 +00:00
|
|
|
|
2011-07-04 11:06:14 +00:00
|
|
|
if (ret == 0) {
|
2009-07-06 15:04:36 +00:00
|
|
|
event = virDomainEventNewFromObj(vm,
|
|
|
|
VIR_DOMAIN_EVENT_STARTED,
|
|
|
|
VIR_DOMAIN_EVENT_STARTED_BOOTED);
|
2011-07-04 11:06:14 +00:00
|
|
|
virDomainAuditStart(vm, "booted", true);
|
|
|
|
} else {
|
|
|
|
virDomainAuditStart(vm, "booted", false);
|
|
|
|
}
|
2009-07-06 15:04:36 +00:00
|
|
|
|
2008-04-10 07:30:52 +00:00
|
|
|
cleanup:
|
2008-12-04 21:12:41 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
2009-07-06 15:04:36 +00:00
|
|
|
if (event)
|
2012-07-13 11:39:29 +00:00
|
|
|
virDomainEventStateQueue(driver->domainEventState, event);
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverUnlock(driver);
|
2008-12-04 21:11:41 +00:00
|
|
|
return ret;
|
2008-04-10 07:30:52 +00:00
|
|
|
}
|
|
|
|
|
2010-06-10 15:55:36 +00:00
|
|
|
/**
|
|
|
|
* lxcDomainStart:
|
|
|
|
* @dom: domain to start
|
|
|
|
*
|
|
|
|
* Looks up domain and starts it.
|
|
|
|
*
|
|
|
|
* Returns 0 on success or -1 in case of error
|
|
|
|
*/
|
|
|
|
static int lxcDomainStart(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
return lxcDomainStartWithFlags(dom, 0);
|
|
|
|
}
|
|
|
|
|
2008-04-10 07:30:52 +00:00
|
|
|
/**
|
|
|
|
* lxcDomainCreateAndStart:
|
|
|
|
* @conn: pointer to connection
|
|
|
|
* @xml: XML definition of domain
|
2010-05-25 17:13:13 +00:00
|
|
|
* @flags: Must be 0 for now
|
2008-04-10 07:30:52 +00:00
|
|
|
*
|
|
|
|
* Creates a domain based on xml and starts it
|
|
|
|
*
|
|
|
|
* Returns 0 on success or -1 in case of error
|
|
|
|
*/
|
|
|
|
static virDomainPtr
|
|
|
|
lxcDomainCreateAndStart(virConnectPtr conn,
|
|
|
|
const char *xml,
|
2010-05-25 17:13:13 +00:00
|
|
|
unsigned int flags) {
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = conn->privateData;
|
2008-12-04 21:12:41 +00:00
|
|
|
virDomainObjPtr vm = NULL;
|
2008-08-13 12:50:55 +00:00
|
|
|
virDomainDefPtr def;
|
2008-04-10 07:30:52 +00:00
|
|
|
virDomainPtr dom = NULL;
|
2009-07-06 15:04:36 +00:00
|
|
|
virDomainEventPtr event = NULL;
|
2008-04-10 07:30:52 +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:12:41 +00:00
|
|
|
lxcDriverLock(driver);
|
2010-02-09 18:58:01 +00:00
|
|
|
if (!(def = virDomainDefParseString(driver->caps, xml,
|
2011-07-11 17:29:09 +00:00
|
|
|
1 << VIR_DOMAIN_VIRT_LXC,
|
2009-01-08 13:54:20 +00:00
|
|
|
VIR_DOMAIN_XML_INACTIVE)))
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
2008-04-10 07:30:52 +00:00
|
|
|
|
2012-01-25 14:12:53 +00:00
|
|
|
if (virSecurityManagerVerify(driver->securityManager, def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2009-11-02 18:37:38 +00:00
|
|
|
if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0)
|
|
|
|
goto cleanup;
|
2009-07-31 14:25:03 +00:00
|
|
|
|
2008-08-13 12:50:55 +00:00
|
|
|
if ((def->nets != NULL) && !(driver->have_netns)) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
"%s", _("System lacks NETNS support"));
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
2008-04-10 07:30:52 +00:00
|
|
|
}
|
|
|
|
|
2008-08-13 12:50:55 +00:00
|
|
|
|
2010-02-09 18:58:01 +00:00
|
|
|
if (!(vm = virDomainAssignDef(driver->caps,
|
2010-03-24 14:31:21 +00:00
|
|
|
&driver->domains, def, false)))
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
|
|
|
def = NULL;
|
2008-04-10 07:30:52 +00:00
|
|
|
|
2012-07-13 11:49:24 +00:00
|
|
|
if (virLXCProcessStart(conn, driver, vm,
|
|
|
|
(flags & VIR_DOMAIN_START_AUTODESTROY),
|
|
|
|
VIR_DOMAIN_RUNNING_BOOTED) < 0) {
|
2011-07-04 11:06:14 +00:00
|
|
|
virDomainAuditStart(vm, "booted", false);
|
2008-08-13 12:50:55 +00:00
|
|
|
virDomainRemoveInactive(&driver->domains, vm);
|
2008-12-04 21:12:41 +00:00
|
|
|
vm = NULL;
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
2008-04-10 07:30:52 +00:00
|
|
|
}
|
|
|
|
|
2009-07-06 15:04:36 +00:00
|
|
|
event = virDomainEventNewFromObj(vm,
|
|
|
|
VIR_DOMAIN_EVENT_STARTED,
|
|
|
|
VIR_DOMAIN_EVENT_STARTED_BOOTED);
|
2011-07-04 11:06:14 +00:00
|
|
|
virDomainAuditStart(vm, "booted", true);
|
2009-07-06 15:04:36 +00:00
|
|
|
|
2008-04-10 07:30:52 +00:00
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
2008-12-04 21:11:41 +00:00
|
|
|
if (dom)
|
2008-04-10 07:30:52 +00:00
|
|
|
dom->id = vm->def->id;
|
|
|
|
|
2008-12-04 21:11:41 +00:00
|
|
|
cleanup:
|
|
|
|
virDomainDefFree(def);
|
2008-12-04 21:12:41 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
2009-07-06 15:04:36 +00:00
|
|
|
if (event)
|
2012-07-13 11:39:29 +00:00
|
|
|
virDomainEventStateQueue(driver->domainEventState, event);
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverUnlock(driver);
|
2008-04-10 07:30:52 +00:00
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
2009-07-06 15:04:36 +00:00
|
|
|
|
2012-01-25 14:12:53 +00:00
|
|
|
static int lxcDomainGetSecurityLabel(virDomainPtr dom, virSecurityLabelPtr seclabel)
|
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = dom->conn->privateData;
|
2012-01-25 14:12:53 +00:00
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
lxcDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
|
|
|
|
memset(seclabel, 0, sizeof(*seclabel));
|
|
|
|
|
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("no domain with matching uuid '%s'"), uuidstr);
|
2012-01-25 14:12:53 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!virDomainVirtTypeToString(vm->def->virtType)) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unknown virt type in domain definition '%d'"),
|
|
|
|
vm->def->virtType);
|
2012-01-25 14:12:53 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Theoretically, the pid can be replaced during this operation and
|
|
|
|
* return the label of a different process. If atomicity is needed,
|
|
|
|
* further validation will be required.
|
|
|
|
*
|
|
|
|
* Comment from Dan Berrange:
|
|
|
|
*
|
|
|
|
* Well the PID as stored in the virDomainObjPtr can't be changed
|
|
|
|
* because you've got a locked object. The OS level PID could have
|
|
|
|
* exited, though and in extreme circumstances have cycled through all
|
|
|
|
* PIDs back to ours. We could sanity check that our PID still exists
|
|
|
|
* after reading the label, by checking that our FD connecting to the
|
|
|
|
* LXC monitor hasn't seen SIGHUP/ERR on poll().
|
|
|
|
*/
|
|
|
|
if (virDomainObjIsActive(vm)) {
|
|
|
|
if (virSecurityManagerGetProcessLabel(driver->securityManager,
|
|
|
|
vm->def, vm->pid, seclabel) < 0) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("Failed to get security label"));
|
2012-01-25 14:12:53 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int lxcNodeGetSecurityModel(virConnectPtr conn,
|
|
|
|
virSecurityModelPtr secmodel)
|
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = conn->privateData;
|
2012-01-25 14:12:53 +00:00
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
lxcDriverLock(driver);
|
|
|
|
memset(secmodel, 0, sizeof(*secmodel));
|
|
|
|
|
|
|
|
/* NULL indicates no driver, which we treat as
|
|
|
|
* success, but simply return no data in *secmodel */
|
|
|
|
if (driver->caps->host.secModel.model == NULL)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!virStrcpy(secmodel->model, driver->caps->host.secModel.model,
|
|
|
|
VIR_SECURITY_MODEL_BUFLEN)) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("security model string exceeds max %d bytes"),
|
|
|
|
VIR_SECURITY_MODEL_BUFLEN - 1);
|
2012-01-25 14:12:53 +00:00
|
|
|
ret = -1;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!virStrcpy(secmodel->doi, driver->caps->host.secModel.doi,
|
|
|
|
VIR_SECURITY_DOI_BUFLEN)) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("security DOI string exceeds max %d bytes"),
|
|
|
|
VIR_SECURITY_DOI_BUFLEN-1);
|
2012-01-25 14:12:53 +00:00
|
|
|
ret = -1;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-07-06 15:04:36 +00:00
|
|
|
static int
|
2010-03-18 14:47:07 +00:00
|
|
|
lxcDomainEventRegister(virConnectPtr conn,
|
|
|
|
virConnectDomainEventCallback callback,
|
|
|
|
void *opaque,
|
|
|
|
virFreeCallback freecb)
|
2009-07-06 15:04:36 +00:00
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = conn->privateData;
|
2009-07-06 15:04:36 +00:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
lxcDriverLock(driver);
|
2011-12-13 11:14:46 +00:00
|
|
|
ret = virDomainEventStateRegister(conn,
|
|
|
|
driver->domainEventState,
|
|
|
|
callback, opaque, freecb);
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverUnlock(driver);
|
2009-07-06 15:04:36 +00:00
|
|
|
|
2008-12-04 21:11:41 +00:00
|
|
|
return ret;
|
2008-04-10 07:30:52 +00:00
|
|
|
}
|
|
|
|
|
2010-03-18 14:47:07 +00:00
|
|
|
|
2009-07-06 15:04:36 +00:00
|
|
|
static int
|
2010-03-18 14:47:07 +00:00
|
|
|
lxcDomainEventDeregister(virConnectPtr conn,
|
|
|
|
virConnectDomainEventCallback callback)
|
2009-07-06 15:04:36 +00:00
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = conn->privateData;
|
2009-07-06 15:04:36 +00:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
lxcDriverLock(driver);
|
2011-01-06 17:42:12 +00:00
|
|
|
ret = virDomainEventStateDeregister(conn,
|
|
|
|
driver->domainEventState,
|
|
|
|
callback);
|
2009-07-06 15:04:36 +00:00
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-03-18 14:47:07 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
lxcDomainEventRegisterAny(virConnectPtr conn,
|
|
|
|
virDomainPtr dom,
|
|
|
|
int eventID,
|
|
|
|
virConnectDomainEventGenericCallback callback,
|
|
|
|
void *opaque,
|
|
|
|
virFreeCallback freecb)
|
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = conn->privateData;
|
2010-03-18 14:47:07 +00:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
lxcDriverLock(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;
|
2010-03-18 14:47:07 +00:00
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
lxcDomainEventDeregisterAny(virConnectPtr conn,
|
|
|
|
int callbackID)
|
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = conn->privateData;
|
2010-03-18 14:47:07 +00:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
lxcDriverLock(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);
|
2010-03-18 14:47:07 +00:00
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-05-13 06:30:58 +00:00
|
|
|
/**
|
2011-07-20 16:51:26 +00:00
|
|
|
* lxcDomainDestroyFlags:
|
2009-11-05 12:35:13 +00:00
|
|
|
* @dom: pointer to domain to destroy
|
2011-07-20 16:51:26 +00:00
|
|
|
* @flags: an OR'ed set of virDomainDestroyFlags
|
2008-05-13 06:30:58 +00:00
|
|
|
*
|
|
|
|
* Sends SIGKILL to container root process to terminate the container
|
|
|
|
*
|
|
|
|
* Returns 0 on success or -1 in case of error
|
|
|
|
*/
|
2011-07-20 16:51:26 +00:00
|
|
|
static int
|
|
|
|
lxcDomainDestroyFlags(virDomainPtr dom,
|
|
|
|
unsigned int flags)
|
2008-05-13 06:30:58 +00:00
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = dom->conn->privateData;
|
2008-12-04 21:11:41 +00:00
|
|
|
virDomainObjPtr vm;
|
2009-07-06 15:04:36 +00:00
|
|
|
virDomainEventPtr event = NULL;
|
2008-12-04 21:11:41 +00:00
|
|
|
int ret = -1;
|
2012-07-17 10:55:38 +00:00
|
|
|
virLXCDomainObjPrivatePtr priv;
|
2008-05-13 06:30:58 +00:00
|
|
|
|
2011-07-20 16:51:26 +00:00
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverLock(driver);
|
2010-05-03 11:59:03 +00:00
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
2008-05-13 06:30:58 +00:00
|
|
|
if (!vm) {
|
2010-05-03 11:59:03 +00:00
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
2008-05-13 06:30:58 +00:00
|
|
|
}
|
|
|
|
|
2010-05-03 12:04:44 +00:00
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("Domain is not running"));
|
2010-05-03 12:04:44 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2012-07-17 10:55:38 +00:00
|
|
|
priv = vm->privateData;
|
2012-07-13 11:49:24 +00:00
|
|
|
ret = virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED);
|
2009-07-06 15:04:36 +00:00
|
|
|
event = virDomainEventNewFromObj(vm,
|
|
|
|
VIR_DOMAIN_EVENT_STOPPED,
|
|
|
|
VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
|
2012-07-17 10:55:38 +00:00
|
|
|
priv->doneStopEvent = true;
|
2011-07-04 11:06:14 +00:00
|
|
|
virDomainAuditStop(vm, "destroyed");
|
2008-12-04 21:12:41 +00:00
|
|
|
if (!vm->persistent) {
|
|
|
|
virDomainRemoveInactive(&driver->domains, vm);
|
|
|
|
vm = NULL;
|
|
|
|
}
|
2008-12-04 21:11:41 +00:00
|
|
|
|
|
|
|
cleanup:
|
2008-12-04 21:12:41 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
2009-07-06 15:04:36 +00:00
|
|
|
if (event)
|
2012-07-13 11:39:29 +00:00
|
|
|
virDomainEventStateQueue(driver->domainEventState, event);
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverUnlock(driver);
|
2008-12-04 21:11:41 +00:00
|
|
|
return ret;
|
2008-04-10 07:30:52 +00:00
|
|
|
}
|
2008-03-27 09:34:06 +00:00
|
|
|
|
2011-07-20 16:51:26 +00:00
|
|
|
/**
|
|
|
|
* lxcDomainDestroy:
|
|
|
|
* @dom: pointer to domain to destroy
|
|
|
|
*
|
|
|
|
* Sends SIGKILL to container root process to terminate the container
|
|
|
|
*
|
|
|
|
* Returns 0 on success or -1 in case of error
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
lxcDomainDestroy(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
return lxcDomainDestroyFlags(dom, 0);
|
|
|
|
}
|
|
|
|
|
2008-06-26 16:05:02 +00:00
|
|
|
static int lxcCheckNetNsSupport(void)
|
|
|
|
{
|
|
|
|
const char *argv[] = {"ip", "link", "set", "lo", "netns", "-1", NULL};
|
|
|
|
int ip_rc;
|
|
|
|
|
2010-02-04 22:41:52 +00:00
|
|
|
if (virRun(argv, &ip_rc) < 0 ||
|
2008-08-13 10:25:34 +00:00
|
|
|
!(WIFEXITED(ip_rc) && (WEXITSTATUS(ip_rc) != 255)))
|
|
|
|
return 0;
|
2008-06-26 16:05:02 +00:00
|
|
|
|
2008-08-13 10:25:34 +00:00
|
|
|
if (lxcContainerAvailable(LXC_CONTAINER_FEATURE_NET) < 0)
|
|
|
|
return 0;
|
2008-06-26 16:05:02 +00:00
|
|
|
|
2008-08-13 10:25:34 +00:00
|
|
|
return 1;
|
2008-06-26 16:05:02 +00:00
|
|
|
}
|
|
|
|
|
2009-07-06 15:05:32 +00:00
|
|
|
|
2012-01-25 14:12:53 +00:00
|
|
|
static int
|
2012-07-13 11:56:29 +00:00
|
|
|
lxcSecurityInit(virLXCDriverPtr driver)
|
2012-01-25 14:12:53 +00:00
|
|
|
{
|
2012-05-10 16:49:29 +00:00
|
|
|
VIR_INFO("lxcSecurityInit %s", driver->securityDriverName);
|
2012-01-25 14:12:53 +00:00
|
|
|
virSecurityManagerPtr mgr = virSecurityManagerNew(driver->securityDriverName,
|
2012-05-10 16:49:29 +00:00
|
|
|
LXC_DRIVER_NAME,
|
2012-01-25 14:12:53 +00:00
|
|
|
false,
|
|
|
|
driver->securityDefaultConfined,
|
|
|
|
driver->securityRequireConfined);
|
|
|
|
if (!mgr)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
driver->securityManager = mgr;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
VIR_ERROR(_("Failed to initialize security drivers"));
|
|
|
|
virSecurityManagerFree(mgr);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-06-12 13:20:13 +00:00
|
|
|
static int lxcStartup(int privileged)
|
2008-03-21 15:03:37 +00:00
|
|
|
{
|
2009-01-30 16:51:33 +00:00
|
|
|
char *ld;
|
2009-07-10 10:40:04 +00:00
|
|
|
int rc;
|
2009-01-30 16:51:33 +00:00
|
|
|
|
|
|
|
/* Valgrind gets very annoyed when we clone containers, so
|
|
|
|
* disable LXC when under valgrind
|
|
|
|
* XXX remove this when valgrind is fixed
|
|
|
|
*/
|
|
|
|
ld = getenv("LD_PRELOAD");
|
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
|
|
|
if (ld && strstr(ld, "vgpreload")) {
|
2011-05-09 09:24:09 +00:00
|
|
|
VIR_INFO("Running under valgrind, disabling driver");
|
Fix return value in virStateInitialize impl for LXC
The LXC driver was mistakenly returning -1 for lxcStartup()
in scenarios that are not an error. This caused the libvirtd
to quit for unprivileged users. This fixes the return code
of LXC driver, and also adds a "name" field to the virStateDriver
struct and logging to make it easier to find these problems
in the future
* src/driver.h: Add a 'name' field to state driver to allow
easy identification during failures
* src/libvirt.c: Log name of failed driver for virStateInit
failures
* src/lxc/lxc_driver.c: Don't return a failure code for
lxcStartup() if LXC is not available on this host, simply
disable the driver.
* src/network/bridge_driver.c, src/node_device/node_device_devkit.c,
src/node_device/node_device_hal.c, src/opennebula/one_driver.c,
src/qemu/qemu_driver.c, src/remote/remote_driver.c,
src/secret/secret_driver.c, src/storage/storage_driver.c,
src/uml/uml_driver.c, src/xen/xen_driver.c: Fill in name
field in virStateDriver struct
2009-11-02 23:18:19 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2008-03-31 12:02:12 +00:00
|
|
|
|
Fix return value in virStateInitialize impl for LXC
The LXC driver was mistakenly returning -1 for lxcStartup()
in scenarios that are not an error. This caused the libvirtd
to quit for unprivileged users. This fixes the return code
of LXC driver, and also adds a "name" field to the virStateDriver
struct and logging to make it easier to find these problems
in the future
* src/driver.h: Add a 'name' field to state driver to allow
easy identification during failures
* src/libvirt.c: Log name of failed driver for virStateInit
failures
* src/lxc/lxc_driver.c: Don't return a failure code for
lxcStartup() if LXC is not available on this host, simply
disable the driver.
* src/network/bridge_driver.c, src/node_device/node_device_devkit.c,
src/node_device/node_device_hal.c, src/opennebula/one_driver.c,
src/qemu/qemu_driver.c, src/remote/remote_driver.c,
src/secret/secret_driver.c, src/storage/storage_driver.c,
src/uml/uml_driver.c, src/xen/xen_driver.c: Fill in name
field in virStateDriver struct
2009-11-02 23:18:19 +00:00
|
|
|
/* Check that the user is root, silently disable if not */
|
2009-06-12 13:20:13 +00:00
|
|
|
if (!privileged) {
|
2011-05-09 09:24:09 +00:00
|
|
|
VIR_INFO("Not running privileged, disabling driver");
|
Fix return value in virStateInitialize impl for LXC
The LXC driver was mistakenly returning -1 for lxcStartup()
in scenarios that are not an error. This caused the libvirtd
to quit for unprivileged users. This fixes the return code
of LXC driver, and also adds a "name" field to the virStateDriver
struct and logging to make it easier to find these problems
in the future
* src/driver.h: Add a 'name' field to state driver to allow
easy identification during failures
* src/libvirt.c: Log name of failed driver for virStateInit
failures
* src/lxc/lxc_driver.c: Don't return a failure code for
lxcStartup() if LXC is not available on this host, simply
disable the driver.
* src/network/bridge_driver.c, src/node_device/node_device_devkit.c,
src/node_device/node_device_hal.c, src/opennebula/one_driver.c,
src/qemu/qemu_driver.c, src/remote/remote_driver.c,
src/secret/secret_driver.c, src/storage/storage_driver.c,
src/uml/uml_driver.c, src/xen/xen_driver.c: Fill in name
field in virStateDriver struct
2009-11-02 23:18:19 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check that this is a container enabled kernel */
|
|
|
|
if (lxcContainerAvailable(0) < 0) {
|
2011-05-09 09:24:09 +00:00
|
|
|
VIR_INFO("LXC support not available in this kernel, disabling driver");
|
Fix return value in virStateInitialize impl for LXC
The LXC driver was mistakenly returning -1 for lxcStartup()
in scenarios that are not an error. This caused the libvirtd
to quit for unprivileged users. This fixes the return code
of LXC driver, and also adds a "name" field to the virStateDriver
struct and logging to make it easier to find these problems
in the future
* src/driver.h: Add a 'name' field to state driver to allow
easy identification during failures
* src/libvirt.c: Log name of failed driver for virStateInit
failures
* src/lxc/lxc_driver.c: Don't return a failure code for
lxcStartup() if LXC is not available on this host, simply
disable the driver.
* src/network/bridge_driver.c, src/node_device/node_device_devkit.c,
src/node_device/node_device_hal.c, src/opennebula/one_driver.c,
src/qemu/qemu_driver.c, src/remote/remote_driver.c,
src/secret/secret_driver.c, src/storage/storage_driver.c,
src/uml/uml_driver.c, src/xen/xen_driver.c: Fill in name
field in virStateDriver struct
2009-11-02 23:18:19 +00:00
|
|
|
return 0;
|
2008-03-31 12:02:12 +00:00
|
|
|
}
|
|
|
|
|
2008-06-06 11:09:57 +00:00
|
|
|
if (VIR_ALLOC(lxc_driver) < 0) {
|
2008-03-27 09:34:06 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2009-01-15 19:56:05 +00:00
|
|
|
if (virMutexInit(&lxc_driver->lock) < 0) {
|
|
|
|
VIR_FREE(lxc_driver);
|
|
|
|
return -1;
|
|
|
|
}
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverLock(lxc_driver);
|
2008-03-21 15:03:37 +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
|
|
|
if (virDomainObjListInit(&lxc_driver->domains) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-12-14 00:25:58 +00:00
|
|
|
lxc_driver->domainEventState = virDomainEventStateNew();
|
2011-01-06 17:42:12 +00:00
|
|
|
if (!lxc_driver->domainEventState)
|
2009-07-06 15:04:36 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2009-10-08 15:40:14 +00:00
|
|
|
lxc_driver->log_libvirtd = 0; /* by default log to container logfile */
|
2008-06-26 16:05:02 +00:00
|
|
|
lxc_driver->have_netns = lxcCheckNetNsSupport();
|
2008-03-21 15:03:37 +00:00
|
|
|
|
2009-07-10 10:40:04 +00:00
|
|
|
rc = virCgroupForDriver("lxc", &lxc_driver->cgroup, privileged, 1);
|
|
|
|
if (rc < 0) {
|
2011-09-26 16:51:47 +00:00
|
|
|
char buf[1024] ATTRIBUTE_UNUSED;
|
2011-02-22 17:35:06 +00:00
|
|
|
VIR_DEBUG("Unable to create cgroup for LXC driver: %s",
|
|
|
|
virStrerror(-rc, buf, sizeof(buf)));
|
|
|
|
/* Don't abort startup. We will explicitly report to
|
|
|
|
* the user when they try to start a VM
|
|
|
|
*/
|
2009-07-10 10:40:04 +00:00
|
|
|
}
|
|
|
|
|
2008-03-21 15:03:37 +00:00
|
|
|
/* Call function to load lxc driver configuration information */
|
2008-12-04 21:12:41 +00:00
|
|
|
if (lxcLoadDriverConfig(lxc_driver) < 0)
|
|
|
|
goto cleanup;
|
2008-03-21 15:03:37 +00:00
|
|
|
|
2012-01-25 14:12:53 +00:00
|
|
|
if (lxcSecurityInit(lxc_driver) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if ((lxc_driver->caps = lxcCapsInit(lxc_driver)) == NULL)
|
2008-12-04 21:12:41 +00:00
|
|
|
goto cleanup;
|
2008-03-21 15:03:37 +00:00
|
|
|
|
2012-07-18 16:20:46 +00:00
|
|
|
virLXCDomainSetPrivateDataHooks(lxc_driver->caps);
|
2009-11-26 17:56:01 +00:00
|
|
|
|
2012-07-13 11:49:24 +00:00
|
|
|
if (virLXCProcessAutoDestroyInit(lxc_driver) < 0)
|
2011-07-13 11:21:54 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2011-05-31 10:03:41 +00:00
|
|
|
/* Get all the running persistent or transient configs first */
|
|
|
|
if (virDomainLoadAllConfigs(lxc_driver->caps,
|
|
|
|
&lxc_driver->domains,
|
|
|
|
lxc_driver->stateDir,
|
|
|
|
NULL,
|
2011-07-11 17:29:09 +00:00
|
|
|
1, 1 << VIR_DOMAIN_VIRT_LXC,
|
|
|
|
NULL, NULL) < 0)
|
2011-05-31 10:03:41 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2012-07-13 11:49:24 +00:00
|
|
|
virLXCProcessReconnectAll(lxc_driver, &lxc_driver->domains);
|
2011-05-31 10:03:41 +00:00
|
|
|
|
|
|
|
/* Then inactive persistent configs */
|
2010-02-09 18:58:01 +00:00
|
|
|
if (virDomainLoadAllConfigs(lxc_driver->caps,
|
2008-08-13 12:50:55 +00:00
|
|
|
&lxc_driver->domains,
|
|
|
|
lxc_driver->configDir,
|
2008-11-17 16:52:32 +00:00
|
|
|
lxc_driver->autostartDir,
|
2011-07-11 17:29:09 +00:00
|
|
|
0, 1 << VIR_DOMAIN_VIRT_LXC,
|
|
|
|
NULL, NULL) < 0)
|
2008-12-04 21:12:41 +00:00
|
|
|
goto cleanup;
|
2008-08-13 12:50:55 +00:00
|
|
|
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverUnlock(lxc_driver);
|
2010-07-29 14:21:17 +00:00
|
|
|
|
2012-07-13 11:49:24 +00:00
|
|
|
virLXCProcessAutostartAll(lxc_driver);
|
2010-07-29 14:21:17 +00:00
|
|
|
|
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(&lxcCallbackDriver);
|
2008-03-21 15:03:37 +00:00
|
|
|
return 0;
|
|
|
|
|
2008-12-04 21:12:41 +00:00
|
|
|
cleanup:
|
|
|
|
lxcDriverUnlock(lxc_driver);
|
|
|
|
lxcShutdown();
|
|
|
|
return -1;
|
2008-03-21 15:03:37 +00:00
|
|
|
}
|
|
|
|
|
2009-07-06 15:05:32 +00:00
|
|
|
static void lxcNotifyLoadDomain(virDomainObjPtr vm, int newVM, void *opaque)
|
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = opaque;
|
2009-07-06 15:05:32 +00:00
|
|
|
|
|
|
|
if (newVM) {
|
|
|
|
virDomainEventPtr event =
|
|
|
|
virDomainEventNewFromObj(vm,
|
|
|
|
VIR_DOMAIN_EVENT_DEFINED,
|
|
|
|
VIR_DOMAIN_EVENT_DEFINED_ADDED);
|
|
|
|
if (event)
|
2012-07-13 11:39:29 +00:00
|
|
|
virDomainEventStateQueue(driver->domainEventState, event);
|
2009-07-06 15:05:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* lxcReload:
|
|
|
|
*
|
|
|
|
* Function to restart the LXC driver, it will recheck the configuration
|
|
|
|
* files and perform autostart
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
lxcReload(void) {
|
|
|
|
if (!lxc_driver)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
lxcDriverLock(lxc_driver);
|
2010-02-09 18:58:01 +00:00
|
|
|
virDomainLoadAllConfigs(lxc_driver->caps,
|
2009-07-06 15:05:32 +00:00
|
|
|
&lxc_driver->domains,
|
|
|
|
lxc_driver->configDir,
|
|
|
|
lxc_driver->autostartDir,
|
2011-07-11 17:29:09 +00:00
|
|
|
0, 1 << VIR_DOMAIN_VIRT_LXC,
|
|
|
|
lxcNotifyLoadDomain, lxc_driver);
|
2009-07-06 15:05:32 +00:00
|
|
|
lxcDriverUnlock(lxc_driver);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-03-27 09:34:06 +00:00
|
|
|
static int lxcShutdown(void)
|
2008-03-21 15:03:37 +00:00
|
|
|
{
|
2008-03-31 12:02:12 +00:00
|
|
|
if (lxc_driver == NULL)
|
2012-03-22 11:33:35 +00:00
|
|
|
return -1;
|
2008-10-10 14:20:37 +00:00
|
|
|
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverLock(lxc_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
|
|
|
virNWFilterUnRegisterCallbackDriver(&lxcCallbackDriver);
|
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
|
|
|
virDomainObjListDeinit(&lxc_driver->domains);
|
2011-01-06 17:42:12 +00:00
|
|
|
virDomainEventStateFree(lxc_driver->domainEventState);
|
2009-07-06 15:04:36 +00:00
|
|
|
|
2012-07-13 11:49:24 +00:00
|
|
|
virLXCProcessAutoDestroyShutdown(lxc_driver);
|
2011-07-13 11:21:54 +00:00
|
|
|
|
2008-12-04 21:12:41 +00:00
|
|
|
virCapabilitiesFree(lxc_driver->caps);
|
2012-01-25 14:12:53 +00:00
|
|
|
virSecurityManagerFree(lxc_driver->securityManager);
|
2008-12-04 21:12:41 +00:00
|
|
|
VIR_FREE(lxc_driver->configDir);
|
|
|
|
VIR_FREE(lxc_driver->autostartDir);
|
|
|
|
VIR_FREE(lxc_driver->stateDir);
|
|
|
|
VIR_FREE(lxc_driver->logDir);
|
|
|
|
lxcDriverUnlock(lxc_driver);
|
2009-01-15 19:56:05 +00:00
|
|
|
virMutexDestroy(&lxc_driver->lock);
|
2008-12-04 21:12:41 +00:00
|
|
|
VIR_FREE(lxc_driver);
|
2008-03-27 09:34:06 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2008-03-21 15:03:37 +00:00
|
|
|
|
2008-03-27 09:34:06 +00:00
|
|
|
/**
|
|
|
|
* lxcActive:
|
|
|
|
*
|
|
|
|
* Checks if the LXC daemon is active, i.e. has an active domain
|
|
|
|
*
|
|
|
|
* Returns 1 if active, 0 otherwise
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
lxcActive(void) {
|
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 active;
|
2008-08-13 12:50:55 +00:00
|
|
|
|
2008-03-31 12:02:12 +00:00
|
|
|
if (lxc_driver == NULL)
|
2012-03-22 11:33:35 +00:00
|
|
|
return 0;
|
2008-08-13 12:50:55 +00:00
|
|
|
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverLock(lxc_driver);
|
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
|
|
|
active = virDomainObjListNumOfDomains(&lxc_driver->domains, 1);
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverUnlock(lxc_driver);
|
2008-03-27 09:34:06 +00:00
|
|
|
|
2008-12-04 21:12:41 +00:00
|
|
|
return active;
|
2008-03-21 15:03:37 +00:00
|
|
|
}
|
|
|
|
|
2010-02-09 18:22:56 +00:00
|
|
|
static int lxcVersion(virConnectPtr conn ATTRIBUTE_UNUSED, unsigned long *version)
|
2008-09-03 17:21:27 +00:00
|
|
|
{
|
|
|
|
struct utsname ver;
|
|
|
|
|
2009-01-20 17:13:33 +00:00
|
|
|
uname(&ver);
|
2008-09-03 17:21:27 +00:00
|
|
|
|
2011-07-01 13:23:02 +00:00
|
|
|
if (virParseVersionString(ver.release, version, true) < 0) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, _("Unknown release: %s"), ver.release);
|
2008-09-03 17:21:27 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2008-03-27 09:34:06 +00:00
|
|
|
|
2011-11-10 12:16:26 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* check whether the host supports CFS bandwidth
|
|
|
|
*
|
|
|
|
* Return 1 when CFS bandwidth is supported, 0 when CFS bandwidth is not
|
|
|
|
* supported, -1 on error.
|
|
|
|
*/
|
|
|
|
static int lxcGetCpuBWStatus(virCgroupPtr cgroup)
|
|
|
|
{
|
|
|
|
char *cfs_period_path = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (!cgroup)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (virCgroupPathOfController(cgroup, VIR_CGROUP_CONTROLLER_CPU,
|
|
|
|
"cpu.cfs_period_us", &cfs_period_path) < 0) {
|
|
|
|
VIR_INFO("cannot get the path of cgroup CPU controller");
|
|
|
|
ret = 0;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (access(cfs_period_path, F_OK) < 0) {
|
|
|
|
ret = 0;
|
|
|
|
} else {
|
|
|
|
ret = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(cfs_period_path);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-07-13 11:56:29 +00:00
|
|
|
static bool lxcCgroupControllerActive(virLXCDriverPtr driver,
|
2011-11-10 12:16:26 +00:00
|
|
|
int controller)
|
|
|
|
{
|
|
|
|
if (driver->cgroup == NULL)
|
|
|
|
return false;
|
|
|
|
if (controller < 0 || controller >= VIR_CGROUP_CONTROLLER_LAST)
|
|
|
|
return false;
|
|
|
|
if (!virCgroupMounted(driver->cgroup, controller))
|
|
|
|
return false;
|
|
|
|
#if 0
|
|
|
|
if (driver->cgroupControllers & (1 << controller))
|
|
|
|
return true;
|
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static char *lxcGetSchedulerType(virDomainPtr domain,
|
2010-02-04 18:19:08 +00:00
|
|
|
int *nparams)
|
2008-10-08 16:28:48 +00:00
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = domain->conn->privateData;
|
2011-11-10 12:16:26 +00:00
|
|
|
char *ret = NULL;
|
|
|
|
int rc;
|
2009-11-08 21:08:54 +00:00
|
|
|
|
2011-11-10 12:16:26 +00:00
|
|
|
lxcDriverLock(driver);
|
|
|
|
if (!lxcCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU)) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("cgroup CPU controller is not mounted"));
|
2011-11-10 12:16:26 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2008-10-08 16:28:48 +00:00
|
|
|
|
2011-11-10 12:16:26 +00:00
|
|
|
if (nparams) {
|
|
|
|
rc = lxcGetCpuBWStatus(driver->cgroup);
|
|
|
|
if (rc < 0)
|
|
|
|
goto cleanup;
|
|
|
|
else if (rc == 0)
|
|
|
|
*nparams = 1;
|
|
|
|
else
|
|
|
|
*nparams = 3;
|
|
|
|
}
|
2009-11-08 21:08:54 +00:00
|
|
|
|
2011-11-10 12:16:26 +00:00
|
|
|
ret = strdup("posix");
|
|
|
|
if (!ret)
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-11-08 21:08:54 +00:00
|
|
|
|
2011-11-10 12:16:26 +00:00
|
|
|
cleanup:
|
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
lxcGetVcpuBWLive(virCgroupPtr cgroup, unsigned long long *period,
|
|
|
|
long long *quota)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
rc = virCgroupGetCpuCfsPeriod(cgroup, period);
|
|
|
|
if (rc < 0) {
|
|
|
|
virReportSystemError(-rc, "%s",
|
|
|
|
_("unable to get cpu bandwidth period tunable"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = virCgroupGetCpuCfsQuota(cgroup, quota);
|
|
|
|
if (rc < 0) {
|
|
|
|
virReportSystemError(-rc, "%s",
|
|
|
|
_("unable to get cpu bandwidth tunable"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int lxcSetVcpuBWLive(virCgroupPtr cgroup, unsigned long long period,
|
|
|
|
long long quota)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
unsigned long long old_period;
|
|
|
|
|
|
|
|
if (period == 0 && quota == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (period) {
|
|
|
|
/* get old period, and we can rollback if set quota failed */
|
|
|
|
rc = virCgroupGetCpuCfsPeriod(cgroup, &old_period);
|
|
|
|
if (rc < 0) {
|
|
|
|
virReportSystemError(-rc,
|
|
|
|
"%s", _("Unable to get cpu bandwidth period"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = virCgroupSetCpuCfsPeriod(cgroup, period);
|
|
|
|
if (rc < 0) {
|
|
|
|
virReportSystemError(-rc,
|
|
|
|
"%s", _("Unable to set cpu bandwidth period"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (quota) {
|
|
|
|
rc = virCgroupSetCpuCfsQuota(cgroup, quota);
|
|
|
|
if (rc < 0) {
|
|
|
|
virReportSystemError(-rc,
|
|
|
|
"%s", _("Unable to set cpu bandwidth quota"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (period) {
|
|
|
|
rc = virCgroupSetCpuCfsPeriod(cgroup, old_period);
|
|
|
|
if (rc < 0)
|
2012-07-10 21:43:08 +00:00
|
|
|
virReportSystemError(-rc, "%s",
|
|
|
|
_("Unable to rollback cpu bandwidth period"));
|
2011-11-10 12:16:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
2008-10-08 16:28:48 +00:00
|
|
|
}
|
|
|
|
|
2011-11-10 12:16:26 +00:00
|
|
|
|
2011-05-17 22:33:53 +00:00
|
|
|
static int
|
2011-11-10 12:16:26 +00:00
|
|
|
lxcSetSchedulerParametersFlags(virDomainPtr dom,
|
2011-05-17 22:33:53 +00:00
|
|
|
virTypedParameterPtr params,
|
|
|
|
int nparams,
|
|
|
|
unsigned int flags)
|
2008-10-08 16:28:48 +00:00
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = dom->conn->privateData;
|
2008-10-08 16:28:48 +00:00
|
|
|
int i;
|
2008-12-04 21:11:41 +00:00
|
|
|
virCgroupPtr group = NULL;
|
|
|
|
virDomainObjPtr vm = NULL;
|
2011-11-10 12:16:26 +00:00
|
|
|
virDomainDefPtr vmdef = NULL;
|
2008-12-04 21:11:41 +00:00
|
|
|
int ret = -1;
|
2011-11-10 12:16:26 +00:00
|
|
|
int rc;
|
2008-10-08 16:28:48 +00:00
|
|
|
|
2011-11-10 12:16:26 +00:00
|
|
|
virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
|
|
|
|
VIR_DOMAIN_AFFECT_CONFIG, -1);
|
2012-01-07 12:47:43 +00:00
|
|
|
if (virTypedParameterArrayValidate(params, nparams,
|
|
|
|
VIR_DOMAIN_SCHEDULER_CPU_SHARES,
|
|
|
|
VIR_TYPED_PARAM_ULLONG,
|
|
|
|
VIR_DOMAIN_SCHEDULER_VCPU_PERIOD,
|
|
|
|
VIR_TYPED_PARAM_ULLONG,
|
|
|
|
VIR_DOMAIN_SCHEDULER_VCPU_QUOTA,
|
|
|
|
VIR_TYPED_PARAM_LLONG,
|
|
|
|
NULL) < 0)
|
|
|
|
return -1;
|
2008-12-04 21:12:41 +00:00
|
|
|
|
|
|
|
lxcDriverLock(driver);
|
2011-11-10 12:16:26 +00:00
|
|
|
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
2008-10-08 16:28:48 +00:00
|
|
|
|
2008-12-04 21:11:41 +00:00
|
|
|
if (vm == NULL) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("No such domain %s"), dom->uuid);
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
2008-10-08 16:28:48 +00:00
|
|
|
}
|
|
|
|
|
2012-01-07 12:36:46 +00:00
|
|
|
if (virDomainLiveConfigHelperMethod(driver->caps, vm, &flags,
|
|
|
|
&vmdef) < 0)
|
|
|
|
goto cleanup;
|
2011-11-10 12:16:26 +00:00
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
|
|
|
|
/* Make a copy for updated domain. */
|
|
|
|
vmdef = virDomainObjCopyPersistentDef(driver->caps, vm);
|
|
|
|
if (!vmdef)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_AFFECT_LIVE) {
|
|
|
|
if (!lxcCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU)) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("cgroup CPU controller is not mounted"));
|
2011-11-10 12:16:26 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("cannot find cgroup for domain %s"),
|
|
|
|
vm->def->name);
|
2011-11-10 12:16:26 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
2008-10-08 16:28:48 +00:00
|
|
|
|
|
|
|
for (i = 0; i < nparams; i++) {
|
2011-05-26 17:39:04 +00:00
|
|
|
virTypedParameterPtr param = ¶ms[i];
|
2010-05-11 13:51:46 +00:00
|
|
|
|
2011-11-10 12:16:26 +00:00
|
|
|
if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_CPU_SHARES)) {
|
|
|
|
if (flags & VIR_DOMAIN_AFFECT_LIVE) {
|
|
|
|
rc = virCgroupSetCpuShares(group, params[i].value.ul);
|
|
|
|
if (rc != 0) {
|
|
|
|
virReportSystemError(-rc, "%s",
|
|
|
|
_("unable to set cpu shares tunable"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
vm->def->cputune.shares = params[i].value.ul;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
|
|
|
|
vmdef->cputune.shares = params[i].value.ul;
|
|
|
|
}
|
|
|
|
} else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_VCPU_PERIOD)) {
|
|
|
|
if (flags & VIR_DOMAIN_AFFECT_LIVE) {
|
|
|
|
rc = lxcSetVcpuBWLive(group, params[i].value.ul, 0);
|
|
|
|
if (rc != 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (params[i].value.ul)
|
|
|
|
vm->def->cputune.period = params[i].value.ul;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
|
|
|
|
vmdef->cputune.period = params[i].value.ul;
|
|
|
|
}
|
|
|
|
} else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_VCPU_QUOTA)) {
|
|
|
|
if (flags & VIR_DOMAIN_AFFECT_LIVE) {
|
|
|
|
rc = lxcSetVcpuBWLive(group, 0, params[i].value.l);
|
|
|
|
if (rc != 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (params[i].value.l)
|
|
|
|
vm->def->cputune.quota = params[i].value.l;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
|
|
|
|
vmdef->cputune.quota = params[i].value.l;
|
|
|
|
}
|
2010-05-11 13:51:46 +00:00
|
|
|
}
|
2011-11-10 12:16:26 +00:00
|
|
|
}
|
2010-05-11 13:51:46 +00:00
|
|
|
|
2011-11-10 12:16:26 +00:00
|
|
|
if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
|
|
|
|
goto cleanup;
|
2008-10-08 16:28:48 +00:00
|
|
|
|
2011-11-10 12:16:26 +00:00
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
|
|
|
|
rc = virDomainSaveConfig(driver->configDir, vmdef);
|
|
|
|
if (rc < 0)
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
2011-03-29 13:42:54 +00:00
|
|
|
|
2011-11-10 12:16:26 +00:00
|
|
|
virDomainObjAssignDef(vm, vmdef, false);
|
|
|
|
vmdef = NULL;
|
2008-10-08 16:28:48 +00:00
|
|
|
}
|
2011-11-10 12:16:26 +00:00
|
|
|
|
2008-12-04 21:11:41 +00:00
|
|
|
ret = 0;
|
2008-10-08 16:28:48 +00:00
|
|
|
|
2008-12-04 21:11:41 +00:00
|
|
|
cleanup:
|
2011-11-10 12:16:26 +00:00
|
|
|
virDomainDefFree(vmdef);
|
2008-10-08 16:28:48 +00:00
|
|
|
virCgroupFree(&group);
|
2008-12-04 21:12:41 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
2011-11-10 12:16:26 +00:00
|
|
|
lxcDriverUnlock(driver);
|
2008-12-04 21:11:41 +00:00
|
|
|
return ret;
|
2008-10-08 16:28:48 +00:00
|
|
|
}
|
|
|
|
|
2011-05-17 22:33:53 +00:00
|
|
|
static int
|
|
|
|
lxcSetSchedulerParameters(virDomainPtr domain,
|
|
|
|
virTypedParameterPtr params,
|
|
|
|
int nparams)
|
|
|
|
{
|
|
|
|
return lxcSetSchedulerParametersFlags(domain, params, nparams, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2011-11-10 12:16:26 +00:00
|
|
|
lxcGetSchedulerParametersFlags(virDomainPtr dom,
|
2011-05-17 22:33:53 +00:00
|
|
|
virTypedParameterPtr params,
|
|
|
|
int *nparams,
|
|
|
|
unsigned int flags)
|
2008-10-08 16:28:48 +00:00
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = dom->conn->privateData;
|
2008-12-04 21:11:41 +00:00
|
|
|
virCgroupPtr group = NULL;
|
|
|
|
virDomainObjPtr vm = NULL;
|
2012-01-07 12:36:46 +00:00
|
|
|
virDomainDefPtr persistentDef;
|
2011-11-10 12:16:26 +00:00
|
|
|
unsigned long long shares = 0;
|
|
|
|
unsigned long long period = 0;
|
|
|
|
long long quota = 0;
|
2008-12-04 21:11:41 +00:00
|
|
|
int ret = -1;
|
2011-11-10 12:16:26 +00:00
|
|
|
int rc;
|
|
|
|
bool cpu_bw_status = false;
|
|
|
|
int saved_nparams = 0;
|
2008-10-08 16:28:48 +00:00
|
|
|
|
2011-11-10 12:16:26 +00:00
|
|
|
virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
|
|
|
|
VIR_DOMAIN_AFFECT_CONFIG, -1);
|
2008-10-08 16:28:48 +00:00
|
|
|
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverLock(driver);
|
2011-11-10 12:16:26 +00:00
|
|
|
|
|
|
|
if (*nparams > 1) {
|
|
|
|
rc = lxcGetCpuBWStatus(driver->cgroup);
|
|
|
|
if (rc < 0)
|
|
|
|
goto cleanup;
|
|
|
|
cpu_bw_status = !!rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
2008-12-04 21:12:41 +00:00
|
|
|
|
2008-12-04 21:11:41 +00:00
|
|
|
if (vm == NULL) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("No such domain %s"), dom->uuid);
|
2011-11-10 12:16:26 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2012-01-07 12:36:46 +00:00
|
|
|
if (virDomainLiveConfigHelperMethod(driver->caps, vm, &flags,
|
|
|
|
&persistentDef) < 0)
|
|
|
|
goto cleanup;
|
2011-11-10 12:16:26 +00:00
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
|
2012-01-07 12:36:46 +00:00
|
|
|
shares = persistentDef->cputune.shares;
|
|
|
|
if (*nparams > 1 && cpu_bw_status) {
|
|
|
|
period = persistentDef->cputune.period;
|
|
|
|
quota = persistentDef->cputune.quota;
|
2011-11-10 12:16:26 +00:00
|
|
|
}
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!lxcCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU)) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("cgroup CPU controller is not mounted"));
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
2008-10-08 16:28:48 +00:00
|
|
|
}
|
|
|
|
|
2011-11-10 12:16:26 +00:00
|
|
|
if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("cannot find cgroup for domain %s"), vm->def->name);
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
2011-11-10 12:16:26 +00:00
|
|
|
}
|
2008-10-08 16:28:48 +00:00
|
|
|
|
2011-11-10 12:16:26 +00:00
|
|
|
rc = virCgroupGetCpuShares(group, &shares);
|
|
|
|
if (rc != 0) {
|
|
|
|
virReportSystemError(-rc, "%s",
|
|
|
|
_("unable to get cpu shares tunable"));
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
2011-11-10 12:16:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (*nparams > 1 && cpu_bw_status) {
|
|
|
|
rc = lxcGetVcpuBWLive(group, &period, "a);
|
|
|
|
if (rc != 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
out:
|
2012-01-07 12:47:43 +00:00
|
|
|
if (virTypedParameterAssign(¶ms[0], VIR_DOMAIN_SCHEDULER_CPU_SHARES,
|
|
|
|
VIR_TYPED_PARAM_ULLONG, shares) < 0)
|
2009-08-03 12:37:44 +00:00
|
|
|
goto cleanup;
|
2011-11-10 12:16:26 +00:00
|
|
|
saved_nparams++;
|
|
|
|
|
|
|
|
if (cpu_bw_status) {
|
|
|
|
if (*nparams > saved_nparams) {
|
2012-01-07 12:47:43 +00:00
|
|
|
if (virTypedParameterAssign(¶ms[1],
|
|
|
|
VIR_DOMAIN_SCHEDULER_VCPU_PERIOD,
|
|
|
|
VIR_TYPED_PARAM_ULLONG, period) < 0)
|
2011-11-10 12:16:26 +00:00
|
|
|
goto cleanup;
|
|
|
|
saved_nparams++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*nparams > saved_nparams) {
|
2012-01-07 12:47:43 +00:00
|
|
|
if (virTypedParameterAssign(¶ms[2],
|
|
|
|
VIR_DOMAIN_SCHEDULER_VCPU_QUOTA,
|
|
|
|
VIR_TYPED_PARAM_LLONG, quota) < 0)
|
2011-11-10 12:16:26 +00:00
|
|
|
goto cleanup;
|
|
|
|
saved_nparams++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*nparams = saved_nparams;
|
|
|
|
|
2008-12-04 21:11:41 +00:00
|
|
|
ret = 0;
|
2008-10-08 16:28:48 +00:00
|
|
|
|
2008-12-04 21:11:41 +00:00
|
|
|
cleanup:
|
|
|
|
virCgroupFree(&group);
|
2008-12-04 21:12:41 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
2011-11-10 12:16:26 +00:00
|
|
|
lxcDriverUnlock(driver);
|
2008-12-04 21:11:41 +00:00
|
|
|
return ret;
|
2008-10-08 16:28:48 +00:00
|
|
|
}
|
|
|
|
|
2011-05-17 22:33:53 +00:00
|
|
|
static int
|
|
|
|
lxcGetSchedulerParameters(virDomainPtr domain,
|
|
|
|
virTypedParameterPtr params,
|
|
|
|
int *nparams)
|
|
|
|
{
|
|
|
|
return lxcGetSchedulerParametersFlags(domain, params, nparams, 0);
|
|
|
|
}
|
|
|
|
|
2011-11-10 12:35:38 +00:00
|
|
|
|
2012-01-07 12:47:43 +00:00
|
|
|
static int
|
|
|
|
lxcDomainSetBlkioParameters(virDomainPtr dom,
|
|
|
|
virTypedParameterPtr params,
|
|
|
|
int nparams,
|
|
|
|
unsigned int flags)
|
2011-11-10 12:35:38 +00:00
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = dom->conn->privateData;
|
2011-11-10 12:35:38 +00:00
|
|
|
int i;
|
|
|
|
virCgroupPtr group = NULL;
|
|
|
|
virDomainObjPtr vm = NULL;
|
|
|
|
virDomainDefPtr persistentDef = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
|
|
|
|
VIR_DOMAIN_AFFECT_CONFIG, -1);
|
2012-01-07 12:47:43 +00:00
|
|
|
if (virTypedParameterArrayValidate(params, nparams,
|
|
|
|
VIR_DOMAIN_BLKIO_WEIGHT,
|
|
|
|
VIR_TYPED_PARAM_UINT,
|
|
|
|
NULL) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2011-11-10 12:35:38 +00:00
|
|
|
lxcDriverLock(driver);
|
|
|
|
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
|
|
|
|
if (vm == NULL) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("No such domain %s"), dom->uuid);
|
2011-11-10 12:35:38 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2012-01-07 12:36:46 +00:00
|
|
|
if (virDomainLiveConfigHelperMethod(driver->caps, vm, &flags,
|
|
|
|
&persistentDef) < 0)
|
|
|
|
goto cleanup;
|
2011-11-10 12:35:38 +00:00
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_AFFECT_LIVE) {
|
|
|
|
if (!lxcCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_BLKIO)) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("blkio cgroup isn't mounted"));
|
2011-11-10 12:35:38 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("cannot find cgroup for domain %s"), vm->def->name);
|
2011-11-10 12:35:38 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < nparams; i++) {
|
|
|
|
virTypedParameterPtr param = ¶ms[i];
|
|
|
|
|
|
|
|
if (STREQ(param->field, VIR_DOMAIN_BLKIO_WEIGHT)) {
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
if (params[i].value.ui > 1000 || params[i].value.ui < 100) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("out of blkio weight range."));
|
2012-01-07 12:36:46 +00:00
|
|
|
goto cleanup;
|
2011-11-10 12:35:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
rc = virCgroupSetBlkioWeight(group, params[i].value.ui);
|
|
|
|
if (rc != 0) {
|
|
|
|
virReportSystemError(-rc, "%s",
|
|
|
|
_("unable to set blkio weight tunable"));
|
2012-01-07 12:36:46 +00:00
|
|
|
goto cleanup;
|
2011-11-10 12:35:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-01-07 12:36:46 +00:00
|
|
|
}
|
|
|
|
if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
|
2011-11-10 12:35:38 +00:00
|
|
|
/* Clang can't see that if we get here, persistentDef was set. */
|
|
|
|
sa_assert(persistentDef);
|
|
|
|
|
|
|
|
for (i = 0; i < nparams; i++) {
|
|
|
|
virTypedParameterPtr param = ¶ms[i];
|
|
|
|
|
|
|
|
if (STREQ(param->field, VIR_DOMAIN_BLKIO_WEIGHT)) {
|
|
|
|
if (params[i].value.ui > 1000 || params[i].value.ui < 100) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("out of blkio weight range."));
|
2012-01-07 12:36:46 +00:00
|
|
|
goto cleanup;
|
2011-11-10 12:35:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
persistentDef->blkio.weight = params[i].value.ui;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virDomainSaveConfig(driver->configDir, persistentDef) < 0)
|
2012-01-07 12:36:46 +00:00
|
|
|
goto cleanup;
|
2011-11-10 12:35:38 +00:00
|
|
|
}
|
|
|
|
|
2012-01-07 12:36:46 +00:00
|
|
|
ret = 0;
|
2011-11-10 12:35:38 +00:00
|
|
|
cleanup:
|
|
|
|
virCgroupFree(&group);
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define LXC_NB_BLKIO_PARAM 1
|
2012-01-07 12:47:43 +00:00
|
|
|
static int
|
|
|
|
lxcDomainGetBlkioParameters(virDomainPtr dom,
|
|
|
|
virTypedParameterPtr params,
|
|
|
|
int *nparams,
|
|
|
|
unsigned int flags)
|
2011-11-10 12:35:38 +00:00
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = dom->conn->privateData;
|
2011-11-10 12:35:38 +00:00
|
|
|
int i;
|
|
|
|
virCgroupPtr group = NULL;
|
|
|
|
virDomainObjPtr vm = NULL;
|
|
|
|
virDomainDefPtr persistentDef = NULL;
|
|
|
|
unsigned int val;
|
|
|
|
int ret = -1;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
|
|
|
|
VIR_DOMAIN_AFFECT_CONFIG, -1);
|
|
|
|
lxcDriverLock(driver);
|
|
|
|
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
|
|
|
|
if (vm == NULL) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("No such domain %s"), dom->uuid);
|
2011-11-10 12:35:38 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((*nparams) == 0) {
|
|
|
|
/* Current number of blkio parameters supported by cgroups */
|
|
|
|
*nparams = LXC_NB_BLKIO_PARAM;
|
|
|
|
ret = 0;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2012-01-07 12:36:46 +00:00
|
|
|
if (virDomainLiveConfigHelperMethod(driver->caps, vm, &flags,
|
|
|
|
&persistentDef) < 0)
|
|
|
|
goto cleanup;
|
2011-11-10 12:35:38 +00:00
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_AFFECT_LIVE) {
|
|
|
|
if (!lxcCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_BLKIO)) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("blkio cgroup isn't mounted"));
|
2011-11-10 12:35:38 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("cannot find cgroup for domain %s"), vm->def->name);
|
2011-11-10 12:35:38 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < *nparams && i < LXC_NB_BLKIO_PARAM; i++) {
|
|
|
|
virTypedParameterPtr param = ¶ms[i];
|
|
|
|
val = 0;
|
|
|
|
|
|
|
|
switch (i) {
|
|
|
|
case 0: /* fill blkio weight here */
|
|
|
|
rc = virCgroupGetBlkioWeight(group, &val);
|
|
|
|
if (rc != 0) {
|
|
|
|
virReportSystemError(-rc, "%s",
|
|
|
|
_("unable to get blkio weight"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2012-01-07 12:47:43 +00:00
|
|
|
if (virTypedParameterAssign(param, VIR_DOMAIN_BLKIO_WEIGHT,
|
|
|
|
VIR_TYPED_PARAM_UINT, val) < 0)
|
2011-11-10 12:35:38 +00:00
|
|
|
goto cleanup;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
/* should not hit here */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
|
|
|
|
for (i = 0; i < *nparams && i < LXC_NB_BLKIO_PARAM; i++) {
|
|
|
|
virTypedParameterPtr param = ¶ms[i];
|
|
|
|
|
|
|
|
switch (i) {
|
|
|
|
case 0: /* fill blkio weight here */
|
2012-01-07 12:47:43 +00:00
|
|
|
if (virTypedParameterAssign(param, VIR_DOMAIN_BLKIO_WEIGHT,
|
|
|
|
VIR_TYPED_PARAM_UINT,
|
|
|
|
persistentDef->blkio.weight) < 0)
|
2011-11-10 12:35:38 +00:00
|
|
|
goto cleanup;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
/* should not hit here */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (LXC_NB_BLKIO_PARAM < *nparams)
|
|
|
|
*nparams = LXC_NB_BLKIO_PARAM;
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (group)
|
|
|
|
virCgroupFree(&group);
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-11-12 13:55:44 +00:00
|
|
|
#ifdef __linux__
|
|
|
|
static int
|
|
|
|
lxcDomainInterfaceStats(virDomainPtr dom,
|
|
|
|
const char *path,
|
|
|
|
struct _virDomainInterfaceStats *stats)
|
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = dom->conn->privateData;
|
2009-11-12 13:55:44 +00:00
|
|
|
virDomainObjPtr vm;
|
|
|
|
int i;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
lxcDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
|
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
2009-11-12 13:55:44 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("Domain is not running"));
|
2009-11-12 13:55:44 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check the path is one of the domain's network interfaces. */
|
|
|
|
for (i = 0 ; i < vm->def->nnets ; i++) {
|
|
|
|
if (vm->def->nets[i]->ifname &&
|
|
|
|
STREQ(vm->def->nets[i]->ifname, path)) {
|
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ret == 0)
|
2010-02-04 23:02:10 +00:00
|
|
|
ret = linuxDomainInterfaceStats(path, stats);
|
2009-11-12 13:55:44 +00:00
|
|
|
else
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("Invalid path, '%s' is not a known interface"), path);
|
2009-11-12 13:55:44 +00:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
static int
|
|
|
|
lxcDomainInterfaceStats(virDomainPtr dom,
|
|
|
|
const char *path ATTRIBUTE_UNUSED,
|
|
|
|
struct _virDomainInterfaceStats *stats ATTRIBUTE_UNUSED)
|
2011-10-27 07:17:59 +00:00
|
|
|
{
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_NO_SUPPORT, "%s", __FUNCTION__);
|
2009-11-12 13:55:44 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-07-06 15:05:32 +00:00
|
|
|
static int lxcDomainGetAutostart(virDomainPtr dom,
|
|
|
|
int *autostart) {
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = dom->conn->privateData;
|
2009-07-06 15:05:32 +00:00
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
lxcDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
|
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
2009-07-06 15:05:32 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
*autostart = vm->autostart;
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int lxcDomainSetAutostart(virDomainPtr dom,
|
|
|
|
int autostart) {
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = dom->conn->privateData;
|
2009-07-06 15:05:32 +00:00
|
|
|
virDomainObjPtr vm;
|
|
|
|
char *configFile = NULL, *autostartLink = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
lxcDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
|
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
2009-07-06 15:05:32 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!vm->persistent) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("Cannot set autostart for transient domain"));
|
2009-07-06 15:05:32 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
autostart = (autostart != 0);
|
|
|
|
|
2009-11-05 12:41:14 +00:00
|
|
|
if (vm->autostart == autostart) {
|
|
|
|
ret = 0;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2009-07-06 15:05:32 +00:00
|
|
|
|
2010-02-09 18:58:01 +00:00
|
|
|
configFile = virDomainConfigFile(driver->configDir,
|
2009-11-05 12:41:14 +00:00
|
|
|
vm->def->name);
|
|
|
|
if (configFile == NULL)
|
|
|
|
goto cleanup;
|
2010-02-09 18:58:01 +00:00
|
|
|
autostartLink = virDomainConfigFile(driver->autostartDir,
|
2009-11-05 12:41:14 +00:00
|
|
|
vm->def->name);
|
|
|
|
if (autostartLink == NULL)
|
|
|
|
goto cleanup;
|
2009-07-06 15:05:32 +00:00
|
|
|
|
2009-11-05 12:41:14 +00:00
|
|
|
if (autostart) {
|
2011-07-05 21:02:53 +00:00
|
|
|
if (virFileMakePath(driver->autostartDir) < 0) {
|
|
|
|
virReportSystemError(errno,
|
2009-11-05 12:41:14 +00:00
|
|
|
_("Cannot create autostart directory %s"),
|
|
|
|
driver->autostartDir);
|
|
|
|
goto cleanup;
|
2009-07-06 15:05:32 +00:00
|
|
|
}
|
|
|
|
|
2009-11-05 12:41:14 +00:00
|
|
|
if (symlink(configFile, autostartLink) < 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-11-05 12:41:14 +00:00
|
|
|
_("Failed to create symlink '%s to '%s'"),
|
|
|
|
autostartLink, configFile);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-11-05 12:41:14 +00:00
|
|
|
_("Failed to delete symlink '%s'"),
|
|
|
|
autostartLink);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2009-07-06 15:05:32 +00:00
|
|
|
}
|
2009-11-05 12:41:14 +00:00
|
|
|
|
|
|
|
vm->autostart = autostart;
|
2009-07-06 15:05:32 +00:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(configFile);
|
|
|
|
VIR_FREE(autostartLink);
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-07-13 11:56:29 +00:00
|
|
|
static int lxcFreezeContainer(virLXCDriverPtr driver, virDomainObjPtr vm)
|
2009-09-21 14:31:22 +00:00
|
|
|
{
|
|
|
|
int timeout = 1000; /* In milliseconds */
|
|
|
|
int check_interval = 1; /* In milliseconds */
|
|
|
|
int exp = 10;
|
|
|
|
int waited_time = 0;
|
|
|
|
int ret = -1;
|
|
|
|
char *state = NULL;
|
|
|
|
virCgroupPtr cgroup = NULL;
|
|
|
|
|
|
|
|
if (!(driver->cgroup &&
|
2010-05-17 17:18:12 +00:00
|
|
|
virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) == 0))
|
2009-09-21 14:31:22 +00:00
|
|
|
return -1;
|
|
|
|
|
2010-05-17 17:18:12 +00:00
|
|
|
/* From here on, we know that cgroup != NULL. */
|
|
|
|
|
2009-09-21 14:31:22 +00:00
|
|
|
while (waited_time < timeout) {
|
|
|
|
int r;
|
|
|
|
/*
|
|
|
|
* Writing "FROZEN" to the "freezer.state" freezes the group,
|
|
|
|
* i.e., the container, temporarily transiting "FREEZING" state.
|
|
|
|
* Once the freezing is completed, the state of the group transits
|
|
|
|
* to "FROZEN".
|
|
|
|
* (see linux-2.6/Documentation/cgroups/freezer-subsystem.txt)
|
|
|
|
*/
|
|
|
|
r = virCgroupSetFreezerState(cgroup, "FROZEN");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Returning EBUSY explicitly indicates that the group is
|
|
|
|
* being freezed but incomplete and other errors are true
|
|
|
|
* errors.
|
|
|
|
*/
|
|
|
|
if (r < 0 && r != -EBUSY) {
|
|
|
|
VIR_DEBUG("Writing freezer.state failed with errno: %d", r);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
if (r == -EBUSY)
|
2011-05-09 09:24:09 +00:00
|
|
|
VIR_DEBUG("Writing freezer.state gets EBUSY");
|
2009-09-21 14:31:22 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Unfortunately, returning 0 (success) is likely to happen
|
|
|
|
* even when the freezing has not been completed. Sometimes
|
|
|
|
* the state of the group remains "FREEZING" like when
|
|
|
|
* returning -EBUSY and even worse may never transit to
|
|
|
|
* "FROZEN" even if writing "FROZEN" again.
|
|
|
|
*
|
|
|
|
* So we don't trust the return value anyway and always
|
|
|
|
* decide that the freezing has been complete only with
|
|
|
|
* the state actually transit to "FROZEN".
|
|
|
|
*/
|
|
|
|
usleep(check_interval * 1000);
|
|
|
|
|
|
|
|
r = virCgroupGetFreezerState(cgroup, &state);
|
|
|
|
|
|
|
|
if (r < 0) {
|
|
|
|
VIR_DEBUG("Reading freezer.state failed with errno: %d", r);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
VIR_DEBUG("Read freezer.state: %s", state);
|
|
|
|
|
|
|
|
if (STREQ(state, "FROZEN")) {
|
|
|
|
ret = 0;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
waited_time += check_interval;
|
|
|
|
/*
|
|
|
|
* Increasing check_interval exponentially starting with
|
|
|
|
* small initial value treats nicely two cases; One is
|
|
|
|
* a container is under no load and waiting for long period
|
|
|
|
* makes no sense. The other is under heavy load. The container
|
|
|
|
* may stay longer time in FREEZING or never transit to FROZEN.
|
|
|
|
* In that case, eager polling will just waste CPU time.
|
|
|
|
*/
|
|
|
|
check_interval *= exp;
|
|
|
|
VIR_FREE(state);
|
|
|
|
}
|
2011-05-09 09:24:09 +00:00
|
|
|
VIR_DEBUG("lxcFreezeContainer timeout");
|
2009-09-21 14:31:22 +00:00
|
|
|
error:
|
|
|
|
/*
|
|
|
|
* If timeout or an error on reading the state occurs,
|
|
|
|
* activate the group again and return an error.
|
|
|
|
* This is likely to fall the group back again gracefully.
|
|
|
|
*/
|
|
|
|
virCgroupSetFreezerState(cgroup, "THAWED");
|
|
|
|
ret = -1;
|
|
|
|
|
|
|
|
cleanup:
|
2010-05-17 17:18:12 +00:00
|
|
|
virCgroupFree(&cgroup);
|
2009-09-21 14:31:22 +00:00
|
|
|
VIR_FREE(state);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int lxcDomainSuspend(virDomainPtr dom)
|
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = dom->conn->privateData;
|
2009-09-21 14:31:22 +00:00
|
|
|
virDomainObjPtr vm;
|
|
|
|
virDomainEventPtr event = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
lxcDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
|
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
2009-09-21 14:31:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
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-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("Domain is not running"));
|
2009-09-21 14:31:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-05-04 09:07:01 +00:00
|
|
|
if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_PAUSED) {
|
2009-09-21 14:31:22 +00:00
|
|
|
if (lxcFreezeContainer(driver, vm) < 0) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
"%s", _("Suspend operation failed"));
|
2009-09-21 14:31:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2011-05-04 09:07:01 +00:00
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
|
2009-09-21 14:31:22 +00:00
|
|
|
|
|
|
|
event = virDomainEventNewFromObj(vm,
|
|
|
|
VIR_DOMAIN_EVENT_SUSPENDED,
|
|
|
|
VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
|
|
|
|
}
|
|
|
|
|
2010-02-09 18:58:01 +00:00
|
|
|
if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
|
2009-09-21 14:31:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (event)
|
2012-07-13 11:39:29 +00:00
|
|
|
virDomainEventStateQueue(driver->domainEventState, event);
|
2009-09-21 14:31:22 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-07-13 11:56:29 +00:00
|
|
|
static int lxcUnfreezeContainer(virLXCDriverPtr driver, virDomainObjPtr vm)
|
2009-09-21 14:31:22 +00:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
virCgroupPtr cgroup = NULL;
|
|
|
|
|
|
|
|
if (!(driver->cgroup &&
|
|
|
|
virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) == 0))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
ret = virCgroupSetFreezerState(cgroup, "THAWED");
|
|
|
|
|
|
|
|
virCgroupFree(&cgroup);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int lxcDomainResume(virDomainPtr dom)
|
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = dom->conn->privateData;
|
2009-09-21 14:31:22 +00:00
|
|
|
virDomainObjPtr vm;
|
|
|
|
virDomainEventPtr event = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
lxcDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
|
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
2009-09-21 14:31:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
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-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("Domain is not running"));
|
2009-09-21 14:31:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-05-04 09:07:01 +00:00
|
|
|
if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
|
2009-09-21 14:31:22 +00:00
|
|
|
if (lxcUnfreezeContainer(driver, vm) < 0) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
"%s", _("Resume operation failed"));
|
2009-09-21 14:31:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2011-05-04 09:07:01 +00:00
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
|
|
|
|
VIR_DOMAIN_RUNNING_UNPAUSED);
|
2009-09-21 14:31:22 +00:00
|
|
|
|
|
|
|
event = virDomainEventNewFromObj(vm,
|
|
|
|
VIR_DOMAIN_EVENT_RESUMED,
|
|
|
|
VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
|
|
|
|
}
|
|
|
|
|
2010-02-09 18:58:01 +00:00
|
|
|
if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
|
2009-09-21 14:31:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (event)
|
2012-07-13 11:39:29 +00:00
|
|
|
virDomainEventStateQueue(driver->domainEventState, event);
|
2009-09-21 14:31:22 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-10-22 13:40:26 +00:00
|
|
|
static int
|
|
|
|
lxcDomainOpenConsole(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)
|
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = dom->conn->privateData;
|
2010-10-22 13:40:26 +00:00
|
|
|
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);
|
|
|
|
|
|
|
|
lxcDriverLock(driver);
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
if (!vm) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("no domain with matching uuid '%s'"), uuidstr);
|
2010-10-22 13:40:26 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-07-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("domain is not running"));
|
2010-10-22 13:40:26 +00:00
|
|
|
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-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("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-13 12:59:51 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("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)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-06-11 09:04:57 +00:00
|
|
|
static int
|
|
|
|
lxcListAllDomains(virConnectPtr conn,
|
|
|
|
virDomainPtr **domains,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
2012-07-13 11:56:29 +00:00
|
|
|
virLXCDriverPtr driver = conn->privateData;
|
2012-06-11 09:04:57 +00:00
|
|
|
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
|
|
|
|
|
|
|
lxcDriverLock(driver);
|
|
|
|
ret = virDomainList(conn, driver->domains.objs, domains, flags);
|
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2008-03-21 15:03:37 +00:00
|
|
|
/* Function Tables */
|
|
|
|
static virDriver lxcDriver = {
|
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_LXC,
|
2012-05-10 16:49:29 +00:00
|
|
|
.name = LXC_DRIVER_NAME,
|
2011-05-13 13:35:01 +00:00
|
|
|
.open = lxcOpen, /* 0.4.2 */
|
|
|
|
.close = lxcClose, /* 0.4.2 */
|
|
|
|
.version = lxcVersion, /* 0.4.6 */
|
|
|
|
.getHostname = virGetHostname, /* 0.6.3 */
|
|
|
|
.nodeGetInfo = nodeGetInfo, /* 0.6.5 */
|
|
|
|
.getCapabilities = lxcGetCapabilities, /* 0.6.5 */
|
|
|
|
.listDomains = lxcListDomains, /* 0.4.2 */
|
|
|
|
.numOfDomains = lxcNumDomains, /* 0.4.2 */
|
2012-06-11 09:04:57 +00:00
|
|
|
.listAllDomains = lxcListAllDomains, /* 0.9.13 */
|
2011-05-13 13:35:01 +00:00
|
|
|
.domainCreateXML = lxcDomainCreateAndStart, /* 0.4.4 */
|
|
|
|
.domainLookupByID = lxcDomainLookupByID, /* 0.4.2 */
|
|
|
|
.domainLookupByUUID = lxcDomainLookupByUUID, /* 0.4.2 */
|
|
|
|
.domainLookupByName = lxcDomainLookupByName, /* 0.4.2 */
|
|
|
|
.domainSuspend = lxcDomainSuspend, /* 0.7.2 */
|
|
|
|
.domainResume = lxcDomainResume, /* 0.7.2 */
|
|
|
|
.domainDestroy = lxcDomainDestroy, /* 0.4.4 */
|
2011-07-20 16:51:26 +00:00
|
|
|
.domainDestroyFlags = lxcDomainDestroyFlags, /* 0.9.4 */
|
2011-05-13 13:35:01 +00:00
|
|
|
.domainGetOSType = lxcGetOSType, /* 0.4.2 */
|
|
|
|
.domainGetMaxMemory = lxcDomainGetMaxMemory, /* 0.7.2 */
|
|
|
|
.domainSetMaxMemory = lxcDomainSetMaxMemory, /* 0.7.2 */
|
|
|
|
.domainSetMemory = lxcDomainSetMemory, /* 0.7.2 */
|
|
|
|
.domainSetMemoryParameters = lxcDomainSetMemoryParameters, /* 0.8.5 */
|
|
|
|
.domainGetMemoryParameters = lxcDomainGetMemoryParameters, /* 0.8.5 */
|
2011-11-10 12:35:38 +00:00
|
|
|
.domainSetBlkioParameters = lxcDomainSetBlkioParameters, /* 0.9.8 */
|
|
|
|
.domainGetBlkioParameters = lxcDomainGetBlkioParameters, /* 0.9.8 */
|
2011-05-13 13:35:01 +00:00
|
|
|
.domainGetInfo = lxcDomainGetInfo, /* 0.4.2 */
|
|
|
|
.domainGetState = lxcDomainGetState, /* 0.9.2 */
|
2012-01-25 14:12:53 +00:00
|
|
|
.domainGetSecurityLabel = lxcDomainGetSecurityLabel, /* 0.9.10 */
|
|
|
|
.nodeGetSecurityModel = lxcNodeGetSecurityModel, /* 0.9.10 */
|
2011-05-13 13:35:01 +00:00
|
|
|
.domainGetXMLDesc = lxcDomainGetXMLDesc, /* 0.4.2 */
|
|
|
|
.listDefinedDomains = lxcListDefinedDomains, /* 0.4.2 */
|
|
|
|
.numOfDefinedDomains = lxcNumDefinedDomains, /* 0.4.2 */
|
|
|
|
.domainCreate = lxcDomainStart, /* 0.4.4 */
|
|
|
|
.domainCreateWithFlags = lxcDomainStartWithFlags, /* 0.8.2 */
|
|
|
|
.domainDefineXML = lxcDomainDefine, /* 0.4.2 */
|
|
|
|
.domainUndefine = lxcDomainUndefine, /* 0.4.2 */
|
2011-07-20 03:08:21 +00:00
|
|
|
.domainUndefineFlags = lxcDomainUndefineFlags, /* 0.9.4 */
|
2011-05-13 13:35:01 +00:00
|
|
|
.domainGetAutostart = lxcDomainGetAutostart, /* 0.7.0 */
|
|
|
|
.domainSetAutostart = lxcDomainSetAutostart, /* 0.7.0 */
|
|
|
|
.domainGetSchedulerType = lxcGetSchedulerType, /* 0.5.0 */
|
|
|
|
.domainGetSchedulerParameters = lxcGetSchedulerParameters, /* 0.5.0 */
|
2011-05-17 22:33:53 +00:00
|
|
|
.domainGetSchedulerParametersFlags = lxcGetSchedulerParametersFlags, /* 0.9.2 */
|
2011-05-13 13:35:01 +00:00
|
|
|
.domainSetSchedulerParameters = lxcSetSchedulerParameters, /* 0.5.0 */
|
2011-05-17 22:33:53 +00:00
|
|
|
.domainSetSchedulerParametersFlags = lxcSetSchedulerParametersFlags, /* 0.9.2 */
|
2011-05-13 13:35:01 +00:00
|
|
|
.domainInterfaceStats = lxcDomainInterfaceStats, /* 0.7.3 */
|
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.6.5 */
|
|
|
|
.nodeGetFreeMemory = nodeGetFreeMemory, /* 0.6.5 */
|
|
|
|
.domainEventRegister = lxcDomainEventRegister, /* 0.7.0 */
|
|
|
|
.domainEventDeregister = lxcDomainEventDeregister, /* 0.7.0 */
|
|
|
|
.isEncrypted = lxcIsEncrypted, /* 0.7.3 */
|
|
|
|
.isSecure = lxcIsSecure, /* 0.7.3 */
|
|
|
|
.domainIsActive = lxcDomainIsActive, /* 0.7.3 */
|
|
|
|
.domainIsPersistent = lxcDomainIsPersistent, /* 0.7.3 */
|
|
|
|
.domainIsUpdated = lxcDomainIsUpdated, /* 0.8.6 */
|
|
|
|
.domainEventRegisterAny = lxcDomainEventRegisterAny, /* 0.8.0 */
|
|
|
|
.domainEventDeregisterAny = lxcDomainEventDeregisterAny, /* 0.8.0 */
|
|
|
|
.domainOpenConsole = lxcDomainOpenConsole, /* 0.8.6 */
|
2011-11-24 13:44:59 +00:00
|
|
|
.isAlive = lxcIsAlive, /* 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 */
|
2008-03-21 15:03:37 +00:00
|
|
|
};
|
|
|
|
|
2008-03-27 09:34:06 +00:00
|
|
|
static virStateDriver lxcStateDriver = {
|
2012-05-10 16:49:29 +00:00
|
|
|
.name = LXC_DRIVER_NAME,
|
2008-10-06 15:40:37 +00:00
|
|
|
.initialize = lxcStartup,
|
|
|
|
.cleanup = lxcShutdown,
|
|
|
|
.active = lxcActive,
|
2009-07-06 15:05:32 +00:00
|
|
|
.reload = lxcReload,
|
2008-03-27 09:34:06 +00:00
|
|
|
};
|
|
|
|
|
2008-03-21 15:03:37 +00:00
|
|
|
int lxcRegister(void)
|
|
|
|
{
|
|
|
|
virRegisterDriver(&lxcDriver);
|
2008-03-27 09:34:06 +00:00
|
|
|
virRegisterStateDriver(&lxcStateDriver);
|
2008-03-21 15:03:37 +00:00
|
|
|
return 0;
|
|
|
|
}
|