2008-11-19 16:58:23 +00:00
|
|
|
/*
|
|
|
|
* uml_driver.c: core driver methods for managing UML guests
|
|
|
|
*
|
2010-02-15 18:22:38 +00:00
|
|
|
* Copyright (C) 2006-2010 Red Hat, Inc.
|
2008-11-19 16:58:23 +00:00
|
|
|
* Copyright (C) 2006-2008 Daniel P. Berrange
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*
|
|
|
|
* Author: Daniel P. Berrange <berrange@redhat.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/poll.h>
|
|
|
|
#include <dirent.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <strings.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <sys/utsname.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <paths.h>
|
|
|
|
#include <pwd.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <sys/wait.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <sys/inotify.h>
|
Move xen driver code into src/xen/ directory
* src/Makefile.am, src/proxy_internal.c, src/proxy_internal.h
src/sexpr.c, src/sexpr.h, src/xen_unified.c, src/xen_unified.h,
src/xen_internal.c, src/xen_internal.h, src/xen_inotify.c,
src/xen_inotify.h, src/xend_internal.c, src/xend_internal.h,
src/xm_internal.c, src/xm_internal.h, src/xs_internal.c,
src/xs_internal.h: Move to src/xen/ directory
* proxy/Makefile.am, proxy/libvirt_proxy.c, src/Makefile.am,
src/libvirt.c, tests/sexpr2xmltest.c, tests/statstest.c,
tests/xencapstest.c, tests/xmconfigtest.c, tests/xml2sexprtest.c:
Adapt to changed xen location
* src/stats_linux.h, src/stats_linux.c: Remove xen specific block
stats APIs
* src/qemu_driver.c, src/uml_driver.c: Add missing sys/un.h include
uncovered after change to stats_linux.h
* src/xen/block_stats.h, src/xen/block_stats.c: Add xen specific
block stats APIs
2009-09-15 15:38:33 +00:00
|
|
|
#include <sys/un.h>
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
#include "uml_driver.h"
|
|
|
|
#include "uml_conf.h"
|
|
|
|
#include "event.h"
|
|
|
|
#include "buf.h"
|
|
|
|
#include "util.h"
|
|
|
|
#include "nodeinfo.h"
|
|
|
|
#include "stats_linux.h"
|
|
|
|
#include "capabilities.h"
|
|
|
|
#include "memory.h"
|
|
|
|
#include "uuid.h"
|
|
|
|
#include "domain_conf.h"
|
|
|
|
#include "datatypes.h"
|
2008-12-22 10:48:59 +00:00
|
|
|
#include "logging.h"
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2009-01-20 17:13:33 +00:00
|
|
|
#define VIR_FROM_THIS VIR_FROM_UML
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
/* For storing short-lived temporary files. */
|
|
|
|
#define TEMPDIR LOCAL_STATE_DIR "/cache/libvirt"
|
|
|
|
|
2009-11-26 17:55:12 +00:00
|
|
|
typedef struct _umlDomainObjPrivate umlDomainObjPrivate;
|
|
|
|
typedef umlDomainObjPrivate *umlDomainObjPrivatePtr;
|
|
|
|
struct _umlDomainObjPrivate {
|
|
|
|
int monitor;
|
|
|
|
int monitorWatch;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
static int umlShutdown(void);
|
|
|
|
|
2009-11-26 17:55:12 +00:00
|
|
|
static void *umlDomainObjPrivateAlloc(void)
|
|
|
|
{
|
|
|
|
umlDomainObjPrivatePtr priv;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(priv) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
priv->monitor = -1;
|
|
|
|
priv->monitorWatch = -1;
|
|
|
|
|
|
|
|
return priv;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void umlDomainObjPrivateFree(void *data)
|
|
|
|
{
|
|
|
|
umlDomainObjPrivatePtr priv = data;
|
|
|
|
|
|
|
|
VIR_FREE(priv);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
static void umlDriverLock(struct uml_driver *driver)
|
|
|
|
{
|
2009-01-15 19:56:05 +00:00
|
|
|
virMutexLock(&driver->lock);
|
2008-12-04 21:14:39 +00:00
|
|
|
}
|
|
|
|
static void umlDriverUnlock(struct uml_driver *driver)
|
|
|
|
{
|
2009-01-15 19:56:05 +00:00
|
|
|
virMutexUnlock(&driver->lock);
|
2008-12-04 21:14:39 +00:00
|
|
|
}
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
static int umlOpenMonitor(virConnectPtr conn,
|
|
|
|
struct uml_driver *driver,
|
|
|
|
virDomainObjPtr vm);
|
2010-02-04 20:02:58 +00:00
|
|
|
static int umlReadPidFile(struct uml_driver *driver,
|
2008-11-19 16:58:23 +00:00
|
|
|
virDomainObjPtr vm);
|
|
|
|
|
|
|
|
static int umlSetCloseExec(int fd) {
|
|
|
|
int flags;
|
|
|
|
if ((flags = fcntl(fd, F_GETFD)) < 0)
|
|
|
|
goto error;
|
|
|
|
flags |= FD_CLOEXEC;
|
|
|
|
if ((fcntl(fd, F_SETFD, flags)) < 0)
|
|
|
|
goto error;
|
|
|
|
return 0;
|
|
|
|
error:
|
2009-06-25 15:02:10 +00:00
|
|
|
VIR_ERROR0(_("Failed to set close-on-exec file descriptor flag"));
|
2008-11-19 16:58:23 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int umlStartVMDaemon(virConnectPtr conn,
|
|
|
|
struct uml_driver *driver,
|
|
|
|
virDomainObjPtr vm);
|
|
|
|
|
|
|
|
static void umlShutdownVMDaemon(virConnectPtr conn,
|
|
|
|
struct uml_driver *driver,
|
|
|
|
virDomainObjPtr vm);
|
|
|
|
|
|
|
|
|
|
|
|
static int umlMonitorCommand (virConnectPtr conn,
|
|
|
|
const struct uml_driver *driver,
|
|
|
|
const virDomainObjPtr vm,
|
|
|
|
const char *cmd,
|
|
|
|
char **reply);
|
|
|
|
|
|
|
|
static struct uml_driver *uml_driver = NULL;
|
|
|
|
|
Convert virDomainObjListPtr to use a hash of domain objects
The current virDomainObjListPtr object stores domain objects in
an array. This means that to find a particular objects requires
O(n) time, and more critically acquiring O(n) mutex locks.
The new impl replaces the array with a virHashTable, keyed off
UUID. Finding a object based on UUID is now O(1) time, and only
requires a single mutex lock. Finding by name/id is unchanged
in complexity.
In changing this, all code which iterates over the array had
to be updated to use a hash table iterator function callback.
Several of the functions which were identically duplicating
across all drivers were pulled into domain_conf.c
* src/conf/domain_conf.h, src/conf/domain_conf.c: Change
virDomainObjListPtr to use virHashTable. Add a initializer
method virDomainObjListInit, and rename virDomainObjListFree
to virDomainObjListDeinit, since its not actually freeing
the container, only its contents. Also add some convenient
methods virDomainObjListGetInactiveNames,
virDomainObjListGetActiveIDs and virDomainObjListNumOfDomains
which can be used to implement the correspondingly named
public API entry points in drivers
* src/libvirt_private.syms: Export new methods from domain_conf.h
* src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_conf.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c: Update all code
to deal with hash tables instead of arrays for domains
2009-10-09 11:33:51 +00:00
|
|
|
struct umlAutostartData {
|
|
|
|
struct uml_driver *driver;
|
|
|
|
virConnectPtr conn;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
umlAutostartDomain(void *payload, const char *name ATTRIBUTE_UNUSED, void *opaque)
|
|
|
|
{
|
|
|
|
virDomainObjPtr vm = payload;
|
|
|
|
const struct umlAutostartData *data = opaque;
|
|
|
|
|
|
|
|
virDomainObjLock(vm);
|
|
|
|
if (vm->autostart &&
|
Rename internal APis
Rename virDomainIsActive to virDomainObjIsActive, and
virInterfaceIsActive to virInterfaceObjIsActive and finally
virNetworkIsActive to virNetworkObjIsActive.
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/conf/interface_conf.h, src/conf/network_conf.c,
src/conf/network_conf.h, src/lxc/lxc_driver.c,
src/network/bridge_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_driver.c, src/qemu/qemu_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c: Update for
renamed APIs.
2009-10-20 14:51:03 +00:00
|
|
|
!virDomainObjIsActive(vm)) {
|
Convert virDomainObjListPtr to use a hash of domain objects
The current virDomainObjListPtr object stores domain objects in
an array. This means that to find a particular objects requires
O(n) time, and more critically acquiring O(n) mutex locks.
The new impl replaces the array with a virHashTable, keyed off
UUID. Finding a object based on UUID is now O(1) time, and only
requires a single mutex lock. Finding by name/id is unchanged
in complexity.
In changing this, all code which iterates over the array had
to be updated to use a hash table iterator function callback.
Several of the functions which were identically duplicating
across all drivers were pulled into domain_conf.c
* src/conf/domain_conf.h, src/conf/domain_conf.c: Change
virDomainObjListPtr to use virHashTable. Add a initializer
method virDomainObjListInit, and rename virDomainObjListFree
to virDomainObjListDeinit, since its not actually freeing
the container, only its contents. Also add some convenient
methods virDomainObjListGetInactiveNames,
virDomainObjListGetActiveIDs and virDomainObjListNumOfDomains
which can be used to implement the correspondingly named
public API entry points in drivers
* src/libvirt_private.syms: Export new methods from domain_conf.h
* src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_conf.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c: Update all code
to deal with hash tables instead of arrays for domains
2009-10-09 11:33:51 +00:00
|
|
|
virResetLastError();
|
|
|
|
if (umlStartVMDaemon(data->conn, data->driver, vm) < 0) {
|
|
|
|
virErrorPtr err = virGetLastError();
|
|
|
|
VIR_ERROR(_("Failed to autostart VM '%s': %s"),
|
|
|
|
vm->def->name, err->message);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
}
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
umlAutostartConfigs(struct uml_driver *driver) {
|
2008-12-08 11:18:47 +00:00
|
|
|
/* XXX: Figure out a better way todo this. The domain
|
|
|
|
* startup code needs a connection handle in order
|
|
|
|
* to lookup the bridge associated with a virtual
|
|
|
|
* network
|
|
|
|
*/
|
2009-06-12 13:20:13 +00:00
|
|
|
virConnectPtr conn = virConnectOpen(driver->privileged ?
|
|
|
|
"uml:///system" :
|
|
|
|
"uml:///session");
|
2008-12-08 11:18:47 +00:00
|
|
|
/* Ignoring NULL conn which is mostly harmless here */
|
2008-11-19 16:58:23 +00:00
|
|
|
|
Convert virDomainObjListPtr to use a hash of domain objects
The current virDomainObjListPtr object stores domain objects in
an array. This means that to find a particular objects requires
O(n) time, and more critically acquiring O(n) mutex locks.
The new impl replaces the array with a virHashTable, keyed off
UUID. Finding a object based on UUID is now O(1) time, and only
requires a single mutex lock. Finding by name/id is unchanged
in complexity.
In changing this, all code which iterates over the array had
to be updated to use a hash table iterator function callback.
Several of the functions which were identically duplicating
across all drivers were pulled into domain_conf.c
* src/conf/domain_conf.h, src/conf/domain_conf.c: Change
virDomainObjListPtr to use virHashTable. Add a initializer
method virDomainObjListInit, and rename virDomainObjListFree
to virDomainObjListDeinit, since its not actually freeing
the container, only its contents. Also add some convenient
methods virDomainObjListGetInactiveNames,
virDomainObjListGetActiveIDs and virDomainObjListNumOfDomains
which can be used to implement the correspondingly named
public API entry points in drivers
* src/libvirt_private.syms: Export new methods from domain_conf.h
* src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_conf.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c: Update all code
to deal with hash tables instead of arrays for domains
2009-10-09 11:33:51 +00:00
|
|
|
struct umlAutostartData data = { driver, conn };
|
|
|
|
|
|
|
|
virHashForEach(driver->domains.objs, umlAutostartDomain, &data);
|
2008-12-08 11:18:47 +00:00
|
|
|
|
2009-03-16 10:30:04 +00:00
|
|
|
if (conn)
|
|
|
|
virConnectClose(conn);
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2010-02-04 18:19:08 +00:00
|
|
|
umlIdentifyOneChrPTY(struct uml_driver *driver,
|
2008-11-19 16:58:23 +00:00
|
|
|
virDomainObjPtr dom,
|
|
|
|
virDomainChrDefPtr def,
|
|
|
|
const char *dev)
|
|
|
|
{
|
|
|
|
char *cmd;
|
|
|
|
char *res = NULL;
|
|
|
|
int retries = 0;
|
2009-11-05 13:19:14 +00:00
|
|
|
if (virAsprintf(&cmd, "config %s%d", dev, def->target.port) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-11-19 16:58:23 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
requery:
|
2009-06-03 10:55:33 +00:00
|
|
|
if (umlMonitorCommand(NULL, driver, dom, cmd, &res) < 0)
|
|
|
|
return -1;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2009-06-03 10:55:33 +00:00
|
|
|
if (res && STRPREFIX(res, "pts:")) {
|
2008-11-19 16:58:23 +00:00
|
|
|
VIR_FREE(def->data.file.path);
|
|
|
|
if ((def->data.file.path = strdup(res + 4)) == NULL) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-11-19 16:58:23 +00:00
|
|
|
VIR_FREE(res);
|
|
|
|
VIR_FREE(cmd);
|
|
|
|
return -1;
|
|
|
|
}
|
2009-06-03 10:55:33 +00:00
|
|
|
} else if (!res || STRPREFIX(res, "pts")) {
|
2008-11-19 16:58:23 +00:00
|
|
|
/* It can take a while to startup, so retry for
|
|
|
|
upto 5 seconds */
|
|
|
|
/* XXX should do this in a better non-blocking
|
|
|
|
way somehow ...perhaps register a timer */
|
|
|
|
if (retries++ < 50) {
|
|
|
|
usleep(1000*10);
|
|
|
|
goto requery;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_FREE(cmd);
|
|
|
|
VIR_FREE(res);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2010-02-04 18:19:08 +00:00
|
|
|
umlIdentifyChrPTY(struct uml_driver *driver,
|
2008-11-19 16:58:23 +00:00
|
|
|
virDomainObjPtr dom)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (dom->def->console &&
|
|
|
|
dom->def->console->type == VIR_DOMAIN_CHR_TYPE_PTY)
|
2010-02-04 18:19:08 +00:00
|
|
|
if (umlIdentifyOneChrPTY(driver, dom,
|
2008-11-19 16:58:23 +00:00
|
|
|
dom->def->console, "con") < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
for (i = 0 ; i < dom->def->nserials; i++)
|
|
|
|
if (dom->def->serials[i]->type == VIR_DOMAIN_CHR_TYPE_PTY &&
|
2010-02-04 18:19:08 +00:00
|
|
|
umlIdentifyOneChrPTY(driver, dom,
|
2008-11-19 16:58:23 +00:00
|
|
|
dom->def->serials[i], "ssl") < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
umlInotifyEvent(int watch,
|
|
|
|
int fd,
|
|
|
|
int events ATTRIBUTE_UNUSED,
|
|
|
|
void *data)
|
|
|
|
{
|
|
|
|
char buf[1024];
|
|
|
|
struct inotify_event *e;
|
|
|
|
int got;
|
|
|
|
char *tmp, *name;
|
|
|
|
struct uml_driver *driver = data;
|
|
|
|
virDomainObjPtr dom;
|
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2008-11-19 16:58:23 +00:00
|
|
|
if (watch != driver->inotifyWatch)
|
2008-12-04 21:14:39 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
reread:
|
|
|
|
got = read(fd, buf, sizeof(buf));
|
|
|
|
if (got == -1) {
|
|
|
|
if (errno == EINTR)
|
|
|
|
goto reread;
|
2008-12-04 21:14:39 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
tmp = buf;
|
|
|
|
while (got) {
|
|
|
|
if (got < sizeof(struct inotify_event))
|
2008-12-04 21:14:39 +00:00
|
|
|
goto cleanup; /* bad */
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
e = (struct inotify_event *)tmp;
|
|
|
|
tmp += sizeof(struct inotify_event);
|
|
|
|
got -= sizeof(struct inotify_event);
|
|
|
|
|
|
|
|
if (got < e->len)
|
2008-12-04 21:14:39 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
tmp += e->len;
|
|
|
|
got -= e->len;
|
|
|
|
|
|
|
|
name = (char *)&(e->name);
|
|
|
|
|
|
|
|
dom = virDomainFindByName(&driver->domains, name);
|
|
|
|
|
|
|
|
if (!dom) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (e->mask & IN_DELETE) {
|
2009-06-03 10:55:33 +00:00
|
|
|
VIR_DEBUG("Got inotify domain shutdown '%s'", name);
|
Rename internal APis
Rename virDomainIsActive to virDomainObjIsActive, and
virInterfaceIsActive to virInterfaceObjIsActive and finally
virNetworkIsActive to virNetworkObjIsActive.
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/conf/interface_conf.h, src/conf/network_conf.c,
src/conf/network_conf.h, src/lxc/lxc_driver.c,
src/network/bridge_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_driver.c, src/qemu/qemu_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c: Update for
renamed APIs.
2009-10-20 14:51:03 +00:00
|
|
|
if (!virDomainObjIsActive(dom)) {
|
2008-12-04 21:14:39 +00:00
|
|
|
virDomainObjUnlock(dom);
|
2008-11-19 16:58:23 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2009-06-03 10:55:33 +00:00
|
|
|
umlShutdownVMDaemon(NULL, driver, dom);
|
2008-11-19 16:58:23 +00:00
|
|
|
} else if (e->mask & (IN_CREATE | IN_MODIFY)) {
|
2009-06-03 10:55:33 +00:00
|
|
|
VIR_DEBUG("Got inotify domain startup '%s'", name);
|
Rename internal APis
Rename virDomainIsActive to virDomainObjIsActive, and
virInterfaceIsActive to virInterfaceObjIsActive and finally
virNetworkIsActive to virNetworkObjIsActive.
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/conf/interface_conf.h, src/conf/network_conf.c,
src/conf/network_conf.h, src/lxc/lxc_driver.c,
src/network/bridge_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_driver.c, src/qemu/qemu_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c: Update for
renamed APIs.
2009-10-20 14:51:03 +00:00
|
|
|
if (virDomainObjIsActive(dom)) {
|
2008-12-04 21:14:39 +00:00
|
|
|
virDomainObjUnlock(dom);
|
2008-11-19 16:58:23 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2010-02-04 20:02:58 +00:00
|
|
|
if (umlReadPidFile(driver, dom) < 0) {
|
2008-12-04 21:14:39 +00:00
|
|
|
virDomainObjUnlock(dom);
|
2008-11-19 16:58:23 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
dom->def->id = driver->nextvmid++;
|
|
|
|
dom->state = VIR_DOMAIN_RUNNING;
|
|
|
|
|
2009-06-03 10:55:33 +00:00
|
|
|
if (umlOpenMonitor(NULL, driver, dom) < 0) {
|
|
|
|
VIR_WARN0("Could not open monitor for new domain");
|
2008-11-19 16:58:23 +00:00
|
|
|
umlShutdownVMDaemon(NULL, driver, dom);
|
2010-02-04 18:19:08 +00:00
|
|
|
} else if (umlIdentifyChrPTY(driver, dom) < 0) {
|
2009-06-03 10:55:33 +00:00
|
|
|
VIR_WARN0("Could not identify charater devices for new domain");
|
2008-11-19 16:58:23 +00:00
|
|
|
umlShutdownVMDaemon(NULL, driver, dom);
|
2009-06-03 10:55:33 +00:00
|
|
|
}
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
2008-12-04 21:14:39 +00:00
|
|
|
virDomainObjUnlock(dom);
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
2008-12-04 21:14:39 +00:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
umlDriverUnlock(driver);
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* umlStartup:
|
|
|
|
*
|
|
|
|
* Initialization function for the Uml daemon
|
|
|
|
*/
|
|
|
|
static int
|
2009-06-12 13:20:13 +00:00
|
|
|
umlStartup(int privileged) {
|
2008-11-19 16:58:23 +00:00
|
|
|
uid_t uid = geteuid();
|
|
|
|
char *base = NULL;
|
|
|
|
char driverConf[PATH_MAX];
|
2009-01-22 19:41:48 +00:00
|
|
|
char *userdir = NULL;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
if (VIR_ALLOC(uml_driver) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2009-06-12 13:20:13 +00:00
|
|
|
uml_driver->privileged = privileged;
|
|
|
|
|
2009-01-15 19:56:05 +00:00
|
|
|
if (virMutexInit(¨_driver->lock) < 0) {
|
|
|
|
VIR_FREE(uml_driver);
|
|
|
|
return -1;
|
|
|
|
}
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(uml_driver);
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
/* Don't have a dom0 so start from 1 */
|
|
|
|
uml_driver->nextvmid = 1;
|
2009-01-29 17:50:00 +00:00
|
|
|
uml_driver->inotifyWatch = -1;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
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(¨_driver->domains) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2010-02-04 22:41:52 +00:00
|
|
|
userdir = virGetUserDirectory(uid);
|
2009-01-22 19:41:48 +00:00
|
|
|
if (!userdir)
|
2008-12-04 21:14:39 +00:00
|
|
|
goto error;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2009-06-12 13:20:13 +00:00
|
|
|
if (privileged) {
|
2008-12-23 13:03:29 +00:00
|
|
|
if (virAsprintf(¨_driver->logDir,
|
|
|
|
"%s/log/libvirt/uml", LOCAL_STATE_DIR) == -1)
|
2008-11-19 16:58:23 +00:00
|
|
|
goto out_of_memory;
|
|
|
|
|
|
|
|
if ((base = strdup (SYSCONF_DIR "/libvirt")) == NULL)
|
|
|
|
goto out_of_memory;
|
|
|
|
} else {
|
2009-01-22 19:41:48 +00:00
|
|
|
|
2008-12-23 13:03:29 +00:00
|
|
|
if (virAsprintf(¨_driver->logDir,
|
2009-01-22 19:41:48 +00:00
|
|
|
"%s/.libvirt/uml/log", userdir) == -1)
|
2008-11-19 16:58:23 +00:00
|
|
|
goto out_of_memory;
|
|
|
|
|
2009-01-22 19:41:48 +00:00
|
|
|
if (virAsprintf(&base, "%s/.libvirt", userdir) == -1)
|
2008-11-19 16:58:23 +00:00
|
|
|
goto out_of_memory;
|
|
|
|
}
|
|
|
|
|
2008-12-23 13:03:29 +00:00
|
|
|
if (virAsprintf(¨_driver->monitorDir,
|
2009-01-22 19:41:48 +00:00
|
|
|
"%s/.uml", userdir) == -1)
|
2008-11-19 16:58:23 +00:00
|
|
|
goto out_of_memory;
|
|
|
|
|
|
|
|
/* Configuration paths are either ~/.libvirt/uml/... (session) or
|
|
|
|
* /etc/libvirt/uml/... (system).
|
|
|
|
*/
|
|
|
|
if (snprintf (driverConf, sizeof(driverConf), "%s/uml.conf", base) == -1)
|
|
|
|
goto out_of_memory;
|
|
|
|
driverConf[sizeof(driverConf)-1] = '\0';
|
|
|
|
|
2008-12-23 13:03:29 +00:00
|
|
|
if (virAsprintf(¨_driver->configDir, "%s/uml", base) == -1)
|
2008-11-19 16:58:23 +00:00
|
|
|
goto out_of_memory;
|
|
|
|
|
2008-12-23 13:03:29 +00:00
|
|
|
if (virAsprintf(¨_driver->autostartDir, "%s/uml/autostart", base) == -1)
|
2008-11-19 16:58:23 +00:00
|
|
|
goto out_of_memory;
|
|
|
|
|
|
|
|
VIR_FREE(base);
|
|
|
|
|
|
|
|
if ((uml_driver->caps = umlCapsInit()) == NULL)
|
|
|
|
goto out_of_memory;
|
|
|
|
|
2009-11-26 17:55:12 +00:00
|
|
|
uml_driver->caps->privateDataAllocFunc = umlDomainObjPrivateAlloc;
|
|
|
|
uml_driver->caps->privateDataFreeFunc = umlDomainObjPrivateFree;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
if ((uml_driver->inotifyFD = inotify_init()) < 0) {
|
2009-06-25 15:02:10 +00:00
|
|
|
VIR_ERROR0(_("cannot initialize inotify"));
|
2008-12-04 21:14:39 +00:00
|
|
|
goto error;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
2010-01-20 23:52:13 +00:00
|
|
|
if (virFileMakePath(uml_driver->monitorDir) != 0) {
|
2009-02-05 16:28:30 +00:00
|
|
|
char ebuf[1024];
|
2009-06-25 15:02:10 +00:00
|
|
|
VIR_ERROR(_("Failed to create monitor directory %s: %s"),
|
2009-02-05 16:28:30 +00:00
|
|
|
uml_driver->monitorDir, virStrerror(errno, ebuf, sizeof ebuf));
|
2008-12-04 21:14:39 +00:00
|
|
|
goto error;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
2009-06-03 10:55:33 +00:00
|
|
|
VIR_INFO("Adding inotify watch on %s", uml_driver->monitorDir);
|
2008-12-02 11:23:27 +00:00
|
|
|
if (inotify_add_watch(uml_driver->inotifyFD,
|
|
|
|
uml_driver->monitorDir,
|
|
|
|
IN_CREATE | IN_MODIFY | IN_DELETE) < 0) {
|
2008-12-04 21:14:39 +00:00
|
|
|
goto error;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
2008-12-02 11:23:27 +00:00
|
|
|
if ((uml_driver->inotifyWatch =
|
|
|
|
virEventAddHandle(uml_driver->inotifyFD, POLLIN,
|
2008-12-04 21:14:39 +00:00
|
|
|
umlInotifyEvent, uml_driver, NULL)) < 0)
|
|
|
|
goto error;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2010-02-09 18:58:01 +00:00
|
|
|
if (virDomainLoadAllConfigs(uml_driver->caps,
|
2008-11-19 16:58:23 +00:00
|
|
|
¨_driver->domains,
|
|
|
|
uml_driver->configDir,
|
|
|
|
uml_driver->autostartDir,
|
2009-06-12 11:38:50 +00:00
|
|
|
0, NULL, NULL) < 0)
|
2008-12-04 21:14:39 +00:00
|
|
|
goto error;
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
umlAutostartConfigs(uml_driver);
|
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(uml_driver);
|
2009-01-22 19:41:48 +00:00
|
|
|
VIR_FREE(userdir);
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
return 0;
|
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
out_of_memory:
|
2009-06-25 15:02:10 +00:00
|
|
|
VIR_ERROR0(_("umlStartup: out of memory"));
|
2008-12-04 21:14:39 +00:00
|
|
|
|
|
|
|
error:
|
2009-01-22 19:41:48 +00:00
|
|
|
VIR_FREE(userdir);
|
2008-11-19 16:58:23 +00:00
|
|
|
VIR_FREE(base);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(uml_driver);
|
|
|
|
umlShutdown();
|
2008-11-19 16:58:23 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* umlReload:
|
|
|
|
*
|
|
|
|
* Function to restart the Uml daemon, it will recheck the configuration
|
|
|
|
* files and update its state and the networking
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
umlReload(void) {
|
|
|
|
if (!uml_driver)
|
|
|
|
return 0;
|
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(uml_driver);
|
2010-02-09 18:58:01 +00:00
|
|
|
virDomainLoadAllConfigs(uml_driver->caps,
|
2008-11-19 16:58:23 +00:00
|
|
|
¨_driver->domains,
|
|
|
|
uml_driver->configDir,
|
|
|
|
uml_driver->autostartDir,
|
2009-06-12 11:38:50 +00:00
|
|
|
0, NULL, NULL);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
umlAutostartConfigs(uml_driver);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(uml_driver);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* umlActive:
|
|
|
|
*
|
|
|
|
* Checks if the Uml daemon is active, i.e. has an active domain or
|
|
|
|
* an active network
|
|
|
|
*
|
|
|
|
* Returns 1 if active, 0 otherwise
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
umlActive(void) {
|
2008-12-04 21:14:39 +00:00
|
|
|
int active = 0;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
if (!uml_driver)
|
|
|
|
return 0;
|
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(uml_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(¨_driver->domains, 1);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(uml_driver);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
return active;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
Convert virDomainObjListPtr to use a hash of domain objects
The current virDomainObjListPtr object stores domain objects in
an array. This means that to find a particular objects requires
O(n) time, and more critically acquiring O(n) mutex locks.
The new impl replaces the array with a virHashTable, keyed off
UUID. Finding a object based on UUID is now O(1) time, and only
requires a single mutex lock. Finding by name/id is unchanged
in complexity.
In changing this, all code which iterates over the array had
to be updated to use a hash table iterator function callback.
Several of the functions which were identically duplicating
across all drivers were pulled into domain_conf.c
* src/conf/domain_conf.h, src/conf/domain_conf.c: Change
virDomainObjListPtr to use virHashTable. Add a initializer
method virDomainObjListInit, and rename virDomainObjListFree
to virDomainObjListDeinit, since its not actually freeing
the container, only its contents. Also add some convenient
methods virDomainObjListGetInactiveNames,
virDomainObjListGetActiveIDs and virDomainObjListNumOfDomains
which can be used to implement the correspondingly named
public API entry points in drivers
* src/libvirt_private.syms: Export new methods from domain_conf.h
* src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_conf.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c: Update all code
to deal with hash tables instead of arrays for domains
2009-10-09 11:33:51 +00:00
|
|
|
static void
|
|
|
|
umlShutdownOneVM(void *payload, const char *name ATTRIBUTE_UNUSED, void *opaque)
|
|
|
|
{
|
|
|
|
virDomainObjPtr dom = payload;
|
|
|
|
struct uml_driver *driver = opaque;
|
|
|
|
|
|
|
|
virDomainObjLock(dom);
|
Rename internal APis
Rename virDomainIsActive to virDomainObjIsActive, and
virInterfaceIsActive to virInterfaceObjIsActive and finally
virNetworkIsActive to virNetworkObjIsActive.
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/conf/interface_conf.h, src/conf/network_conf.c,
src/conf/network_conf.h, src/lxc/lxc_driver.c,
src/network/bridge_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_driver.c, src/qemu/qemu_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c: Update for
renamed APIs.
2009-10-20 14:51:03 +00:00
|
|
|
if (virDomainObjIsActive(dom))
|
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
|
|
|
umlShutdownVMDaemon(NULL, driver, dom);
|
|
|
|
virDomainObjUnlock(dom);
|
|
|
|
}
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
/**
|
|
|
|
* umlShutdown:
|
|
|
|
*
|
|
|
|
* Shutdown the Uml daemon, it will stop all active domains and networks
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
umlShutdown(void) {
|
|
|
|
if (!uml_driver)
|
|
|
|
return -1;
|
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(uml_driver);
|
2009-01-29 17:50:00 +00:00
|
|
|
if (uml_driver->inotifyWatch != -1)
|
|
|
|
virEventRemoveHandle(uml_driver->inotifyWatch);
|
2008-11-19 16:58:23 +00:00
|
|
|
close(uml_driver->inotifyFD);
|
|
|
|
virCapabilitiesFree(uml_driver->caps);
|
|
|
|
|
Convert virDomainObjListPtr to use a hash of domain objects
The current virDomainObjListPtr object stores domain objects in
an array. This means that to find a particular objects requires
O(n) time, and more critically acquiring O(n) mutex locks.
The new impl replaces the array with a virHashTable, keyed off
UUID. Finding a object based on UUID is now O(1) time, and only
requires a single mutex lock. Finding by name/id is unchanged
in complexity.
In changing this, all code which iterates over the array had
to be updated to use a hash table iterator function callback.
Several of the functions which were identically duplicating
across all drivers were pulled into domain_conf.c
* src/conf/domain_conf.h, src/conf/domain_conf.c: Change
virDomainObjListPtr to use virHashTable. Add a initializer
method virDomainObjListInit, and rename virDomainObjListFree
to virDomainObjListDeinit, since its not actually freeing
the container, only its contents. Also add some convenient
methods virDomainObjListGetInactiveNames,
virDomainObjListGetActiveIDs and virDomainObjListNumOfDomains
which can be used to implement the correspondingly named
public API entry points in drivers
* src/libvirt_private.syms: Export new methods from domain_conf.h
* src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_conf.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c: Update all code
to deal with hash tables instead of arrays for domains
2009-10-09 11:33:51 +00:00
|
|
|
/* shutdown active VMs
|
|
|
|
* XXX allow them to stay around & reconnect */
|
|
|
|
virHashForEach(uml_driver->domains.objs, umlShutdownOneVM, uml_driver);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
Convert virDomainObjListPtr to use a hash of domain objects
The current virDomainObjListPtr object stores domain objects in
an array. This means that to find a particular objects requires
O(n) time, and more critically acquiring O(n) mutex locks.
The new impl replaces the array with a virHashTable, keyed off
UUID. Finding a object based on UUID is now O(1) time, and only
requires a single mutex lock. Finding by name/id is unchanged
in complexity.
In changing this, all code which iterates over the array had
to be updated to use a hash table iterator function callback.
Several of the functions which were identically duplicating
across all drivers were pulled into domain_conf.c
* src/conf/domain_conf.h, src/conf/domain_conf.c: Change
virDomainObjListPtr to use virHashTable. Add a initializer
method virDomainObjListInit, and rename virDomainObjListFree
to virDomainObjListDeinit, since its not actually freeing
the container, only its contents. Also add some convenient
methods virDomainObjListGetInactiveNames,
virDomainObjListGetActiveIDs and virDomainObjListNumOfDomains
which can be used to implement the correspondingly named
public API entry points in drivers
* src/libvirt_private.syms: Export new methods from domain_conf.h
* src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_conf.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c: Update all code
to deal with hash tables instead of arrays for domains
2009-10-09 11:33:51 +00:00
|
|
|
virDomainObjListDeinit(¨_driver->domains);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
VIR_FREE(uml_driver->logDir);
|
|
|
|
VIR_FREE(uml_driver->configDir);
|
|
|
|
VIR_FREE(uml_driver->autostartDir);
|
|
|
|
VIR_FREE(uml_driver->monitorDir);
|
|
|
|
|
|
|
|
if (uml_driver->brctl)
|
|
|
|
brShutdown(uml_driver->brctl);
|
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(uml_driver);
|
2009-01-15 19:56:05 +00:00
|
|
|
virMutexDestroy(¨_driver->lock);
|
2008-11-19 16:58:23 +00:00
|
|
|
VIR_FREE(uml_driver);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-02-04 20:02:58 +00:00
|
|
|
static int umlReadPidFile(struct uml_driver *driver,
|
2008-11-19 16:58:23 +00:00
|
|
|
virDomainObjPtr vm)
|
|
|
|
{
|
|
|
|
int rc = -1;
|
|
|
|
FILE *file;
|
|
|
|
char *pidfile = NULL;
|
|
|
|
int retries = 0;
|
|
|
|
|
|
|
|
vm->pid = -1;
|
2008-12-23 13:03:29 +00:00
|
|
|
if (virAsprintf(&pidfile, "%s/%s/pid",
|
|
|
|
driver->monitorDir, vm->def->name) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-11-19 16:58:23 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
reopen:
|
|
|
|
if (!(file = fopen(pidfile, "r"))) {
|
|
|
|
if (errno == ENOENT &&
|
|
|
|
retries++ < 50) {
|
|
|
|
usleep(1000 * 100);
|
|
|
|
goto reopen;
|
|
|
|
}
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fscanf(file, "%d", &vm->pid) != 1) {
|
|
|
|
errno = EINVAL;
|
2009-03-16 10:41:37 +00:00
|
|
|
fclose(file);
|
2008-11-19 16:58:23 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fclose(file) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
rc = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (rc != 0)
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("failed to read pid: %s"),
|
|
|
|
pidfile);
|
2008-11-19 16:58:23 +00:00
|
|
|
VIR_FREE(pidfile);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int umlMonitorAddress(virConnectPtr conn,
|
|
|
|
const struct uml_driver *driver,
|
|
|
|
virDomainObjPtr vm,
|
|
|
|
struct sockaddr_un *addr) {
|
|
|
|
char *sockname;
|
2009-08-03 12:37:44 +00:00
|
|
|
int retval = 0;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-23 13:03:29 +00:00
|
|
|
if (virAsprintf(&sockname, "%s/%s/mconsole",
|
|
|
|
driver->monitorDir, vm->def->name) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-11-19 16:58:23 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(addr, 0, sizeof *addr);
|
|
|
|
addr->sun_family = AF_UNIX;
|
2009-08-03 12:37:44 +00:00
|
|
|
if (virStrcpyStatic(addr->sun_path, sockname) == NULL) {
|
|
|
|
umlReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unix path %s too long for destination"), sockname);
|
|
|
|
retval = -1;
|
|
|
|
}
|
2008-11-19 16:58:23 +00:00
|
|
|
VIR_FREE(sockname);
|
2009-08-03 12:37:44 +00:00
|
|
|
return retval;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int umlOpenMonitor(virConnectPtr conn,
|
|
|
|
struct uml_driver *driver,
|
|
|
|
virDomainObjPtr vm) {
|
|
|
|
struct sockaddr_un addr;
|
|
|
|
struct stat sb;
|
|
|
|
int retries = 0;
|
2009-11-26 17:55:12 +00:00
|
|
|
umlDomainObjPrivatePtr priv = vm->privateData;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
if (umlMonitorAddress(conn, driver, vm, &addr) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2009-06-03 10:55:33 +00:00
|
|
|
VIR_DEBUG("Dest address for monitor is '%s'", addr.sun_path);
|
2008-11-19 16:58:23 +00:00
|
|
|
restat:
|
|
|
|
if (stat(addr.sun_path, &sb) < 0) {
|
|
|
|
if (errno == ENOENT &&
|
2009-06-03 10:55:33 +00:00
|
|
|
retries++ < 50) {
|
2008-11-19 16:58:23 +00:00
|
|
|
usleep(1000 * 100);
|
|
|
|
goto restat;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2009-11-26 17:55:12 +00:00
|
|
|
if ((priv->monitor = socket(PF_UNIX, SOCK_DGRAM, 0)) < 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
"%s", _("cannot open socket"));
|
2008-11-19 16:58:23 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(addr.sun_path, 0, sizeof addr.sun_path);
|
2009-06-03 10:55:33 +00:00
|
|
|
sprintf(addr.sun_path + 1, "libvirt-uml-%u", vm->pid);
|
|
|
|
VIR_DEBUG("Reply address for monitor is '%s'", addr.sun_path+1);
|
2009-11-26 17:55:12 +00:00
|
|
|
if (bind(priv->monitor, (struct sockaddr *)&addr, sizeof addr) < 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
"%s", _("cannot bind socket"));
|
2009-11-26 17:55:12 +00:00
|
|
|
close(priv->monitor);
|
|
|
|
priv->monitor = -1;
|
2008-11-19 16:58:23 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define MONITOR_MAGIC 0xcafebabe
|
|
|
|
#define MONITOR_BUFLEN 512
|
|
|
|
#define MONITOR_VERSION 2
|
|
|
|
|
|
|
|
struct monitor_request {
|
|
|
|
uint32_t magic;
|
|
|
|
uint32_t version;
|
|
|
|
uint32_t length;
|
|
|
|
char data[MONITOR_BUFLEN];
|
|
|
|
};
|
|
|
|
|
|
|
|
struct monitor_response {
|
|
|
|
uint32_t error;
|
|
|
|
uint32_t extra;
|
|
|
|
uint32_t length;
|
|
|
|
char data[MONITOR_BUFLEN];
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static int umlMonitorCommand(virConnectPtr conn,
|
|
|
|
const struct uml_driver *driver,
|
|
|
|
const virDomainObjPtr vm,
|
|
|
|
const char *cmd,
|
|
|
|
char **reply)
|
|
|
|
{
|
|
|
|
struct monitor_request req;
|
|
|
|
struct monitor_response res;
|
|
|
|
char *retdata = NULL;
|
|
|
|
int retlen = 0, ret = 0;
|
|
|
|
struct sockaddr_un addr;
|
|
|
|
unsigned int addrlen;
|
2009-11-26 17:55:12 +00:00
|
|
|
umlDomainObjPrivatePtr priv = vm->privateData;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2009-06-03 10:55:33 +00:00
|
|
|
VIR_DEBUG("Run command '%s'", cmd);
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
*reply = NULL;
|
|
|
|
|
|
|
|
if (umlMonitorAddress(conn, driver, vm, &addr) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
|
|
req.magic = MONITOR_MAGIC;
|
|
|
|
req.version = MONITOR_VERSION;
|
|
|
|
req.length = strlen(cmd);
|
|
|
|
if (req.length > (MONITOR_BUFLEN-1)) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(EINVAL,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("cannot send too long command %s (%d bytes)"),
|
|
|
|
cmd, req.length);
|
2008-11-19 16:58:23 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2009-08-03 12:37:44 +00:00
|
|
|
if (virStrcpyStatic(req.data, cmd) == NULL) {
|
|
|
|
umlReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Command %s too long for destination"), cmd);
|
|
|
|
return -1;
|
|
|
|
}
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2009-11-26 17:55:12 +00:00
|
|
|
if (sendto(priv->monitor, &req, sizeof req, 0,
|
2008-11-19 16:58:23 +00:00
|
|
|
(struct sockaddr *)&addr, sizeof addr) != (sizeof req)) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("cannot send command %s"),
|
|
|
|
cmd);
|
2008-11-19 16:58:23 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
|
|
|
addrlen = sizeof(addr);
|
2009-11-26 17:55:12 +00:00
|
|
|
if (recvfrom(priv->monitor, &res, sizeof res, 0,
|
2008-11-19 16:58:23 +00:00
|
|
|
(struct sockaddr *)&addr, &addrlen) < 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("cannot read reply %s"),
|
|
|
|
cmd);
|
2008-11-19 16:58:23 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_REALLOC_N(retdata, retlen + res.length) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-11-19 16:58:23 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
memcpy(retdata + retlen, res.data, res.length);
|
|
|
|
retlen += res.length - 1;
|
|
|
|
retdata[retlen] = '\0';
|
|
|
|
|
|
|
|
if (res.error)
|
|
|
|
ret = -1;
|
|
|
|
|
|
|
|
} while (res.extra);
|
|
|
|
|
2009-06-03 10:55:33 +00:00
|
|
|
VIR_DEBUG("Command reply is '%s'", NULLSTR(retdata));
|
|
|
|
|
2010-02-15 18:22:38 +00:00
|
|
|
if (ret < 0)
|
|
|
|
VIR_FREE(retdata);
|
|
|
|
else
|
|
|
|
*reply = retdata;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
error:
|
|
|
|
VIR_FREE(retdata);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-06-03 11:13:33 +00:00
|
|
|
static int umlCleanupTapDevices(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|
|
|
virDomainObjPtr vm) {
|
|
|
|
int i;
|
|
|
|
int err;
|
|
|
|
int ret = 0;
|
|
|
|
brControl *brctl = NULL;
|
|
|
|
VIR_ERROR0("Cleanup tap");
|
|
|
|
if (brInit(&brctl) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
for (i = 0 ; i < vm->def->nnets ; i++) {
|
|
|
|
virDomainNetDefPtr def = vm->def->nets[i];
|
|
|
|
|
|
|
|
if (def->type != VIR_DOMAIN_NET_TYPE_BRIDGE &&
|
|
|
|
def->type != VIR_DOMAIN_NET_TYPE_NETWORK)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
VIR_ERROR("Cleanup '%s'", def->ifname);
|
|
|
|
err = brDeleteTap(brctl, def->ifname);
|
|
|
|
if (err) {
|
|
|
|
VIR_ERROR("Cleanup failed %d", err);
|
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
VIR_ERROR0("Cleanup tap done");
|
|
|
|
brShutdown(brctl);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
static int umlStartVMDaemon(virConnectPtr conn,
|
|
|
|
struct uml_driver *driver,
|
|
|
|
virDomainObjPtr vm) {
|
|
|
|
const char **argv = NULL, **tmp;
|
|
|
|
const char **progenv = NULL;
|
2008-12-18 11:58:28 +00:00
|
|
|
int i, ret;
|
|
|
|
pid_t pid;
|
2008-11-19 16:58:23 +00:00
|
|
|
char *logfile;
|
|
|
|
int logfd = -1;
|
|
|
|
struct stat sb;
|
|
|
|
fd_set keepfd;
|
2009-02-05 16:28:30 +00:00
|
|
|
char ebuf[1024];
|
2009-11-26 17:55:12 +00:00
|
|
|
umlDomainObjPrivatePtr priv = vm->privateData;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
FD_ZERO(&keepfd);
|
|
|
|
|
Rename internal APis
Rename virDomainIsActive to virDomainObjIsActive, and
virInterfaceIsActive to virInterfaceObjIsActive and finally
virNetworkIsActive to virNetworkObjIsActive.
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/conf/interface_conf.h, src/conf/network_conf.c,
src/conf/network_conf.h, src/lxc/lxc_driver.c,
src/network/bridge_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_driver.c, src/qemu/qemu_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c: Update for
renamed APIs.
2009-10-20 14:51:03 +00:00
|
|
|
if (virDomainObjIsActive(vm)) {
|
2008-11-19 16:58:23 +00:00
|
|
|
umlReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("VM is already active"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!vm->def->os.kernel) {
|
|
|
|
umlReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("no kernel specified"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
/* Make sure the binary we are about to try exec'ing exists.
|
|
|
|
* Technically we could catch the exec() failure, but that's
|
|
|
|
* in a sub-process so its hard to feed back a useful error
|
|
|
|
*/
|
|
|
|
if (stat(vm->def->os.kernel, &sb) < 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("Cannot find UML kernel %s"),
|
|
|
|
vm->def->os.kernel);
|
2008-11-19 16:58:23 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2010-01-20 23:52:13 +00:00
|
|
|
if (virFileMakePath(driver->logDir) != 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("cannot create log directory %s"),
|
|
|
|
driver->logDir);
|
2008-11-19 16:58:23 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2008-12-23 13:03:29 +00:00
|
|
|
if (virAsprintf(&logfile, "%s/%s.log",
|
|
|
|
driver->logDir, vm->def->name) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-11-19 16:58:23 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((logfd = open(logfile, O_CREAT | O_TRUNC | O_WRONLY,
|
|
|
|
S_IRUSR | S_IWUSR)) < 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("failed to create logfile %s"),
|
|
|
|
logfile);
|
2008-11-19 16:58:23 +00:00
|
|
|
VIR_FREE(logfile);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
VIR_FREE(logfile);
|
|
|
|
|
|
|
|
if (umlSetCloseExec(logfd) < 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
"%s", _("Unable to set VM logfile close-on-exec flag"));
|
2008-11-19 16:58:23 +00:00
|
|
|
close(logfd);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (umlBuildCommandLine(conn, driver, vm,
|
2009-06-03 11:13:33 +00:00
|
|
|
&argv, &progenv) < 0) {
|
2008-11-19 16:58:23 +00:00
|
|
|
close(logfd);
|
2009-06-03 11:13:33 +00:00
|
|
|
umlCleanupTapDevices(conn, vm);
|
2008-11-19 16:58:23 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp = progenv;
|
|
|
|
while (*tmp) {
|
|
|
|
if (safewrite(logfd, *tmp, strlen(*tmp)) < 0)
|
2009-06-25 15:02:10 +00:00
|
|
|
VIR_WARN(_("Unable to write envv to logfile: %s"),
|
2009-02-05 16:28:30 +00:00
|
|
|
virStrerror(errno, ebuf, sizeof ebuf));
|
2008-11-19 16:58:23 +00:00
|
|
|
if (safewrite(logfd, " ", 1) < 0)
|
2009-06-25 15:02:10 +00:00
|
|
|
VIR_WARN(_("Unable to write envv to logfile: %s"),
|
2009-02-05 16:28:30 +00:00
|
|
|
virStrerror(errno, ebuf, sizeof ebuf));
|
2008-11-19 16:58:23 +00:00
|
|
|
tmp++;
|
|
|
|
}
|
|
|
|
tmp = argv;
|
|
|
|
while (*tmp) {
|
|
|
|
if (safewrite(logfd, *tmp, strlen(*tmp)) < 0)
|
2009-06-25 15:02:10 +00:00
|
|
|
VIR_WARN(_("Unable to write argv to logfile: %s"),
|
2009-02-05 16:28:30 +00:00
|
|
|
virStrerror(errno, ebuf, sizeof ebuf));
|
2008-11-19 16:58:23 +00:00
|
|
|
if (safewrite(logfd, " ", 1) < 0)
|
2009-06-25 15:02:10 +00:00
|
|
|
VIR_WARN(_("Unable to write argv to logfile: %s"),
|
2009-02-05 16:28:30 +00:00
|
|
|
virStrerror(errno, ebuf, sizeof ebuf));
|
2008-11-19 16:58:23 +00:00
|
|
|
tmp++;
|
|
|
|
}
|
|
|
|
if (safewrite(logfd, "\n", 1) < 0)
|
2009-06-25 15:02:10 +00:00
|
|
|
VIR_WARN(_("Unable to write argv to logfile: %s"),
|
2009-02-05 16:28:30 +00:00
|
|
|
virStrerror(errno, ebuf, sizeof ebuf));
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2009-11-26 17:55:12 +00:00
|
|
|
priv->monitor = -1;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2010-02-04 22:41:52 +00:00
|
|
|
ret = virExecDaemonize(argv, progenv, &keepfd, &pid,
|
2009-05-11 13:34:37 +00:00
|
|
|
-1, &logfd, &logfd,
|
2009-06-29 17:00:52 +00:00
|
|
|
VIR_EXEC_CLEAR_CAPS,
|
|
|
|
NULL, NULL, NULL);
|
2008-11-19 16:58:23 +00:00
|
|
|
close(logfd);
|
|
|
|
|
|
|
|
for (i = 0 ; argv[i] ; i++)
|
|
|
|
VIR_FREE(argv[i]);
|
|
|
|
VIR_FREE(argv);
|
|
|
|
|
|
|
|
for (i = 0 ; progenv[i] ; i++)
|
|
|
|
VIR_FREE(progenv[i]);
|
|
|
|
VIR_FREE(progenv);
|
|
|
|
|
2009-06-03 11:13:33 +00:00
|
|
|
if (ret < 0)
|
|
|
|
umlCleanupTapDevices(conn, vm);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
/* NB we don't mark it running here - we do that async
|
|
|
|
with inotify */
|
2009-06-03 11:13:33 +00:00
|
|
|
/* XXX what if someone else tries to start it again
|
|
|
|
before we get the inotification ? Sounds like
|
|
|
|
trouble.... */
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void umlShutdownVMDaemon(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|
|
|
struct uml_driver *driver ATTRIBUTE_UNUSED,
|
|
|
|
virDomainObjPtr vm)
|
|
|
|
{
|
|
|
|
int ret;
|
2009-11-26 17:55:12 +00:00
|
|
|
umlDomainObjPrivatePtr priv = vm->privateData;
|
|
|
|
|
Rename internal APis
Rename virDomainIsActive to virDomainObjIsActive, and
virInterfaceIsActive to virInterfaceObjIsActive and finally
virNetworkIsActive to virNetworkObjIsActive.
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/conf/interface_conf.h, src/conf/network_conf.c,
src/conf/network_conf.h, src/lxc/lxc_driver.c,
src/network/bridge_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_driver.c, src/qemu/qemu_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c: Update for
renamed APIs.
2009-10-20 14:51:03 +00:00
|
|
|
if (!virDomainObjIsActive(vm))
|
2008-11-19 16:58:23 +00:00
|
|
|
return;
|
|
|
|
|
2009-06-03 10:55:33 +00:00
|
|
|
virKillProcess(vm->pid, SIGTERM);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2009-11-26 17:55:12 +00:00
|
|
|
if (priv->monitor != -1)
|
|
|
|
close(priv->monitor);
|
|
|
|
priv->monitor = -1;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
if ((ret = waitpid(vm->pid, NULL, 0)) != vm->pid) {
|
2009-06-25 15:02:10 +00:00
|
|
|
VIR_WARN(_("Got unexpected pid %d != %d"),
|
2008-11-19 16:58:23 +00:00
|
|
|
ret, vm->pid);
|
|
|
|
}
|
|
|
|
|
|
|
|
vm->pid = -1;
|
|
|
|
vm->def->id = -1;
|
|
|
|
vm->state = VIR_DOMAIN_SHUTOFF;
|
|
|
|
|
2009-06-03 11:13:33 +00:00
|
|
|
umlCleanupTapDevices(conn, vm);
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
if (vm->newDef) {
|
|
|
|
virDomainDefFree(vm->def);
|
|
|
|
vm->def = vm->newDef;
|
|
|
|
vm->def->id = -1;
|
|
|
|
vm->newDef = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static virDrvOpenStatus umlOpen(virConnectPtr conn,
|
|
|
|
virConnectAuthPtr auth ATTRIBUTE_UNUSED,
|
|
|
|
int flags ATTRIBUTE_UNUSED) {
|
2009-06-12 12:06:15 +00:00
|
|
|
if (conn->uri == NULL) {
|
|
|
|
if (uml_driver == NULL)
|
|
|
|
return VIR_DRV_OPEN_DECLINED;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2009-06-12 13:20:13 +00:00
|
|
|
conn->uri = xmlParseURI(uml_driver->privileged ?
|
2009-06-12 12:06:15 +00:00
|
|
|
"uml:///system" :
|
|
|
|
"uml:///session");
|
|
|
|
if (!conn->uri) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-06-12 12:06:15 +00:00
|
|
|
return VIR_DRV_OPEN_ERROR;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (conn->uri->scheme == NULL ||
|
|
|
|
STRNEQ (conn->uri->scheme, "uml"))
|
|
|
|
return VIR_DRV_OPEN_DECLINED;
|
|
|
|
|
|
|
|
/* Allow remote driver to deal with URIs with hostname server */
|
|
|
|
if (conn->uri->server != NULL)
|
|
|
|
return VIR_DRV_OPEN_DECLINED;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
|
2009-06-12 12:06:15 +00:00
|
|
|
/* Check path and tell them correct path if they made a mistake */
|
2009-06-12 13:20:13 +00:00
|
|
|
if (uml_driver->privileged) {
|
2008-11-19 16:58:23 +00:00
|
|
|
if (STRNEQ (conn->uri->path, "/system") &&
|
2009-06-12 12:06:15 +00:00
|
|
|
STRNEQ (conn->uri->path, "/session")) {
|
|
|
|
umlReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unexpected UML URI path '%s', try uml:///system"),
|
|
|
|
conn->uri->path);
|
|
|
|
return VIR_DRV_OPEN_ERROR;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (STRNEQ (conn->uri->path, "/session")) {
|
|
|
|
umlReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unexpected UML URI path '%s', try uml:///session"),
|
|
|
|
conn->uri->path);
|
|
|
|
return VIR_DRV_OPEN_ERROR;
|
|
|
|
}
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
2009-06-12 12:06:15 +00:00
|
|
|
|
|
|
|
/* URI was good, but driver isn't active */
|
|
|
|
if (uml_driver == NULL) {
|
|
|
|
umlReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("uml state driver is not active"));
|
2008-11-19 16:58:23 +00:00
|
|
|
return VIR_DRV_OPEN_ERROR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
conn->privateData = uml_driver;
|
|
|
|
|
|
|
|
return VIR_DRV_OPEN_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int umlClose(virConnectPtr conn) {
|
2008-12-04 21:13:58 +00:00
|
|
|
/*struct uml_driver *driver = conn->privateData;*/
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
conn->privateData = NULL;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *umlGetType(virConnectPtr conn ATTRIBUTE_UNUSED) {
|
|
|
|
return "UML";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Implmentation of new APIs to checking state/persistence of objects
This implements the virConnectIsSecure, virConnectIsEncrypted,
virDomainIsPersistent, virDomainIsActive, virNetworkIsActive,
virNetworkIsPersistent, virStoragePoolIsActive,
virStoragePoolIsPersistent, virInterfaceIsActive APIs in
(nearly) all drivers. Exceptions are:
phyp: missing domainIsActive/Persistent
esx: missing domainIsPersistent
opennebula: missing domainIsActive/Persistent
* src/remote/remote_protocol.x: Define remote wire ABI for newly
added APIs.
* daemon/remote_dispatch*.h: Re-generated from remote_protocol.x
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/opennebula/one_driver.c, src/openvz/openvz_conf.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/remote/remote_driver.c, src/storage/storage_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c, src/xen/xen_driver.h, src/xen/xen_inotify.c,
src/xen/xen_inotify.h: Implement all the new APIs where possible
2009-10-20 14:12:03 +00:00
|
|
|
static int umlIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
/* Trivially secure, since always inside the daemon */
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int umlIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
/* Not encrypted, but remote driver takes care of that */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
static char *umlGetCapabilities(virConnectPtr conn) {
|
|
|
|
struct uml_driver *driver = (struct uml_driver *)conn->privateData;
|
|
|
|
char *xml;
|
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2008-12-04 21:13:58 +00:00
|
|
|
if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL)
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
return xml;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int umlGetProcessInfo(unsigned long long *cpuTime, int pid) {
|
|
|
|
char proc[PATH_MAX];
|
|
|
|
FILE *pidinfo;
|
|
|
|
unsigned long long usertime, systime;
|
|
|
|
|
|
|
|
if (snprintf(proc, sizeof(proc), "/proc/%d/stat", pid) >= (int)sizeof(proc)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(pidinfo = fopen(proc, "r"))) {
|
|
|
|
/*printf("cannot read pid info");*/
|
|
|
|
/* VM probably shut down, so fake 0 */
|
|
|
|
*cpuTime = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fscanf(pidinfo, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %llu %llu", &usertime, &systime) != 2) {
|
|
|
|
umlDebug("not enough arg");
|
2009-03-16 10:41:37 +00:00
|
|
|
fclose(pidinfo);
|
2008-11-19 16:58:23 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We got jiffies
|
|
|
|
* We want nanoseconds
|
|
|
|
* _SC_CLK_TCK is jiffies per second
|
|
|
|
* So calulate thus....
|
|
|
|
*/
|
|
|
|
*cpuTime = 1000ull * 1000ull * 1000ull * (usertime + systime) / (unsigned long long)sysconf(_SC_CLK_TCK);
|
|
|
|
|
|
|
|
umlDebug("Got %llu %llu %llu", usertime, systime, *cpuTime);
|
|
|
|
|
|
|
|
fclose(pidinfo);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static virDomainPtr umlDomainLookupByID(virConnectPtr conn,
|
|
|
|
int id) {
|
|
|
|
struct uml_driver *driver = (struct uml_driver *)conn->privateData;
|
2008-12-04 21:13:58 +00:00
|
|
|
virDomainObjPtr vm;
|
|
|
|
virDomainPtr dom = NULL;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2008-12-04 21:13:58 +00:00
|
|
|
vm = virDomainFindByID(&driver->domains, id);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!vm) {
|
|
|
|
umlReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
|
|
|
if (dom) dom->id = vm->def->id;
|
2008-12-04 21:13:58 +00:00
|
|
|
|
|
|
|
cleanup:
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
2008-11-19 16:58:23 +00:00
|
|
|
return dom;
|
|
|
|
}
|
2008-12-04 21:13:58 +00:00
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
static virDomainPtr umlDomainLookupByUUID(virConnectPtr conn,
|
|
|
|
const unsigned char *uuid) {
|
|
|
|
struct uml_driver *driver = (struct uml_driver *)conn->privateData;
|
2008-12-04 21:13:58 +00:00
|
|
|
virDomainObjPtr vm;
|
|
|
|
virDomainPtr dom = NULL;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2008-12-04 21:13:58 +00:00
|
|
|
vm = virDomainFindByUUID(&driver->domains, uuid);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!vm) {
|
|
|
|
umlReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
|
|
|
if (dom) dom->id = vm->def->id;
|
2008-12-04 21:13:58 +00:00
|
|
|
|
|
|
|
cleanup:
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
2008-11-19 16:58:23 +00:00
|
|
|
return dom;
|
|
|
|
}
|
2008-12-04 21:13:58 +00:00
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
static virDomainPtr umlDomainLookupByName(virConnectPtr conn,
|
|
|
|
const char *name) {
|
|
|
|
struct uml_driver *driver = (struct uml_driver *)conn->privateData;
|
2008-12-04 21:13:58 +00:00
|
|
|
virDomainObjPtr vm;
|
|
|
|
virDomainPtr dom = NULL;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2008-12-04 21:13:58 +00:00
|
|
|
vm = virDomainFindByName(&driver->domains, name);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!vm) {
|
|
|
|
umlReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
|
|
|
if (dom) dom->id = vm->def->id;
|
2008-12-04 21:13:58 +00:00
|
|
|
|
|
|
|
cleanup:
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
2008-11-19 16:58:23 +00:00
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
Implmentation of new APIs to checking state/persistence of objects
This implements the virConnectIsSecure, virConnectIsEncrypted,
virDomainIsPersistent, virDomainIsActive, virNetworkIsActive,
virNetworkIsPersistent, virStoragePoolIsActive,
virStoragePoolIsPersistent, virInterfaceIsActive APIs in
(nearly) all drivers. Exceptions are:
phyp: missing domainIsActive/Persistent
esx: missing domainIsPersistent
opennebula: missing domainIsActive/Persistent
* src/remote/remote_protocol.x: Define remote wire ABI for newly
added APIs.
* daemon/remote_dispatch*.h: Re-generated from remote_protocol.x
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/opennebula/one_driver.c, src/openvz/openvz_conf.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/remote/remote_driver.c, src/storage/storage_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c, src/xen/xen_driver.h, src/xen/xen_inotify.c,
src/xen/xen_inotify.h: Implement all the new APIs where possible
2009-10-20 14:12:03 +00:00
|
|
|
|
|
|
|
static int umlDomainIsActive(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr obj;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
umlDriverLock(driver);
|
|
|
|
obj = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
umlDriverUnlock(driver);
|
|
|
|
if (!obj) {
|
|
|
|
umlReportError(dom->conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
ret = virDomainObjIsActive(obj);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (obj)
|
|
|
|
virDomainObjUnlock(obj);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int umlDomainIsPersistent(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr obj;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
umlDriverLock(driver);
|
|
|
|
obj = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
umlDriverUnlock(driver);
|
|
|
|
if (!obj) {
|
|
|
|
umlReportError(dom->conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
ret = obj->persistent;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (obj)
|
|
|
|
virDomainObjUnlock(obj);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
static int umlGetVersion(virConnectPtr conn, unsigned long *version) {
|
2008-12-04 21:14:39 +00:00
|
|
|
struct uml_driver *driver = conn->privateData;
|
2008-11-19 16:58:23 +00:00
|
|
|
struct utsname ut;
|
|
|
|
int major, minor, micro;
|
2008-12-04 21:14:39 +00:00
|
|
|
int ret = -1;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
uname(&ut);
|
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2008-11-19 16:58:23 +00:00
|
|
|
if (sscanf(ut.release, "%u.%u.%u",
|
|
|
|
&major, &minor, µ) != 3) {
|
|
|
|
umlReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("cannot parse version %s"), ut.release);
|
2008-12-04 21:14:39 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
*version = driver->umlVersion;
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
umlDriverUnlock(driver);
|
|
|
|
return ret;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int umlListDomains(virConnectPtr conn, int *ids, int nids) {
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = conn->privateData;
|
Convert virDomainObjListPtr to use a hash of domain objects
The current virDomainObjListPtr object stores domain objects in
an array. This means that to find a particular objects requires
O(n) time, and more critically acquiring O(n) mutex locks.
The new impl replaces the array with a virHashTable, keyed off
UUID. Finding a object based on UUID is now O(1) time, and only
requires a single mutex lock. Finding by name/id is unchanged
in complexity.
In changing this, all code which iterates over the array had
to be updated to use a hash table iterator function callback.
Several of the functions which were identically duplicating
across all drivers were pulled into domain_conf.c
* src/conf/domain_conf.h, src/conf/domain_conf.c: Change
virDomainObjListPtr to use virHashTable. Add a initializer
method virDomainObjListInit, and rename virDomainObjListFree
to virDomainObjListDeinit, since its not actually freeing
the container, only its contents. Also add some convenient
methods virDomainObjListGetInactiveNames,
virDomainObjListGetActiveIDs and virDomainObjListNumOfDomains
which can be used to implement the correspondingly named
public API entry points in drivers
* src/libvirt_private.syms: Export new methods from domain_conf.h
* src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_conf.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c: Update all code
to deal with hash tables instead of arrays for domains
2009-10-09 11:33:51 +00:00
|
|
|
int n;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
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:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
Convert virDomainObjListPtr to use a hash of domain objects
The current virDomainObjListPtr object stores domain objects in
an array. This means that to find a particular objects requires
O(n) time, and more critically acquiring O(n) mutex locks.
The new impl replaces the array with a virHashTable, keyed off
UUID. Finding a object based on UUID is now O(1) time, and only
requires a single mutex lock. Finding by name/id is unchanged
in complexity.
In changing this, all code which iterates over the array had
to be updated to use a hash table iterator function callback.
Several of the functions which were identically duplicating
across all drivers were pulled into domain_conf.c
* src/conf/domain_conf.h, src/conf/domain_conf.c: Change
virDomainObjListPtr to use virHashTable. Add a initializer
method virDomainObjListInit, and rename virDomainObjListFree
to virDomainObjListDeinit, since its not actually freeing
the container, only its contents. Also add some convenient
methods virDomainObjListGetInactiveNames,
virDomainObjListGetActiveIDs and virDomainObjListNumOfDomains
which can be used to implement the correspondingly named
public API entry points in drivers
* src/libvirt_private.syms: Export new methods from domain_conf.h
* src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_conf.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c: Update all code
to deal with hash tables instead of arrays for domains
2009-10-09 11:33:51 +00:00
|
|
|
return n;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
static int umlNumDomains(virConnectPtr conn) {
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = conn->privateData;
|
Convert virDomainObjListPtr to use a hash of domain objects
The current virDomainObjListPtr object stores domain objects in
an array. This means that to find a particular objects requires
O(n) time, and more critically acquiring O(n) mutex locks.
The new impl replaces the array with a virHashTable, keyed off
UUID. Finding a object based on UUID is now O(1) time, and only
requires a single mutex lock. Finding by name/id is unchanged
in complexity.
In changing this, all code which iterates over the array had
to be updated to use a hash table iterator function callback.
Several of the functions which were identically duplicating
across all drivers were pulled into domain_conf.c
* src/conf/domain_conf.h, src/conf/domain_conf.c: Change
virDomainObjListPtr to use virHashTable. Add a initializer
method virDomainObjListInit, and rename virDomainObjListFree
to virDomainObjListDeinit, since its not actually freeing
the container, only its contents. Also add some convenient
methods virDomainObjListGetInactiveNames,
virDomainObjListGetActiveIDs and virDomainObjListNumOfDomains
which can be used to implement the correspondingly named
public API entry points in drivers
* src/libvirt_private.syms: Export new methods from domain_conf.h
* src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_conf.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c: Update all code
to deal with hash tables instead of arrays for domains
2009-10-09 11:33:51 +00:00
|
|
|
int n;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
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:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
static virDomainPtr umlDomainCreate(virConnectPtr conn, const char *xml,
|
|
|
|
unsigned int flags ATTRIBUTE_UNUSED) {
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = conn->privateData;
|
2008-11-19 16:58:23 +00:00
|
|
|
virDomainDefPtr def;
|
2008-12-04 21:14:39 +00:00
|
|
|
virDomainObjPtr vm = NULL;
|
2008-12-04 21:13:58 +00:00
|
|
|
virDomainPtr dom = NULL;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2010-02-09 18:58:01 +00:00
|
|
|
if (!(def = virDomainDefParseString(driver->caps, xml,
|
2009-01-08 13:54:20 +00:00
|
|
|
VIR_DOMAIN_XML_INACTIVE)))
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2009-11-02 18:37:38 +00:00
|
|
|
if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0)
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2010-02-09 18:58:01 +00:00
|
|
|
if (!(vm = virDomainAssignDef(driver->caps,
|
2008-11-19 16:58:23 +00:00
|
|
|
&driver->domains,
|
2008-12-04 21:13:58 +00:00
|
|
|
def)))
|
|
|
|
goto cleanup;
|
|
|
|
def = NULL;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
if (umlStartVMDaemon(conn, driver, vm) < 0) {
|
|
|
|
virDomainRemoveInactive(&driver->domains,
|
|
|
|
vm);
|
2008-12-04 21:13:58 +00:00
|
|
|
vm = NULL;
|
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
|
|
|
if (dom) dom->id = vm->def->id;
|
2008-12-04 21:13:58 +00:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virDomainDefFree(def);
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
umlDriverUnlock(driver);
|
2008-11-19 16:58:23 +00:00
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int umlDomainShutdown(virDomainPtr dom) {
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
2008-12-01 11:08:16 +00:00
|
|
|
char *info = NULL;
|
2008-12-04 21:13:58 +00:00
|
|
|
int ret = -1;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2008-12-04 21:13:58 +00:00
|
|
|
vm = virDomainFindByID(&driver->domains, dom->id);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!vm) {
|
|
|
|
umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
|
|
|
|
_("no domain with matching id %d"), dom->id);
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
if (umlMonitorCommand(driver, vm, "system_powerdown", &info) < 0) {
|
|
|
|
umlReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
|
|
|
|
"%s", _("shutdown operation failed"));
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
2008-12-04 21:13:58 +00:00
|
|
|
ret = 0;
|
2008-11-19 16:58:23 +00:00
|
|
|
#endif
|
|
|
|
|
2008-12-04 21:13:58 +00:00
|
|
|
cleanup:
|
|
|
|
VIR_FREE(info);
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
2008-12-04 21:13:58 +00:00
|
|
|
return ret;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int umlDomainDestroy(virDomainPtr dom) {
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2008-12-04 21:13:58 +00:00
|
|
|
vm = virDomainFindByID(&driver->domains, dom->id);
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!vm) {
|
|
|
|
umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
|
|
|
|
_("no domain with matching id %d"), dom->id);
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
umlShutdownVMDaemon(dom->conn, driver, vm);
|
2008-12-04 21:13:58 +00:00
|
|
|
if (!vm->persistent) {
|
2008-11-19 16:58:23 +00:00
|
|
|
virDomainRemoveInactive(&driver->domains,
|
|
|
|
vm);
|
2008-12-04 21:13:58 +00:00
|
|
|
vm = NULL;
|
|
|
|
}
|
|
|
|
ret = 0;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:13:58 +00:00
|
|
|
cleanup:
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
umlDriverUnlock(driver);
|
2008-12-04 21:13:58 +00:00
|
|
|
return ret;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static char *umlDomainGetOSType(virDomainPtr dom) {
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
char *type = NULL;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2008-12-04 21:13:58 +00:00
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!vm) {
|
|
|
|
umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
|
|
|
|
"%s", _("no domain with matching uuid"));
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
2008-12-04 21:13:58 +00:00
|
|
|
if (!(type = strdup(vm->def->os.type)))
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-12-04 21:13:58 +00:00
|
|
|
|
|
|
|
cleanup:
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
2008-11-19 16:58:23 +00:00
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Returns max memory in kb, 0 if error */
|
|
|
|
static unsigned long umlDomainGetMaxMemory(virDomainPtr dom) {
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
unsigned long ret = 0;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2008-12-04 21:13:58 +00:00
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
|
|
|
umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
|
2008-12-04 21:13:58 +00:00
|
|
|
_("no domain with matching uuid '%s'"), uuidstr);
|
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
2008-12-04 21:13:58 +00:00
|
|
|
ret = vm->def->maxmem;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:13:58 +00:00
|
|
|
cleanup:
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
2008-12-04 21:13:58 +00:00
|
|
|
return ret;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int umlDomainSetMaxMemory(virDomainPtr dom, unsigned long newmax) {
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2008-12-04 21:13:58 +00:00
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
|
|
|
umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
|
|
|
|
_("no domain with matching uuid '%s'"), uuidstr);
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (newmax < vm->def->memory) {
|
|
|
|
umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
|
|
|
|
"%s", _("cannot set max memory lower than current memory"));
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
vm->def->maxmem = newmax;
|
2008-12-04 21:13:58 +00:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
2008-12-04 21:13:58 +00:00
|
|
|
return ret;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int umlDomainSetMemory(virDomainPtr dom, unsigned long newmem) {
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2008-12-04 21:13:58 +00:00
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
|
|
|
umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
|
|
|
|
_("no domain with matching uuid '%s'"), uuidstr);
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
Rename internal APis
Rename virDomainIsActive to virDomainObjIsActive, and
virInterfaceIsActive to virInterfaceObjIsActive and finally
virNetworkIsActive to virNetworkObjIsActive.
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/conf/interface_conf.h, src/conf/network_conf.c,
src/conf/network_conf.h, src/lxc/lxc_driver.c,
src/network/bridge_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_driver.c, src/qemu/qemu_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c: Update for
renamed APIs.
2009-10-20 14:51:03 +00:00
|
|
|
if (virDomainObjIsActive(vm)) {
|
2008-11-19 16:58:23 +00:00
|
|
|
umlReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
|
|
|
|
"%s", _("cannot set memory of an active domain"));
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (newmem > vm->def->maxmem) {
|
|
|
|
umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
|
|
|
|
"%s", _("cannot set memory higher than max memory"));
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
vm->def->memory = newmem;
|
2008-12-04 21:13:58 +00:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
2008-12-04 21:13:58 +00:00
|
|
|
return ret;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int umlDomainGetInfo(virDomainPtr dom,
|
|
|
|
virDomainInfoPtr info) {
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2008-12-04 21:13:58 +00:00
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!vm) {
|
|
|
|
umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
|
2008-12-04 21:13:58 +00:00
|
|
|
"%s", _("no domain with matching uuid"));
|
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
info->state = vm->state;
|
|
|
|
|
Rename internal APis
Rename virDomainIsActive to virDomainObjIsActive, and
virInterfaceIsActive to virInterfaceObjIsActive and finally
virNetworkIsActive to virNetworkObjIsActive.
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/conf/interface_conf.h, src/conf/network_conf.c,
src/conf/network_conf.h, src/lxc/lxc_driver.c,
src/network/bridge_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_driver.c, src/qemu/qemu_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c: Update for
renamed APIs.
2009-10-20 14:51:03 +00:00
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2008-11-19 16:58:23 +00:00
|
|
|
info->cpuTime = 0;
|
|
|
|
} else {
|
|
|
|
if (umlGetProcessInfo(&(info->cpuTime), vm->pid) < 0) {
|
2008-12-04 21:13:58 +00:00
|
|
|
umlReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
|
|
|
|
"%s", _("cannot read cputime for domain"));
|
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
info->maxMem = vm->def->maxmem;
|
|
|
|
info->memory = vm->def->memory;
|
|
|
|
info->nrVirtCpu = vm->def->vcpus;
|
2008-12-04 21:13:58 +00:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
2008-12-04 21:13:58 +00:00
|
|
|
return ret;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static char *umlDomainDumpXML(virDomainPtr dom,
|
|
|
|
int flags ATTRIBUTE_UNUSED) {
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
char *ret = NULL;
|
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2008-12-04 21:13:58 +00:00
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!vm) {
|
|
|
|
umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
|
|
|
|
"%s", _("no domain with matching uuid"));
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
2010-02-09 18:58:01 +00:00
|
|
|
ret = virDomainDefFormat((flags & VIR_DOMAIN_XML_INACTIVE) && vm->newDef ?
|
2008-12-04 21:13:58 +00:00
|
|
|
vm->newDef : vm->def,
|
|
|
|
flags);
|
|
|
|
|
|
|
|
cleanup:
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
2008-12-04 21:13:58 +00:00
|
|
|
return ret;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int umlListDefinedDomains(virConnectPtr conn,
|
|
|
|
char **const names, int nnames) {
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = conn->privateData;
|
Convert virDomainObjListPtr to use a hash of domain objects
The current virDomainObjListPtr object stores domain objects in
an array. This means that to find a particular objects requires
O(n) time, and more critically acquiring O(n) mutex locks.
The new impl replaces the array with a virHashTable, keyed off
UUID. Finding a object based on UUID is now O(1) time, and only
requires a single mutex lock. Finding by name/id is unchanged
in complexity.
In changing this, all code which iterates over the array had
to be updated to use a hash table iterator function callback.
Several of the functions which were identically duplicating
across all drivers were pulled into domain_conf.c
* src/conf/domain_conf.h, src/conf/domain_conf.c: Change
virDomainObjListPtr to use virHashTable. Add a initializer
method virDomainObjListInit, and rename virDomainObjListFree
to virDomainObjListDeinit, since its not actually freeing
the container, only its contents. Also add some convenient
methods virDomainObjListGetInactiveNames,
virDomainObjListGetActiveIDs and virDomainObjListNumOfDomains
which can be used to implement the correspondingly named
public API entry points in drivers
* src/libvirt_private.syms: Export new methods from domain_conf.h
* src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_conf.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c: Update all code
to deal with hash tables instead of arrays for domains
2009-10-09 11:33:51 +00:00
|
|
|
int n;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
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:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
Convert virDomainObjListPtr to use a hash of domain objects
The current virDomainObjListPtr object stores domain objects in
an array. This means that to find a particular objects requires
O(n) time, and more critically acquiring O(n) mutex locks.
The new impl replaces the array with a virHashTable, keyed off
UUID. Finding a object based on UUID is now O(1) time, and only
requires a single mutex lock. Finding by name/id is unchanged
in complexity.
In changing this, all code which iterates over the array had
to be updated to use a hash table iterator function callback.
Several of the functions which were identically duplicating
across all drivers were pulled into domain_conf.c
* src/conf/domain_conf.h, src/conf/domain_conf.c: Change
virDomainObjListPtr to use virHashTable. Add a initializer
method virDomainObjListInit, and rename virDomainObjListFree
to virDomainObjListDeinit, since its not actually freeing
the container, only its contents. Also add some convenient
methods virDomainObjListGetInactiveNames,
virDomainObjListGetActiveIDs and virDomainObjListNumOfDomains
which can be used to implement the correspondingly named
public API entry points in drivers
* src/libvirt_private.syms: Export new methods from domain_conf.h
* src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_conf.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c: Update all code
to deal with hash tables instead of arrays for domains
2009-10-09 11:33:51 +00:00
|
|
|
return n;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int umlNumDefinedDomains(virConnectPtr conn) {
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = conn->privateData;
|
Convert virDomainObjListPtr to use a hash of domain objects
The current virDomainObjListPtr object stores domain objects in
an array. This means that to find a particular objects requires
O(n) time, and more critically acquiring O(n) mutex locks.
The new impl replaces the array with a virHashTable, keyed off
UUID. Finding a object based on UUID is now O(1) time, and only
requires a single mutex lock. Finding by name/id is unchanged
in complexity.
In changing this, all code which iterates over the array had
to be updated to use a hash table iterator function callback.
Several of the functions which were identically duplicating
across all drivers were pulled into domain_conf.c
* src/conf/domain_conf.h, src/conf/domain_conf.c: Change
virDomainObjListPtr to use virHashTable. Add a initializer
method virDomainObjListInit, and rename virDomainObjListFree
to virDomainObjListDeinit, since its not actually freeing
the container, only its contents. Also add some convenient
methods virDomainObjListGetInactiveNames,
virDomainObjListGetActiveIDs and virDomainObjListNumOfDomains
which can be used to implement the correspondingly named
public API entry points in drivers
* src/libvirt_private.syms: Export new methods from domain_conf.h
* src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_conf.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/test/test_driver.c,
src/uml/uml_driver.c, src/vbox/vbox_tmpl.c: Update all code
to deal with hash tables instead of arrays for domains
2009-10-09 11:33:51 +00:00
|
|
|
int n;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
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:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int umlDomainStart(virDomainPtr dom) {
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2008-12-04 21:13:58 +00:00
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
2008-12-04 21:14:39 +00:00
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!vm) {
|
|
|
|
umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
|
|
|
|
"%s", _("no domain with matching uuid"));
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
2008-12-04 21:13:58 +00:00
|
|
|
ret = umlStartVMDaemon(dom->conn, driver, vm);
|
|
|
|
|
|
|
|
cleanup:
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
umlDriverUnlock(driver);
|
2008-12-04 21:13:58 +00:00
|
|
|
return ret;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static virDomainPtr umlDomainDefine(virConnectPtr conn, const char *xml) {
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = conn->privateData;
|
2008-11-19 16:58:23 +00:00
|
|
|
virDomainDefPtr def;
|
2008-12-04 21:14:39 +00:00
|
|
|
virDomainObjPtr vm = NULL;
|
2008-12-04 21:13:58 +00:00
|
|
|
virDomainPtr dom = NULL;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2010-02-09 18:58:01 +00:00
|
|
|
if (!(def = virDomainDefParseString(driver->caps, xml,
|
2009-01-08 13:54:20 +00:00
|
|
|
VIR_DOMAIN_XML_INACTIVE)))
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2009-11-02 18:37:38 +00:00
|
|
|
if (virDomainObjIsDuplicate(&driver->domains, def, 0) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2010-02-09 18:58:01 +00:00
|
|
|
if (!(vm = virDomainAssignDef(driver->caps,
|
2008-11-19 16:58:23 +00:00
|
|
|
&driver->domains,
|
2008-12-04 21:13:58 +00:00
|
|
|
def)))
|
|
|
|
goto cleanup;
|
|
|
|
def = NULL;
|
2008-11-19 16:58:23 +00:00
|
|
|
vm->persistent = 1;
|
|
|
|
|
2010-02-09 18:58:01 +00:00
|
|
|
if (virDomainSaveConfig(driver->configDir,
|
2008-11-19 16:58:23 +00:00
|
|
|
vm->newDef ? vm->newDef : vm->def) < 0) {
|
|
|
|
virDomainRemoveInactive(&driver->domains,
|
|
|
|
vm);
|
2008-12-04 21:14:39 +00:00
|
|
|
vm = NULL;
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
|
|
|
if (dom) dom->id = vm->def->id;
|
2008-12-04 21:13:58 +00:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virDomainDefFree(def);
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
umlDriverUnlock(driver);
|
2008-11-19 16:58:23 +00:00
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int umlDomainUndefine(virDomainPtr dom) {
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2008-12-04 21:13:58 +00:00
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!vm) {
|
|
|
|
umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
|
|
|
|
"%s", _("no domain with matching uuid"));
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
Rename internal APis
Rename virDomainIsActive to virDomainObjIsActive, and
virInterfaceIsActive to virInterfaceObjIsActive and finally
virNetworkIsActive to virNetworkObjIsActive.
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/conf/interface_conf.h, src/conf/network_conf.c,
src/conf/network_conf.h, src/lxc/lxc_driver.c,
src/network/bridge_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_driver.c, src/qemu/qemu_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c: Update for
renamed APIs.
2009-10-20 14:51:03 +00:00
|
|
|
if (virDomainObjIsActive(vm)) {
|
2008-11-19 16:58:23 +00:00
|
|
|
umlReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("cannot delete active domain"));
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!vm->persistent) {
|
|
|
|
umlReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("cannot undefine transient domain"));
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
2010-02-09 18:58:01 +00:00
|
|
|
if (virDomainDeleteConfig(driver->configDir, driver->autostartDir, vm) < 0)
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
|
|
|
virDomainRemoveInactive(&driver->domains,
|
|
|
|
vm);
|
2008-12-04 21:14:39 +00:00
|
|
|
vm = NULL;
|
2008-12-04 21:13:58 +00:00
|
|
|
ret = 0;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:13:58 +00:00
|
|
|
cleanup:
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
umlDriverUnlock(driver);
|
2008-12-04 21:13:58 +00:00
|
|
|
return ret;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int umlDomainGetAutostart(virDomainPtr dom,
|
|
|
|
int *autostart) {
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2008-12-04 21:13:58 +00:00
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
2008-12-04 21:14:39 +00:00
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!vm) {
|
|
|
|
umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
|
|
|
|
"%s", _("no domain with matching uuid"));
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
*autostart = vm->autostart;
|
2008-12-04 21:13:58 +00:00
|
|
|
ret = 0;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:13:58 +00:00
|
|
|
cleanup:
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
2009-05-19 11:06:25 +00:00
|
|
|
umlDriverUnlock(driver);
|
2008-12-04 21:13:58 +00:00
|
|
|
return ret;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int umlDomainSetAutostart(virDomainPtr dom,
|
|
|
|
int autostart) {
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
2008-12-04 21:14:39 +00:00
|
|
|
virDomainObjPtr vm;
|
2008-11-19 16:58:23 +00:00
|
|
|
char *configFile = NULL, *autostartLink = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!vm) {
|
|
|
|
umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
|
|
|
|
"%s", _("no domain with matching uuid"));
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!vm->persistent) {
|
|
|
|
umlReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("cannot set autostart for transient domain"));
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
autostart = (autostart != 0);
|
|
|
|
|
2008-12-04 21:13:58 +00:00
|
|
|
if (vm->autostart != autostart) {
|
2010-02-09 18:58:01 +00:00
|
|
|
if ((configFile = virDomainConfigFile(driver->configDir, vm->def->name)) == NULL)
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2010-02-09 18:58:01 +00:00
|
|
|
if ((autostartLink = virDomainConfigFile(driver->autostartDir, vm->def->name)) == NULL)
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:13:58 +00:00
|
|
|
if (autostart) {
|
|
|
|
int err;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:13:58 +00:00
|
|
|
if ((err = virFileMakePath(driver->autostartDir))) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(err,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("cannot create autostart directory %s"),
|
|
|
|
driver->autostartDir);
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:13:58 +00:00
|
|
|
if (symlink(configFile, autostartLink) < 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("Failed to create symlink '%s to '%s'"),
|
|
|
|
autostartLink, configFile);
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("Failed to delete symlink '%s'"),
|
|
|
|
autostartLink);
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
2008-12-04 21:13:58 +00:00
|
|
|
vm->autostart = autostart;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(configFile);
|
|
|
|
VIR_FREE(autostartLink);
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
2009-05-19 11:06:25 +00:00
|
|
|
umlDriverUnlock(driver);
|
2008-11-19 16:58:23 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
umlDomainBlockPeek (virDomainPtr dom,
|
|
|
|
const char *path,
|
|
|
|
unsigned long long offset, size_t size,
|
|
|
|
void *buffer,
|
|
|
|
unsigned int flags ATTRIBUTE_UNUSED)
|
|
|
|
{
|
2008-12-04 21:13:58 +00:00
|
|
|
struct uml_driver *driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
int fd = -1, ret = -1, i;
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverLock(driver);
|
2008-12-04 21:13:58 +00:00
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
2008-12-04 21:14:39 +00:00
|
|
|
umlDriverUnlock(driver);
|
|
|
|
|
2008-11-19 16:58:23 +00:00
|
|
|
if (!vm) {
|
|
|
|
umlReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
|
2008-12-10 16:35:00 +00:00
|
|
|
"%s", _("no domain with matching uuid"));
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!path || path[0] == '\0') {
|
|
|
|
umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
|
2008-12-10 16:35:00 +00:00
|
|
|
"%s", _("NULL or empty path"));
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Check the path belongs to this domain. */
|
|
|
|
for (i = 0 ; i < vm->def->ndisks ; i++) {
|
|
|
|
if (vm->def->disks[i]->src != NULL &&
|
2008-12-04 21:13:58 +00:00
|
|
|
STREQ (vm->def->disks[i]->src, path)) {
|
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
}
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
2008-12-04 21:13:58 +00:00
|
|
|
if (ret == 0) {
|
|
|
|
ret = -1;
|
|
|
|
/* The path is correct, now try to open it and get its size. */
|
|
|
|
fd = open (path, O_RDONLY);
|
|
|
|
if (fd == -1) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("cannot open %s"), path);
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2008-11-19 16:58:23 +00:00
|
|
|
|
2008-12-04 21:13:58 +00:00
|
|
|
/* Seek and read. */
|
|
|
|
/* NB. Because we configure with AC_SYS_LARGEFILE, off_t should
|
|
|
|
* be 64 bits on all platforms.
|
|
|
|
*/
|
|
|
|
if (lseek (fd, offset, SEEK_SET) == (off_t) -1 ||
|
|
|
|
saferead (fd, buffer, size) == (ssize_t) -1) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("cannot read %s"), path);
|
2008-12-04 21:13:58 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
} else {
|
|
|
|
umlReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
|
2008-12-10 16:35:00 +00:00
|
|
|
"%s", _("invalid path"));
|
2008-11-19 16:58:23 +00:00
|
|
|
}
|
|
|
|
|
2008-12-04 21:13:58 +00:00
|
|
|
cleanup:
|
2008-11-19 16:58:23 +00:00
|
|
|
if (fd >= 0) close (fd);
|
2008-12-04 21:14:39 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
2008-11-19 16:58:23 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static virDriver umlDriver = {
|
|
|
|
VIR_DRV_UML,
|
|
|
|
"UML",
|
|
|
|
umlOpen, /* open */
|
|
|
|
umlClose, /* close */
|
|
|
|
NULL, /* supports_feature */
|
|
|
|
umlGetType, /* type */
|
|
|
|
umlGetVersion, /* version */
|
2009-11-12 15:53:26 +00:00
|
|
|
NULL, /* libvirtVersion (impl. in libvirt.c) */
|
2009-10-23 17:01:22 +00:00
|
|
|
virGetHostname, /* getHostname */
|
2008-11-19 16:58:23 +00:00
|
|
|
NULL, /* getMaxVcpus */
|
2009-06-03 13:28:02 +00:00
|
|
|
nodeGetInfo, /* nodeGetInfo */
|
2008-11-19 16:58:23 +00:00
|
|
|
umlGetCapabilities, /* getCapabilities */
|
|
|
|
umlListDomains, /* listDomains */
|
|
|
|
umlNumDomains, /* numOfDomains */
|
|
|
|
umlDomainCreate, /* domainCreateXML */
|
|
|
|
umlDomainLookupByID, /* domainLookupByID */
|
|
|
|
umlDomainLookupByUUID, /* domainLookupByUUID */
|
|
|
|
umlDomainLookupByName, /* domainLookupByName */
|
|
|
|
NULL, /* domainSuspend */
|
|
|
|
NULL, /* domainResume */
|
|
|
|
umlDomainShutdown, /* domainShutdown */
|
|
|
|
NULL, /* domainReboot */
|
|
|
|
umlDomainDestroy, /* domainDestroy */
|
|
|
|
umlDomainGetOSType, /* domainGetOSType */
|
|
|
|
umlDomainGetMaxMemory, /* domainGetMaxMemory */
|
|
|
|
umlDomainSetMaxMemory, /* domainSetMaxMemory */
|
|
|
|
umlDomainSetMemory, /* domainSetMemory */
|
|
|
|
umlDomainGetInfo, /* 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-11-19 16:58:23 +00:00
|
|
|
umlDomainDumpXML, /* domainDumpXML */
|
2009-09-06 14:03:06 +00:00
|
|
|
NULL, /* domainXMLFromNative */
|
|
|
|
NULL, /* domainXMLToNative */
|
2009-03-31 15:47:16 +00:00
|
|
|
umlListDefinedDomains, /* listDefinedDomains */
|
|
|
|
umlNumDefinedDomains, /* numOfDefinedDomains */
|
2008-11-19 16:58:23 +00:00
|
|
|
umlDomainStart, /* domainCreate */
|
|
|
|
umlDomainDefine, /* domainDefineXML */
|
|
|
|
umlDomainUndefine, /* domainUndefine */
|
|
|
|
NULL, /* domainAttachDevice */
|
2010-01-14 01:44:26 +00:00
|
|
|
NULL, /* domainAttachDeviceFlags */
|
2008-11-19 16:58:23 +00:00
|
|
|
NULL, /* domainDetachDevice */
|
2010-01-14 01:44:26 +00:00
|
|
|
NULL, /* domainDetachDeviceFlags */
|
2008-11-19 16:58:23 +00:00
|
|
|
umlDomainGetAutostart, /* domainGetAutostart */
|
|
|
|
umlDomainSetAutostart, /* domainSetAutostart */
|
|
|
|
NULL, /* domainGetSchedulerType */
|
|
|
|
NULL, /* domainGetSchedulerParameters */
|
|
|
|
NULL, /* domainSetSchedulerParameters */
|
|
|
|
NULL, /* domainMigratePrepare */
|
|
|
|
NULL, /* domainMigratePerform */
|
|
|
|
NULL, /* domainMigrateFinish */
|
|
|
|
NULL, /* domainBlockStats */
|
|
|
|
NULL, /* domainInterfaceStats */
|
2009-12-20 12:28:42 +00:00
|
|
|
NULL, /* domainMemoryStats */
|
2008-11-19 16:58:23 +00:00
|
|
|
umlDomainBlockPeek, /* domainBlockPeek */
|
|
|
|
NULL, /* domainMemoryPeek */
|
2009-08-27 18:13:11 +00:00
|
|
|
nodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */
|
|
|
|
nodeGetFreeMemory, /* getFreeMemory */
|
2008-11-19 16:58:23 +00:00
|
|
|
NULL, /* domainEventRegister */
|
2009-03-31 15:47:16 +00:00
|
|
|
NULL, /* domainEventDeregister */
|
2008-11-19 16:58:23 +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 */
|
Implmentation of new APIs to checking state/persistence of objects
This implements the virConnectIsSecure, virConnectIsEncrypted,
virDomainIsPersistent, virDomainIsActive, virNetworkIsActive,
virNetworkIsPersistent, virStoragePoolIsActive,
virStoragePoolIsPersistent, virInterfaceIsActive APIs in
(nearly) all drivers. Exceptions are:
phyp: missing domainIsActive/Persistent
esx: missing domainIsPersistent
opennebula: missing domainIsActive/Persistent
* src/remote/remote_protocol.x: Define remote wire ABI for newly
added APIs.
* daemon/remote_dispatch*.h: Re-generated from remote_protocol.x
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/opennebula/one_driver.c, src/openvz/openvz_conf.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/remote/remote_driver.c, src/storage/storage_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c, src/xen/xen_driver.h, src/xen/xen_inotify.c,
src/xen/xen_inotify.h: Implement all the new APIs where possible
2009-10-20 14:12:03 +00:00
|
|
|
umlIsEncrypted,
|
|
|
|
umlIsSecure,
|
|
|
|
umlDomainIsActive,
|
|
|
|
umlDomainIsPersistent,
|
2009-12-18 13:59:39 +00:00
|
|
|
NULL, /* cpuCompare */
|
2010-02-02 11:34:01 +00:00
|
|
|
NULL, /* cpuBaseline */
|
Stub out internal driver entry points for job processing
The internal glue layer for the new pubic API
* src/driver.h: Define internal driver API contract
* src/libvirt.c, src/libvirt_public.syms: Wire up public
API to internal driver API
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/qemu/qemu_driver.c, src/remote/remote_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c: Stub new entry point
2010-02-03 11:32:24 +00:00
|
|
|
NULL, /* domainGetJobInfo */
|
Wire up internal entry points for virDomainAbortJob API
This provides the internal glue for the driver API
* src/driver.h: Internal API contract
* src/libvirt.c, src/libvirt_public.syms: Connect public API
to driver API
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/qemu/qemu_driver.c, src/remote/remote_driver.c,
src/test/test_driver.c src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c: Stub out entry points
2010-02-04 16:16:35 +00:00
|
|
|
NULL, /* domainAbortJob */
|
2008-11-19 16:58:23 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static virStateDriver umlStateDriver = {
|
Fix return value in virStateInitialize impl for LXC
The LXC driver was mistakenly returning -1 for lxcStartup()
in scenarios that are not an error. This caused the libvirtd
to quit for unprivileged users. This fixes the return code
of LXC driver, and also adds a "name" field to the virStateDriver
struct and logging to make it easier to find these problems
in the future
* src/driver.h: Add a 'name' field to state driver to allow
easy identification during failures
* src/libvirt.c: Log name of failed driver for virStateInit
failures
* src/lxc/lxc_driver.c: Don't return a failure code for
lxcStartup() if LXC is not available on this host, simply
disable the driver.
* src/network/bridge_driver.c, src/node_device/node_device_devkit.c,
src/node_device/node_device_hal.c, src/opennebula/one_driver.c,
src/qemu/qemu_driver.c, src/remote/remote_driver.c,
src/secret/secret_driver.c, src/storage/storage_driver.c,
src/uml/uml_driver.c, src/xen/xen_driver.c: Fill in name
field in virStateDriver struct
2009-11-02 23:18:19 +00:00
|
|
|
.name = "UML",
|
2008-11-19 16:58:23 +00:00
|
|
|
.initialize = umlStartup,
|
|
|
|
.cleanup = umlShutdown,
|
|
|
|
.reload = umlReload,
|
|
|
|
.active = umlActive,
|
|
|
|
};
|
|
|
|
|
|
|
|
int umlRegister(void) {
|
|
|
|
virRegisterDriver(¨Driver);
|
|
|
|
virRegisterStateDriver(¨StateDriver);
|
|
|
|
return 0;
|
|
|
|
}
|