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
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#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>
|
2008-05-09 07:16:30 +00:00
|
|
|
#include <stdbool.h>
|
2008-03-21 15:03:37 +00:00
|
|
|
#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"
|
2008-03-21 15:03:37 +00:00
|
|
|
#include "lxc_driver.h"
|
2008-06-09 22:51:32 +00:00
|
|
|
#include "memory.h"
|
2008-04-10 07:30:52 +00:00
|
|
|
#include "util.h"
|
2008-06-26 16:09:48 +00:00
|
|
|
#include "bridge.h"
|
|
|
|
#include "veth.h"
|
2008-08-13 10:52:15 +00:00
|
|
|
#include "event.h"
|
2009-06-03 13:29:23 +00:00
|
|
|
#include "nodeinfo.h"
|
2009-07-06 15:05:32 +00:00
|
|
|
#include "uuid.h"
|
2008-08-13 10:52:15 +00:00
|
|
|
|
2008-03-21 15:03:37 +00:00
|
|
|
|
2009-01-20 17:13:33 +00:00
|
|
|
#define VIR_FROM_THIS VIR_FROM_LXC
|
|
|
|
|
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);
|
2008-03-31 12:02:12 +00:00
|
|
|
static lxc_driver_t *lxc_driver = NULL;
|
2008-03-21 15:03:37 +00:00
|
|
|
|
|
|
|
/* Functions */
|
|
|
|
|
2008-12-04 21:12:41 +00:00
|
|
|
static void lxcDriverLock(lxc_driver_t *driver)
|
|
|
|
{
|
2009-01-15 19:56:05 +00:00
|
|
|
virMutexLock(&driver->lock);
|
2008-12-04 21:12:41 +00:00
|
|
|
}
|
|
|
|
static void lxcDriverUnlock(lxc_driver_t *driver)
|
|
|
|
{
|
2009-01-15 19:56:05 +00:00
|
|
|
virMutexUnlock(&driver->lock);
|
2008-12-04 21:12:41 +00:00
|
|
|
}
|
|
|
|
|
2009-07-06 15:04:36 +00:00
|
|
|
static void lxcDomainEventFlush(int timer, void *opaque);
|
|
|
|
static void lxcDomainEventQueue(lxc_driver_t *driver,
|
|
|
|
virDomainEventPtr event);
|
|
|
|
|
2008-12-04 21:12:41 +00:00
|
|
|
|
2008-03-21 15:03:37 +00:00
|
|
|
static virDrvOpenStatus lxcOpen(virConnectPtr conn,
|
|
|
|
virConnectAuthPtr auth ATTRIBUTE_UNUSED,
|
|
|
|
int flags ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
/* 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
|
|
|
|
2008-11-17 11:44:51 +00:00
|
|
|
conn->uri = xmlParseURI("lxc:///");
|
|
|
|
if (!conn->uri) {
|
2009-01-29 12:10:32 +00:00
|
|
|
virReportOOMError(conn);
|
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 */
|
|
|
|
if (STRNEQ(conn->uri->path, "/")) {
|
|
|
|
lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unexpected LXC URI path '%s', try lxc:///"),
|
|
|
|
conn->uri->path);
|
|
|
|
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) {
|
|
|
|
lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR,
|
2009-07-23 16:27:47 +00:00
|
|
|
"%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)
|
|
|
|
{
|
2009-07-06 15:04:36 +00:00
|
|
|
lxc_driver_t *driver = conn->privateData;
|
|
|
|
|
|
|
|
lxcDriverLock(driver);
|
|
|
|
virDomainEventCallbackListRemoveConn(conn, driver->domainEventCallbacks);
|
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
|
2008-03-27 09:34:06 +00:00
|
|
|
conn->privateData = NULL;
|
|
|
|
return 0;
|
2008-03-21 15:03:37 +00:00
|
|
|
}
|
|
|
|
|
2009-06-03 13:29:23 +00:00
|
|
|
static char *lxcGetCapabilities(virConnectPtr conn) {
|
|
|
|
lxc_driver_t *driver = conn->privateData;
|
|
|
|
char *xml;
|
|
|
|
|
|
|
|
lxcDriverLock(driver);
|
|
|
|
if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL)
|
|
|
|
virReportOOMError(conn);
|
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
|
|
|
|
return xml;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-03-21 15:03:37 +00:00
|
|
|
static virDomainPtr lxcDomainLookupByID(virConnectPtr conn,
|
|
|
|
int id)
|
|
|
|
{
|
2008-12-04 21:11:41 +00:00
|
|
|
lxc_driver_t *driver = conn->privateData;
|
|
|
|
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) {
|
|
|
|
lxcError(conn, NULL, VIR_ERR_NO_DOMAIN, NULL);
|
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)
|
|
|
|
{
|
2008-12-04 21:11:41 +00:00
|
|
|
lxc_driver_t *driver = conn->privateData;
|
|
|
|
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) {
|
|
|
|
lxcError(conn, NULL, VIR_ERR_NO_DOMAIN, NULL);
|
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)
|
|
|
|
{
|
2008-12-04 21:11:41 +00:00
|
|
|
lxc_driver_t *driver = conn->privateData;
|
|
|
|
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) {
|
|
|
|
lxcError(conn, NULL, VIR_ERR_NO_DOMAIN, NULL);
|
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;
|
|
|
|
}
|
|
|
|
|
2008-08-13 12:50:55 +00:00
|
|
|
static int lxcListDomains(virConnectPtr conn, int *ids, int nids) {
|
2008-12-04 21:11:41 +00:00
|
|
|
lxc_driver_t *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) {
|
2008-12-04 21:11:41 +00:00
|
|
|
lxc_driver_t *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) {
|
2008-12-04 21:11:41 +00:00
|
|
|
lxc_driver_t *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) {
|
2008-12-04 21:11:41 +00:00
|
|
|
lxc_driver_t *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)
|
|
|
|
{
|
2008-12-04 21:11:41 +00:00
|
|
|
lxc_driver_t *driver = conn->privateData;
|
|
|
|
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;
|
|
|
|
int newVM = 1;
|
2008-03-21 15:03:37 +00:00
|
|
|
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverLock(driver);
|
2009-01-08 13:54:20 +00:00
|
|
|
if (!(def = virDomainDefParseString(conn, driver->caps, xml,
|
|
|
|
VIR_DOMAIN_XML_INACTIVE)))
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
2008-03-21 15:03:37 +00:00
|
|
|
|
2009-07-31 14:25:03 +00:00
|
|
|
/* See if a VM with matching UUID already exists */
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, def->uuid);
|
|
|
|
if (vm) {
|
|
|
|
/* UUID matches, but if names don't match, refuse it */
|
|
|
|
if (STRNEQ(vm->def->name, def->name)) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(vm->def->uuid, uuidstr);
|
|
|
|
lxcError(conn, NULL, VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("domain '%s' is already defined with uuid %s"),
|
|
|
|
vm->def->name, uuidstr);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* UUID & name match */
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
newVM = 0;
|
|
|
|
} else {
|
|
|
|
/* UUID does not match, but if a name matches, refuse it */
|
|
|
|
vm = virDomainFindByName(&driver->domains, def->name);
|
|
|
|
if (vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(vm->def->uuid, uuidstr);
|
|
|
|
lxcError(conn, NULL, VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("domain '%s' is already defined with uuid %s"),
|
|
|
|
def->name, uuidstr);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-06-26 16:08:59 +00:00
|
|
|
if ((def->nets != NULL) && !(driver->have_netns)) {
|
|
|
|
lxcError(conn, NULL, VIR_ERR_NO_SUPPORT,
|
avoid many format string warnings
Building with --disable-nls exposed many new warnings like these:
virsh.c:4952: warning: format not a string literal and no format ...
util.c:163: warning: format not a string literal and no format arguments
All but one of the following changes add a "%s" argument before
the offending _(...) argument.
This was the only manual change:
* src/lxc_driver.c (lxcVersion): Use %s and strerror(errno)
rather than %m, to avoid a warning from gcc -Wformat-security.
Add "%s" before each warned about format-string-with-no-%-directive:
* src/domain_conf.c (virDomainHostdevSubsysUsbDefParseXML)
(virDomainDefParseString, virDomainDefParseFile):
* src/hash.c (virGetConnect, __virGetDomain, virReleaseDomain)
(__virGetNetwork, virReleaseNetwork, __virGetStoragePool)
(virReleaseStoragePool, __virGetStorageVol, virReleaseStorageVol):
* src/lxc_container.c (lxcContainerChild):
* src/lxc_driver.c (lxcDomainDefine, lxcDomainUndefine)
(lxcDomainGetInfo, lxcGetOSType, lxcDomainDumpXML)
(lxcSetupInterfaces, lxcDomainStart, lxcDomainCreateAndStart)
(lxcVersion, lxcGetSchedulerParameters):
* src/network_conf.c (virNetworkDefParseString)
(virNetworkDefParseFile):
* src/openvz_conf.c (openvzReadNetworkConf, openvzLoadDomains):
* src/openvz_driver.c (openvzDomainDefineCmd)
(openvzDomainGetInfo, openvzDomainDumpXML, openvzDomainShutdown)
(openvzDomainReboot, ADD_ARG_LIT, openvzDomainDefineXML)
(openvzDomainCreateXML, openvzDomainCreate, openvzDomainUndefine)
(openvzDomainSetAutostart, openvzDomainGetAutostart)
(openvzDomainSetVcpus):
* src/qemu_driver.c (qemudDomainBlockPeek, qemudDomainMemoryPeek):
* src/remote_internal.c (remoteDomainBlockPeek)
(remoteDomainMemoryPeek, remoteAuthPolkit):
* src/sexpr.c (sexpr_new, _string2sexpr):
* src/storage_backend_disk.c (virStorageBackendDiskMakeDataVol)
(virStorageBackendDiskCreateVol):
* src/storage_backend_fs.c
(virStorageBackendFileSystemNetFindPoolSources):
* src/storage_backend_logical.c (virStorageBackendLogicalFindLVs)
(virStorageBackendLogicalFindPoolSources):
* src/test.c (testOpenDefault, testOpenFromFile, testOpen)
(testGetDomainInfo, testDomainRestore)
(testNodeGetCellsFreeMemory):
* src/util.c (virExec):
* src/virsh.c (cmdAttachDevice, cmdDetachDevice)
(cmdAttachInterface, cmdDetachInterface, cmdAttachDisk)
(cmdDetachDisk, cmdEdit):
* src/xend_internal.c (do_connect, wr_sync, xend_op_ext)
(urlencode, xenDaemonDomainCreateXML)
(xenDaemonDomainLookupByName_ids, xenDaemonDomainLookupByID)
(xenDaemonParseSxprOS, xend_parse_sexp_desc_char)
(xenDaemonParseSxprChar, xenDaemonParseSxprDisks)
(xenDaemonParseSxpr, sexpr_to_xend_topology, sexpr_to_domain)
(xenDaemonDomainFetch, xenDaemonDomainGetAutostart)
(xenDaemonDomainSetAutostart, xenDaemonDomainMigratePerform)
(xenDaemonDomainDefineXML, xenDaemonGetSchedulerType)
(xenDaemonGetSchedulerParameters)
(xenDaemonSetSchedulerParameters, xenDaemonDomainBlockPeek)
(xenDaemonFormatSxprChr, virDomainXMLDevID):
* src/xm_internal.c (xenXMConfigCacheRefresh, xenXMDomainPinVcpu)
(xenXMDomainCreate, xenXMDomainDefineXML)
(xenXMDomainAttachDevice, xenXMDomainDetachDevice):
* src/xml.c (virXPathString, virXPathNumber, virXPathLong)
(virXPathULong, virXPathBoolean, virXPathNode, virXPathNodeSet):
* src/xs_internal.c (xenStoreOpen):
2008-10-13 16:46:28 +00:00
|
|
|
"%s", _("System lacks NETNS support"));
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
2008-06-26 16:08:59 +00:00
|
|
|
}
|
|
|
|
|
2009-10-06 11:50:58 +00:00
|
|
|
if (!(vm = virDomainAssignDef(conn, driver->caps,
|
|
|
|
&driver->domains, def)))
|
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
|
|
|
|
2008-08-13 12:50:55 +00:00
|
|
|
if (virDomainSaveConfig(conn,
|
|
|
|
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,
|
|
|
|
newVM ?
|
|
|
|
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)
|
|
|
|
lxcDomainEventQueue(driver, event);
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverUnlock(driver);
|
2008-03-21 15:03:37 +00:00
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int lxcDomainUndefine(virDomainPtr dom)
|
|
|
|
{
|
2008-12-04 21:11:41 +00:00
|
|
|
lxc_driver_t *driver = dom->conn->privateData;
|
|
|
|
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
|
|
|
|
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) {
|
|
|
|
lxcError(dom->conn, dom, VIR_ERR_INVALID_DOMAIN,
|
avoid many format string warnings
Building with --disable-nls exposed many new warnings like these:
virsh.c:4952: warning: format not a string literal and no format ...
util.c:163: warning: format not a string literal and no format arguments
All but one of the following changes add a "%s" argument before
the offending _(...) argument.
This was the only manual change:
* src/lxc_driver.c (lxcVersion): Use %s and strerror(errno)
rather than %m, to avoid a warning from gcc -Wformat-security.
Add "%s" before each warned about format-string-with-no-%-directive:
* src/domain_conf.c (virDomainHostdevSubsysUsbDefParseXML)
(virDomainDefParseString, virDomainDefParseFile):
* src/hash.c (virGetConnect, __virGetDomain, virReleaseDomain)
(__virGetNetwork, virReleaseNetwork, __virGetStoragePool)
(virReleaseStoragePool, __virGetStorageVol, virReleaseStorageVol):
* src/lxc_container.c (lxcContainerChild):
* src/lxc_driver.c (lxcDomainDefine, lxcDomainUndefine)
(lxcDomainGetInfo, lxcGetOSType, lxcDomainDumpXML)
(lxcSetupInterfaces, lxcDomainStart, lxcDomainCreateAndStart)
(lxcVersion, lxcGetSchedulerParameters):
* src/network_conf.c (virNetworkDefParseString)
(virNetworkDefParseFile):
* src/openvz_conf.c (openvzReadNetworkConf, openvzLoadDomains):
* src/openvz_driver.c (openvzDomainDefineCmd)
(openvzDomainGetInfo, openvzDomainDumpXML, openvzDomainShutdown)
(openvzDomainReboot, ADD_ARG_LIT, openvzDomainDefineXML)
(openvzDomainCreateXML, openvzDomainCreate, openvzDomainUndefine)
(openvzDomainSetAutostart, openvzDomainGetAutostart)
(openvzDomainSetVcpus):
* src/qemu_driver.c (qemudDomainBlockPeek, qemudDomainMemoryPeek):
* src/remote_internal.c (remoteDomainBlockPeek)
(remoteDomainMemoryPeek, remoteAuthPolkit):
* src/sexpr.c (sexpr_new, _string2sexpr):
* src/storage_backend_disk.c (virStorageBackendDiskMakeDataVol)
(virStorageBackendDiskCreateVol):
* src/storage_backend_fs.c
(virStorageBackendFileSystemNetFindPoolSources):
* src/storage_backend_logical.c (virStorageBackendLogicalFindLVs)
(virStorageBackendLogicalFindPoolSources):
* src/test.c (testOpenDefault, testOpenFromFile, testOpen)
(testGetDomainInfo, testDomainRestore)
(testNodeGetCellsFreeMemory):
* src/util.c (virExec):
* src/virsh.c (cmdAttachDevice, cmdDetachDevice)
(cmdAttachInterface, cmdDetachInterface, cmdAttachDisk)
(cmdDetachDisk, cmdEdit):
* src/xend_internal.c (do_connect, wr_sync, xend_op_ext)
(urlencode, xenDaemonDomainCreateXML)
(xenDaemonDomainLookupByName_ids, xenDaemonDomainLookupByID)
(xenDaemonParseSxprOS, xend_parse_sexp_desc_char)
(xenDaemonParseSxprChar, xenDaemonParseSxprDisks)
(xenDaemonParseSxpr, sexpr_to_xend_topology, sexpr_to_domain)
(xenDaemonDomainFetch, xenDaemonDomainGetAutostart)
(xenDaemonDomainSetAutostart, xenDaemonDomainMigratePerform)
(xenDaemonDomainDefineXML, xenDaemonGetSchedulerType)
(xenDaemonGetSchedulerParameters)
(xenDaemonSetSchedulerParameters, xenDaemonDomainBlockPeek)
(xenDaemonFormatSxprChr, virDomainXMLDevID):
* src/xm_internal.c (xenXMConfigCacheRefresh, xenXMDomainPinVcpu)
(xenXMDomainCreate, xenXMDomainDefineXML)
(xenXMDomainAttachDevice, xenXMDomainDetachDevice):
* src/xml.c (virXPathString, virXPathNumber, virXPathLong)
(virXPathULong, virXPathBoolean, virXPathNode, virXPathNodeSet):
* src/xs_internal.c (xenStoreOpen):
2008-10-13 16:46:28 +00:00
|
|
|
"%s", _("no domain with matching uuid"));
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
2008-03-21 15:03:37 +00:00
|
|
|
}
|
|
|
|
|
2008-08-13 12:50:55 +00:00
|
|
|
if (virDomainIsActive(vm)) {
|
2009-05-20 07:12:00 +00:00
|
|
|
lxcError(dom->conn, dom, VIR_ERR_OPERATION_INVALID,
|
avoid many format string warnings
Building with --disable-nls exposed many new warnings like these:
virsh.c:4952: warning: format not a string literal and no format ...
util.c:163: warning: format not a string literal and no format arguments
All but one of the following changes add a "%s" argument before
the offending _(...) argument.
This was the only manual change:
* src/lxc_driver.c (lxcVersion): Use %s and strerror(errno)
rather than %m, to avoid a warning from gcc -Wformat-security.
Add "%s" before each warned about format-string-with-no-%-directive:
* src/domain_conf.c (virDomainHostdevSubsysUsbDefParseXML)
(virDomainDefParseString, virDomainDefParseFile):
* src/hash.c (virGetConnect, __virGetDomain, virReleaseDomain)
(__virGetNetwork, virReleaseNetwork, __virGetStoragePool)
(virReleaseStoragePool, __virGetStorageVol, virReleaseStorageVol):
* src/lxc_container.c (lxcContainerChild):
* src/lxc_driver.c (lxcDomainDefine, lxcDomainUndefine)
(lxcDomainGetInfo, lxcGetOSType, lxcDomainDumpXML)
(lxcSetupInterfaces, lxcDomainStart, lxcDomainCreateAndStart)
(lxcVersion, lxcGetSchedulerParameters):
* src/network_conf.c (virNetworkDefParseString)
(virNetworkDefParseFile):
* src/openvz_conf.c (openvzReadNetworkConf, openvzLoadDomains):
* src/openvz_driver.c (openvzDomainDefineCmd)
(openvzDomainGetInfo, openvzDomainDumpXML, openvzDomainShutdown)
(openvzDomainReboot, ADD_ARG_LIT, openvzDomainDefineXML)
(openvzDomainCreateXML, openvzDomainCreate, openvzDomainUndefine)
(openvzDomainSetAutostart, openvzDomainGetAutostart)
(openvzDomainSetVcpus):
* src/qemu_driver.c (qemudDomainBlockPeek, qemudDomainMemoryPeek):
* src/remote_internal.c (remoteDomainBlockPeek)
(remoteDomainMemoryPeek, remoteAuthPolkit):
* src/sexpr.c (sexpr_new, _string2sexpr):
* src/storage_backend_disk.c (virStorageBackendDiskMakeDataVol)
(virStorageBackendDiskCreateVol):
* src/storage_backend_fs.c
(virStorageBackendFileSystemNetFindPoolSources):
* src/storage_backend_logical.c (virStorageBackendLogicalFindLVs)
(virStorageBackendLogicalFindPoolSources):
* src/test.c (testOpenDefault, testOpenFromFile, testOpen)
(testGetDomainInfo, testDomainRestore)
(testNodeGetCellsFreeMemory):
* src/util.c (virExec):
* src/virsh.c (cmdAttachDevice, cmdDetachDevice)
(cmdAttachInterface, cmdDetachInterface, cmdAttachDisk)
(cmdDetachDisk, cmdEdit):
* src/xend_internal.c (do_connect, wr_sync, xend_op_ext)
(urlencode, xenDaemonDomainCreateXML)
(xenDaemonDomainLookupByName_ids, xenDaemonDomainLookupByID)
(xenDaemonParseSxprOS, xend_parse_sexp_desc_char)
(xenDaemonParseSxprChar, xenDaemonParseSxprDisks)
(xenDaemonParseSxpr, sexpr_to_xend_topology, sexpr_to_domain)
(xenDaemonDomainFetch, xenDaemonDomainGetAutostart)
(xenDaemonDomainSetAutostart, xenDaemonDomainMigratePerform)
(xenDaemonDomainDefineXML, xenDaemonGetSchedulerType)
(xenDaemonGetSchedulerParameters)
(xenDaemonSetSchedulerParameters, xenDaemonDomainBlockPeek)
(xenDaemonFormatSxprChr, virDomainXMLDevID):
* src/xm_internal.c (xenXMConfigCacheRefresh, xenXMDomainPinVcpu)
(xenXMDomainCreate, xenXMDomainDefineXML)
(xenXMDomainAttachDevice, xenXMDomainDetachDevice):
* src/xml.c (virXPathString, virXPathNumber, virXPathLong)
(virXPathULong, virXPathBoolean, virXPathNode, virXPathNodeSet):
* src/xs_internal.c (xenStoreOpen):
2008-10-13 16:46:28 +00:00
|
|
|
"%s", _("cannot delete active domain"));
|
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) {
|
2009-05-20 07:12:00 +00:00
|
|
|
lxcError(dom->conn, dom, VIR_ERR_OPERATION_INVALID,
|
2008-08-20 19:42:36 +00:00
|
|
|
"%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
|
|
|
|
2008-08-20 19:42:36 +00:00
|
|
|
if (virDomainDeleteConfig(dom->conn,
|
|
|
|
driver->configDir,
|
|
|
|
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);
|
|
|
|
|
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
|
|
|
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)
|
|
|
|
lxcDomainEventQueue(driver, 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
|
|
|
}
|
|
|
|
|
|
|
|
static int lxcDomainGetInfo(virDomainPtr dom,
|
|
|
|
virDomainInfoPtr info)
|
|
|
|
{
|
2008-12-04 21:11:41 +00:00
|
|
|
lxc_driver_t *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
2009-03-06 14:44:04 +00:00
|
|
|
virCgroupPtr cgroup = NULL;
|
2008-12-04 21:11:41 +00:00
|
|
|
int ret = -1;
|
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) {
|
|
|
|
lxcError(dom->conn, dom, VIR_ERR_INVALID_DOMAIN,
|
avoid many format string warnings
Building with --disable-nls exposed many new warnings like these:
virsh.c:4952: warning: format not a string literal and no format ...
util.c:163: warning: format not a string literal and no format arguments
All but one of the following changes add a "%s" argument before
the offending _(...) argument.
This was the only manual change:
* src/lxc_driver.c (lxcVersion): Use %s and strerror(errno)
rather than %m, to avoid a warning from gcc -Wformat-security.
Add "%s" before each warned about format-string-with-no-%-directive:
* src/domain_conf.c (virDomainHostdevSubsysUsbDefParseXML)
(virDomainDefParseString, virDomainDefParseFile):
* src/hash.c (virGetConnect, __virGetDomain, virReleaseDomain)
(__virGetNetwork, virReleaseNetwork, __virGetStoragePool)
(virReleaseStoragePool, __virGetStorageVol, virReleaseStorageVol):
* src/lxc_container.c (lxcContainerChild):
* src/lxc_driver.c (lxcDomainDefine, lxcDomainUndefine)
(lxcDomainGetInfo, lxcGetOSType, lxcDomainDumpXML)
(lxcSetupInterfaces, lxcDomainStart, lxcDomainCreateAndStart)
(lxcVersion, lxcGetSchedulerParameters):
* src/network_conf.c (virNetworkDefParseString)
(virNetworkDefParseFile):
* src/openvz_conf.c (openvzReadNetworkConf, openvzLoadDomains):
* src/openvz_driver.c (openvzDomainDefineCmd)
(openvzDomainGetInfo, openvzDomainDumpXML, openvzDomainShutdown)
(openvzDomainReboot, ADD_ARG_LIT, openvzDomainDefineXML)
(openvzDomainCreateXML, openvzDomainCreate, openvzDomainUndefine)
(openvzDomainSetAutostart, openvzDomainGetAutostart)
(openvzDomainSetVcpus):
* src/qemu_driver.c (qemudDomainBlockPeek, qemudDomainMemoryPeek):
* src/remote_internal.c (remoteDomainBlockPeek)
(remoteDomainMemoryPeek, remoteAuthPolkit):
* src/sexpr.c (sexpr_new, _string2sexpr):
* src/storage_backend_disk.c (virStorageBackendDiskMakeDataVol)
(virStorageBackendDiskCreateVol):
* src/storage_backend_fs.c
(virStorageBackendFileSystemNetFindPoolSources):
* src/storage_backend_logical.c (virStorageBackendLogicalFindLVs)
(virStorageBackendLogicalFindPoolSources):
* src/test.c (testOpenDefault, testOpenFromFile, testOpen)
(testGetDomainInfo, testDomainRestore)
(testNodeGetCellsFreeMemory):
* src/util.c (virExec):
* src/virsh.c (cmdAttachDevice, cmdDetachDevice)
(cmdAttachInterface, cmdDetachInterface, cmdAttachDisk)
(cmdDetachDisk, cmdEdit):
* src/xend_internal.c (do_connect, wr_sync, xend_op_ext)
(urlencode, xenDaemonDomainCreateXML)
(xenDaemonDomainLookupByName_ids, xenDaemonDomainLookupByID)
(xenDaemonParseSxprOS, xend_parse_sexp_desc_char)
(xenDaemonParseSxprChar, xenDaemonParseSxprDisks)
(xenDaemonParseSxpr, sexpr_to_xend_topology, sexpr_to_domain)
(xenDaemonDomainFetch, xenDaemonDomainGetAutostart)
(xenDaemonDomainSetAutostart, xenDaemonDomainMigratePerform)
(xenDaemonDomainDefineXML, xenDaemonGetSchedulerType)
(xenDaemonGetSchedulerParameters)
(xenDaemonSetSchedulerParameters, xenDaemonDomainBlockPeek)
(xenDaemonFormatSxprChr, virDomainXMLDevID):
* src/xm_internal.c (xenXMConfigCacheRefresh, xenXMDomainPinVcpu)
(xenXMDomainCreate, xenXMDomainDefineXML)
(xenXMDomainAttachDevice, xenXMDomainDetachDevice):
* src/xml.c (virXPathString, virXPathNumber, virXPathLong)
(virXPathULong, virXPathBoolean, virXPathNode, virXPathNodeSet):
* src/xs_internal.c (xenStoreOpen):
2008-10-13 16:46:28 +00:00
|
|
|
"%s", _("no domain with matching uuid"));
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
2008-03-21 15:03:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
info->state = vm->state;
|
|
|
|
|
2009-07-10 10:40:04 +00:00
|
|
|
if (!virDomainIsActive(vm) || driver->cgroup == NULL) {
|
2008-03-21 15:03:37 +00:00
|
|
|
info->cpuTime = 0;
|
2009-10-07 13:26:23 +00:00
|
|
|
info->memory = vm->def->memory;
|
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) {
|
2009-03-06 14:44:04 +00:00
|
|
|
lxcError(dom->conn, dom, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unable to get cgroup for %s\n"), vm->def->name);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virCgroupGetCpuacctUsage(cgroup, &(info->cpuTime)) < 0) {
|
2009-10-07 13:26:23 +00:00
|
|
|
lxcError(dom->conn, dom, VIR_ERR_OPERATION_FAILED,
|
|
|
|
"%s", _("cannot read cputime for domain"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (virCgroupGetMemoryUsage(cgroup, &(info->memory)) < 0) {
|
|
|
|
lxcError(dom->conn, dom, VIR_ERR_OPERATION_FAILED,
|
|
|
|
"%s", _("cannot read memory usage for domain"));
|
2009-03-06 14:44:04 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2008-03-21 15:03:37 +00:00
|
|
|
}
|
|
|
|
|
2008-08-13 12:50:55 +00:00
|
|
|
info->maxMem = vm->def->maxmem;
|
2008-03-21 15:03:37 +00:00
|
|
|
info->nrVirtCpu = 1;
|
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
|
|
|
}
|
|
|
|
|
2008-08-13 12:50:55 +00:00
|
|
|
static char *lxcGetOSType(virDomainPtr dom)
|
2008-03-21 15:03:37 +00:00
|
|
|
{
|
2008-12-04 21:11:41 +00:00
|
|
|
lxc_driver_t *driver = dom->conn->privateData;
|
|
|
|
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) {
|
|
|
|
lxcError(dom->conn, dom, VIR_ERR_INVALID_DOMAIN,
|
avoid many format string warnings
Building with --disable-nls exposed many new warnings like these:
virsh.c:4952: warning: format not a string literal and no format ...
util.c:163: warning: format not a string literal and no format arguments
All but one of the following changes add a "%s" argument before
the offending _(...) argument.
This was the only manual change:
* src/lxc_driver.c (lxcVersion): Use %s and strerror(errno)
rather than %m, to avoid a warning from gcc -Wformat-security.
Add "%s" before each warned about format-string-with-no-%-directive:
* src/domain_conf.c (virDomainHostdevSubsysUsbDefParseXML)
(virDomainDefParseString, virDomainDefParseFile):
* src/hash.c (virGetConnect, __virGetDomain, virReleaseDomain)
(__virGetNetwork, virReleaseNetwork, __virGetStoragePool)
(virReleaseStoragePool, __virGetStorageVol, virReleaseStorageVol):
* src/lxc_container.c (lxcContainerChild):
* src/lxc_driver.c (lxcDomainDefine, lxcDomainUndefine)
(lxcDomainGetInfo, lxcGetOSType, lxcDomainDumpXML)
(lxcSetupInterfaces, lxcDomainStart, lxcDomainCreateAndStart)
(lxcVersion, lxcGetSchedulerParameters):
* src/network_conf.c (virNetworkDefParseString)
(virNetworkDefParseFile):
* src/openvz_conf.c (openvzReadNetworkConf, openvzLoadDomains):
* src/openvz_driver.c (openvzDomainDefineCmd)
(openvzDomainGetInfo, openvzDomainDumpXML, openvzDomainShutdown)
(openvzDomainReboot, ADD_ARG_LIT, openvzDomainDefineXML)
(openvzDomainCreateXML, openvzDomainCreate, openvzDomainUndefine)
(openvzDomainSetAutostart, openvzDomainGetAutostart)
(openvzDomainSetVcpus):
* src/qemu_driver.c (qemudDomainBlockPeek, qemudDomainMemoryPeek):
* src/remote_internal.c (remoteDomainBlockPeek)
(remoteDomainMemoryPeek, remoteAuthPolkit):
* src/sexpr.c (sexpr_new, _string2sexpr):
* src/storage_backend_disk.c (virStorageBackendDiskMakeDataVol)
(virStorageBackendDiskCreateVol):
* src/storage_backend_fs.c
(virStorageBackendFileSystemNetFindPoolSources):
* src/storage_backend_logical.c (virStorageBackendLogicalFindLVs)
(virStorageBackendLogicalFindPoolSources):
* src/test.c (testOpenDefault, testOpenFromFile, testOpen)
(testGetDomainInfo, testDomainRestore)
(testNodeGetCellsFreeMemory):
* src/util.c (virExec):
* src/virsh.c (cmdAttachDevice, cmdDetachDevice)
(cmdAttachInterface, cmdDetachInterface, cmdAttachDisk)
(cmdDetachDisk, cmdEdit):
* src/xend_internal.c (do_connect, wr_sync, xend_op_ext)
(urlencode, xenDaemonDomainCreateXML)
(xenDaemonDomainLookupByName_ids, xenDaemonDomainLookupByID)
(xenDaemonParseSxprOS, xend_parse_sexp_desc_char)
(xenDaemonParseSxprChar, xenDaemonParseSxprDisks)
(xenDaemonParseSxpr, sexpr_to_xend_topology, sexpr_to_domain)
(xenDaemonDomainFetch, xenDaemonDomainGetAutostart)
(xenDaemonDomainSetAutostart, xenDaemonDomainMigratePerform)
(xenDaemonDomainDefineXML, xenDaemonGetSchedulerType)
(xenDaemonGetSchedulerParameters)
(xenDaemonSetSchedulerParameters, xenDaemonDomainBlockPeek)
(xenDaemonFormatSxprChr, virDomainXMLDevID):
* src/xm_internal.c (xenXMConfigCacheRefresh, xenXMDomainPinVcpu)
(xenXMDomainCreate, xenXMDomainDefineXML)
(xenXMDomainAttachDevice, xenXMDomainDetachDevice):
* src/xml.c (virXPathString, virXPathNumber, virXPathLong)
(virXPathULong, virXPathBoolean, virXPathNode, virXPathNodeSet):
* src/xs_internal.c (xenStoreOpen):
2008-10-13 16:46:28 +00:00
|
|
|
"%s", _("no domain with matching uuid"));
|
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);
|
|
|
|
|
|
|
|
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 */
|
|
|
|
static unsigned long lxcDomainGetMaxMemory(virDomainPtr dom) {
|
|
|
|
lxc_driver_t *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
unsigned long ret = 0;
|
|
|
|
|
|
|
|
lxcDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
|
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
|
|
|
lxcError(dom->conn, dom, VIR_ERR_NO_DOMAIN,
|
|
|
|
_("no domain with matching uuid '%s'"), uuidstr);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = vm->def->maxmem;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int lxcDomainSetMaxMemory(virDomainPtr dom, unsigned long newmax) {
|
|
|
|
lxc_driver_t *driver = dom->conn->privateData;
|
|
|
|
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);
|
|
|
|
lxcError(dom->conn, dom, VIR_ERR_NO_DOMAIN,
|
|
|
|
_("no domain with matching uuid '%s'"), uuidstr);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (newmax < vm->def->memory) {
|
|
|
|
lxcError(dom->conn, dom, VIR_ERR_INVALID_ARG,
|
|
|
|
"%s", _("cannot set max memory lower than current memory"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
vm->def->maxmem = newmax;
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int lxcDomainSetMemory(virDomainPtr dom, unsigned long newmem) {
|
|
|
|
lxc_driver_t *driver = dom->conn->privateData;
|
|
|
|
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);
|
|
|
|
lxcError(dom->conn, dom, VIR_ERR_NO_DOMAIN,
|
|
|
|
_("no domain with matching uuid '%s'"), uuidstr);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (newmem > vm->def->maxmem) {
|
|
|
|
lxcError(dom->conn, dom, VIR_ERR_INVALID_ARG,
|
|
|
|
"%s", _("cannot set memory higher than max memory"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virDomainIsActive(vm)) {
|
|
|
|
if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) != 0) {
|
|
|
|
lxcError(dom->conn, dom, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unable to get cgroup for %s\n"), vm->def->name);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virCgroupSetMemory(cgroup, newmem) < 0) {
|
|
|
|
lxcError(dom->conn, dom, VIR_ERR_OPERATION_FAILED,
|
|
|
|
"%s", _("cannot set memory for domain"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
vm->def->memory = newmem;
|
|
|
|
}
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
if (cgroup)
|
|
|
|
virCgroupFree(&cgroup);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2008-03-21 15:03:37 +00:00
|
|
|
static char *lxcDomainDumpXML(virDomainPtr dom,
|
2008-08-13 12:50:55 +00:00
|
|
|
int flags)
|
2008-03-21 15:03:37 +00:00
|
|
|
{
|
2008-12-04 21:11:41 +00:00
|
|
|
lxc_driver_t *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
char *ret = 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, dom->uuid);
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
|
2008-03-21 15:03:37 +00:00
|
|
|
if (!vm) {
|
|
|
|
lxcError(dom->conn, dom, VIR_ERR_INVALID_DOMAIN,
|
avoid many format string warnings
Building with --disable-nls exposed many new warnings like these:
virsh.c:4952: warning: format not a string literal and no format ...
util.c:163: warning: format not a string literal and no format arguments
All but one of the following changes add a "%s" argument before
the offending _(...) argument.
This was the only manual change:
* src/lxc_driver.c (lxcVersion): Use %s and strerror(errno)
rather than %m, to avoid a warning from gcc -Wformat-security.
Add "%s" before each warned about format-string-with-no-%-directive:
* src/domain_conf.c (virDomainHostdevSubsysUsbDefParseXML)
(virDomainDefParseString, virDomainDefParseFile):
* src/hash.c (virGetConnect, __virGetDomain, virReleaseDomain)
(__virGetNetwork, virReleaseNetwork, __virGetStoragePool)
(virReleaseStoragePool, __virGetStorageVol, virReleaseStorageVol):
* src/lxc_container.c (lxcContainerChild):
* src/lxc_driver.c (lxcDomainDefine, lxcDomainUndefine)
(lxcDomainGetInfo, lxcGetOSType, lxcDomainDumpXML)
(lxcSetupInterfaces, lxcDomainStart, lxcDomainCreateAndStart)
(lxcVersion, lxcGetSchedulerParameters):
* src/network_conf.c (virNetworkDefParseString)
(virNetworkDefParseFile):
* src/openvz_conf.c (openvzReadNetworkConf, openvzLoadDomains):
* src/openvz_driver.c (openvzDomainDefineCmd)
(openvzDomainGetInfo, openvzDomainDumpXML, openvzDomainShutdown)
(openvzDomainReboot, ADD_ARG_LIT, openvzDomainDefineXML)
(openvzDomainCreateXML, openvzDomainCreate, openvzDomainUndefine)
(openvzDomainSetAutostart, openvzDomainGetAutostart)
(openvzDomainSetVcpus):
* src/qemu_driver.c (qemudDomainBlockPeek, qemudDomainMemoryPeek):
* src/remote_internal.c (remoteDomainBlockPeek)
(remoteDomainMemoryPeek, remoteAuthPolkit):
* src/sexpr.c (sexpr_new, _string2sexpr):
* src/storage_backend_disk.c (virStorageBackendDiskMakeDataVol)
(virStorageBackendDiskCreateVol):
* src/storage_backend_fs.c
(virStorageBackendFileSystemNetFindPoolSources):
* src/storage_backend_logical.c (virStorageBackendLogicalFindLVs)
(virStorageBackendLogicalFindPoolSources):
* src/test.c (testOpenDefault, testOpenFromFile, testOpen)
(testGetDomainInfo, testDomainRestore)
(testNodeGetCellsFreeMemory):
* src/util.c (virExec):
* src/virsh.c (cmdAttachDevice, cmdDetachDevice)
(cmdAttachInterface, cmdDetachInterface, cmdAttachDisk)
(cmdDetachDisk, cmdEdit):
* src/xend_internal.c (do_connect, wr_sync, xend_op_ext)
(urlencode, xenDaemonDomainCreateXML)
(xenDaemonDomainLookupByName_ids, xenDaemonDomainLookupByID)
(xenDaemonParseSxprOS, xend_parse_sexp_desc_char)
(xenDaemonParseSxprChar, xenDaemonParseSxprDisks)
(xenDaemonParseSxpr, sexpr_to_xend_topology, sexpr_to_domain)
(xenDaemonDomainFetch, xenDaemonDomainGetAutostart)
(xenDaemonDomainSetAutostart, xenDaemonDomainMigratePerform)
(xenDaemonDomainDefineXML, xenDaemonGetSchedulerType)
(xenDaemonGetSchedulerParameters)
(xenDaemonSetSchedulerParameters, xenDaemonDomainBlockPeek)
(xenDaemonFormatSxprChr, virDomainXMLDevID):
* src/xm_internal.c (xenXMConfigCacheRefresh, xenXMDomainPinVcpu)
(xenXMDomainCreate, xenXMDomainDefineXML)
(xenXMDomainAttachDevice, xenXMDomainDetachDevice):
* src/xml.c (virXPathString, virXPathNumber, virXPathLong)
(virXPathULong, virXPathBoolean, virXPathNode, virXPathNodeSet):
* src/xs_internal.c (xenStoreOpen):
2008-10-13 16:46:28 +00:00
|
|
|
"%s", _("no domain with matching uuid"));
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
2008-03-21 15:03:37 +00:00
|
|
|
}
|
|
|
|
|
2008-12-04 21:11:41 +00:00
|
|
|
ret = virDomainDefFormat(dom->conn,
|
|
|
|
(flags & VIR_DOMAIN_XML_INACTIVE) &&
|
|
|
|
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
|
|
|
|
|
|
|
/**
|
|
|
|
* lxcVmCleanup:
|
|
|
|
* @vm: Ptr to VM to clean up
|
|
|
|
*
|
|
|
|
* waitpid() on the container process. kill and wait the tty process
|
|
|
|
* This is called by both lxcDomainDestroy and lxcSigHandler when a
|
|
|
|
* container exits.
|
|
|
|
*
|
|
|
|
* Returns 0 on success or -1 in case of error
|
|
|
|
*/
|
|
|
|
static int lxcVMCleanup(virConnectPtr conn,
|
|
|
|
lxc_driver_t *driver,
|
2008-08-13 12:50:55 +00:00
|
|
|
virDomainObjPtr vm)
|
2008-08-13 10:52:15 +00:00
|
|
|
{
|
|
|
|
int rc = -1;
|
|
|
|
int waitRc;
|
|
|
|
int childStatus = -1;
|
2008-10-03 16:46:01 +00:00
|
|
|
virCgroupPtr cgroup;
|
2008-10-10 16:08:01 +00:00
|
|
|
int i;
|
2008-08-13 10:52:15 +00:00
|
|
|
|
|
|
|
while (((waitRc = waitpid(vm->pid, &childStatus, 0)) == -1) &&
|
|
|
|
errno == EINTR)
|
|
|
|
; /* empty */
|
|
|
|
|
|
|
|
if ((waitRc != vm->pid) && (errno != ECHILD)) {
|
2009-01-20 17:13:33 +00:00
|
|
|
virReportSystemError(conn, errno,
|
|
|
|
_("waitpid failed to wait for container %d: %d"),
|
|
|
|
vm->pid, waitRc);
|
2008-08-13 10:52:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
rc = 0;
|
|
|
|
|
|
|
|
if (WIFEXITED(childStatus)) {
|
|
|
|
rc = WEXITSTATUS(childStatus);
|
|
|
|
DEBUG("container exited with rc: %d", rc);
|
|
|
|
}
|
|
|
|
|
2008-11-19 16:19:36 +00:00
|
|
|
virEventRemoveHandle(vm->monitorWatch);
|
2008-08-13 10:52:15 +00:00
|
|
|
close(vm->monitor);
|
|
|
|
|
|
|
|
virFileDeletePid(driver->stateDir, vm->def->name);
|
2008-08-20 20:55:32 +00:00
|
|
|
virDomainDeleteConfig(conn, driver->stateDir, NULL, vm);
|
2008-08-13 10:52:15 +00:00
|
|
|
|
|
|
|
vm->state = VIR_DOMAIN_SHUTOFF;
|
|
|
|
vm->pid = -1;
|
|
|
|
vm->def->id = -1;
|
|
|
|
vm->monitor = -1;
|
|
|
|
|
2008-10-10 16:08:01 +00:00
|
|
|
for (i = 0 ; i < vm->def->nnets ; i++) {
|
|
|
|
vethInterfaceUpOrDown(vm->def->nets[i]->ifname, 0);
|
|
|
|
vethDelete(vm->def->nets[i]->ifname);
|
2008-08-22 15:35:37 +00:00
|
|
|
}
|
|
|
|
|
2009-07-10 10:40:04 +00:00
|
|
|
if (driver->cgroup &&
|
|
|
|
virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) == 0) {
|
2008-10-03 16:46:01 +00:00
|
|
|
virCgroupRemove(cgroup);
|
|
|
|
virCgroupFree(&cgroup);
|
|
|
|
}
|
|
|
|
|
2009-07-06 15:04:36 +00:00
|
|
|
if (vm->newDef) {
|
|
|
|
virDomainDefFree(vm->def);
|
|
|
|
vm->def = vm->newDef;
|
|
|
|
vm->def->id = -1;
|
|
|
|
vm->newDef = NULL;
|
|
|
|
}
|
|
|
|
|
2008-08-13 10:52:15 +00:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2008-06-26 16:09:48 +00:00
|
|
|
/**
|
|
|
|
* lxcSetupInterfaces:
|
2008-08-13 10:52:15 +00:00
|
|
|
* @def: pointer to virtual machine structure
|
2008-06-26 16:09:48 +00:00
|
|
|
*
|
|
|
|
* Sets up the container interfaces by creating the veth device pairs and
|
|
|
|
* attaching the parent end to the appropriate bridge. The container end
|
|
|
|
* will moved into the container namespace later after clone has been called.
|
|
|
|
*
|
|
|
|
* Returns 0 on success or -1 in case of error
|
|
|
|
*/
|
|
|
|
static int lxcSetupInterfaces(virConnectPtr conn,
|
2008-08-13 12:50:55 +00:00
|
|
|
virDomainDefPtr def,
|
2008-08-13 10:52:15 +00:00
|
|
|
unsigned int *nveths,
|
|
|
|
char ***veths)
|
2008-06-26 16:09:48 +00:00
|
|
|
{
|
2008-10-10 16:08:01 +00:00
|
|
|
int rc = -1, i;
|
2008-08-13 10:52:15 +00:00
|
|
|
char *bridge = NULL;
|
2008-06-26 16:09:48 +00:00
|
|
|
char parentVeth[PATH_MAX] = "";
|
|
|
|
char containerVeth[PATH_MAX] = "";
|
2008-08-13 10:52:15 +00:00
|
|
|
brControl *brctl = NULL;
|
2008-06-26 16:09:48 +00:00
|
|
|
|
2008-08-13 10:52:15 +00:00
|
|
|
if (brInit(&brctl) != 0)
|
2008-06-26 16:09:48 +00:00
|
|
|
return -1;
|
|
|
|
|
2008-10-10 16:08:01 +00:00
|
|
|
for (i = 0 ; i < def->nnets ; i++) {
|
|
|
|
switch (def->nets[i]->type) {
|
2008-08-13 12:50:55 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_NETWORK:
|
|
|
|
{
|
|
|
|
virNetworkPtr network = virNetworkLookupByName(conn,
|
2008-10-10 16:08:01 +00:00
|
|
|
def->nets[i]->data.network.name);
|
2008-06-26 16:09:48 +00:00
|
|
|
if (!network) {
|
|
|
|
goto error_exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
bridge = virNetworkGetBridgeName(network);
|
|
|
|
|
|
|
|
virNetworkFree(network);
|
2008-08-13 12:50:55 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case VIR_DOMAIN_NET_TYPE_BRIDGE:
|
2008-10-10 16:08:01 +00:00
|
|
|
bridge = def->nets[i]->data.bridge.brname;
|
2008-08-13 12:50:55 +00:00
|
|
|
break;
|
2008-06-26 16:09:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DEBUG("bridge: %s", bridge);
|
|
|
|
if (NULL == bridge) {
|
|
|
|
lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR,
|
avoid many format string warnings
Building with --disable-nls exposed many new warnings like these:
virsh.c:4952: warning: format not a string literal and no format ...
util.c:163: warning: format not a string literal and no format arguments
All but one of the following changes add a "%s" argument before
the offending _(...) argument.
This was the only manual change:
* src/lxc_driver.c (lxcVersion): Use %s and strerror(errno)
rather than %m, to avoid a warning from gcc -Wformat-security.
Add "%s" before each warned about format-string-with-no-%-directive:
* src/domain_conf.c (virDomainHostdevSubsysUsbDefParseXML)
(virDomainDefParseString, virDomainDefParseFile):
* src/hash.c (virGetConnect, __virGetDomain, virReleaseDomain)
(__virGetNetwork, virReleaseNetwork, __virGetStoragePool)
(virReleaseStoragePool, __virGetStorageVol, virReleaseStorageVol):
* src/lxc_container.c (lxcContainerChild):
* src/lxc_driver.c (lxcDomainDefine, lxcDomainUndefine)
(lxcDomainGetInfo, lxcGetOSType, lxcDomainDumpXML)
(lxcSetupInterfaces, lxcDomainStart, lxcDomainCreateAndStart)
(lxcVersion, lxcGetSchedulerParameters):
* src/network_conf.c (virNetworkDefParseString)
(virNetworkDefParseFile):
* src/openvz_conf.c (openvzReadNetworkConf, openvzLoadDomains):
* src/openvz_driver.c (openvzDomainDefineCmd)
(openvzDomainGetInfo, openvzDomainDumpXML, openvzDomainShutdown)
(openvzDomainReboot, ADD_ARG_LIT, openvzDomainDefineXML)
(openvzDomainCreateXML, openvzDomainCreate, openvzDomainUndefine)
(openvzDomainSetAutostart, openvzDomainGetAutostart)
(openvzDomainSetVcpus):
* src/qemu_driver.c (qemudDomainBlockPeek, qemudDomainMemoryPeek):
* src/remote_internal.c (remoteDomainBlockPeek)
(remoteDomainMemoryPeek, remoteAuthPolkit):
* src/sexpr.c (sexpr_new, _string2sexpr):
* src/storage_backend_disk.c (virStorageBackendDiskMakeDataVol)
(virStorageBackendDiskCreateVol):
* src/storage_backend_fs.c
(virStorageBackendFileSystemNetFindPoolSources):
* src/storage_backend_logical.c (virStorageBackendLogicalFindLVs)
(virStorageBackendLogicalFindPoolSources):
* src/test.c (testOpenDefault, testOpenFromFile, testOpen)
(testGetDomainInfo, testDomainRestore)
(testNodeGetCellsFreeMemory):
* src/util.c (virExec):
* src/virsh.c (cmdAttachDevice, cmdDetachDevice)
(cmdAttachInterface, cmdDetachInterface, cmdAttachDisk)
(cmdDetachDisk, cmdEdit):
* src/xend_internal.c (do_connect, wr_sync, xend_op_ext)
(urlencode, xenDaemonDomainCreateXML)
(xenDaemonDomainLookupByName_ids, xenDaemonDomainLookupByID)
(xenDaemonParseSxprOS, xend_parse_sexp_desc_char)
(xenDaemonParseSxprChar, xenDaemonParseSxprDisks)
(xenDaemonParseSxpr, sexpr_to_xend_topology, sexpr_to_domain)
(xenDaemonDomainFetch, xenDaemonDomainGetAutostart)
(xenDaemonDomainSetAutostart, xenDaemonDomainMigratePerform)
(xenDaemonDomainDefineXML, xenDaemonGetSchedulerType)
(xenDaemonGetSchedulerParameters)
(xenDaemonSetSchedulerParameters, xenDaemonDomainBlockPeek)
(xenDaemonFormatSxprChr, virDomainXMLDevID):
* src/xm_internal.c (xenXMConfigCacheRefresh, xenXMDomainPinVcpu)
(xenXMDomainCreate, xenXMDomainDefineXML)
(xenXMDomainAttachDevice, xenXMDomainDetachDevice):
* src/xml.c (virXPathString, virXPathNumber, virXPathLong)
(virXPathULong, virXPathBoolean, virXPathNode, virXPathNodeSet):
* src/xs_internal.c (xenStoreOpen):
2008-10-13 16:46:28 +00:00
|
|
|
"%s", _("failed to get bridge for interface"));
|
2008-06-26 16:09:48 +00:00
|
|
|
goto error_exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEBUG0("calling vethCreate()");
|
2008-10-10 16:08:01 +00:00
|
|
|
if (NULL != def->nets[i]->ifname) {
|
|
|
|
strcpy(parentVeth, def->nets[i]->ifname);
|
2008-06-26 16:09:48 +00:00
|
|
|
}
|
|
|
|
DEBUG("parentVeth: %s, containerVeth: %s", parentVeth, containerVeth);
|
|
|
|
if (0 != (rc = vethCreate(parentVeth, PATH_MAX, containerVeth, PATH_MAX))) {
|
|
|
|
lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("failed to create veth device pair: %d"), rc);
|
|
|
|
goto error_exit;
|
|
|
|
}
|
2008-10-10 16:08:01 +00:00
|
|
|
if (NULL == def->nets[i]->ifname) {
|
|
|
|
def->nets[i]->ifname = strdup(parentVeth);
|
2008-06-26 16:09:48 +00:00
|
|
|
}
|
2008-08-13 10:52:15 +00:00
|
|
|
if (VIR_REALLOC_N(*veths, (*nveths)+1) < 0)
|
|
|
|
goto error_exit;
|
|
|
|
if (((*veths)[(*nveths)++] = strdup(containerVeth)) == NULL)
|
2008-06-26 16:09:48 +00:00
|
|
|
goto error_exit;
|
|
|
|
|
2008-10-10 16:08:01 +00:00
|
|
|
if (NULL == def->nets[i]->ifname) {
|
2008-08-13 10:52:15 +00:00
|
|
|
lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
avoid many format string warnings
Building with --disable-nls exposed many new warnings like these:
virsh.c:4952: warning: format not a string literal and no format ...
util.c:163: warning: format not a string literal and no format arguments
All but one of the following changes add a "%s" argument before
the offending _(...) argument.
This was the only manual change:
* src/lxc_driver.c (lxcVersion): Use %s and strerror(errno)
rather than %m, to avoid a warning from gcc -Wformat-security.
Add "%s" before each warned about format-string-with-no-%-directive:
* src/domain_conf.c (virDomainHostdevSubsysUsbDefParseXML)
(virDomainDefParseString, virDomainDefParseFile):
* src/hash.c (virGetConnect, __virGetDomain, virReleaseDomain)
(__virGetNetwork, virReleaseNetwork, __virGetStoragePool)
(virReleaseStoragePool, __virGetStorageVol, virReleaseStorageVol):
* src/lxc_container.c (lxcContainerChild):
* src/lxc_driver.c (lxcDomainDefine, lxcDomainUndefine)
(lxcDomainGetInfo, lxcGetOSType, lxcDomainDumpXML)
(lxcSetupInterfaces, lxcDomainStart, lxcDomainCreateAndStart)
(lxcVersion, lxcGetSchedulerParameters):
* src/network_conf.c (virNetworkDefParseString)
(virNetworkDefParseFile):
* src/openvz_conf.c (openvzReadNetworkConf, openvzLoadDomains):
* src/openvz_driver.c (openvzDomainDefineCmd)
(openvzDomainGetInfo, openvzDomainDumpXML, openvzDomainShutdown)
(openvzDomainReboot, ADD_ARG_LIT, openvzDomainDefineXML)
(openvzDomainCreateXML, openvzDomainCreate, openvzDomainUndefine)
(openvzDomainSetAutostart, openvzDomainGetAutostart)
(openvzDomainSetVcpus):
* src/qemu_driver.c (qemudDomainBlockPeek, qemudDomainMemoryPeek):
* src/remote_internal.c (remoteDomainBlockPeek)
(remoteDomainMemoryPeek, remoteAuthPolkit):
* src/sexpr.c (sexpr_new, _string2sexpr):
* src/storage_backend_disk.c (virStorageBackendDiskMakeDataVol)
(virStorageBackendDiskCreateVol):
* src/storage_backend_fs.c
(virStorageBackendFileSystemNetFindPoolSources):
* src/storage_backend_logical.c (virStorageBackendLogicalFindLVs)
(virStorageBackendLogicalFindPoolSources):
* src/test.c (testOpenDefault, testOpenFromFile, testOpen)
(testGetDomainInfo, testDomainRestore)
(testNodeGetCellsFreeMemory):
* src/util.c (virExec):
* src/virsh.c (cmdAttachDevice, cmdDetachDevice)
(cmdAttachInterface, cmdDetachInterface, cmdAttachDisk)
(cmdDetachDisk, cmdEdit):
* src/xend_internal.c (do_connect, wr_sync, xend_op_ext)
(urlencode, xenDaemonDomainCreateXML)
(xenDaemonDomainLookupByName_ids, xenDaemonDomainLookupByID)
(xenDaemonParseSxprOS, xend_parse_sexp_desc_char)
(xenDaemonParseSxprChar, xenDaemonParseSxprDisks)
(xenDaemonParseSxpr, sexpr_to_xend_topology, sexpr_to_domain)
(xenDaemonDomainFetch, xenDaemonDomainGetAutostart)
(xenDaemonDomainSetAutostart, xenDaemonDomainMigratePerform)
(xenDaemonDomainDefineXML, xenDaemonGetSchedulerType)
(xenDaemonGetSchedulerParameters)
(xenDaemonSetSchedulerParameters, xenDaemonDomainBlockPeek)
(xenDaemonFormatSxprChr, virDomainXMLDevID):
* src/xm_internal.c (xenXMConfigCacheRefresh, xenXMDomainPinVcpu)
(xenXMDomainCreate, xenXMDomainDefineXML)
(xenXMDomainAttachDevice, xenXMDomainDetachDevice):
* src/xml.c (virXPathString, virXPathNumber, virXPathLong)
(virXPathULong, virXPathBoolean, virXPathNode, virXPathNodeSet):
* src/xs_internal.c (xenStoreOpen):
2008-10-13 16:46:28 +00:00
|
|
|
"%s", _("failed to allocate veth names"));
|
2008-06-26 16:09:48 +00:00
|
|
|
goto error_exit;
|
|
|
|
}
|
|
|
|
|
2009-10-21 10:04:02 +00:00
|
|
|
if (def->nets[i]->mac) {
|
|
|
|
char macaddr[VIR_MAC_STRING_BUFLEN];
|
|
|
|
virFormatMacAddr(def->nets[i]->mac, macaddr);
|
|
|
|
if (0 != (rc = setMacAddr(containerVeth, macaddr))) {
|
|
|
|
virReportSystemError(conn, rc,
|
|
|
|
_("failed to set %s to %s"),
|
|
|
|
macaddr, containerVeth);
|
|
|
|
goto error_exit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-08-13 10:52:15 +00:00
|
|
|
if (0 != (rc = brAddInterface(brctl, bridge, parentVeth))) {
|
2009-01-20 17:13:33 +00:00
|
|
|
virReportSystemError(conn, rc,
|
|
|
|
_("failed to add %s device to %s"),
|
|
|
|
parentVeth, bridge);
|
2008-06-26 16:09:48 +00:00
|
|
|
goto error_exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (0 != (rc = vethInterfaceUpOrDown(parentVeth, 1))) {
|
2009-01-20 17:13:33 +00:00
|
|
|
virReportSystemError(conn, rc, "%s",
|
|
|
|
_("failed to enable parent ns veth device"));
|
2008-06-26 16:09:48 +00:00
|
|
|
goto error_exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = 0;
|
|
|
|
|
|
|
|
error_exit:
|
2008-08-13 10:52:15 +00:00
|
|
|
brShutdown(brctl);
|
2008-06-26 16:09:48 +00:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2008-04-10 07:30:52 +00:00
|
|
|
|
2008-08-13 10:52:15 +00:00
|
|
|
static int lxcMonitorClient(virConnectPtr conn,
|
|
|
|
lxc_driver_t * driver,
|
2008-08-13 12:50:55 +00:00
|
|
|
virDomainObjPtr vm)
|
2008-04-10 07:30:52 +00:00
|
|
|
{
|
2008-08-13 10:52:15 +00:00
|
|
|
char *sockpath = NULL;
|
|
|
|
int fd;
|
|
|
|
struct sockaddr_un addr;
|
2008-04-10 07:30:52 +00:00
|
|
|
|
2008-12-23 13:03:29 +00:00
|
|
|
if (virAsprintf(&sockpath, "%s/%s.sock",
|
|
|
|
driver->stateDir, vm->def->name) < 0) {
|
2009-01-29 12:10:32 +00:00
|
|
|
virReportOOMError(conn);
|
2008-08-13 10:52:15 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
|
2009-01-20 17:13:33 +00:00
|
|
|
virReportSystemError(conn, errno, "%s",
|
|
|
|
_("failed to create client socket"));
|
2008-08-13 10:52:15 +00:00
|
|
|
goto error;
|
2008-04-10 07:30:52 +00:00
|
|
|
}
|
|
|
|
|
2008-08-13 10:52:15 +00:00
|
|
|
memset(&addr, 0, sizeof(addr));
|
|
|
|
addr.sun_family = AF_UNIX;
|
2009-08-03 12:37:44 +00:00
|
|
|
if (virStrcpyStatic(addr.sun_path, sockpath) == NULL) {
|
|
|
|
lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Socket path %s too big for destination"), sockpath);
|
|
|
|
goto error;
|
|
|
|
}
|
2008-08-13 10:52:15 +00:00
|
|
|
|
|
|
|
if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
2009-01-20 17:13:33 +00:00
|
|
|
virReportSystemError(conn, errno, "%s",
|
|
|
|
_("failed to connect to client socket"));
|
2008-08-13 10:52:15 +00:00
|
|
|
goto error;
|
2008-04-10 07:30:52 +00:00
|
|
|
}
|
|
|
|
|
2008-08-13 10:52:15 +00:00
|
|
|
VIR_FREE(sockpath);
|
|
|
|
return fd;
|
2008-04-10 07:30:52 +00:00
|
|
|
|
2008-08-13 10:52:15 +00:00
|
|
|
error:
|
|
|
|
VIR_FREE(sockpath);
|
|
|
|
if (fd != -1)
|
|
|
|
close(fd);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int lxcVmTerminate(virConnectPtr conn,
|
|
|
|
lxc_driver_t *driver,
|
2008-08-13 12:50:55 +00:00
|
|
|
virDomainObjPtr vm,
|
2008-08-13 10:52:15 +00:00
|
|
|
int signum)
|
|
|
|
{
|
|
|
|
if (signum == 0)
|
|
|
|
signum = SIGINT;
|
2008-08-13 10:14:47 +00:00
|
|
|
|
2008-08-20 20:55:32 +00:00
|
|
|
if (vm->pid <= 0) {
|
|
|
|
lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("invalid PID %d for container"), vm->pid);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2008-08-13 10:52:15 +00:00
|
|
|
if (kill(vm->pid, signum) < 0) {
|
|
|
|
if (errno != ESRCH) {
|
2009-01-20 17:13:33 +00:00
|
|
|
virReportSystemError(conn, errno,
|
|
|
|
_("failed to kill pid %d"),
|
|
|
|
vm->pid);
|
2008-08-13 10:52:15 +00:00
|
|
|
return -1;
|
2008-08-13 10:14:47 +00:00
|
|
|
}
|
2008-04-10 07:30:52 +00:00
|
|
|
}
|
|
|
|
|
2008-08-13 10:52:15 +00:00
|
|
|
vm->state = VIR_DOMAIN_SHUTDOWN;
|
2008-08-13 10:14:47 +00:00
|
|
|
|
2008-08-13 10:52:15 +00:00
|
|
|
return lxcVMCleanup(conn, driver, vm);
|
|
|
|
}
|
2008-04-10 07:30:52 +00:00
|
|
|
|
2008-11-19 16:19:36 +00:00
|
|
|
static void lxcMonitorEvent(int watch,
|
|
|
|
int fd,
|
2008-08-13 10:52:15 +00:00
|
|
|
int events ATTRIBUTE_UNUSED,
|
|
|
|
void *data)
|
|
|
|
{
|
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
|
|
|
lxc_driver_t *driver = lxc_driver;
|
|
|
|
virDomainObjPtr vm = data;
|
2009-07-06 15:04:36 +00:00
|
|
|
virDomainEventPtr event = NULL;
|
2008-04-10 07:30:52 +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
|
|
|
virDomainObjLock(vm);
|
|
|
|
lxcDriverUnlock(driver);
|
2008-11-19 16:19:36 +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 (vm->monitor != fd || vm->monitorWatch != watch) {
|
2008-11-19 16:19:36 +00:00
|
|
|
virEventRemoveHandle(watch);
|
2008-12-04 21:12:41 +00:00
|
|
|
goto cleanup;
|
2008-04-10 07:30:52 +00:00
|
|
|
}
|
|
|
|
|
2009-07-06 15:04:36 +00:00
|
|
|
if (lxcVmTerminate(NULL, driver, vm, SIGINT) < 0) {
|
2008-11-19 16:19:36 +00:00
|
|
|
virEventRemoveHandle(watch);
|
2009-07-06 15:04:36 +00:00
|
|
|
} else {
|
|
|
|
event = virDomainEventNewFromObj(vm,
|
|
|
|
VIR_DOMAIN_EVENT_STOPPED,
|
|
|
|
VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
|
|
|
|
}
|
2009-07-31 13:38:46 +00:00
|
|
|
if (!vm->persistent) {
|
|
|
|
virDomainRemoveInactive(&driver->domains, vm);
|
|
|
|
vm = NULL;
|
|
|
|
}
|
2008-12-04 21:12:41 +00:00
|
|
|
|
|
|
|
cleanup:
|
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
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
if (event) {
|
|
|
|
lxcDriverLock(driver);
|
2009-07-06 15:04:36 +00:00
|
|
|
lxcDomainEventQueue(driver, event);
|
Convert virDomainObjListPtr to use a hash of domain objects
The current virDomainObjListPtr object stores domain objects in
an array. This means that to find a particular objects requires
O(n) time, and more critically acquiring O(n) mutex locks.
The new impl replaces the array with a virHashTable, keyed off
UUID. Finding a object based on UUID is now O(1) time, and only
requires a single mutex lock. Finding by name/id is unchanged
in complexity.
In changing this, all code which iterates over the array had
to be updated to use a hash table iterator function callback.
Several of the functions which were identically duplicating
across all drivers were pulled into domain_conf.c
* src/conf/domain_conf.h, src/conf/domain_conf.c: Change
virDomainObjListPtr to use virHashTable. Add a initializer
method virDomainObjListInit, and rename virDomainObjListFree
to virDomainObjListDeinit, since its not actually freeing
the container, only its contents. Also add some convenient
methods virDomainObjListGetInactiveNames,
virDomainObjListGetActiveIDs and virDomainObjListNumOfDomains
which can be used to implement the correspondingly named
public API entry points in drivers
* src/libvirt_private.syms: Export new methods from domain_conf.h
* src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_conf.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c: Update all code
to deal with hash tables instead of arrays for domains
2009-10-09 11:33:51 +00:00
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
}
|
2008-04-10 07:30:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-08-20 20:55:32 +00:00
|
|
|
static int lxcControllerStart(virConnectPtr conn,
|
|
|
|
virDomainObjPtr vm,
|
|
|
|
int nveths,
|
|
|
|
char **veths,
|
|
|
|
int appPty,
|
|
|
|
int logfd)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int rc;
|
|
|
|
int largc = 0, larga = 0;
|
|
|
|
const char **largv = NULL;
|
2009-10-08 15:16:08 +00:00
|
|
|
int lenvc = 0, lenva = 0;
|
|
|
|
const char **lenv = NULL;
|
|
|
|
char *filterstr;
|
|
|
|
char *outputstr;
|
|
|
|
char *tmp;
|
2009-10-08 15:40:14 +00:00
|
|
|
int log_level;
|
2008-08-20 20:55:32 +00:00
|
|
|
pid_t child;
|
|
|
|
int status;
|
2008-08-27 11:42:52 +00:00
|
|
|
fd_set keepfd;
|
|
|
|
char appPtyStr[30];
|
2008-09-05 11:52:12 +00:00
|
|
|
const char *emulator;
|
2009-10-08 15:40:14 +00:00
|
|
|
lxc_driver_t *driver = conn->privateData;
|
2008-08-27 11:42:52 +00:00
|
|
|
|
|
|
|
FD_ZERO(&keepfd);
|
2008-08-20 20:55:32 +00:00
|
|
|
|
|
|
|
#define ADD_ARG_SPACE \
|
|
|
|
do { \
|
|
|
|
if (largc == larga) { \
|
|
|
|
larga += 10; \
|
|
|
|
if (VIR_REALLOC_N(largv, larga) < 0) \
|
|
|
|
goto no_memory; \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define ADD_ARG(thisarg) \
|
|
|
|
do { \
|
|
|
|
ADD_ARG_SPACE; \
|
|
|
|
largv[largc++] = thisarg; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define ADD_ARG_LIT(thisarg) \
|
|
|
|
do { \
|
|
|
|
ADD_ARG_SPACE; \
|
|
|
|
if ((largv[largc++] = strdup(thisarg)) == NULL) \
|
|
|
|
goto no_memory; \
|
|
|
|
} while (0)
|
|
|
|
|
2009-10-08 15:16:08 +00:00
|
|
|
#define ADD_ENV_SPACE \
|
|
|
|
do { \
|
|
|
|
if (lenvc == lenva) { \
|
|
|
|
lenva += 10; \
|
|
|
|
if (VIR_REALLOC_N(lenv, lenva) < 0) \
|
|
|
|
goto no_memory; \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define ADD_ENV(thisarg) \
|
|
|
|
do { \
|
|
|
|
ADD_ENV_SPACE; \
|
|
|
|
lenv[lenvc++] = thisarg; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define ADD_ENV_PAIR(envname, val) \
|
|
|
|
do { \
|
|
|
|
char *envval; \
|
|
|
|
ADD_ENV_SPACE; \
|
|
|
|
if (virAsprintf(&envval, "%s=%s", envname, val) < 0) \
|
|
|
|
goto no_memory; \
|
|
|
|
lenv[lenvc++] = envval; \
|
|
|
|
} while (0)
|
|
|
|
|
2009-10-14 14:54:29 +00:00
|
|
|
#define ADD_ENV_COPY(envname) \
|
|
|
|
do { \
|
|
|
|
char *val = getenv(envname); \
|
|
|
|
if (val != NULL) { \
|
|
|
|
ADD_ENV_PAIR(envname, val); \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The controller may call ip command, so we have to remain PATH.
|
|
|
|
*/
|
|
|
|
ADD_ENV_COPY("PATH");
|
|
|
|
|
2009-10-08 15:40:14 +00:00
|
|
|
log_level = virLogGetDefaultPriority();
|
|
|
|
if (virAsprintf(&tmp, "LIBVIRT_DEBUG=%d", log_level) < 0)
|
2009-10-08 15:16:08 +00:00
|
|
|
goto no_memory;
|
|
|
|
ADD_ENV(tmp);
|
|
|
|
|
|
|
|
if (virLogGetNbFilters() > 0) {
|
|
|
|
filterstr = virLogGetFilters();
|
|
|
|
if (!filterstr)
|
|
|
|
goto no_memory;
|
|
|
|
ADD_ENV_PAIR("LIBVIRT_LOG_FILTERS", filterstr);
|
|
|
|
VIR_FREE(filterstr);
|
|
|
|
}
|
|
|
|
|
2009-10-08 15:40:14 +00:00
|
|
|
if (driver->log_libvirtd) {
|
|
|
|
if (virLogGetNbOutputs() > 0) {
|
|
|
|
outputstr = virLogGetOutputs();
|
|
|
|
if (!outputstr)
|
|
|
|
goto no_memory;
|
|
|
|
ADD_ENV_PAIR("LIBVIRT_LOG_OUTPUTS", outputstr);
|
|
|
|
VIR_FREE(outputstr);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (virAsprintf(&tmp, "LIBVIRT_LOG_OUTPUTS=%d:stderr", log_level) < 0)
|
2009-10-08 15:16:08 +00:00
|
|
|
goto no_memory;
|
2009-10-08 15:40:14 +00:00
|
|
|
ADD_ENV(tmp);
|
2009-10-08 15:16:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ADD_ENV(NULL);
|
|
|
|
|
2008-08-27 11:42:52 +00:00
|
|
|
snprintf(appPtyStr, sizeof(appPtyStr), "%d", appPty);
|
|
|
|
|
2008-09-05 11:52:12 +00:00
|
|
|
emulator = vm->def->emulator;
|
|
|
|
|
|
|
|
ADD_ARG_LIT(emulator);
|
2008-08-20 20:55:32 +00:00
|
|
|
ADD_ARG_LIT("--name");
|
|
|
|
ADD_ARG_LIT(vm->def->name);
|
|
|
|
ADD_ARG_LIT("--console");
|
2008-08-27 11:42:52 +00:00
|
|
|
ADD_ARG_LIT(appPtyStr);
|
2008-08-20 20:55:32 +00:00
|
|
|
ADD_ARG_LIT("--background");
|
|
|
|
|
|
|
|
for (i = 0 ; i < nveths ; i++) {
|
|
|
|
ADD_ARG_LIT("--veth");
|
|
|
|
ADD_ARG_LIT(veths[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
ADD_ARG(NULL);
|
|
|
|
|
2008-08-27 11:42:52 +00:00
|
|
|
FD_SET(appPty, &keepfd);
|
|
|
|
|
2009-10-08 15:16:08 +00:00
|
|
|
if (virExec(conn, largv, lenv, &keepfd, &child,
|
2009-01-29 17:27:54 +00:00
|
|
|
-1, &logfd, &logfd,
|
2008-08-20 20:55:32 +00:00
|
|
|
VIR_EXEC_NONE) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* We now wait for the process to exit - the controller
|
|
|
|
* will fork() itself into the background - waiting for
|
|
|
|
* it to exit thus guarentees it has written its pidfile
|
|
|
|
*/
|
|
|
|
while ((rc = waitpid(child, &status, 0) == -1) && errno == EINTR);
|
|
|
|
if (rc == -1) {
|
2009-01-20 17:13:33 +00:00
|
|
|
virReportSystemError(conn, errno,
|
|
|
|
_("cannot wait for '%s'"),
|
|
|
|
largv[0]);
|
2008-08-20 20:55:32 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(WIFEXITED(status) && WEXITSTATUS(status) == 0)) {
|
|
|
|
lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("container '%s' unexpectedly shutdown during startup"),
|
|
|
|
largv[0]);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef ADD_ARG
|
|
|
|
#undef ADD_ARG_LIT
|
|
|
|
#undef ADD_ARG_SPACE
|
2009-10-08 15:16:08 +00:00
|
|
|
#undef ADD_ENV_SPACE
|
|
|
|
#undef ADD_ENV_PAIR
|
2008-08-20 20:55:32 +00:00
|
|
|
|
2009-10-08 15:16:08 +00:00
|
|
|
return 0;
|
2008-08-20 20:55:32 +00:00
|
|
|
|
|
|
|
no_memory:
|
2009-01-29 12:10:32 +00:00
|
|
|
virReportOOMError(conn);
|
2009-10-08 15:16:08 +00:00
|
|
|
cleanup:
|
|
|
|
if (largv) {
|
|
|
|
for (i = 0 ; i < largc ; i++)
|
|
|
|
VIR_FREE(largv[i]);
|
|
|
|
VIR_FREE(largv);
|
|
|
|
}
|
|
|
|
if (lenv) {
|
|
|
|
for (i=0 ; i < lenvc ; i++)
|
|
|
|
VIR_FREE(lenv[i]);
|
|
|
|
VIR_FREE(lenv);
|
|
|
|
}
|
|
|
|
return -1;
|
2008-08-20 20:55:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-04-10 07:30:52 +00:00
|
|
|
/**
|
|
|
|
* lxcVmStart:
|
|
|
|
* @conn: pointer to connection
|
|
|
|
* @driver: pointer to driver structure
|
|
|
|
* @vm: pointer to virtual machine structure
|
|
|
|
*
|
|
|
|
* Starts a vm
|
|
|
|
*
|
|
|
|
* Returns 0 on success or -1 in case of error
|
|
|
|
*/
|
|
|
|
static int lxcVmStart(virConnectPtr conn,
|
|
|
|
lxc_driver_t * driver,
|
2008-08-13 12:50:55 +00:00
|
|
|
virDomainObjPtr vm)
|
2008-04-10 07:30:52 +00:00
|
|
|
{
|
2009-10-13 14:36:59 +00:00
|
|
|
int rc = -1, r;
|
2008-08-13 10:52:15 +00:00
|
|
|
unsigned int i;
|
|
|
|
int parentTty;
|
2008-08-13 12:50:55 +00:00
|
|
|
char *parentTtyPath = NULL;
|
2008-08-13 10:52:15 +00:00
|
|
|
char *logfile = NULL;
|
|
|
|
int logfd = -1;
|
|
|
|
unsigned int nveths = 0;
|
|
|
|
char **veths = NULL;
|
|
|
|
|
2009-10-13 14:36:59 +00:00
|
|
|
if ((r = virFileMakePath(driver->logDir)) < 0) {
|
|
|
|
virReportSystemError(conn, r,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("cannot create log directory '%s'"),
|
|
|
|
driver->logDir);
|
2008-08-13 10:52:15 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2008-04-10 07:30:52 +00:00
|
|
|
|
2008-12-23 13:03:29 +00:00
|
|
|
if (virAsprintf(&logfile, "%s/%s.log",
|
|
|
|
driver->logDir, vm->def->name) < 0) {
|
2009-01-29 12:10:32 +00:00
|
|
|
virReportOOMError(conn);
|
2008-08-13 10:52:15 +00:00
|
|
|
return -1;
|
2008-04-10 07:30:52 +00:00
|
|
|
}
|
|
|
|
|
2008-08-13 10:52:15 +00:00
|
|
|
/* open parent tty */
|
2008-08-13 12:50:55 +00:00
|
|
|
if (virFileOpenTty(&parentTty, &parentTtyPath, 1) < 0) {
|
2009-01-20 17:13:33 +00:00
|
|
|
virReportSystemError(conn, errno, "%s",
|
|
|
|
_("failed to allocate tty"));
|
2008-04-10 07:30:52 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2008-08-13 12:50:55 +00:00
|
|
|
if (vm->def->console &&
|
|
|
|
vm->def->console->type == VIR_DOMAIN_CHR_TYPE_PTY) {
|
|
|
|
VIR_FREE(vm->def->console->data.file.path);
|
|
|
|
vm->def->console->data.file.path = parentTtyPath;
|
|
|
|
} else {
|
|
|
|
VIR_FREE(parentTtyPath);
|
|
|
|
}
|
2008-04-10 07:30:52 +00:00
|
|
|
|
2008-08-13 10:52:15 +00:00
|
|
|
if (lxcSetupInterfaces(conn, vm->def, &nveths, &veths) != 0)
|
2008-06-26 16:09:48 +00:00
|
|
|
goto cleanup;
|
2008-04-10 07:30:52 +00:00
|
|
|
|
2008-08-20 20:55:32 +00:00
|
|
|
/* Persist the live configuration now we have veth & tty info */
|
2009-10-13 14:36:59 +00:00
|
|
|
if (virDomainSaveConfig(conn, driver->stateDir, vm->def) < 0)
|
2008-08-20 20:55:32 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2009-10-08 15:37:09 +00:00
|
|
|
if ((logfd = open(logfile, O_WRONLY | O_APPEND | O_CREAT,
|
2008-08-13 10:52:15 +00:00
|
|
|
S_IRUSR|S_IWUSR)) < 0) {
|
2009-01-20 17:13:33 +00:00
|
|
|
virReportSystemError(conn, errno,
|
|
|
|
_("failed to open '%s'"),
|
|
|
|
logfile);
|
2008-06-26 16:09:48 +00:00
|
|
|
goto cleanup;
|
2008-04-10 07:30:52 +00:00
|
|
|
}
|
|
|
|
|
2008-08-20 20:55:32 +00:00
|
|
|
if (lxcControllerStart(conn,
|
|
|
|
vm,
|
|
|
|
nveths, veths,
|
|
|
|
parentTty, logfd) < 0)
|
2008-06-26 16:09:48 +00:00
|
|
|
goto cleanup;
|
2008-08-13 10:52:15 +00:00
|
|
|
|
|
|
|
/* Connect to the controller as a client *first* because
|
|
|
|
* this will block until the child has written their
|
|
|
|
* pid file out to disk */
|
|
|
|
if ((vm->monitor = lxcMonitorClient(conn, driver, vm)) < 0)
|
2008-06-26 16:09:48 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2008-08-13 10:52:15 +00:00
|
|
|
/* And get its pid */
|
2009-10-13 14:36:59 +00:00
|
|
|
if ((r = virFileReadPid(driver->stateDir, vm->def->name, &vm->pid)) != 0) {
|
|
|
|
virReportSystemError(conn, r,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("Failed to read pid file %s/%s.pid"),
|
|
|
|
driver->stateDir, vm->def->name);
|
2008-06-26 16:09:48 +00:00
|
|
|
goto cleanup;
|
2008-08-13 10:52:15 +00:00
|
|
|
}
|
2008-06-26 16:09:48 +00:00
|
|
|
|
2008-08-13 10:52:15 +00:00
|
|
|
vm->def->id = vm->pid;
|
2008-06-26 16:09:48 +00:00
|
|
|
vm->state = VIR_DOMAIN_RUNNING;
|
|
|
|
|
2008-11-19 16:19:36 +00:00
|
|
|
if ((vm->monitorWatch = virEventAddHandle(
|
|
|
|
vm->monitor,
|
|
|
|
VIR_EVENT_HANDLE_ERROR | VIR_EVENT_HANDLE_HANGUP,
|
|
|
|
lxcMonitorEvent,
|
2008-11-19 16:24:01 +00:00
|
|
|
driver, NULL)) < 0) {
|
2008-08-13 10:52:15 +00:00
|
|
|
lxcVmTerminate(conn, driver, vm, 0);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2008-06-26 16:09:48 +00:00
|
|
|
|
2008-08-13 10:52:15 +00:00
|
|
|
rc = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
for (i = 0 ; i < nveths ; i++) {
|
|
|
|
if (rc != 0)
|
|
|
|
vethDelete(veths[i]);
|
|
|
|
VIR_FREE(veths[i]);
|
|
|
|
}
|
|
|
|
if (rc != 0 && vm->monitor != -1) {
|
|
|
|
close(vm->monitor);
|
|
|
|
vm->monitor = -1;
|
|
|
|
}
|
|
|
|
if (parentTty != -1)
|
|
|
|
close(parentTty);
|
|
|
|
if (logfd != -1)
|
|
|
|
close(logfd);
|
|
|
|
VIR_FREE(logfile);
|
2008-04-10 07:30:52 +00:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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)
|
|
|
|
{
|
2008-12-04 21:11:41 +00:00
|
|
|
lxc_driver_t *driver = dom->conn->privateData;
|
|
|
|
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
|
|
|
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverLock(driver);
|
2008-12-04 21:11:41 +00:00
|
|
|
vm = virDomainFindByName(&driver->domains, dom->name);
|
2008-04-10 07:30:52 +00:00
|
|
|
if (!vm) {
|
2008-12-04 21:11:41 +00:00
|
|
|
lxcError(dom->conn, dom, VIR_ERR_INVALID_DOMAIN,
|
2008-11-07 16:43:58 +00:00
|
|
|
_("no domain named %s"), dom->name);
|
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)) {
|
2008-12-04 21:11:41 +00:00
|
|
|
lxcError(dom->conn, NULL, VIR_ERR_NO_SUPPORT,
|
avoid many format string warnings
Building with --disable-nls exposed many new warnings like these:
virsh.c:4952: warning: format not a string literal and no format ...
util.c:163: warning: format not a string literal and no format arguments
All but one of the following changes add a "%s" argument before
the offending _(...) argument.
This was the only manual change:
* src/lxc_driver.c (lxcVersion): Use %s and strerror(errno)
rather than %m, to avoid a warning from gcc -Wformat-security.
Add "%s" before each warned about format-string-with-no-%-directive:
* src/domain_conf.c (virDomainHostdevSubsysUsbDefParseXML)
(virDomainDefParseString, virDomainDefParseFile):
* src/hash.c (virGetConnect, __virGetDomain, virReleaseDomain)
(__virGetNetwork, virReleaseNetwork, __virGetStoragePool)
(virReleaseStoragePool, __virGetStorageVol, virReleaseStorageVol):
* src/lxc_container.c (lxcContainerChild):
* src/lxc_driver.c (lxcDomainDefine, lxcDomainUndefine)
(lxcDomainGetInfo, lxcGetOSType, lxcDomainDumpXML)
(lxcSetupInterfaces, lxcDomainStart, lxcDomainCreateAndStart)
(lxcVersion, lxcGetSchedulerParameters):
* src/network_conf.c (virNetworkDefParseString)
(virNetworkDefParseFile):
* src/openvz_conf.c (openvzReadNetworkConf, openvzLoadDomains):
* src/openvz_driver.c (openvzDomainDefineCmd)
(openvzDomainGetInfo, openvzDomainDumpXML, openvzDomainShutdown)
(openvzDomainReboot, ADD_ARG_LIT, openvzDomainDefineXML)
(openvzDomainCreateXML, openvzDomainCreate, openvzDomainUndefine)
(openvzDomainSetAutostart, openvzDomainGetAutostart)
(openvzDomainSetVcpus):
* src/qemu_driver.c (qemudDomainBlockPeek, qemudDomainMemoryPeek):
* src/remote_internal.c (remoteDomainBlockPeek)
(remoteDomainMemoryPeek, remoteAuthPolkit):
* src/sexpr.c (sexpr_new, _string2sexpr):
* src/storage_backend_disk.c (virStorageBackendDiskMakeDataVol)
(virStorageBackendDiskCreateVol):
* src/storage_backend_fs.c
(virStorageBackendFileSystemNetFindPoolSources):
* src/storage_backend_logical.c (virStorageBackendLogicalFindLVs)
(virStorageBackendLogicalFindPoolSources):
* src/test.c (testOpenDefault, testOpenFromFile, testOpen)
(testGetDomainInfo, testDomainRestore)
(testNodeGetCellsFreeMemory):
* src/util.c (virExec):
* src/virsh.c (cmdAttachDevice, cmdDetachDevice)
(cmdAttachInterface, cmdDetachInterface, cmdAttachDisk)
(cmdDetachDisk, cmdEdit):
* src/xend_internal.c (do_connect, wr_sync, xend_op_ext)
(urlencode, xenDaemonDomainCreateXML)
(xenDaemonDomainLookupByName_ids, xenDaemonDomainLookupByID)
(xenDaemonParseSxprOS, xend_parse_sexp_desc_char)
(xenDaemonParseSxprChar, xenDaemonParseSxprDisks)
(xenDaemonParseSxpr, sexpr_to_xend_topology, sexpr_to_domain)
(xenDaemonDomainFetch, xenDaemonDomainGetAutostart)
(xenDaemonDomainSetAutostart, xenDaemonDomainMigratePerform)
(xenDaemonDomainDefineXML, xenDaemonGetSchedulerType)
(xenDaemonGetSchedulerParameters)
(xenDaemonSetSchedulerParameters, xenDaemonDomainBlockPeek)
(xenDaemonFormatSxprChr, virDomainXMLDevID):
* src/xm_internal.c (xenXMConfigCacheRefresh, xenXMDomainPinVcpu)
(xenXMDomainCreate, xenXMDomainDefineXML)
(xenXMDomainAttachDevice, xenXMDomainDetachDevice):
* src/xml.c (virXPathString, virXPathNumber, virXPathLong)
(virXPathULong, virXPathBoolean, virXPathNode, virXPathNodeSet):
* src/xs_internal.c (xenStoreOpen):
2008-10-13 16:46:28 +00:00
|
|
|
"%s", _("System lacks NETNS support"));
|
2008-08-13 12:50:55 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2008-12-04 21:11:41 +00:00
|
|
|
ret = lxcVmStart(dom->conn, driver, vm);
|
2008-04-10 07:30:52 +00:00
|
|
|
|
2009-07-06 15:04:36 +00:00
|
|
|
if (ret == 0)
|
|
|
|
event = virDomainEventNewFromObj(vm,
|
|
|
|
VIR_DOMAIN_EVENT_STARTED,
|
|
|
|
VIR_DOMAIN_EVENT_STARTED_BOOTED);
|
|
|
|
|
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)
|
|
|
|
lxcDomainEventQueue(driver, 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
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* lxcDomainCreateAndStart:
|
|
|
|
* @conn: pointer to connection
|
|
|
|
* @xml: XML definition of domain
|
|
|
|
* @flags: Unused
|
|
|
|
*
|
|
|
|
* 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,
|
|
|
|
unsigned int flags ATTRIBUTE_UNUSED) {
|
2008-12-04 21:11:41 +00:00
|
|
|
lxc_driver_t *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
|
|
|
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverLock(driver);
|
2009-01-08 13:54:20 +00:00
|
|
|
if (!(def = virDomainDefParseString(conn, driver->caps, xml,
|
|
|
|
VIR_DOMAIN_XML_INACTIVE)))
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
2008-04-10 07:30:52 +00:00
|
|
|
|
2009-07-31 14:25:03 +00:00
|
|
|
/* See if a VM with matching UUID already exists */
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, def->uuid);
|
|
|
|
if (vm) {
|
|
|
|
/* UUID matches, but if names don't match, refuse it */
|
|
|
|
if (STRNEQ(vm->def->name, def->name)) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(vm->def->uuid, uuidstr);
|
|
|
|
lxcError(conn, NULL, VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("domain '%s' is already defined with uuid %s"),
|
|
|
|
vm->def->name, uuidstr);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* UUID & name match, but if VM is already active, refuse it */
|
|
|
|
if (virDomainIsActive(vm)) {
|
|
|
|
lxcError(conn, NULL, VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("domain is already active as '%s'"), vm->def->name);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
} else {
|
|
|
|
/* UUID does not match, but if a name matches, refuse it */
|
|
|
|
vm = virDomainFindByName(&driver->domains, def->name);
|
|
|
|
if (vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(vm->def->uuid, uuidstr);
|
|
|
|
lxcError(conn, NULL, VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("domain '%s' is already defined with uuid %s"),
|
|
|
|
def->name, uuidstr);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-08-13 12:50:55 +00:00
|
|
|
if ((def->nets != NULL) && !(driver->have_netns)) {
|
|
|
|
lxcError(conn, NULL, VIR_ERR_NO_SUPPORT,
|
avoid many format string warnings
Building with --disable-nls exposed many new warnings like these:
virsh.c:4952: warning: format not a string literal and no format ...
util.c:163: warning: format not a string literal and no format arguments
All but one of the following changes add a "%s" argument before
the offending _(...) argument.
This was the only manual change:
* src/lxc_driver.c (lxcVersion): Use %s and strerror(errno)
rather than %m, to avoid a warning from gcc -Wformat-security.
Add "%s" before each warned about format-string-with-no-%-directive:
* src/domain_conf.c (virDomainHostdevSubsysUsbDefParseXML)
(virDomainDefParseString, virDomainDefParseFile):
* src/hash.c (virGetConnect, __virGetDomain, virReleaseDomain)
(__virGetNetwork, virReleaseNetwork, __virGetStoragePool)
(virReleaseStoragePool, __virGetStorageVol, virReleaseStorageVol):
* src/lxc_container.c (lxcContainerChild):
* src/lxc_driver.c (lxcDomainDefine, lxcDomainUndefine)
(lxcDomainGetInfo, lxcGetOSType, lxcDomainDumpXML)
(lxcSetupInterfaces, lxcDomainStart, lxcDomainCreateAndStart)
(lxcVersion, lxcGetSchedulerParameters):
* src/network_conf.c (virNetworkDefParseString)
(virNetworkDefParseFile):
* src/openvz_conf.c (openvzReadNetworkConf, openvzLoadDomains):
* src/openvz_driver.c (openvzDomainDefineCmd)
(openvzDomainGetInfo, openvzDomainDumpXML, openvzDomainShutdown)
(openvzDomainReboot, ADD_ARG_LIT, openvzDomainDefineXML)
(openvzDomainCreateXML, openvzDomainCreate, openvzDomainUndefine)
(openvzDomainSetAutostart, openvzDomainGetAutostart)
(openvzDomainSetVcpus):
* src/qemu_driver.c (qemudDomainBlockPeek, qemudDomainMemoryPeek):
* src/remote_internal.c (remoteDomainBlockPeek)
(remoteDomainMemoryPeek, remoteAuthPolkit):
* src/sexpr.c (sexpr_new, _string2sexpr):
* src/storage_backend_disk.c (virStorageBackendDiskMakeDataVol)
(virStorageBackendDiskCreateVol):
* src/storage_backend_fs.c
(virStorageBackendFileSystemNetFindPoolSources):
* src/storage_backend_logical.c (virStorageBackendLogicalFindLVs)
(virStorageBackendLogicalFindPoolSources):
* src/test.c (testOpenDefault, testOpenFromFile, testOpen)
(testGetDomainInfo, testDomainRestore)
(testNodeGetCellsFreeMemory):
* src/util.c (virExec):
* src/virsh.c (cmdAttachDevice, cmdDetachDevice)
(cmdAttachInterface, cmdDetachInterface, cmdAttachDisk)
(cmdDetachDisk, cmdEdit):
* src/xend_internal.c (do_connect, wr_sync, xend_op_ext)
(urlencode, xenDaemonDomainCreateXML)
(xenDaemonDomainLookupByName_ids, xenDaemonDomainLookupByID)
(xenDaemonParseSxprOS, xend_parse_sexp_desc_char)
(xenDaemonParseSxprChar, xenDaemonParseSxprDisks)
(xenDaemonParseSxpr, sexpr_to_xend_topology, sexpr_to_domain)
(xenDaemonDomainFetch, xenDaemonDomainGetAutostart)
(xenDaemonDomainSetAutostart, xenDaemonDomainMigratePerform)
(xenDaemonDomainDefineXML, xenDaemonGetSchedulerType)
(xenDaemonGetSchedulerParameters)
(xenDaemonSetSchedulerParameters, xenDaemonDomainBlockPeek)
(xenDaemonFormatSxprChr, virDomainXMLDevID):
* src/xm_internal.c (xenXMConfigCacheRefresh, xenXMDomainPinVcpu)
(xenXMDomainCreate, xenXMDomainDefineXML)
(xenXMDomainAttachDevice, xenXMDomainDetachDevice):
* src/xml.c (virXPathString, virXPathNumber, virXPathLong)
(virXPathULong, virXPathBoolean, virXPathNode, virXPathNodeSet):
* src/xs_internal.c (xenStoreOpen):
2008-10-13 16:46:28 +00:00
|
|
|
"%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
|
|
|
|
2009-10-06 11:50:58 +00:00
|
|
|
if (!(vm = virDomainAssignDef(conn, driver->caps,
|
|
|
|
&driver->domains, def)))
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
|
|
|
def = NULL;
|
2008-04-10 07:30:52 +00:00
|
|
|
|
|
|
|
if (lxcVmStart(conn, driver, vm) < 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-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);
|
|
|
|
|
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)
|
|
|
|
lxcDomainEventQueue(driver, event);
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverUnlock(driver);
|
2008-04-10 07:30:52 +00:00
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* lxcDomainShutdown:
|
|
|
|
* @dom: Ptr to domain to shutdown
|
|
|
|
*
|
|
|
|
* Sends SIGINT to container root process to request it to shutdown
|
|
|
|
*
|
|
|
|
* Returns 0 on success or -1 in case of error
|
|
|
|
*/
|
|
|
|
static int lxcDomainShutdown(virDomainPtr dom)
|
|
|
|
{
|
2008-12-04 21:11:41 +00:00
|
|
|
lxc_driver_t *driver = dom->conn->privateData;
|
|
|
|
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
|
|
|
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverLock(driver);
|
2008-12-04 21:11:41 +00:00
|
|
|
vm = virDomainFindByID(&driver->domains, dom->id);
|
2008-04-10 07:30:52 +00:00
|
|
|
if (!vm) {
|
|
|
|
lxcError(dom->conn, dom, VIR_ERR_INVALID_DOMAIN,
|
|
|
|
_("no domain with id %d"), dom->id);
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
2008-04-10 07:30:52 +00:00
|
|
|
}
|
|
|
|
|
2008-12-04 21:11:41 +00:00
|
|
|
ret = lxcVmTerminate(dom->conn, driver, vm, 0);
|
2009-07-06 15:04:36 +00:00
|
|
|
event = virDomainEventNewFromObj(vm,
|
|
|
|
VIR_DOMAIN_EVENT_STOPPED,
|
|
|
|
VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
|
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)
|
|
|
|
lxcDomainEventQueue(driver, event);
|
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
lxcDomainEventRegister (virConnectPtr conn,
|
|
|
|
virConnectDomainEventCallback callback,
|
|
|
|
void *opaque,
|
|
|
|
virFreeCallback freecb)
|
|
|
|
{
|
|
|
|
lxc_driver_t *driver = conn->privateData;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
lxcDriverLock(driver);
|
|
|
|
ret = virDomainEventCallbackListAdd(conn, driver->domainEventCallbacks,
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2009-07-06 15:04:36 +00:00
|
|
|
static int
|
|
|
|
lxcDomainEventDeregister (virConnectPtr conn,
|
|
|
|
virConnectDomainEventCallback callback)
|
|
|
|
{
|
|
|
|
lxc_driver_t *driver = conn->privateData;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
lxcDriverLock(driver);
|
|
|
|
if (driver->domainEventDispatching)
|
|
|
|
ret = virDomainEventCallbackListMarkDelete(conn, driver->domainEventCallbacks,
|
|
|
|
callback);
|
|
|
|
else
|
|
|
|
ret = virDomainEventCallbackListRemove(conn, driver->domainEventCallbacks,
|
|
|
|
callback);
|
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void lxcDomainEventDispatchFunc(virConnectPtr conn,
|
|
|
|
virDomainEventPtr event,
|
|
|
|
virConnectDomainEventCallback cb,
|
|
|
|
void *cbopaque,
|
|
|
|
void *opaque)
|
|
|
|
{
|
|
|
|
lxc_driver_t *driver = opaque;
|
|
|
|
|
|
|
|
/* Drop the lock whle dispatching, for sake of re-entrancy */
|
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
virDomainEventDispatchDefaultFunc(conn, event, cb, cbopaque, NULL);
|
|
|
|
lxcDriverLock(driver);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void lxcDomainEventFlush(int timer ATTRIBUTE_UNUSED, void *opaque)
|
|
|
|
{
|
|
|
|
lxc_driver_t *driver = opaque;
|
|
|
|
virDomainEventQueue tempQueue;
|
|
|
|
|
|
|
|
lxcDriverLock(driver);
|
|
|
|
|
|
|
|
driver->domainEventDispatching = 1;
|
|
|
|
|
|
|
|
/* Copy the queue, so we're reentrant safe */
|
|
|
|
tempQueue.count = driver->domainEventQueue->count;
|
|
|
|
tempQueue.events = driver->domainEventQueue->events;
|
|
|
|
driver->domainEventQueue->count = 0;
|
|
|
|
driver->domainEventQueue->events = NULL;
|
|
|
|
|
|
|
|
virEventUpdateTimeout(driver->domainEventTimer, -1);
|
|
|
|
virDomainEventQueueDispatch(&tempQueue,
|
|
|
|
driver->domainEventCallbacks,
|
|
|
|
lxcDomainEventDispatchFunc,
|
|
|
|
driver);
|
|
|
|
|
|
|
|
/* Purge any deleted callbacks */
|
|
|
|
virDomainEventCallbackListPurgeMarked(driver->domainEventCallbacks);
|
|
|
|
|
|
|
|
driver->domainEventDispatching = 0;
|
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* driver must be locked before calling */
|
|
|
|
static void lxcDomainEventQueue(lxc_driver_t *driver,
|
|
|
|
virDomainEventPtr event)
|
|
|
|
{
|
|
|
|
if (virDomainEventQueuePush(driver->domainEventQueue,
|
|
|
|
event) < 0)
|
|
|
|
virDomainEventFree(event);
|
|
|
|
if (lxc_driver->domainEventQueue->count == 1)
|
|
|
|
virEventUpdateTimeout(driver->domainEventTimer, 0);
|
|
|
|
}
|
2008-05-13 06:30:58 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* lxcDomainDestroy:
|
|
|
|
* @dom: Ptr 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)
|
|
|
|
{
|
2008-12-04 21:11:41 +00:00
|
|
|
lxc_driver_t *driver = dom->conn->privateData;
|
|
|
|
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-05-13 06:30:58 +00:00
|
|
|
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverLock(driver);
|
2008-12-04 21:11:41 +00:00
|
|
|
vm = virDomainFindByID(&driver->domains, dom->id);
|
2008-05-13 06:30:58 +00:00
|
|
|
if (!vm) {
|
|
|
|
lxcError(dom->conn, dom, VIR_ERR_INVALID_DOMAIN,
|
|
|
|
_("no domain with id %d"), dom->id);
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
2008-05-13 06:30:58 +00:00
|
|
|
}
|
|
|
|
|
2008-12-04 21:11:41 +00:00
|
|
|
ret = lxcVmTerminate(dom->conn, driver, vm, SIGKILL);
|
2009-07-06 15:04:36 +00:00
|
|
|
event = virDomainEventNewFromObj(vm,
|
|
|
|
VIR_DOMAIN_EVENT_STOPPED,
|
|
|
|
VIR_DOMAIN_EVENT_STOPPED_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)
|
|
|
|
lxcDomainEventQueue(driver, 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
|
|
|
|
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;
|
|
|
|
|
2008-08-13 10:25:34 +00:00
|
|
|
if (virRun(NULL, argv, &ip_rc) < 0 ||
|
|
|
|
!(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
|
|
|
|
Convert virDomainObjListPtr to use a hash of domain objects
The current virDomainObjListPtr object stores domain objects in
an array. This means that to find a particular objects requires
O(n) time, and more critically acquiring O(n) mutex locks.
The new impl replaces the array with a virHashTable, keyed off
UUID. Finding a object based on UUID is now O(1) time, and only
requires a single mutex lock. Finding by name/id is unchanged
in complexity.
In changing this, all code which iterates over the array had
to be updated to use a hash table iterator function callback.
Several of the functions which were identically duplicating
across all drivers were pulled into domain_conf.c
* src/conf/domain_conf.h, src/conf/domain_conf.c: Change
virDomainObjListPtr to use virHashTable. Add a initializer
method virDomainObjListInit, and rename virDomainObjListFree
to virDomainObjListDeinit, since its not actually freeing
the container, only its contents. Also add some convenient
methods virDomainObjListGetInactiveNames,
virDomainObjListGetActiveIDs and virDomainObjListNumOfDomains
which can be used to implement the correspondingly named
public API entry points in drivers
* src/libvirt_private.syms: Export new methods from domain_conf.h
* src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_conf.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c: Update all code
to deal with hash tables instead of arrays for domains
2009-10-09 11:33:51 +00:00
|
|
|
struct lxcAutostartData {
|
|
|
|
lxc_driver_t *driver;
|
|
|
|
virConnectPtr conn;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
lxcAutostartDomain(void *payload, const char *name ATTRIBUTE_UNUSED, void *opaque)
|
|
|
|
{
|
|
|
|
virDomainObjPtr vm = payload;
|
|
|
|
const struct lxcAutostartData *data = opaque;
|
|
|
|
|
|
|
|
virDomainObjLock(vm);
|
|
|
|
if (vm->autostart &&
|
|
|
|
!virDomainIsActive(vm)) {
|
|
|
|
int ret = lxcVmStart(data->conn, data->driver, vm);
|
|
|
|
if (ret < 0) {
|
|
|
|
virErrorPtr err = virGetLastError();
|
|
|
|
VIR_ERROR(_("Failed to autostart VM '%s': %s\n"),
|
|
|
|
vm->def->name,
|
|
|
|
err ? err->message : "");
|
|
|
|
} else {
|
|
|
|
virDomainEventPtr event =
|
|
|
|
virDomainEventNewFromObj(vm,
|
|
|
|
VIR_DOMAIN_EVENT_STARTED,
|
|
|
|
VIR_DOMAIN_EVENT_STARTED_BOOTED);
|
|
|
|
if (event)
|
|
|
|
lxcDomainEventQueue(data->driver, event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
}
|
|
|
|
|
2009-07-06 15:05:32 +00:00
|
|
|
static void
|
|
|
|
lxcAutostartConfigs(lxc_driver_t *driver) {
|
|
|
|
/* XXX: Figure out a better way todo this. The domain
|
|
|
|
* startup code needs a connection handle in order
|
|
|
|
* to lookup the bridge associated with a virtual
|
|
|
|
* network
|
|
|
|
*/
|
|
|
|
virConnectPtr conn = virConnectOpen("lxc:///");
|
|
|
|
/* Ignoring NULL conn which is mostly harmless here */
|
|
|
|
|
Convert virDomainObjListPtr to use a hash of domain objects
The current virDomainObjListPtr object stores domain objects in
an array. This means that to find a particular objects requires
O(n) time, and more critically acquiring O(n) mutex locks.
The new impl replaces the array with a virHashTable, keyed off
UUID. Finding a object based on UUID is now O(1) time, and only
requires a single mutex lock. Finding by name/id is unchanged
in complexity.
In changing this, all code which iterates over the array had
to be updated to use a hash table iterator function callback.
Several of the functions which were identically duplicating
across all drivers were pulled into domain_conf.c
* src/conf/domain_conf.h, src/conf/domain_conf.c: Change
virDomainObjListPtr to use virHashTable. Add a initializer
method virDomainObjListInit, and rename virDomainObjListFree
to virDomainObjListDeinit, since its not actually freeing
the container, only its contents. Also add some convenient
methods virDomainObjListGetInactiveNames,
virDomainObjListGetActiveIDs and virDomainObjListNumOfDomains
which can be used to implement the correspondingly named
public API entry points in drivers
* src/libvirt_private.syms: Export new methods from domain_conf.h
* src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_conf.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c: Update all code
to deal with hash tables instead of arrays for domains
2009-10-09 11:33:51 +00:00
|
|
|
struct lxcAutostartData data = { driver, conn };
|
|
|
|
|
2009-07-06 15:05:32 +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
|
|
|
virHashForEach(driver->domains.objs, lxcAutostartDomain, &data);
|
2009-07-06 15:05:32 +00:00
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
|
|
|
|
if (conn)
|
|
|
|
virConnectClose(conn);
|
|
|
|
}
|
|
|
|
|
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
|
|
|
static void
|
|
|
|
lxcReconnectVM(void *payload, const char *name ATTRIBUTE_UNUSED, void *opaque)
|
|
|
|
{
|
|
|
|
virDomainObjPtr vm = payload;
|
|
|
|
lxc_driver_t *driver = opaque;
|
|
|
|
char *config = NULL;
|
|
|
|
virDomainDefPtr tmp;
|
|
|
|
|
|
|
|
virDomainObjLock(vm);
|
|
|
|
if ((vm->monitor = lxcMonitorClient(NULL, driver, vm)) < 0) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Read pid from controller */
|
|
|
|
if ((virFileReadPid(lxc_driver->stateDir, vm->def->name, &vm->pid)) != 0) {
|
|
|
|
close(vm->monitor);
|
|
|
|
vm->monitor = -1;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((config = virDomainConfigFile(NULL,
|
|
|
|
driver->stateDir,
|
|
|
|
vm->def->name)) == NULL)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* Try and load the live config */
|
|
|
|
tmp = virDomainDefParseFile(NULL, driver->caps, config, 0);
|
|
|
|
VIR_FREE(config);
|
|
|
|
if (tmp) {
|
|
|
|
vm->newDef = vm->def;
|
|
|
|
vm->def = tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vm->pid != 0) {
|
|
|
|
vm->def->id = vm->pid;
|
|
|
|
vm->state = VIR_DOMAIN_RUNNING;
|
|
|
|
} else {
|
|
|
|
vm->def->id = -1;
|
|
|
|
close(vm->monitor);
|
|
|
|
vm->monitor = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
}
|
|
|
|
|
2009-07-06 15:05:32 +00:00
|
|
|
|
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");
|
|
|
|
if (ld && strstr(ld, "vgpreload"))
|
|
|
|
return -1;
|
2008-03-31 12:02:12 +00:00
|
|
|
|
|
|
|
/* Check that the user is root */
|
2009-06-12 13:20:13 +00:00
|
|
|
if (!privileged) {
|
2008-03-31 12:02:12 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2008-03-27 09:34:06 +00:00
|
|
|
/* Check that this is a container enabled kernel */
|
2009-08-12 10:07:41 +00:00
|
|
|
if (lxcContainerAvailable(0) < 0) {
|
|
|
|
VIR_INFO0("LXC support not available in this kernel, disabling driver");
|
2008-12-04 21:12:41 +00:00
|
|
|
goto cleanup;
|
2009-08-12 10:07:41 +00:00
|
|
|
}
|
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;
|
|
|
|
|
2009-08-12 10:07:41 +00:00
|
|
|
if (VIR_ALLOC(lxc_driver->domainEventCallbacks) < 0)
|
2009-07-06 15:04:36 +00:00
|
|
|
goto cleanup;
|
|
|
|
if (!(lxc_driver->domainEventQueue = virDomainEventQueueNew()))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if ((lxc_driver->domainEventTimer =
|
|
|
|
virEventAddTimeout(-1, lxcDomainEventFlush, lxc_driver, NULL)) < 0)
|
|
|
|
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) {
|
|
|
|
char buf[1024];
|
|
|
|
VIR_WARN("Unable to create cgroup for driver: %s",
|
|
|
|
virStrerror(-rc, buf, sizeof(buf)));
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2008-12-04 21:12:41 +00:00
|
|
|
if ((lxc_driver->caps = lxcCapsInit()) == NULL)
|
|
|
|
goto cleanup;
|
2008-03-21 15:03:37 +00:00
|
|
|
|
2008-08-13 12:50:55 +00:00
|
|
|
if (virDomainLoadAllConfigs(NULL,
|
|
|
|
lxc_driver->caps,
|
|
|
|
&lxc_driver->domains,
|
|
|
|
lxc_driver->configDir,
|
2008-11-17 16:52:32 +00:00
|
|
|
lxc_driver->autostartDir,
|
2009-06-12 11:38:50 +00:00
|
|
|
0, NULL, NULL) < 0)
|
2008-12-04 21:12:41 +00:00
|
|
|
goto cleanup;
|
2008-08-13 12:50:55 +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
|
|
|
virHashForEach(lxc_driver->domains.objs, lxcReconnectVM, lxc_driver);
|
2008-08-13 10:52:15 +00:00
|
|
|
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverUnlock(lxc_driver);
|
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)
|
|
|
|
{
|
|
|
|
lxc_driver_t *driver = opaque;
|
|
|
|
|
|
|
|
if (newVM) {
|
|
|
|
virDomainEventPtr event =
|
|
|
|
virDomainEventNewFromObj(vm,
|
|
|
|
VIR_DOMAIN_EVENT_DEFINED,
|
|
|
|
VIR_DOMAIN_EVENT_DEFINED_ADDED);
|
|
|
|
if (event)
|
|
|
|
lxcDomainEventQueue(driver, event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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);
|
|
|
|
virDomainLoadAllConfigs(NULL,
|
|
|
|
lxc_driver->caps,
|
|
|
|
&lxc_driver->domains,
|
|
|
|
lxc_driver->configDir,
|
|
|
|
lxc_driver->autostartDir,
|
|
|
|
0, lxcNotifyLoadDomain, lxc_driver);
|
|
|
|
lxcDriverUnlock(lxc_driver);
|
|
|
|
|
|
|
|
lxcAutostartConfigs(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)
|
2008-03-31 14:38:12 +00:00
|
|
|
return(-1);
|
2008-10-10 14:20:37 +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
|
|
|
virDomainObjListDeinit(&lxc_driver->domains);
|
2008-12-04 21:12:41 +00:00
|
|
|
|
2009-07-06 15:04:36 +00:00
|
|
|
virDomainEventCallbackListFree(lxc_driver->domainEventCallbacks);
|
|
|
|
virDomainEventQueueFree(lxc_driver->domainEventQueue);
|
|
|
|
|
|
|
|
if (lxc_driver->domainEventTimer != -1)
|
|
|
|
virEventRemoveTimeout(lxc_driver->domainEventTimer);
|
|
|
|
|
2008-12-04 21:12:41 +00:00
|
|
|
virCapabilitiesFree(lxc_driver->caps);
|
|
|
|
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)
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2008-09-03 17:21:27 +00:00
|
|
|
static int lxcVersion(virConnectPtr conn, unsigned long *version)
|
|
|
|
{
|
|
|
|
struct utsname ver;
|
|
|
|
int maj;
|
|
|
|
int min;
|
|
|
|
int rev;
|
|
|
|
|
2009-01-20 17:13:33 +00:00
|
|
|
uname(&ver);
|
2008-09-03 17:21:27 +00:00
|
|
|
|
|
|
|
if (sscanf(ver.release, "%i.%i.%i", &maj, &min, &rev) != 3) {
|
|
|
|
lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unknown release: %s"), ver.release);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
*version = (maj * 1000 * 1000) + (min * 1000) + rev;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2008-03-27 09:34:06 +00:00
|
|
|
|
2008-10-10 09:32:27 +00:00
|
|
|
static char *lxcGetSchedulerType(virDomainPtr domain ATTRIBUTE_UNUSED,
|
|
|
|
int *nparams)
|
2008-10-08 16:28:48 +00:00
|
|
|
{
|
|
|
|
if (nparams)
|
|
|
|
*nparams = 1;
|
|
|
|
|
|
|
|
return strdup("posix");
|
|
|
|
}
|
|
|
|
|
2008-12-04 21:11:41 +00:00
|
|
|
static int lxcSetSchedulerParameters(virDomainPtr domain,
|
2008-10-08 16:28:48 +00:00
|
|
|
virSchedParameterPtr params,
|
|
|
|
int nparams)
|
|
|
|
{
|
2008-12-04 21:12:41 +00:00
|
|
|
lxc_driver_t *driver = domain->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;
|
|
|
|
int ret = -1;
|
2008-10-08 16:28:48 +00:00
|
|
|
|
2009-07-10 10:40:04 +00:00
|
|
|
if (driver->cgroup == NULL)
|
2008-12-04 21:12:41 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
lxcDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, domain->uuid);
|
2008-10-08 16:28:48 +00:00
|
|
|
|
2008-12-04 21:11:41 +00:00
|
|
|
if (vm == NULL) {
|
|
|
|
lxcError(NULL, domain, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("No such domain %s"), domain->uuid);
|
|
|
|
goto cleanup;
|
2008-10-08 16:28:48 +00:00
|
|
|
}
|
|
|
|
|
2009-07-10 10:40:04 +00:00
|
|
|
if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0)
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
2008-10-08 16:28:48 +00:00
|
|
|
|
|
|
|
for (i = 0; i < nparams; i++) {
|
|
|
|
virSchedParameterPtr param = ¶ms[i];
|
2009-07-09 13:11:21 +00:00
|
|
|
if (param->type != VIR_DOMAIN_SCHED_FIELD_ULLONG) {
|
|
|
|
lxcError(NULL, domain, VIR_ERR_INVALID_ARG,
|
|
|
|
_("invalid type for cpu_shares tunable, expected a 'ullong'"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2008-10-08 16:28:48 +00:00
|
|
|
|
|
|
|
if (STREQ(param->field, "cpu_shares")) {
|
2009-07-09 13:11:21 +00:00
|
|
|
if (virCgroupSetCpuShares(group, params[i].value.ul) != 0)
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
2008-10-08 16:28:48 +00:00
|
|
|
} else {
|
2008-12-04 21:11:41 +00:00
|
|
|
lxcError(NULL, domain, VIR_ERR_INVALID_ARG,
|
2008-10-08 16:28:48 +00:00
|
|
|
_("Invalid parameter `%s'"), param->field);
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
2008-10-08 16:28:48 +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:
|
2009-09-02 13:02:06 +00:00
|
|
|
lxcDriverUnlock(driver);
|
2008-10-08 16:28:48 +00:00
|
|
|
virCgroupFree(&group);
|
2008-12-04 21:12:41 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
2008-12-04 21:11:41 +00:00
|
|
|
return ret;
|
2008-10-08 16:28:48 +00:00
|
|
|
}
|
|
|
|
|
2008-12-04 21:11:41 +00:00
|
|
|
static int lxcGetSchedulerParameters(virDomainPtr domain,
|
2008-10-08 16:28:48 +00:00
|
|
|
virSchedParameterPtr params,
|
|
|
|
int *nparams)
|
|
|
|
{
|
2008-12-04 21:12:41 +00:00
|
|
|
lxc_driver_t *driver = domain->conn->privateData;
|
2008-12-04 21:11:41 +00:00
|
|
|
virCgroupPtr group = NULL;
|
|
|
|
virDomainObjPtr vm = NULL;
|
2009-07-09 13:11:21 +00:00
|
|
|
unsigned long long val;
|
2008-12-04 21:11:41 +00:00
|
|
|
int ret = -1;
|
2008-10-08 16:28:48 +00:00
|
|
|
|
2009-07-10 10:40:04 +00:00
|
|
|
if (driver->cgroup == NULL)
|
2008-12-04 21:12:41 +00:00
|
|
|
return -1;
|
2008-10-08 16:28:48 +00:00
|
|
|
|
|
|
|
if ((*nparams) != 1) {
|
2008-12-04 21:11:41 +00:00
|
|
|
lxcError(NULL, domain, VIR_ERR_INVALID_ARG,
|
avoid many format string warnings
Building with --disable-nls exposed many new warnings like these:
virsh.c:4952: warning: format not a string literal and no format ...
util.c:163: warning: format not a string literal and no format arguments
All but one of the following changes add a "%s" argument before
the offending _(...) argument.
This was the only manual change:
* src/lxc_driver.c (lxcVersion): Use %s and strerror(errno)
rather than %m, to avoid a warning from gcc -Wformat-security.
Add "%s" before each warned about format-string-with-no-%-directive:
* src/domain_conf.c (virDomainHostdevSubsysUsbDefParseXML)
(virDomainDefParseString, virDomainDefParseFile):
* src/hash.c (virGetConnect, __virGetDomain, virReleaseDomain)
(__virGetNetwork, virReleaseNetwork, __virGetStoragePool)
(virReleaseStoragePool, __virGetStorageVol, virReleaseStorageVol):
* src/lxc_container.c (lxcContainerChild):
* src/lxc_driver.c (lxcDomainDefine, lxcDomainUndefine)
(lxcDomainGetInfo, lxcGetOSType, lxcDomainDumpXML)
(lxcSetupInterfaces, lxcDomainStart, lxcDomainCreateAndStart)
(lxcVersion, lxcGetSchedulerParameters):
* src/network_conf.c (virNetworkDefParseString)
(virNetworkDefParseFile):
* src/openvz_conf.c (openvzReadNetworkConf, openvzLoadDomains):
* src/openvz_driver.c (openvzDomainDefineCmd)
(openvzDomainGetInfo, openvzDomainDumpXML, openvzDomainShutdown)
(openvzDomainReboot, ADD_ARG_LIT, openvzDomainDefineXML)
(openvzDomainCreateXML, openvzDomainCreate, openvzDomainUndefine)
(openvzDomainSetAutostart, openvzDomainGetAutostart)
(openvzDomainSetVcpus):
* src/qemu_driver.c (qemudDomainBlockPeek, qemudDomainMemoryPeek):
* src/remote_internal.c (remoteDomainBlockPeek)
(remoteDomainMemoryPeek, remoteAuthPolkit):
* src/sexpr.c (sexpr_new, _string2sexpr):
* src/storage_backend_disk.c (virStorageBackendDiskMakeDataVol)
(virStorageBackendDiskCreateVol):
* src/storage_backend_fs.c
(virStorageBackendFileSystemNetFindPoolSources):
* src/storage_backend_logical.c (virStorageBackendLogicalFindLVs)
(virStorageBackendLogicalFindPoolSources):
* src/test.c (testOpenDefault, testOpenFromFile, testOpen)
(testGetDomainInfo, testDomainRestore)
(testNodeGetCellsFreeMemory):
* src/util.c (virExec):
* src/virsh.c (cmdAttachDevice, cmdDetachDevice)
(cmdAttachInterface, cmdDetachInterface, cmdAttachDisk)
(cmdDetachDisk, cmdEdit):
* src/xend_internal.c (do_connect, wr_sync, xend_op_ext)
(urlencode, xenDaemonDomainCreateXML)
(xenDaemonDomainLookupByName_ids, xenDaemonDomainLookupByID)
(xenDaemonParseSxprOS, xend_parse_sexp_desc_char)
(xenDaemonParseSxprChar, xenDaemonParseSxprDisks)
(xenDaemonParseSxpr, sexpr_to_xend_topology, sexpr_to_domain)
(xenDaemonDomainFetch, xenDaemonDomainGetAutostart)
(xenDaemonDomainSetAutostart, xenDaemonDomainMigratePerform)
(xenDaemonDomainDefineXML, xenDaemonGetSchedulerType)
(xenDaemonGetSchedulerParameters)
(xenDaemonSetSchedulerParameters, xenDaemonDomainBlockPeek)
(xenDaemonFormatSxprChr, virDomainXMLDevID):
* src/xm_internal.c (xenXMConfigCacheRefresh, xenXMDomainPinVcpu)
(xenXMDomainCreate, xenXMDomainDefineXML)
(xenXMDomainAttachDevice, xenXMDomainDetachDevice):
* src/xml.c (virXPathString, virXPathNumber, virXPathLong)
(virXPathULong, virXPathBoolean, virXPathNode, virXPathNodeSet):
* src/xs_internal.c (xenStoreOpen):
2008-10-13 16:46:28 +00:00
|
|
|
"%s", _("Invalid parameter count"));
|
2008-12-04 21:12:41 +00:00
|
|
|
return -1;
|
2008-10-08 16:28:48 +00:00
|
|
|
}
|
|
|
|
|
2008-12-04 21:12:41 +00:00
|
|
|
lxcDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, domain->uuid);
|
|
|
|
|
2008-12-04 21:11:41 +00:00
|
|
|
if (vm == NULL) {
|
|
|
|
lxcError(NULL, domain, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("No such domain %s"), domain->uuid);
|
|
|
|
goto cleanup;
|
2008-10-08 16:28:48 +00:00
|
|
|
}
|
|
|
|
|
2009-07-10 10:40:04 +00:00
|
|
|
if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0)
|
2008-12-04 21:11:41 +00:00
|
|
|
goto cleanup;
|
2008-10-08 16:28:48 +00:00
|
|
|
|
2008-12-04 21:11:41 +00:00
|
|
|
if (virCgroupGetCpuShares(group, &val) != 0)
|
|
|
|
goto cleanup;
|
2008-10-24 11:20:08 +00:00
|
|
|
params[0].value.ul = val;
|
2009-08-03 12:37:44 +00:00
|
|
|
if (virStrcpyStatic(params[0].field, "cpu_shares") == NULL) {
|
|
|
|
lxcError(NULL, domain, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("Field cpu_shares too big for destination"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2008-10-08 16:28:48 +00:00
|
|
|
params[0].type = VIR_DOMAIN_SCHED_FIELD_ULLONG;
|
|
|
|
|
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:
|
2009-09-02 13:02:06 +00:00
|
|
|
lxcDriverUnlock(driver);
|
2008-12-04 21:11:41 +00:00
|
|
|
virCgroupFree(&group);
|
2008-12-04 21:12:41 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
2008-12-04 21:11:41 +00:00
|
|
|
return ret;
|
2008-10-08 16:28:48 +00:00
|
|
|
}
|
|
|
|
|
2009-07-06 15:05:32 +00:00
|
|
|
static int lxcDomainGetAutostart(virDomainPtr dom,
|
|
|
|
int *autostart) {
|
|
|
|
lxc_driver_t *driver = dom->conn->privateData;
|
|
|
|
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);
|
|
|
|
lxcError(dom->conn, dom, VIR_ERR_NO_DOMAIN,
|
|
|
|
_("no domain with matching uuid '%s'"), uuidstr);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
*autostart = vm->autostart;
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int lxcDomainSetAutostart(virDomainPtr dom,
|
|
|
|
int autostart) {
|
|
|
|
lxc_driver_t *driver = dom->conn->privateData;
|
|
|
|
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);
|
|
|
|
lxcError(dom->conn, dom, VIR_ERR_NO_DOMAIN,
|
|
|
|
_("no domain with matching uuid '%s'"), uuidstr);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!vm->persistent) {
|
|
|
|
lxcError(dom->conn, dom, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("cannot set autostart for transient domain"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
autostart = (autostart != 0);
|
|
|
|
|
|
|
|
if (vm->autostart != autostart) {
|
|
|
|
if ((configFile = virDomainConfigFile(dom->conn, driver->configDir, vm->def->name)) == NULL)
|
|
|
|
goto cleanup;
|
|
|
|
if ((autostartLink = virDomainConfigFile(dom->conn, driver->autostartDir, vm->def->name)) == NULL)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (autostart) {
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if ((err = virFileMakePath(driver->autostartDir))) {
|
|
|
|
virReportSystemError(dom->conn, err,
|
|
|
|
_("cannot create autostart directory %s"),
|
|
|
|
driver->autostartDir);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (symlink(configFile, autostartLink) < 0) {
|
|
|
|
virReportSystemError(dom->conn, errno,
|
|
|
|
_("Failed to create symlink '%s to '%s'"),
|
|
|
|
autostartLink, configFile);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
|
|
|
|
virReportSystemError(dom->conn, errno,
|
|
|
|
_("Failed to delete symlink '%s'"),
|
|
|
|
autostartLink);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
vm->autostart = autostart;
|
|
|
|
}
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(configFile);
|
|
|
|
VIR_FREE(autostartLink);
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2009-04-15 09:34:56 +00:00
|
|
|
static char *lxcGetHostname (virConnectPtr conn)
|
|
|
|
{
|
|
|
|
char *result;
|
|
|
|
|
|
|
|
result = virGetHostname();
|
|
|
|
if (result == NULL) {
|
|
|
|
virReportSystemError (conn, errno,
|
|
|
|
"%s", _("failed to determine host name"));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
/* Caller frees this string. */
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2009-09-21 14:31:22 +00:00
|
|
|
static int lxcFreezeContainer(lxc_driver_t *driver, virDomainObjPtr vm)
|
|
|
|
{
|
|
|
|
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 &&
|
|
|
|
virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) == 0))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
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)
|
|
|
|
VIR_DEBUG0("Writing freezer.state gets EBUSY");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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);
|
|
|
|
}
|
|
|
|
VIR_DEBUG0("lxcFreezeContainer timeout");
|
|
|
|
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:
|
|
|
|
if (cgroup)
|
|
|
|
virCgroupFree(&cgroup);
|
|
|
|
VIR_FREE(state);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int lxcDomainSuspend(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
lxc_driver_t *driver = dom->conn->privateData;
|
|
|
|
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);
|
|
|
|
lxcError(dom->conn, dom, VIR_ERR_NO_DOMAIN,
|
|
|
|
_("no domain with matching uuid '%s'"), uuidstr);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!virDomainIsActive(vm)) {
|
|
|
|
lxcError(dom->conn, dom, VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("domain is not running"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vm->state != VIR_DOMAIN_PAUSED) {
|
|
|
|
if (lxcFreezeContainer(driver, vm) < 0) {
|
|
|
|
lxcError(dom->conn, dom, VIR_ERR_OPERATION_FAILED,
|
|
|
|
"%s", _("suspend operation failed"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
vm->state = VIR_DOMAIN_PAUSED;
|
|
|
|
|
|
|
|
event = virDomainEventNewFromObj(vm,
|
|
|
|
VIR_DOMAIN_EVENT_SUSPENDED,
|
|
|
|
VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virDomainSaveStatus(dom->conn, driver->stateDir, vm) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (event)
|
|
|
|
lxcDomainEventQueue(driver, event);
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int lxcUnfreezeContainer(lxc_driver_t *driver, virDomainObjPtr vm)
|
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
lxc_driver_t *driver = dom->conn->privateData;
|
|
|
|
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);
|
|
|
|
lxcError(dom->conn, dom, VIR_ERR_NO_DOMAIN,
|
|
|
|
_("no domain with matching uuid '%s'"), uuidstr);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!virDomainIsActive(vm)) {
|
|
|
|
lxcError(dom->conn, dom, VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("domain is not running"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vm->state == VIR_DOMAIN_PAUSED) {
|
|
|
|
if (lxcUnfreezeContainer(driver, vm) < 0) {
|
|
|
|
lxcError(dom->conn, dom, VIR_ERR_OPERATION_FAILED,
|
|
|
|
"%s", _("resume operation failed"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
vm->state = VIR_DOMAIN_RUNNING;
|
|
|
|
|
|
|
|
event = virDomainEventNewFromObj(vm,
|
|
|
|
VIR_DOMAIN_EVENT_RESUMED,
|
|
|
|
VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virDomainSaveStatus(dom->conn, driver->stateDir, vm) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (event)
|
|
|
|
lxcDomainEventQueue(driver, event);
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
lxcDriverUnlock(driver);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-03-21 15:03:37 +00:00
|
|
|
/* Function Tables */
|
|
|
|
static virDriver lxcDriver = {
|
|
|
|
VIR_DRV_LXC, /* the number virDrvNo */
|
|
|
|
"LXC", /* the name of the driver */
|
|
|
|
lxcOpen, /* open */
|
|
|
|
lxcClose, /* close */
|
|
|
|
NULL, /* supports_feature */
|
|
|
|
NULL, /* type */
|
2008-09-03 17:21:27 +00:00
|
|
|
lxcVersion, /* version */
|
2009-04-15 09:34:56 +00:00
|
|
|
lxcGetHostname, /* getHostname */
|
2008-03-21 15:03:37 +00:00
|
|
|
NULL, /* getMaxVcpus */
|
2009-06-03 13:29:23 +00:00
|
|
|
nodeGetInfo, /* nodeGetInfo */
|
|
|
|
lxcGetCapabilities, /* getCapabilities */
|
2008-03-21 15:03:37 +00:00
|
|
|
lxcListDomains, /* listDomains */
|
|
|
|
lxcNumDomains, /* numOfDomains */
|
2008-10-10 09:32:27 +00:00
|
|
|
lxcDomainCreateAndStart, /* domainCreateXML */
|
2008-03-21 15:03:37 +00:00
|
|
|
lxcDomainLookupByID, /* domainLookupByID */
|
|
|
|
lxcDomainLookupByUUID, /* domainLookupByUUID */
|
|
|
|
lxcDomainLookupByName, /* domainLookupByName */
|
2009-09-21 14:31:22 +00:00
|
|
|
lxcDomainSuspend, /* domainSuspend */
|
|
|
|
lxcDomainResume, /* domainResume */
|
2008-04-10 07:30:52 +00:00
|
|
|
lxcDomainShutdown, /* domainShutdown */
|
2008-03-21 15:03:37 +00:00
|
|
|
NULL, /* domainReboot */
|
2008-04-10 07:30:52 +00:00
|
|
|
lxcDomainDestroy, /* domainDestroy */
|
2008-03-21 15:03:37 +00:00
|
|
|
lxcGetOSType, /* domainGetOSType */
|
2009-10-07 13:26:23 +00:00
|
|
|
lxcDomainGetMaxMemory, /* domainGetMaxMemory */
|
|
|
|
lxcDomainSetMaxMemory, /* domainSetMaxMemory */
|
|
|
|
lxcDomainSetMemory, /* domainSetMemory */
|
2008-03-21 15:03:37 +00:00
|
|
|
lxcDomainGetInfo, /* domainGetInfo */
|
|
|
|
NULL, /* domainSave */
|
|
|
|
NULL, /* domainRestore */
|
|
|
|
NULL, /* domainCoreDump */
|
|
|
|
NULL, /* domainSetVcpus */
|
|
|
|
NULL, /* domainPinVcpu */
|
|
|
|
NULL, /* domainGetVcpus */
|
|
|
|
NULL, /* domainGetMaxVcpus */
|
2009-03-03 09:14:28 +00:00
|
|
|
NULL, /* domainGetSecurityLabel */
|
|
|
|
NULL, /* nodeGetSecurityModel */
|
2008-03-21 15:03:37 +00:00
|
|
|
lxcDomainDumpXML, /* domainDumpXML */
|
2009-09-06 14:03:06 +00:00
|
|
|
NULL, /* domainXMLFromNative */
|
|
|
|
NULL, /* domainXMLToNative */
|
2008-03-21 15:03:37 +00:00
|
|
|
lxcListDefinedDomains, /* listDefinedDomains */
|
|
|
|
lxcNumDefinedDomains, /* numOfDefinedDomains */
|
2008-04-10 07:30:52 +00:00
|
|
|
lxcDomainStart, /* domainCreate */
|
2008-03-21 15:03:37 +00:00
|
|
|
lxcDomainDefine, /* domainDefineXML */
|
|
|
|
lxcDomainUndefine, /* domainUndefine */
|
|
|
|
NULL, /* domainAttachDevice */
|
|
|
|
NULL, /* domainDetachDevice */
|
2009-07-06 15:05:32 +00:00
|
|
|
lxcDomainGetAutostart, /* domainGetAutostart */
|
|
|
|
lxcDomainSetAutostart, /* domainSetAutostart */
|
2008-10-08 16:28:48 +00:00
|
|
|
lxcGetSchedulerType, /* domainGetSchedulerType */
|
|
|
|
lxcGetSchedulerParameters, /* domainGetSchedulerParameters */
|
|
|
|
lxcSetSchedulerParameters, /* domainSetSchedulerParameters */
|
2008-03-21 15:03:37 +00:00
|
|
|
NULL, /* domainMigratePrepare */
|
|
|
|
NULL, /* domainMigratePerform */
|
|
|
|
NULL, /* domainMigrateFinish */
|
|
|
|
NULL, /* domainBlockStats */
|
|
|
|
NULL, /* domainInterfaceStats */
|
2008-06-12 13:48:29 +00:00
|
|
|
NULL, /* domainBlockPeek */
|
|
|
|
NULL, /* domainMemoryPeek */
|
2009-06-03 13:29:23 +00:00
|
|
|
nodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */
|
|
|
|
nodeGetFreeMemory, /* getFreeMemory */
|
2009-07-06 15:04:36 +00:00
|
|
|
lxcDomainEventRegister, /* domainEventRegister */
|
|
|
|
lxcDomainEventDeregister, /* domainEventDeregister */
|
2008-11-14 08:42:47 +00:00
|
|
|
NULL, /* domainMigratePrepare2 */
|
|
|
|
NULL, /* domainMigrateFinish2 */
|
2009-03-31 15:47:16 +00:00
|
|
|
NULL, /* nodeDeviceDettach */
|
2009-03-02 16:25:13 +00:00
|
|
|
NULL, /* nodeDeviceReAttach */
|
|
|
|
NULL, /* nodeDeviceReset */
|
2009-09-30 10:51:54 +00:00
|
|
|
NULL, /* domainMigratePrepareTunnel */
|
2008-03-21 15:03:37 +00:00
|
|
|
};
|
|
|
|
|
2008-03-27 09:34:06 +00:00
|
|
|
static virStateDriver lxcStateDriver = {
|
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;
|
|
|
|
}
|