2011-02-10 22:42:34 +00:00
|
|
|
/*---------------------------------------------------------------------------*/
|
xml: use long long internally, to centralize overflow checks
On 64-bit platforms, unsigned long and unsigned long long are
identical, so we don't have to worry about overflow checks.
On 32-bit platforms, anywhere we narrow unsigned long long back
to unsigned long, we have to worry about overflow; it's easier
to do this in one place by having most of the code use the same
or wider types, and only doing the narrowing at the last minute.
Therefore, the memory set commands remain unsigned long, and
the memory get command now centralizes the overflow check into
libvirt.c, so that drivers don't have to repeat the work.
This also fixes a bug where xen returned the wrong value on
failure (most APIs return -1 on failure, but getMaxMemory
must return 0 on failure).
* src/driver.h (virDrvDomainGetMaxMemory): Use long long.
* src/libvirt.c (virDomainGetMaxMemory): Raise overflow.
* src/test/test_driver.c (testGetMaxMemory): Fix driver.
* src/rpc/gendispatch.pl (name_to_ProcName): Likewise.
* src/xen/xen_hypervisor.c (xenHypervisorGetMaxMemory): Likewise.
* src/xen/xen_driver.c (xenUnifiedDomainGetMaxMemory): Likewise.
* src/xen/xend_internal.c (xenDaemonDomainGetMaxMemory):
Likewise.
* src/xen/xend_internal.h (xenDaemonDomainGetMaxMemory):
Likewise.
* src/xen/xm_internal.c (xenXMDomainGetMaxMemory): Likewise.
* src/xen/xm_internal.h (xenXMDomainGetMaxMemory): Likewise.
* src/xen/xs_internal.c (xenStoreDomainGetMaxMemory): Likewise.
* src/xen/xs_internal.h (xenStoreDomainGetMaxMemory): Likewise.
* src/xenapi/xenapi_driver.c (xenapiDomainGetMaxMemory):
Likewise.
* src/esx/esx_driver.c (esxDomainGetMaxMemory): Likewise.
* src/libxl/libxl_driver.c (libxlDomainGetMaxMemory): Likewise.
* src/qemu/qemu_driver.c (qemudDomainGetMaxMemory): Likewise.
* src/lxc/lxc_driver.c (lxcDomainGetMaxMemory): Likewise.
* src/uml/uml_driver.c (umlDomainGetMaxMemory): Likewise.
2012-03-03 00:47:16 +00:00
|
|
|
/* Copyright (C) 2006-2012 Red Hat, Inc.
|
|
|
|
* Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany.
|
2011-02-10 22:42:34 +00:00
|
|
|
* Copyright (C) 2011 Univention GmbH.
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2012-09-20 22:30:55 +00:00
|
|
|
* License along with this library. If not, see
|
2012-07-21 10:06:23 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2011-03-29 12:24:05 +00:00
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Jim Fehlig <jfehlig@novell.com>
|
|
|
|
* Markus Groß <gross@univention.de>
|
|
|
|
* Daniel P. Berrange <berrange@redhat.com>
|
2011-02-10 22:42:34 +00:00
|
|
|
*/
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <sys/utsname.h>
|
2011-03-29 12:31:45 +00:00
|
|
|
#include <math.h>
|
2011-02-10 22:42:34 +00:00
|
|
|
#include <libxl.h>
|
2011-05-30 09:53:02 +00:00
|
|
|
#include <fcntl.h>
|
2011-02-10 22:42:34 +00:00
|
|
|
|
|
|
|
#include "internal.h"
|
|
|
|
#include "logging.h"
|
|
|
|
#include "virterror_internal.h"
|
2011-03-29 12:39:18 +00:00
|
|
|
#include "conf.h"
|
2011-02-10 22:42:34 +00:00
|
|
|
#include "datatypes.h"
|
2011-07-19 18:32:58 +00:00
|
|
|
#include "virfile.h"
|
2011-02-10 22:42:34 +00:00
|
|
|
#include "memory.h"
|
|
|
|
#include "uuid.h"
|
|
|
|
#include "command.h"
|
|
|
|
#include "libxl_driver.h"
|
|
|
|
#include "libxl_conf.h"
|
2011-03-29 12:39:18 +00:00
|
|
|
#include "xen_xm.h"
|
2012-01-07 12:47:43 +00:00
|
|
|
#include "virtypedparam.h"
|
2012-02-24 18:48:55 +00:00
|
|
|
#include "viruri.h"
|
2011-02-10 22:42:34 +00:00
|
|
|
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_LIBXL
|
|
|
|
|
|
|
|
#define LIBXL_DOM_REQ_POWEROFF 0
|
|
|
|
#define LIBXL_DOM_REQ_REBOOT 1
|
|
|
|
#define LIBXL_DOM_REQ_SUSPEND 2
|
|
|
|
#define LIBXL_DOM_REQ_CRASH 3
|
|
|
|
#define LIBXL_DOM_REQ_HALT 4
|
|
|
|
|
2011-03-29 12:39:18 +00:00
|
|
|
#define LIBXL_CONFIG_FORMAT_XM "xen-xm"
|
|
|
|
|
2011-03-29 12:46:55 +00:00
|
|
|
/* Number of Xen scheduler parameters */
|
|
|
|
#define XEN_SCHED_CREDIT_NPARAM 2
|
|
|
|
|
2012-06-11 09:03:27 +00:00
|
|
|
static void libxlDomainManagedSaveLoad(void *payload,
|
|
|
|
const void *n ATTRIBUTE_UNUSED,
|
|
|
|
void *opaque);
|
|
|
|
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
static libxlDriverPrivatePtr libxl_driver = NULL;
|
|
|
|
|
|
|
|
/* Function declarations */
|
|
|
|
static int
|
2011-05-30 09:53:02 +00:00
|
|
|
libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm,
|
|
|
|
bool start_paused, int restore_fd);
|
2011-02-10 22:42:34 +00:00
|
|
|
|
|
|
|
/* Function definitions */
|
|
|
|
static void
|
|
|
|
libxlDriverLock(libxlDriverPrivatePtr driver)
|
|
|
|
{
|
|
|
|
virMutexLock(&driver->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
libxlDriverUnlock(libxlDriverPrivatePtr driver)
|
|
|
|
{
|
|
|
|
virMutexUnlock(&driver->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *
|
|
|
|
libxlDomainObjPrivateAlloc(void)
|
|
|
|
{
|
|
|
|
libxlDomainObjPrivatePtr priv;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(priv) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
libxl_ctx_init(&priv->ctx, LIBXL_VERSION, libxl_driver->logger);
|
|
|
|
priv->waiterFD = -1;
|
|
|
|
priv->eventHdl = -1;
|
|
|
|
|
|
|
|
return priv;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
libxlDomainObjPrivateFree(void *data)
|
|
|
|
{
|
|
|
|
libxlDomainObjPrivatePtr priv = data;
|
|
|
|
|
|
|
|
if (priv->eventHdl >= 0)
|
|
|
|
virEventRemoveHandle(priv->eventHdl);
|
|
|
|
|
|
|
|
if (priv->dWaiter) {
|
|
|
|
libxl_stop_waiting(&priv->ctx, priv->dWaiter);
|
|
|
|
libxl_free_waiter(priv->dWaiter);
|
|
|
|
VIR_FREE(priv->dWaiter);
|
|
|
|
}
|
|
|
|
|
|
|
|
libxl_ctx_free(&priv->ctx);
|
|
|
|
VIR_FREE(priv);
|
|
|
|
}
|
|
|
|
|
2011-03-29 12:18:24 +00:00
|
|
|
|
|
|
|
/* driver must be locked before calling */
|
|
|
|
static void
|
|
|
|
libxlDomainEventQueue(libxlDriverPrivatePtr driver, virDomainEventPtr event)
|
|
|
|
{
|
2011-05-12 14:47:08 +00:00
|
|
|
virDomainEventStateQueue(driver->domainEventState, event);
|
2011-03-29 12:18:24 +00:00
|
|
|
}
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
/*
|
|
|
|
* Remove reference to domain object.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
libxlDomainObjUnref(void *data)
|
|
|
|
{
|
|
|
|
virDomainObjPtr vm = data;
|
|
|
|
|
2012-07-11 13:35:46 +00:00
|
|
|
virObjectUnref(vm);
|
2011-02-10 22:42:34 +00:00
|
|
|
}
|
|
|
|
|
2011-03-28 10:49:22 +00:00
|
|
|
static void
|
|
|
|
libxlAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED,
|
|
|
|
void *opaque)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = opaque;
|
|
|
|
virDomainObjPtr vm = payload;
|
|
|
|
virErrorPtr err;
|
|
|
|
|
|
|
|
virDomainObjLock(vm);
|
|
|
|
virResetLastError();
|
|
|
|
|
|
|
|
if (vm->autostart && !virDomainObjIsActive(vm) &&
|
2011-05-30 09:53:02 +00:00
|
|
|
libxlVmStart(driver, vm, false, -1) < 0) {
|
2011-03-28 10:49:22 +00:00
|
|
|
err = virGetLastError();
|
|
|
|
VIR_ERROR(_("Failed to autostart VM '%s': %s"),
|
|
|
|
vm->def->name,
|
|
|
|
err ? err->message : _("unknown error"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
}
|
|
|
|
|
2011-04-18 09:16:33 +00:00
|
|
|
static int
|
|
|
|
libxlDoNodeGetInfo(libxlDriverPrivatePtr driver, virNodeInfoPtr info)
|
|
|
|
{
|
|
|
|
libxl_physinfo phy_info;
|
|
|
|
const libxl_version_info* ver_info;
|
|
|
|
struct utsname utsname;
|
|
|
|
|
|
|
|
if (libxl_get_physinfo(&driver->ctx, &phy_info)) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("libxl_get_physinfo_info failed"));
|
2011-04-18 09:16:33 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((ver_info = libxl_get_version_info(&driver->ctx)) == NULL) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("libxl_get_version_info failed"));
|
2011-04-18 09:16:33 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
uname(&utsname);
|
|
|
|
if (virStrncpy(info->model,
|
|
|
|
utsname.machine,
|
|
|
|
strlen(utsname.machine),
|
|
|
|
sizeof(info->model)) == NULL) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("machine type %s too big for destination"),
|
|
|
|
utsname.machine);
|
2011-04-18 09:16:33 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
info->memory = phy_info.total_pages * (ver_info->pagesize / 1024);
|
|
|
|
info->cpus = phy_info.nr_cpus;
|
|
|
|
info->nodes = phy_info.nr_nodes;
|
|
|
|
info->cores = phy_info.cores_per_socket;
|
|
|
|
info->threads = phy_info.threads_per_core;
|
|
|
|
info->sockets = 1;
|
|
|
|
info->mhz = phy_info.cpu_khz / 1000;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-06-02 12:24:30 +00:00
|
|
|
static char *
|
|
|
|
libxlDomainManagedSavePath(libxlDriverPrivatePtr driver, virDomainObjPtr vm) {
|
|
|
|
char *ret;
|
|
|
|
|
|
|
|
if (virAsprintf(&ret, "%s/%s.save", driver->saveDir, vm->def->name) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This internal function expects the driver lock to already be held on
|
|
|
|
* entry. */
|
|
|
|
static int ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4)
|
|
|
|
libxlSaveImageOpen(libxlDriverPrivatePtr driver, const char *from,
|
|
|
|
virDomainDefPtr *ret_def, libxlSavefileHeaderPtr ret_hdr)
|
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
virDomainDefPtr def = NULL;
|
|
|
|
libxlSavefileHeader hdr;
|
|
|
|
char *xml = NULL;
|
|
|
|
|
util: refactor virFileOpenAs
virFileOpenAs previously would only try opening a file as the current
user, or as a different user, but wouldn't try both methods in a
single call. This made it cumbersome to use as a replacement for
open(2). Additionally, it had a lot of historical baggage that led to
it being difficult to understand.
This patch refactors virFileOpenAs in the following ways:
* reorganize the code so that everything dealing with both the parent
and child sides of the "fork+setuid+setgid+open" method are in a
separate function. This makes the public function easier to understand.
* Allow a single call to virFileOpenAs() to first attempt the open as
the current user, and if that fails to automatically re-try after
doing fork+setuid (if deemed appropriate, i.e. errno indicates it
would now be successful, and the file is on a networkFS). This makes
it possible (in many, but possibly not all, cases) to drop-in
virFileOpenAs() as a replacement for open(2).
(NB: currently qemuOpenFile() calls virFileOpenAs() twice, once
without forking, then again with forking. That unfortunately can't
be changed without at least some discussion of the ramifications,
because the requested file permissions are different in each case,
which is something that a single call to virFileOpenAs() can't deal
with.)
* Add a flag so that any fchown() of the file to a different uid:gid
is explicitly requested when the function is called, rather than it
being implied by the presence of the O_CREAT flag. This just makes
for less subtle surprises to consumers. (Commit
b1643dc15c5de886fefe56ad18608d65f1325a2c added the check for O_CREAT
before forcing ownership. This patch just makes that restriction
more explicit.)
* If either the uid or gid is specified as "-1", virFileOpenAs will
interpret this to mean "the current [gu]id".
All current consumers of virFileOpenAs should retain their present
behavior (after a few minor changes to their setup code and
arguments).
2012-01-13 20:26:45 +00:00
|
|
|
if ((fd = virFileOpenAs(from, O_RDONLY, 0, -1, -1, 0)) < 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
"%s", _("cannot read domain image"));
|
2011-06-02 12:24:30 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (saferead(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
"%s", _("failed to read libxl header"));
|
2011-06-02 12:24:30 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (memcmp(hdr.magic, LIBXL_SAVE_MAGIC, sizeof(hdr.magic))) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s", _("image magic is incorrect"));
|
2011-06-02 12:24:30 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hdr.version > LIBXL_SAVE_VERSION) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("image version is not supported (%d > %d)"),
|
|
|
|
hdr.version, LIBXL_SAVE_VERSION);
|
2011-06-02 12:24:30 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hdr.xmlLen <= 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("invalid XML length: %d"), hdr.xmlLen);
|
2011-06-02 12:24:30 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(xml, hdr.xmlLen) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (saferead(fd, xml, hdr.xmlLen) != hdr.xmlLen) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("failed to read XML"));
|
2011-06-02 12:24:30 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(def = virDomainDefParseString(driver->caps, xml,
|
2011-07-11 17:29:09 +00:00
|
|
|
1 << VIR_DOMAIN_VIRT_XEN,
|
2011-06-02 12:24:30 +00:00
|
|
|
VIR_DOMAIN_XML_INACTIVE)))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
VIR_FREE(xml);
|
|
|
|
|
|
|
|
*ret_def = def;
|
|
|
|
*ret_hdr = hdr;
|
|
|
|
|
|
|
|
return fd;
|
|
|
|
|
|
|
|
error:
|
|
|
|
VIR_FREE(xml);
|
|
|
|
virDomainDefFree(def);
|
|
|
|
VIR_FORCE_CLOSE(fd);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
/*
|
|
|
|
* Cleanup function for domain that has reached shutoff state.
|
|
|
|
*
|
|
|
|
* virDomainObjPtr should be locked on invocation
|
|
|
|
*/
|
|
|
|
static void
|
2011-05-04 09:07:01 +00:00
|
|
|
libxlVmCleanup(libxlDriverPrivatePtr driver,
|
|
|
|
virDomainObjPtr vm,
|
|
|
|
virDomainShutoffReason reason)
|
2011-02-10 22:42:34 +00:00
|
|
|
{
|
|
|
|
libxlDomainObjPrivatePtr priv = vm->privateData;
|
|
|
|
int vnc_port;
|
|
|
|
char *file;
|
2011-04-18 09:16:33 +00:00
|
|
|
int i;
|
2011-02-10 22:42:34 +00:00
|
|
|
|
|
|
|
if (priv->eventHdl >= 0) {
|
|
|
|
virEventRemoveHandle(priv->eventHdl);
|
|
|
|
priv->eventHdl = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (priv->dWaiter) {
|
|
|
|
libxl_stop_waiting(&priv->ctx, priv->dWaiter);
|
|
|
|
libxl_free_waiter(priv->dWaiter);
|
|
|
|
VIR_FREE(priv->dWaiter);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vm->persistent) {
|
|
|
|
vm->def->id = -1;
|
2011-05-04 09:07:01 +00:00
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, reason);
|
2011-02-10 22:42:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ((vm->def->ngraphics == 1) &&
|
|
|
|
vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
|
|
|
|
vm->def->graphics[0]->data.vnc.autoport) {
|
|
|
|
vnc_port = vm->def->graphics[0]->data.vnc.port;
|
|
|
|
if (vnc_port >= LIBXL_VNC_PORT_MIN) {
|
|
|
|
if (virBitmapClearBit(driver->reservedVNCPorts,
|
|
|
|
vnc_port - LIBXL_VNC_PORT_MIN) < 0)
|
|
|
|
VIR_DEBUG("Could not mark port %d as unused", vnc_port);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-04-18 09:16:33 +00:00
|
|
|
/* Remove any cputune settings */
|
|
|
|
if (vm->def->cputune.nvcpupin) {
|
|
|
|
for (i = 0; i < vm->def->cputune.nvcpupin; ++i) {
|
|
|
|
VIR_FREE(vm->def->cputune.vcpupin[i]->cpumask);
|
|
|
|
VIR_FREE(vm->def->cputune.vcpupin[i]);
|
|
|
|
}
|
|
|
|
VIR_FREE(vm->def->cputune.vcpupin);
|
|
|
|
vm->def->cputune.nvcpupin = 0;
|
|
|
|
}
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
if (virAsprintf(&file, "%s/%s.xml", driver->stateDir, vm->def->name) > 0) {
|
|
|
|
if (unlink(file) < 0 && errno != ENOENT && errno != ENOTDIR)
|
|
|
|
VIR_DEBUG("Failed to remove domain XML for %s", vm->def->name);
|
|
|
|
VIR_FREE(file);
|
|
|
|
}
|
2011-05-26 15:16:31 +00:00
|
|
|
|
|
|
|
if (vm->newDef) {
|
|
|
|
virDomainDefFree(vm->def);
|
|
|
|
vm->def = vm->newDef;
|
|
|
|
vm->def->id = -1;
|
|
|
|
vm->newDef = NULL;
|
|
|
|
}
|
2011-02-10 22:42:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Reap a domain from libxenlight.
|
|
|
|
*
|
|
|
|
* virDomainObjPtr should be locked on invocation
|
|
|
|
*/
|
|
|
|
static int
|
2011-05-04 09:07:01 +00:00
|
|
|
libxlVmReap(libxlDriverPrivatePtr driver,
|
|
|
|
virDomainObjPtr vm,
|
|
|
|
int force,
|
|
|
|
virDomainShutoffReason reason)
|
2011-02-10 22:42:34 +00:00
|
|
|
{
|
|
|
|
libxlDomainObjPrivatePtr priv = vm->privateData;
|
|
|
|
|
|
|
|
if (libxl_domain_destroy(&priv->ctx, vm->def->id, force) < 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unable to cleanup domain %d"), vm->def->id);
|
2011-02-10 22:42:34 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-05-04 09:07:01 +00:00
|
|
|
libxlVmCleanup(driver, vm, reason);
|
2011-02-10 22:42:34 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Handle previously registered event notification from libxenlight
|
|
|
|
*/
|
|
|
|
static void libxlEventHandler(int watch,
|
|
|
|
int fd,
|
|
|
|
int events,
|
|
|
|
void *data)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = libxl_driver;
|
|
|
|
virDomainObjPtr vm = data;
|
|
|
|
libxlDomainObjPrivatePtr priv;
|
2011-03-29 12:18:24 +00:00
|
|
|
virDomainEventPtr dom_event = NULL;
|
2011-02-10 22:42:34 +00:00
|
|
|
libxl_event event;
|
|
|
|
libxl_dominfo info;
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
virDomainObjLock(vm);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
|
|
|
|
priv = vm->privateData;
|
|
|
|
|
|
|
|
memset(&event, 0, sizeof(event));
|
|
|
|
memset(&info, 0, sizeof(info));
|
|
|
|
|
|
|
|
if (priv->waiterFD != fd || priv->eventHdl != watch) {
|
|
|
|
virEventRemoveHandle(watch);
|
|
|
|
priv->eventHdl = -1;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(events & VIR_EVENT_HANDLE_READABLE))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (libxl_get_event(&priv->ctx, &event))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (event.type == LIBXL_EVENT_DOMAIN_DEATH) {
|
2011-05-04 09:07:01 +00:00
|
|
|
virDomainShutoffReason reason;
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
/* libxl_event_get_domain_death_info returns 1 if death
|
|
|
|
* event was for this domid */
|
|
|
|
if (libxl_event_get_domain_death_info(&priv->ctx,
|
|
|
|
vm->def->id,
|
|
|
|
&event,
|
|
|
|
&info) != 1)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
virEventRemoveHandle(watch);
|
|
|
|
priv->eventHdl = -1;
|
|
|
|
switch (info.shutdown_reason) {
|
|
|
|
case SHUTDOWN_poweroff:
|
|
|
|
case SHUTDOWN_crash:
|
2011-05-04 09:07:01 +00:00
|
|
|
if (info.shutdown_reason == SHUTDOWN_crash) {
|
2011-03-29 12:18:24 +00:00
|
|
|
dom_event = virDomainEventNewFromObj(vm,
|
|
|
|
VIR_DOMAIN_EVENT_STOPPED,
|
|
|
|
VIR_DOMAIN_EVENT_STOPPED_CRASHED);
|
2011-05-04 09:07:01 +00:00
|
|
|
reason = VIR_DOMAIN_SHUTOFF_CRASHED;
|
|
|
|
} else {
|
|
|
|
reason = VIR_DOMAIN_SHUTOFF_SHUTDOWN;
|
|
|
|
}
|
|
|
|
libxlVmReap(driver, vm, 0, reason);
|
2011-02-10 22:42:34 +00:00
|
|
|
if (!vm->persistent) {
|
|
|
|
virDomainRemoveInactive(&driver->domains, vm);
|
|
|
|
vm = NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SHUTDOWN_reboot:
|
2011-05-04 09:07:01 +00:00
|
|
|
libxlVmReap(driver, vm, 0, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
|
2011-05-30 09:53:02 +00:00
|
|
|
libxlVmStart(driver, vm, 0, -1);
|
2011-02-10 22:42:34 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
VIR_INFO("Unhandled shutdown_reason %d", info.shutdown_reason);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
2011-03-29 12:18:24 +00:00
|
|
|
if (dom_event) {
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
libxlDomainEventQueue(driver, dom_event);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
}
|
2011-02-10 22:42:34 +00:00
|
|
|
libxl_free_event(&event);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Register domain events with libxenlight and insert event handles
|
|
|
|
* in libvirt's event loop.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
libxlCreateDomEvents(virDomainObjPtr vm)
|
|
|
|
{
|
|
|
|
libxlDomainObjPrivatePtr priv = vm->privateData;
|
|
|
|
int fd;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(priv->dWaiter) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (libxl_wait_for_domain_death(&priv->ctx, vm->def->id, priv->dWaiter))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
libxl_get_wait_fd(&priv->ctx, &fd);
|
|
|
|
if (fd < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
priv->waiterFD = fd;
|
|
|
|
/* Add a reference to the domain object while it is injected in
|
|
|
|
* the event loop.
|
|
|
|
*/
|
2012-07-11 13:35:46 +00:00
|
|
|
virObjectRef(vm);
|
2011-02-10 22:42:34 +00:00
|
|
|
if ((priv->eventHdl = virEventAddHandle(
|
|
|
|
fd,
|
|
|
|
VIR_EVENT_HANDLE_READABLE | VIR_EVENT_HANDLE_ERROR,
|
|
|
|
libxlEventHandler,
|
|
|
|
vm, libxlDomainObjUnref)) < 0) {
|
2012-07-11 13:35:46 +00:00
|
|
|
virObjectUnref(vm);
|
2011-02-10 22:42:34 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
libxl_free_waiter(priv->dWaiter);
|
|
|
|
VIR_FREE(priv->dWaiter);
|
|
|
|
priv->eventHdl = -1;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-04-18 09:16:33 +00:00
|
|
|
static int
|
|
|
|
libxlDomainSetVcpuAffinites(libxlDriverPrivatePtr driver, virDomainObjPtr vm)
|
|
|
|
{
|
|
|
|
libxlDomainObjPrivatePtr priv = vm->privateData;
|
|
|
|
virDomainDefPtr def = vm->def;
|
|
|
|
libxl_cpumap map;
|
|
|
|
uint8_t *cpumask = NULL;
|
|
|
|
uint8_t *cpumap = NULL;
|
|
|
|
virNodeInfo nodeinfo;
|
|
|
|
size_t cpumaplen;
|
|
|
|
int vcpu, i;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (libxlDoNodeGetInfo(driver, &nodeinfo) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo));
|
|
|
|
|
|
|
|
for (vcpu = 0; vcpu < def->cputune.nvcpupin; ++vcpu) {
|
|
|
|
if (vcpu != def->cputune.vcpupin[vcpu]->vcpuid)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(cpumap, cpumaplen) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
cpumask = (uint8_t*) def->cputune.vcpupin[vcpu]->cpumask;
|
|
|
|
|
|
|
|
for (i = 0; i < VIR_DOMAIN_CPUMASK_LEN; ++i) {
|
2011-06-07 08:51:51 +00:00
|
|
|
if (cpumask[i])
|
|
|
|
VIR_USE_CPU(cpumap, i);
|
2011-04-18 09:16:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
map.size = cpumaplen;
|
|
|
|
map.map = cpumap;
|
|
|
|
|
|
|
|
if (libxl_set_vcpuaffinity(&priv->ctx, def->id, vcpu, &map) != 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to pin vcpu '%d' with libxenlight"), vcpu);
|
2011-04-18 09:16:33 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_FREE(cpumap);
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(cpumap);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-05-04 10:17:06 +00:00
|
|
|
static int
|
|
|
|
libxlFreeMem(libxlDomainObjPrivatePtr priv, libxl_domain_config *d_config)
|
|
|
|
{
|
|
|
|
uint32_t needed_mem;
|
|
|
|
uint32_t free_mem;
|
|
|
|
int i;
|
|
|
|
int ret = -1;
|
|
|
|
int tries = 3;
|
|
|
|
int wait_secs = 10;
|
|
|
|
|
|
|
|
if ((ret = libxl_domain_need_memory(&priv->ctx, &d_config->b_info,
|
|
|
|
&d_config->dm_info,
|
|
|
|
&needed_mem)) >= 0) {
|
|
|
|
for (i = 0; i < tries; ++i) {
|
|
|
|
if ((ret = libxl_get_free_memory(&priv->ctx, &free_mem)) < 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (free_mem >= needed_mem) {
|
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((ret = libxl_set_memory_target(&priv->ctx, 0,
|
|
|
|
free_mem - needed_mem,
|
|
|
|
/* relative */ 1, 0)) < 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
ret = libxl_wait_for_free_memory(&priv->ctx, 0, needed_mem,
|
|
|
|
wait_secs);
|
|
|
|
if (ret == 0 || ret != ERROR_NOMEM)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if ((ret = libxl_wait_for_memory_target(&priv->ctx, 0, 1)) < 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
/*
|
|
|
|
* Start a domain through libxenlight.
|
|
|
|
*
|
|
|
|
* virDomainObjPtr should be locked on invocation
|
|
|
|
*/
|
|
|
|
static int
|
2011-05-30 09:53:02 +00:00
|
|
|
libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm,
|
|
|
|
bool start_paused, int restore_fd)
|
2011-02-10 22:42:34 +00:00
|
|
|
{
|
|
|
|
libxl_domain_config d_config;
|
2011-06-02 12:24:30 +00:00
|
|
|
virDomainDefPtr def = NULL;
|
2011-03-29 12:18:24 +00:00
|
|
|
virDomainEventPtr event = NULL;
|
2011-06-02 12:24:30 +00:00
|
|
|
libxlSavefileHeader hdr;
|
2011-02-10 22:42:34 +00:00
|
|
|
int ret;
|
|
|
|
uint32_t domid = 0;
|
|
|
|
char *dom_xml = NULL;
|
2011-06-02 21:41:13 +00:00
|
|
|
char *managed_save_path = NULL;
|
|
|
|
int managed_save_fd = -1;
|
2011-02-10 22:42:34 +00:00
|
|
|
pid_t child_console_pid = -1;
|
|
|
|
libxlDomainObjPrivatePtr priv = vm->privateData;
|
|
|
|
|
2011-06-02 12:24:30 +00:00
|
|
|
/* If there is a managed saved state restore it instead of starting
|
|
|
|
* from scratch. The old state is removed once the restoring succeeded. */
|
|
|
|
if (restore_fd < 0) {
|
2011-06-02 21:41:13 +00:00
|
|
|
managed_save_path = libxlDomainManagedSavePath(driver, vm);
|
|
|
|
if (managed_save_path == NULL)
|
2011-06-02 12:24:30 +00:00
|
|
|
goto error;
|
|
|
|
|
2011-06-02 21:41:13 +00:00
|
|
|
if (virFileExists(managed_save_path)) {
|
2011-06-02 12:24:30 +00:00
|
|
|
|
2011-06-02 21:41:13 +00:00
|
|
|
managed_save_fd = libxlSaveImageOpen(driver, managed_save_path,
|
|
|
|
&def, &hdr);
|
|
|
|
if (managed_save_fd < 0)
|
2011-06-02 12:24:30 +00:00
|
|
|
goto error;
|
|
|
|
|
2011-06-02 21:41:13 +00:00
|
|
|
restore_fd = managed_save_fd;
|
|
|
|
|
2011-06-02 12:24:30 +00:00
|
|
|
if (STRNEQ(vm->def->name, def->name) ||
|
|
|
|
memcmp(vm->def->uuid, def->uuid, VIR_UUID_BUFLEN)) {
|
|
|
|
char vm_uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
char def_uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(vm->def->uuid, vm_uuidstr);
|
|
|
|
virUUIDFormat(def->uuid, def_uuidstr);
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("cannot restore domain '%s' uuid %s from a file"
|
|
|
|
" which belongs to domain '%s' uuid %s"),
|
|
|
|
vm->def->name, vm_uuidstr, def->name, def_uuidstr);
|
2011-06-02 12:24:30 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainObjAssignDef(vm, def, true);
|
|
|
|
def = NULL;
|
|
|
|
|
2011-06-02 21:41:13 +00:00
|
|
|
if (unlink(managed_save_path) < 0) {
|
|
|
|
VIR_WARN("Failed to remove the managed state %s",
|
|
|
|
managed_save_path);
|
|
|
|
}
|
2012-06-11 09:03:27 +00:00
|
|
|
vm->hasManagedSave = false;
|
2011-06-02 12:24:30 +00:00
|
|
|
}
|
2011-06-02 21:41:13 +00:00
|
|
|
VIR_FREE(managed_save_path);
|
2011-06-02 12:24:30 +00:00
|
|
|
}
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
memset(&d_config, 0, sizeof(d_config));
|
|
|
|
|
2011-06-02 12:24:30 +00:00
|
|
|
if (libxlBuildDomainConfig(driver, vm->def, &d_config) < 0 )
|
2011-02-10 22:42:34 +00:00
|
|
|
return -1;
|
|
|
|
|
2011-05-04 10:17:06 +00:00
|
|
|
if (libxlFreeMem(priv, &d_config) < 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("libxenlight failed to get free memory for domain '%s'"),
|
|
|
|
d_config.c_info.name);
|
2011-05-04 10:17:06 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2011-05-30 09:53:02 +00:00
|
|
|
if (restore_fd < 0)
|
|
|
|
ret = libxl_domain_create_new(&priv->ctx, &d_config,
|
|
|
|
NULL, &child_console_pid, &domid);
|
|
|
|
else
|
|
|
|
ret = libxl_domain_create_restore(&priv->ctx, &d_config, NULL,
|
|
|
|
&child_console_pid, &domid,
|
|
|
|
restore_fd);
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
if (ret) {
|
2011-05-30 09:53:02 +00:00
|
|
|
if (restore_fd < 0)
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("libxenlight failed to create new domain '%s'"),
|
|
|
|
d_config.c_info.name);
|
2011-05-30 09:53:02 +00:00
|
|
|
else
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("libxenlight failed to restore domain '%s'"),
|
|
|
|
d_config.c_info.name);
|
2011-02-10 22:42:34 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2011-06-02 12:24:30 +00:00
|
|
|
vm->def->id = domid;
|
|
|
|
if ((dom_xml = virDomainDefFormat(vm->def, 0)) == NULL)
|
2011-02-10 22:42:34 +00:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (libxl_userdata_store(&priv->ctx, domid, "libvirt-xml",
|
|
|
|
(uint8_t *)dom_xml, strlen(dom_xml) + 1)) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("libxenlight failed to store userdata"));
|
2011-02-10 22:42:34 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (libxlCreateDomEvents(vm) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2011-04-18 09:16:33 +00:00
|
|
|
if (libxlDomainSetVcpuAffinites(driver, vm) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
if (!start_paused) {
|
|
|
|
libxl_domain_unpause(&priv->ctx, domid);
|
2011-05-04 09:07:01 +00:00
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_BOOTED);
|
2011-02-10 22:42:34 +00:00
|
|
|
} else {
|
2011-05-04 09:07:01 +00:00
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
|
2011-02-10 22:42:34 +00:00
|
|
|
}
|
|
|
|
|
2011-03-29 12:18:24 +00:00
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2011-03-29 12:18:24 +00:00
|
|
|
event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STARTED,
|
2011-05-30 09:53:02 +00:00
|
|
|
restore_fd < 0 ?
|
|
|
|
VIR_DOMAIN_EVENT_STARTED_BOOTED :
|
|
|
|
VIR_DOMAIN_EVENT_STARTED_RESTORED);
|
2011-03-29 12:18:24 +00:00
|
|
|
libxlDomainEventQueue(driver, event);
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
libxl_domain_config_destroy(&d_config);
|
|
|
|
VIR_FREE(dom_xml);
|
2011-06-02 21:41:13 +00:00
|
|
|
VIR_FORCE_CLOSE(managed_save_fd);
|
2011-02-10 22:42:34 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
if (domid > 0) {
|
|
|
|
libxl_domain_destroy(&priv->ctx, domid, 0);
|
2011-06-02 12:24:30 +00:00
|
|
|
vm->def->id = -1;
|
2011-05-04 09:07:01 +00:00
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_FAILED);
|
2011-02-10 22:42:34 +00:00
|
|
|
}
|
|
|
|
libxl_domain_config_destroy(&d_config);
|
|
|
|
VIR_FREE(dom_xml);
|
2011-06-02 21:41:13 +00:00
|
|
|
VIR_FREE(managed_save_path);
|
2011-06-02 12:24:30 +00:00
|
|
|
virDomainDefFree(def);
|
2011-06-02 21:41:13 +00:00
|
|
|
VIR_FORCE_CLOSE(managed_save_fd);
|
2011-02-10 22:42:34 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Reconnect to running domains that were previously started/created
|
|
|
|
* with libxenlight driver.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
libxlReconnectDomain(void *payload,
|
|
|
|
const void *name ATTRIBUTE_UNUSED,
|
|
|
|
void *opaque)
|
|
|
|
{
|
|
|
|
virDomainObjPtr vm = payload;
|
|
|
|
libxlDriverPrivatePtr driver = opaque;
|
|
|
|
int rc;
|
|
|
|
libxl_dominfo d_info;
|
|
|
|
int len;
|
|
|
|
uint8_t *data = NULL;
|
|
|
|
|
|
|
|
virDomainObjLock(vm);
|
|
|
|
|
|
|
|
/* Does domain still exist? */
|
|
|
|
rc = libxl_domain_info(&driver->ctx, &d_info, vm->def->id);
|
|
|
|
if (rc == ERROR_INVAL) {
|
|
|
|
goto out;
|
|
|
|
} else if (rc != 0) {
|
|
|
|
VIR_DEBUG("libxl_domain_info failed (code %d), ignoring domain %d",
|
|
|
|
rc, vm->def->id);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Is this a domain that was under libvirt control? */
|
|
|
|
if (libxl_userdata_retrieve(&driver->ctx, vm->def->id,
|
|
|
|
"libvirt-xml", &data, &len)) {
|
|
|
|
VIR_DEBUG("libxl_userdata_retrieve failed, ignoring domain %d", vm->def->id);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Update domid in case it changed (e.g. reboot) while we were gone? */
|
|
|
|
vm->def->id = d_info.domid;
|
2011-05-04 09:07:01 +00:00
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_UNKNOWN);
|
2011-02-10 22:42:34 +00:00
|
|
|
|
|
|
|
/* Recreate domain death et. al. events */
|
|
|
|
libxlCreateDomEvents(vm);
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
return;
|
|
|
|
|
|
|
|
out:
|
2011-05-04 09:07:01 +00:00
|
|
|
libxlVmCleanup(driver, vm, VIR_DOMAIN_SHUTOFF_UNKNOWN);
|
2011-02-10 22:42:34 +00:00
|
|
|
if (!vm->persistent)
|
|
|
|
virDomainRemoveInactive(&driver->domains, vm);
|
|
|
|
else
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
libxlReconnectDomains(libxlDriverPrivatePtr driver)
|
|
|
|
{
|
|
|
|
virHashForEach(driver->domains.objs, libxlReconnectDomain, driver);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlShutdown(void)
|
|
|
|
{
|
|
|
|
if (!libxl_driver)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
libxlDriverLock(libxl_driver);
|
|
|
|
virCapabilitiesFree(libxl_driver->caps);
|
|
|
|
virDomainObjListDeinit(&libxl_driver->domains);
|
|
|
|
libxl_ctx_free(&libxl_driver->ctx);
|
|
|
|
xtl_logger_destroy(libxl_driver->logger);
|
|
|
|
if (libxl_driver->logger_file)
|
|
|
|
VIR_FORCE_FCLOSE(libxl_driver->logger_file);
|
|
|
|
|
|
|
|
virBitmapFree(libxl_driver->reservedVNCPorts);
|
|
|
|
|
|
|
|
VIR_FREE(libxl_driver->configDir);
|
|
|
|
VIR_FREE(libxl_driver->autostartDir);
|
|
|
|
VIR_FREE(libxl_driver->logDir);
|
|
|
|
VIR_FREE(libxl_driver->stateDir);
|
|
|
|
VIR_FREE(libxl_driver->libDir);
|
|
|
|
VIR_FREE(libxl_driver->saveDir);
|
|
|
|
|
2011-05-13 17:21:59 +00:00
|
|
|
virDomainEventStateFree(libxl_driver->domainEventState);
|
2011-03-29 12:18:24 +00:00
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
libxlDriverUnlock(libxl_driver);
|
|
|
|
virMutexDestroy(&libxl_driver->lock);
|
|
|
|
VIR_FREE(libxl_driver);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlStartup(int privileged) {
|
|
|
|
const libxl_version_info *ver_info;
|
|
|
|
char *log_file = NULL;
|
|
|
|
virCommandPtr cmd;
|
2011-04-01 11:30:53 +00:00
|
|
|
int status, ret = 0;
|
2012-03-26 18:42:22 +00:00
|
|
|
char ebuf[1024];
|
2011-02-10 22:42:34 +00:00
|
|
|
|
|
|
|
/* Disable libxl driver if non-root */
|
|
|
|
if (!privileged) {
|
2011-05-09 09:24:09 +00:00
|
|
|
VIR_INFO("Not running privileged, disabling libxenlight driver");
|
2011-02-10 22:42:34 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Disable driver if legacy xen toolstack (xend) is in use */
|
|
|
|
cmd = virCommandNewArgList("/usr/sbin/xend", "status", NULL);
|
|
|
|
if (virCommandRun(cmd, &status) == 0 && status == 0) {
|
2011-05-09 09:24:09 +00:00
|
|
|
VIR_INFO("Legacy xen tool stack seems to be in use, disabling "
|
2011-02-10 22:42:34 +00:00
|
|
|
"libxenlight driver.");
|
|
|
|
virCommandFree(cmd);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
virCommandFree(cmd);
|
|
|
|
|
|
|
|
if (VIR_ALLOC(libxl_driver) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (virMutexInit(&libxl_driver->lock) < 0) {
|
2011-05-09 09:24:09 +00:00
|
|
|
VIR_ERROR(_("cannot initialize mutex"));
|
2011-02-10 22:42:34 +00:00
|
|
|
VIR_FREE(libxl_driver);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
libxlDriverLock(libxl_driver);
|
|
|
|
|
|
|
|
/* Allocate bitmap for vnc port reservation */
|
|
|
|
if ((libxl_driver->reservedVNCPorts =
|
2012-09-14 07:46:56 +00:00
|
|
|
virBitmapNew(LIBXL_VNC_PORT_MAX - LIBXL_VNC_PORT_MIN)) == NULL)
|
2011-02-10 22:42:34 +00:00
|
|
|
goto out_of_memory;
|
|
|
|
|
|
|
|
if (virDomainObjListInit(&libxl_driver->domains) < 0)
|
|
|
|
goto out_of_memory;
|
|
|
|
|
|
|
|
if (virAsprintf(&libxl_driver->configDir,
|
|
|
|
"%s", LIBXL_CONFIG_DIR) == -1)
|
|
|
|
goto out_of_memory;
|
|
|
|
|
|
|
|
if (virAsprintf(&libxl_driver->autostartDir,
|
|
|
|
"%s", LIBXL_AUTOSTART_DIR) == -1)
|
|
|
|
goto out_of_memory;
|
|
|
|
|
|
|
|
if (virAsprintf(&libxl_driver->logDir,
|
|
|
|
"%s", LIBXL_LOG_DIR) == -1)
|
|
|
|
goto out_of_memory;
|
|
|
|
|
|
|
|
if (virAsprintf(&libxl_driver->stateDir,
|
|
|
|
"%s", LIBXL_STATE_DIR) == -1)
|
|
|
|
goto out_of_memory;
|
|
|
|
|
|
|
|
if (virAsprintf(&libxl_driver->libDir,
|
|
|
|
"%s", LIBXL_LIB_DIR) == -1)
|
|
|
|
goto out_of_memory;
|
|
|
|
|
|
|
|
if (virAsprintf(&libxl_driver->saveDir,
|
|
|
|
"%s", LIBXL_SAVE_DIR) == -1)
|
|
|
|
goto out_of_memory;
|
|
|
|
|
2011-07-05 21:02:53 +00:00
|
|
|
if (virFileMakePath(libxl_driver->logDir) < 0) {
|
2011-02-10 22:42:34 +00:00
|
|
|
VIR_ERROR(_("Failed to create log dir '%s': %s"),
|
2012-03-29 09:52:04 +00:00
|
|
|
libxl_driver->logDir, virStrerror(errno, ebuf, sizeof(ebuf)));
|
2011-02-10 22:42:34 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2011-07-05 21:02:53 +00:00
|
|
|
if (virFileMakePath(libxl_driver->stateDir) < 0) {
|
2011-02-10 22:42:34 +00:00
|
|
|
VIR_ERROR(_("Failed to create state dir '%s': %s"),
|
2012-03-29 09:52:04 +00:00
|
|
|
libxl_driver->stateDir, virStrerror(errno, ebuf, sizeof(ebuf)));
|
2011-02-10 22:42:34 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2011-07-05 21:02:53 +00:00
|
|
|
if (virFileMakePath(libxl_driver->libDir) < 0) {
|
2011-02-10 22:42:34 +00:00
|
|
|
VIR_ERROR(_("Failed to create lib dir '%s': %s"),
|
2012-03-29 09:52:04 +00:00
|
|
|
libxl_driver->libDir, virStrerror(errno, ebuf, sizeof(ebuf)));
|
2011-02-10 22:42:34 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2011-07-05 21:02:53 +00:00
|
|
|
if (virFileMakePath(libxl_driver->saveDir) < 0) {
|
2011-02-10 22:42:34 +00:00
|
|
|
VIR_ERROR(_("Failed to create save dir '%s': %s"),
|
2012-03-29 09:52:04 +00:00
|
|
|
libxl_driver->saveDir, virStrerror(errno, ebuf, sizeof(ebuf)));
|
2011-02-10 22:42:34 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virAsprintf(&log_file, "%s/libxl.log", libxl_driver->logDir) < 0) {
|
|
|
|
goto out_of_memory;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((libxl_driver->logger_file = fopen(log_file, "a")) == NULL) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("failed to create logfile %s"),
|
|
|
|
log_file);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
VIR_FREE(log_file);
|
|
|
|
|
2011-12-14 00:25:58 +00:00
|
|
|
libxl_driver->domainEventState = virDomainEventStateNew();
|
2011-05-13 17:21:59 +00:00
|
|
|
if (!libxl_driver->domainEventState)
|
2011-03-29 12:18:24 +00:00
|
|
|
goto error;
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
libxl_driver->logger =
|
|
|
|
(xentoollog_logger *)xtl_createlogger_stdiostream(libxl_driver->logger_file, XTL_DEBUG, 0);
|
|
|
|
if (!libxl_driver->logger) {
|
2011-08-31 15:53:09 +00:00
|
|
|
VIR_INFO("cannot create logger for libxenlight, disabling driver");
|
2011-04-01 11:30:53 +00:00
|
|
|
goto fail;
|
2011-02-10 22:42:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (libxl_ctx_init(&libxl_driver->ctx,
|
|
|
|
LIBXL_VERSION,
|
|
|
|
libxl_driver->logger)) {
|
2011-08-31 15:53:09 +00:00
|
|
|
VIR_INFO("cannot initialize libxenlight context, probably not running in a Xen Dom0, disabling driver");
|
2011-04-01 11:30:53 +00:00
|
|
|
goto fail;
|
2011-02-10 22:42:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ((ver_info = libxl_get_version_info(&libxl_driver->ctx)) == NULL) {
|
2011-08-31 15:53:09 +00:00
|
|
|
VIR_INFO("cannot version information from libxenlight, disabling driver");
|
2011-04-01 11:30:53 +00:00
|
|
|
goto fail;
|
2011-02-10 22:42:34 +00:00
|
|
|
}
|
|
|
|
libxl_driver->version = (ver_info->xen_version_major * 1000000) +
|
|
|
|
(ver_info->xen_version_minor * 1000);
|
|
|
|
|
|
|
|
if ((libxl_driver->caps =
|
|
|
|
libxlMakeCapabilities(&libxl_driver->ctx)) == NULL) {
|
2011-05-09 09:24:09 +00:00
|
|
|
VIR_ERROR(_("cannot create capabilities for libxenlight"));
|
2011-02-10 22:42:34 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
libxl_driver->caps->privateDataAllocFunc = libxlDomainObjPrivateAlloc;
|
|
|
|
libxl_driver->caps->privateDataFreeFunc = libxlDomainObjPrivateFree;
|
|
|
|
|
|
|
|
/* Load running domains first. */
|
|
|
|
if (virDomainLoadAllConfigs(libxl_driver->caps,
|
|
|
|
&libxl_driver->domains,
|
|
|
|
libxl_driver->stateDir,
|
|
|
|
libxl_driver->autostartDir,
|
2011-07-11 17:29:09 +00:00
|
|
|
1, 1 << VIR_DOMAIN_VIRT_XEN,
|
|
|
|
NULL, NULL) < 0)
|
2011-02-10 22:42:34 +00:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
libxlReconnectDomains(libxl_driver);
|
|
|
|
|
|
|
|
/* Then inactive persistent configs */
|
|
|
|
if (virDomainLoadAllConfigs(libxl_driver->caps,
|
|
|
|
&libxl_driver->domains,
|
|
|
|
libxl_driver->configDir,
|
|
|
|
libxl_driver->autostartDir,
|
2011-07-11 17:29:09 +00:00
|
|
|
0, 1 << VIR_DOMAIN_VIRT_XEN,
|
|
|
|
NULL, NULL) < 0)
|
2011-02-10 22:42:34 +00:00
|
|
|
goto error;
|
|
|
|
|
2011-03-28 10:49:22 +00:00
|
|
|
virHashForEach(libxl_driver->domains.objs, libxlAutostartDomain,
|
|
|
|
libxl_driver);
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2012-06-11 09:03:27 +00:00
|
|
|
virHashForEach(libxl_driver->domains.objs, libxlDomainManagedSaveLoad,
|
|
|
|
libxl_driver);
|
|
|
|
|
2011-03-28 10:49:22 +00:00
|
|
|
libxlDriverUnlock(libxl_driver);
|
2011-02-10 22:42:34 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
out_of_memory:
|
|
|
|
virReportOOMError();
|
|
|
|
error:
|
2011-04-01 11:30:53 +00:00
|
|
|
ret = -1;
|
|
|
|
fail:
|
2011-02-10 22:42:34 +00:00
|
|
|
VIR_FREE(log_file);
|
|
|
|
if (libxl_driver)
|
|
|
|
libxlDriverUnlock(libxl_driver);
|
|
|
|
libxlShutdown();
|
2011-04-01 11:30:53 +00:00
|
|
|
return ret;
|
2011-02-10 22:42:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlReload(void)
|
|
|
|
{
|
|
|
|
if (!libxl_driver)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
libxlDriverLock(libxl_driver);
|
|
|
|
virDomainLoadAllConfigs(libxl_driver->caps,
|
|
|
|
&libxl_driver->domains,
|
|
|
|
libxl_driver->configDir,
|
|
|
|
libxl_driver->autostartDir,
|
2011-07-11 17:29:09 +00:00
|
|
|
1, 1 << VIR_DOMAIN_VIRT_XEN,
|
|
|
|
NULL, libxl_driver);
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2011-03-28 10:49:22 +00:00
|
|
|
virHashForEach(libxl_driver->domains.objs, libxlAutostartDomain,
|
|
|
|
libxl_driver);
|
|
|
|
|
|
|
|
libxlDriverUnlock(libxl_driver);
|
2011-02-10 22:42:34 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlActive(void)
|
|
|
|
{
|
|
|
|
if (!libxl_driver)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static virDrvOpenStatus
|
|
|
|
libxlOpen(virConnectPtr conn,
|
|
|
|
virConnectAuthPtr auth ATTRIBUTE_UNUSED,
|
2011-07-06 22:17:10 +00:00
|
|
|
unsigned int flags)
|
2011-02-10 22:42:34 +00:00
|
|
|
{
|
2011-07-06 22:17:10 +00:00
|
|
|
virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
if (conn->uri == NULL) {
|
|
|
|
if (libxl_driver == NULL)
|
|
|
|
return VIR_DRV_OPEN_DECLINED;
|
|
|
|
|
Centralize error reporting for URI parsing/formatting problems
Move error reporting out of the callers, into virURIParse
and virURIFormat, to get consistency.
* include/libvirt/virterror.h, src/util/virterror.c: Add VIR_FROM_URI
* src/util/viruri.c, src/util/viruri.h: Add error reporting
* src/esx/esx_driver.c, src/libvirt.c, src/libxl/libxl_driver.c,
src/lxc/lxc_driver.c, src/openvz/openvz_driver.c,
src/qemu/qemu_driver.c, src/qemu/qemu_migration.c,
src/remote/remote_driver.c, src/uml/uml_driver.c,
src/vbox/vbox_tmpl.c, src/vmx/vmx.c, src/xen/xen_driver.c,
src/xen/xend_internal.c, tests/viruritest.c: Remove error
reporting
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2012-03-20 12:16:54 +00:00
|
|
|
if (!(conn->uri = virURIParse("xen:///")))
|
2011-02-10 22:42:34 +00:00
|
|
|
return VIR_DRV_OPEN_ERROR;
|
|
|
|
} else {
|
|
|
|
/* Only xen scheme */
|
|
|
|
if (conn->uri->scheme == NULL || STRNEQ(conn->uri->scheme, "xen"))
|
|
|
|
return VIR_DRV_OPEN_DECLINED;
|
|
|
|
|
|
|
|
/* If server name is given, its for remote driver */
|
|
|
|
if (conn->uri->server != NULL)
|
|
|
|
return VIR_DRV_OPEN_DECLINED;
|
|
|
|
|
|
|
|
/* Error if xen or libxl scheme specified but driver not started. */
|
|
|
|
if (libxl_driver == NULL) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("libxenlight state driver is not active"));
|
2011-02-10 22:42:34 +00:00
|
|
|
return VIR_DRV_OPEN_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* /session isn't supported in libxenlight */
|
|
|
|
if (conn->uri->path &&
|
|
|
|
STRNEQ(conn->uri->path, "") &&
|
|
|
|
STRNEQ(conn->uri->path, "/") &&
|
|
|
|
STRNEQ(conn->uri->path, "/system")) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unexpected Xen URI path '%s', try xen:///"),
|
|
|
|
NULLSTR(conn->uri->path));
|
2011-02-10 22:42:34 +00:00
|
|
|
return VIR_DRV_OPEN_ERROR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
conn->privateData = libxl_driver;
|
|
|
|
|
|
|
|
return VIR_DRV_OPEN_SUCCESS;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlClose(virConnectPtr conn ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
conn->privateData = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
libxlGetType(virConnectPtr conn ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
return "xenlight";
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlGetVersion(virConnectPtr conn, unsigned long *version)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
*version = driver->version;
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlGetMaxVcpus(virConnectPtr conn, const char *type ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
|
|
|
|
ret = libxl_get_max_cpus(&driver->ctx);
|
|
|
|
/* libxl_get_max_cpus() will return 0 if there were any failures,
|
|
|
|
e.g. xc_physinfo() failing */
|
|
|
|
if (ret == 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info)
|
|
|
|
{
|
2011-04-18 09:16:33 +00:00
|
|
|
return libxlDoNodeGetInfo(conn->privateData, info);
|
2011-02-10 22:42:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
|
|
|
libxlGetCapabilities(virConnectPtr conn)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
char *xml;
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL)
|
|
|
|
virReportOOMError();
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
|
|
|
|
return xml;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlListDomains(virConnectPtr conn, int *ids, int nids)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
int n;
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
n = virDomainObjListGetActiveIDs(&driver->domains, ids, nids);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlNumDomains(virConnectPtr conn)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
int n;
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
n = virDomainObjListNumOfDomains(&driver->domains, 1);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
static virDomainPtr
|
|
|
|
libxlDomainCreateXML(virConnectPtr conn, const char *xml,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
virDomainDefPtr def;
|
|
|
|
virDomainObjPtr vm = NULL;
|
|
|
|
virDomainPtr dom = NULL;
|
|
|
|
|
|
|
|
virCheckFlags(VIR_DOMAIN_START_PAUSED, NULL);
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
if (!(def = virDomainDefParseString(driver->caps, xml,
|
2011-07-11 17:29:09 +00:00
|
|
|
1 << VIR_DOMAIN_VIRT_XEN,
|
2011-02-10 22:42:34 +00:00
|
|
|
VIR_DOMAIN_XML_INACTIVE)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(vm = virDomainAssignDef(driver->caps,
|
|
|
|
&driver->domains, def, false)))
|
|
|
|
goto cleanup;
|
|
|
|
def = NULL;
|
|
|
|
|
2011-05-30 09:53:02 +00:00
|
|
|
if (libxlVmStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0,
|
|
|
|
-1) < 0) {
|
2011-02-10 22:42:34 +00:00
|
|
|
virDomainRemoveInactive(&driver->domains, vm);
|
|
|
|
vm = NULL;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
|
|
|
if (dom)
|
|
|
|
dom->id = vm->def->id;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virDomainDefFree(def);
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
|
|
|
static virDomainPtr
|
|
|
|
libxlDomainLookupByID(virConnectPtr conn, int id)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
virDomainPtr dom = NULL;
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
vm = virDomainFindByID(&driver->domains, id);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
|
|
|
|
if (!vm) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, NULL);
|
2011-02-10 22:42:34 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
|
|
|
if (dom)
|
|
|
|
dom->id = vm->def->id;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
|
|
|
static virDomainPtr
|
|
|
|
libxlDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
virDomainPtr dom = NULL;
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, uuid);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
|
|
|
|
if (!vm) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, NULL);
|
2011-02-10 22:42:34 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
|
|
|
if (dom)
|
|
|
|
dom->id = vm->def->id;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
|
|
|
static virDomainPtr
|
|
|
|
libxlDomainLookupByName(virConnectPtr conn, const char *name)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
virDomainPtr dom = NULL;
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
vm = virDomainFindByName(&driver->domains, name);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
|
|
|
|
if (!vm) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, NULL);
|
2011-02-10 22:42:34 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
|
|
|
if (dom)
|
|
|
|
dom->id = vm->def->id;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
2011-03-29 12:55:38 +00:00
|
|
|
static int
|
|
|
|
libxlDomainSuspend(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
libxlDomainObjPrivatePtr priv;
|
|
|
|
virDomainEventPtr event = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
|
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
2011-03-29 12:55:38 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
|
2011-03-29 12:55:38 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv = vm->privateData;
|
|
|
|
|
2011-05-04 09:07:01 +00:00
|
|
|
if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_PAUSED) {
|
2011-03-29 12:55:38 +00:00
|
|
|
if (libxl_domain_pause(&priv->ctx, dom->id) != 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to suspend domain '%d' with libxenlight"),
|
|
|
|
dom->id);
|
2011-03-29 12:55:38 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-05-04 09:07:01 +00:00
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
|
2011-03-29 12:55:38 +00:00
|
|
|
|
|
|
|
event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_SUSPENDED,
|
|
|
|
VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
if (event) {
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
libxlDomainEventQueue(driver, event);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainResume(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
libxlDomainObjPrivatePtr priv;
|
|
|
|
virDomainEventPtr event = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
|
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
2011-03-29 12:55:38 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
|
2011-03-29 12:55:38 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv = vm->privateData;
|
|
|
|
|
2011-05-04 09:07:01 +00:00
|
|
|
if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
|
2011-03-29 12:55:38 +00:00
|
|
|
if (libxl_domain_unpause(&priv->ctx, dom->id) != 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to resume domain '%d' with libxenlight"),
|
|
|
|
dom->id);
|
2011-03-29 12:55:38 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-05-04 09:07:01 +00:00
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
|
|
|
|
VIR_DOMAIN_RUNNING_UNPAUSED);
|
2011-03-29 12:55:38 +00:00
|
|
|
|
|
|
|
event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_RESUMED,
|
|
|
|
VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
if (event) {
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
libxlDomainEventQueue(driver, event);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
static int
|
2011-10-05 17:31:55 +00:00
|
|
|
libxlDomainShutdownFlags(virDomainPtr dom, unsigned int flags)
|
2011-02-10 22:42:34 +00:00
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
|
|
|
libxlDomainObjPrivatePtr priv;
|
|
|
|
|
2011-10-05 17:31:55 +00:00
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
libxlDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
2011-02-10 22:42:34 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("Domain is not running"));
|
2011-02-10 22:42:34 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv = vm->privateData;
|
|
|
|
if (libxl_domain_shutdown(&priv->ctx, dom->id, LIBXL_DOM_REQ_POWEROFF) != 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to shutdown domain '%d' with libxenlight"),
|
|
|
|
dom->id);
|
2011-02-10 22:42:34 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vm is marked shutoff (or removed from domains list if not persistent)
|
|
|
|
* in shutdown event handler.
|
|
|
|
*/
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-10-05 17:31:55 +00:00
|
|
|
static int
|
|
|
|
libxlDomainShutdown(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
return libxlDomainShutdownFlags(dom, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
static int
|
2011-07-06 22:17:10 +00:00
|
|
|
libxlDomainReboot(virDomainPtr dom, unsigned int flags)
|
2011-02-10 22:42:34 +00:00
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
|
|
|
libxlDomainObjPrivatePtr priv;
|
|
|
|
|
2011-07-06 22:17:10 +00:00
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
libxlDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
2011-02-10 22:42:34 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("Domain is not running"));
|
2011-02-10 22:42:34 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv = vm->privateData;
|
|
|
|
if (libxl_domain_shutdown(&priv->ctx, dom->id, LIBXL_DOM_REQ_REBOOT) != 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to reboot domain '%d' with libxenlight"),
|
|
|
|
dom->id);
|
2011-02-10 22:42:34 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2011-07-20 16:47:46 +00:00
|
|
|
libxlDomainDestroyFlags(virDomainPtr dom,
|
|
|
|
unsigned int flags)
|
2011-02-10 22:42:34 +00:00
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
2011-03-29 12:18:24 +00:00
|
|
|
virDomainEventPtr event = NULL;
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2011-07-20 16:47:46 +00:00
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
libxlDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
2011-02-10 22:42:34 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("Domain is not running"));
|
2011-02-10 22:42:34 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-03-29 12:18:24 +00:00
|
|
|
event = virDomainEventNewFromObj(vm,VIR_DOMAIN_EVENT_STOPPED,
|
|
|
|
VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
|
|
|
|
|
2011-05-04 09:07:01 +00:00
|
|
|
if (libxlVmReap(driver, vm, 1, VIR_DOMAIN_SHUTOFF_DESTROYED) != 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to destroy domain '%d'"), dom->id);
|
2011-02-10 22:42:34 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!vm->persistent) {
|
|
|
|
virDomainRemoveInactive(&driver->domains, vm);
|
|
|
|
vm = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
2011-03-29 12:18:24 +00:00
|
|
|
if (event)
|
|
|
|
libxlDomainEventQueue(driver, event);
|
2011-02-10 22:42:34 +00:00
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-07-20 16:47:46 +00:00
|
|
|
static int
|
|
|
|
libxlDomainDestroy(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
return libxlDomainDestroyFlags(dom, 0);
|
|
|
|
}
|
|
|
|
|
2011-03-29 12:49:43 +00:00
|
|
|
static char *
|
|
|
|
libxlDomainGetOSType(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
char *type = NULL;
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
2011-03-29 12:49:43 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(type = strdup(vm->def->os.type)))
|
|
|
|
virReportOOMError();
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
xml: use long long internally, to centralize overflow checks
On 64-bit platforms, unsigned long and unsigned long long are
identical, so we don't have to worry about overflow checks.
On 32-bit platforms, anywhere we narrow unsigned long long back
to unsigned long, we have to worry about overflow; it's easier
to do this in one place by having most of the code use the same
or wider types, and only doing the narrowing at the last minute.
Therefore, the memory set commands remain unsigned long, and
the memory get command now centralizes the overflow check into
libvirt.c, so that drivers don't have to repeat the work.
This also fixes a bug where xen returned the wrong value on
failure (most APIs return -1 on failure, but getMaxMemory
must return 0 on failure).
* src/driver.h (virDrvDomainGetMaxMemory): Use long long.
* src/libvirt.c (virDomainGetMaxMemory): Raise overflow.
* src/test/test_driver.c (testGetMaxMemory): Fix driver.
* src/rpc/gendispatch.pl (name_to_ProcName): Likewise.
* src/xen/xen_hypervisor.c (xenHypervisorGetMaxMemory): Likewise.
* src/xen/xen_driver.c (xenUnifiedDomainGetMaxMemory): Likewise.
* src/xen/xend_internal.c (xenDaemonDomainGetMaxMemory):
Likewise.
* src/xen/xend_internal.h (xenDaemonDomainGetMaxMemory):
Likewise.
* src/xen/xm_internal.c (xenXMDomainGetMaxMemory): Likewise.
* src/xen/xm_internal.h (xenXMDomainGetMaxMemory): Likewise.
* src/xen/xs_internal.c (xenStoreDomainGetMaxMemory): Likewise.
* src/xen/xs_internal.h (xenStoreDomainGetMaxMemory): Likewise.
* src/xenapi/xenapi_driver.c (xenapiDomainGetMaxMemory):
Likewise.
* src/esx/esx_driver.c (esxDomainGetMaxMemory): Likewise.
* src/libxl/libxl_driver.c (libxlDomainGetMaxMemory): Likewise.
* src/qemu/qemu_driver.c (qemudDomainGetMaxMemory): Likewise.
* src/lxc/lxc_driver.c (lxcDomainGetMaxMemory): Likewise.
* src/uml/uml_driver.c (umlDomainGetMaxMemory): Likewise.
2012-03-03 00:47:16 +00:00
|
|
|
static unsigned long long
|
2011-03-21 09:35:53 +00:00
|
|
|
libxlDomainGetMaxMemory(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
xml: use long long internally, to centralize overflow checks
On 64-bit platforms, unsigned long and unsigned long long are
identical, so we don't have to worry about overflow checks.
On 32-bit platforms, anywhere we narrow unsigned long long back
to unsigned long, we have to worry about overflow; it's easier
to do this in one place by having most of the code use the same
or wider types, and only doing the narrowing at the last minute.
Therefore, the memory set commands remain unsigned long, and
the memory get command now centralizes the overflow check into
libvirt.c, so that drivers don't have to repeat the work.
This also fixes a bug where xen returned the wrong value on
failure (most APIs return -1 on failure, but getMaxMemory
must return 0 on failure).
* src/driver.h (virDrvDomainGetMaxMemory): Use long long.
* src/libvirt.c (virDomainGetMaxMemory): Raise overflow.
* src/test/test_driver.c (testGetMaxMemory): Fix driver.
* src/rpc/gendispatch.pl (name_to_ProcName): Likewise.
* src/xen/xen_hypervisor.c (xenHypervisorGetMaxMemory): Likewise.
* src/xen/xen_driver.c (xenUnifiedDomainGetMaxMemory): Likewise.
* src/xen/xend_internal.c (xenDaemonDomainGetMaxMemory):
Likewise.
* src/xen/xend_internal.h (xenDaemonDomainGetMaxMemory):
Likewise.
* src/xen/xm_internal.c (xenXMDomainGetMaxMemory): Likewise.
* src/xen/xm_internal.h (xenXMDomainGetMaxMemory): Likewise.
* src/xen/xs_internal.c (xenStoreDomainGetMaxMemory): Likewise.
* src/xen/xs_internal.h (xenStoreDomainGetMaxMemory): Likewise.
* src/xenapi/xenapi_driver.c (xenapiDomainGetMaxMemory):
Likewise.
* src/esx/esx_driver.c (esxDomainGetMaxMemory): Likewise.
* src/libxl/libxl_driver.c (libxlDomainGetMaxMemory): Likewise.
* src/qemu/qemu_driver.c (qemudDomainGetMaxMemory): Likewise.
* src/lxc/lxc_driver.c (lxcDomainGetMaxMemory): Likewise.
* src/uml/uml_driver.c (umlDomainGetMaxMemory): Likewise.
2012-03-03 00:47:16 +00:00
|
|
|
unsigned long long ret = 0;
|
2011-03-21 09:35:53 +00:00
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
|
|
|
|
if (!vm) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, "%s", _("no domain with matching uuid"));
|
2011-03-21 09:35:53 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
ret = vm->def->mem.max_balloon;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2011-05-30 09:53:03 +00:00
|
|
|
libxlDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem,
|
2011-03-21 09:35:53 +00:00
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
libxlDomainObjPrivatePtr priv;
|
|
|
|
virDomainObjPtr vm;
|
2011-05-30 09:53:03 +00:00
|
|
|
virDomainDefPtr persistentDef = NULL;
|
|
|
|
bool isActive;
|
2011-03-21 09:35:53 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(VIR_DOMAIN_MEM_LIVE |
|
2011-05-30 09:53:03 +00:00
|
|
|
VIR_DOMAIN_MEM_CONFIG |
|
|
|
|
VIR_DOMAIN_MEM_MAXIMUM, -1);
|
2011-03-21 09:35:53 +00:00
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
|
|
|
|
if (!vm) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, "%s", _("no domain with matching uuid"));
|
2011-03-21 09:35:53 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-05-30 09:53:03 +00:00
|
|
|
isActive = virDomainObjIsActive(vm);
|
|
|
|
|
|
|
|
if (flags == VIR_DOMAIN_MEM_CURRENT) {
|
|
|
|
if (isActive)
|
|
|
|
flags = VIR_DOMAIN_MEM_LIVE;
|
|
|
|
else
|
|
|
|
flags = VIR_DOMAIN_MEM_CONFIG;
|
|
|
|
}
|
|
|
|
if (flags == VIR_DOMAIN_MEM_MAXIMUM) {
|
|
|
|
if (isActive)
|
|
|
|
flags = VIR_DOMAIN_MEM_LIVE | VIR_DOMAIN_MEM_MAXIMUM;
|
|
|
|
else
|
|
|
|
flags = VIR_DOMAIN_MEM_CONFIG | VIR_DOMAIN_MEM_MAXIMUM;
|
2011-03-21 09:35:53 +00:00
|
|
|
}
|
|
|
|
|
2011-05-30 09:53:03 +00:00
|
|
|
if (!isActive && (flags & VIR_DOMAIN_MEM_LIVE)) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("cannot set memory on an inactive domain"));
|
2011-03-21 09:35:53 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_MEM_CONFIG) {
|
|
|
|
if (!vm->persistent) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("cannot change persistent config of a transient domain"));
|
2011-03-21 09:35:53 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2011-05-30 09:53:03 +00:00
|
|
|
if (!(persistentDef = virDomainObjGetPersistentDef(driver->caps, vm)))
|
2011-03-21 09:35:53 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-05-30 09:53:03 +00:00
|
|
|
if (flags & VIR_DOMAIN_MEM_MAXIMUM) {
|
|
|
|
/* resize the maximum memory */
|
2011-03-21 09:35:53 +00:00
|
|
|
|
2011-05-30 09:53:03 +00:00
|
|
|
if (flags & VIR_DOMAIN_MEM_LIVE) {
|
|
|
|
priv = vm->privateData;
|
|
|
|
if (libxl_domain_setmaxmem(&priv->ctx, dom->id, newmem) < 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to set maximum memory for domain '%d'"
|
|
|
|
" with libxenlight"), dom->id);
|
2011-05-30 09:53:03 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_MEM_CONFIG) {
|
|
|
|
/* Help clang 2.8 decipher the logic flow. */
|
|
|
|
sa_assert(persistentDef);
|
|
|
|
persistentDef->mem.max_balloon = newmem;
|
|
|
|
if (persistentDef->mem.cur_balloon > newmem)
|
|
|
|
persistentDef->mem.cur_balloon = newmem;
|
|
|
|
ret = virDomainSaveConfig(driver->configDir, persistentDef);
|
2011-03-21 09:35:53 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-05-30 09:53:03 +00:00
|
|
|
} else {
|
|
|
|
/* resize the current memory */
|
2011-03-21 09:35:53 +00:00
|
|
|
|
2011-05-30 09:53:03 +00:00
|
|
|
if (newmem > vm->def->mem.max_balloon) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("cannot set memory higher than max memory"));
|
2011-05-30 09:53:03 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_MEM_LIVE) {
|
|
|
|
priv = vm->privateData;
|
|
|
|
if (libxl_set_memory_target(&priv->ctx, dom->id, newmem, 0,
|
|
|
|
/* force */ 1) < 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to set memory for domain '%d'"
|
|
|
|
" with libxenlight"), dom->id);
|
2011-05-30 09:53:03 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_MEM_CONFIG) {
|
|
|
|
sa_assert(persistentDef);
|
|
|
|
persistentDef->mem.cur_balloon = newmem;
|
|
|
|
ret = virDomainSaveConfig(driver->configDir, persistentDef);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2011-03-21 09:35:53 +00:00
|
|
|
}
|
|
|
|
|
2011-05-30 09:53:03 +00:00
|
|
|
ret = 0;
|
|
|
|
|
2011-03-21 09:35:53 +00:00
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainSetMemory(virDomainPtr dom, unsigned long memory)
|
|
|
|
{
|
|
|
|
return libxlDomainSetMemoryFlags(dom, memory, VIR_DOMAIN_MEM_LIVE);
|
|
|
|
}
|
|
|
|
|
2011-05-30 09:53:03 +00:00
|
|
|
static int
|
|
|
|
libxlDomainSetMaxMemory(virDomainPtr dom, unsigned long memory)
|
|
|
|
{
|
|
|
|
return libxlDomainSetMemoryFlags(dom, memory, VIR_DOMAIN_MEM_MAXIMUM);
|
|
|
|
}
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
static int
|
|
|
|
libxlDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
2011-03-21 09:35:51 +00:00
|
|
|
libxl_dominfo d_info;
|
2011-02-10 22:42:34 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
|
|
|
|
if (!vm) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, "%s",
|
|
|
|
_("no domain with matching uuid"));
|
2011-02-10 22:42:34 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-03-21 09:35:51 +00:00
|
|
|
if (!virDomainObjIsActive(vm)) {
|
|
|
|
info->cpuTime = 0;
|
|
|
|
info->memory = vm->def->mem.cur_balloon;
|
2011-06-02 12:16:32 +00:00
|
|
|
info->maxMem = vm->def->mem.max_balloon;
|
2011-03-21 09:35:51 +00:00
|
|
|
} else {
|
|
|
|
if (libxl_domain_info(&driver->ctx, &d_info, dom->id) != 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("libxl_domain_info failed for domain '%d'"), dom->id);
|
2011-03-21 09:35:51 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
info->cpuTime = d_info.cpu_time;
|
|
|
|
info->memory = d_info.current_memkb;
|
2011-06-02 12:16:32 +00:00
|
|
|
info->maxMem = d_info.max_memkb;
|
2011-03-21 09:35:51 +00:00
|
|
|
}
|
|
|
|
|
2011-05-04 09:07:01 +00:00
|
|
|
info->state = virDomainObjGetState(vm, NULL);
|
2011-02-10 22:42:34 +00:00
|
|
|
info->nrVirtCpu = vm->def->vcpus;
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-05-02 09:35:29 +00:00
|
|
|
static int
|
|
|
|
libxlDomainGetState(virDomainPtr dom,
|
|
|
|
int *state,
|
|
|
|
int *reason,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
|
|
|
|
if (!vm) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, "%s",
|
|
|
|
_("no domain with matching uuid"));
|
2011-05-02 09:35:29 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-05-04 09:07:01 +00:00
|
|
|
*state = virDomainObjGetState(vm, reason);
|
2011-05-02 09:35:29 +00:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-06-02 12:24:30 +00:00
|
|
|
/* This internal function expects the driver lock to already be held on
|
|
|
|
* entry and the vm must be active. */
|
2011-05-30 09:53:02 +00:00
|
|
|
static int
|
2011-06-02 12:24:30 +00:00
|
|
|
libxlDoDomainSave(libxlDriverPrivatePtr driver, virDomainObjPtr vm,
|
|
|
|
const char *to)
|
2011-05-30 09:53:02 +00:00
|
|
|
{
|
2011-06-02 12:24:30 +00:00
|
|
|
libxlDomainObjPrivatePtr priv = vm->privateData;
|
2011-05-30 09:53:02 +00:00
|
|
|
libxlSavefileHeader hdr;
|
|
|
|
virDomainEventPtr event = NULL;
|
|
|
|
char *xml = NULL;
|
|
|
|
uint32_t xml_len;
|
|
|
|
int fd;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("Domain '%d' has to be running because libxenlight will"
|
|
|
|
" suspend it"), vm->def->id);
|
2011-05-30 09:53:02 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((fd = virFileOpenAs(to, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR,
|
util: refactor virFileOpenAs
virFileOpenAs previously would only try opening a file as the current
user, or as a different user, but wouldn't try both methods in a
single call. This made it cumbersome to use as a replacement for
open(2). Additionally, it had a lot of historical baggage that led to
it being difficult to understand.
This patch refactors virFileOpenAs in the following ways:
* reorganize the code so that everything dealing with both the parent
and child sides of the "fork+setuid+setgid+open" method are in a
separate function. This makes the public function easier to understand.
* Allow a single call to virFileOpenAs() to first attempt the open as
the current user, and if that fails to automatically re-try after
doing fork+setuid (if deemed appropriate, i.e. errno indicates it
would now be successful, and the file is on a networkFS). This makes
it possible (in many, but possibly not all, cases) to drop-in
virFileOpenAs() as a replacement for open(2).
(NB: currently qemuOpenFile() calls virFileOpenAs() twice, once
without forking, then again with forking. That unfortunately can't
be changed without at least some discussion of the ramifications,
because the requested file permissions are different in each case,
which is something that a single call to virFileOpenAs() can't deal
with.)
* Add a flag so that any fchown() of the file to a different uid:gid
is explicitly requested when the function is called, rather than it
being implied by the presence of the O_CREAT flag. This just makes
for less subtle surprises to consumers. (Commit
b1643dc15c5de886fefe56ad18608d65f1325a2c added the check for O_CREAT
before forcing ownership. This patch just makes that restriction
more explicit.)
* If either the uid or gid is specified as "-1", virFileOpenAs will
interpret this to mean "the current [gu]id".
All current consumers of virFileOpenAs should retain their present
behavior (after a few minor changes to their setup code and
arguments).
2012-01-13 20:26:45 +00:00
|
|
|
-1, -1, 0)) < 0) {
|
2011-05-30 09:53:02 +00:00
|
|
|
virReportSystemError(-fd,
|
|
|
|
_("Failed to create domain save file '%s'"), to);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((xml = virDomainDefFormat(vm->def, 0)) == NULL)
|
|
|
|
goto cleanup;
|
|
|
|
xml_len = strlen(xml) + 1;
|
|
|
|
|
|
|
|
memset(&hdr, 0, sizeof(hdr));
|
|
|
|
memcpy(hdr.magic, LIBXL_SAVE_MAGIC, sizeof(hdr.magic));
|
|
|
|
hdr.version = LIBXL_SAVE_VERSION;
|
|
|
|
hdr.xmlLen = xml_len;
|
|
|
|
|
|
|
|
if (safewrite(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
|
|
|
|
_("Failed to write save file header"));
|
2011-05-30 09:53:02 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (safewrite(fd, xml, xml_len) != xml_len) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
|
|
|
|
_("Failed to write xml description"));
|
2011-05-30 09:53:02 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-06-02 12:24:30 +00:00
|
|
|
if (libxl_domain_suspend(&priv->ctx, NULL, vm->def->id, fd) != 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to save domain '%d' with libxenlight"),
|
|
|
|
vm->def->id);
|
2011-05-30 09:53:02 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
|
|
|
|
VIR_DOMAIN_EVENT_STOPPED_SAVED);
|
|
|
|
|
|
|
|
if (libxlVmReap(driver, vm, 1, VIR_DOMAIN_SHUTOFF_SAVED) != 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to destroy domain '%d'"), vm->def->id);
|
2011-05-30 09:53:02 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2012-06-11 09:03:27 +00:00
|
|
|
vm->hasManagedSave = true;
|
|
|
|
|
2011-05-30 09:53:02 +00:00
|
|
|
if (!vm->persistent) {
|
|
|
|
virDomainRemoveInactive(&driver->domains, vm);
|
|
|
|
vm = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(xml);
|
|
|
|
if (VIR_CLOSE(fd) < 0)
|
|
|
|
virReportSystemError(errno, "%s", _("cannot close file"));
|
|
|
|
if (event)
|
|
|
|
libxlDomainEventQueue(driver, event);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
save: wire up trivial save/restore flags implementations
For all hypervisors that support save and restore, the new API
now performs the same functions as the old.
VBox is excluded from this list, because its existing domainsave
is broken (there is no corresponding domainrestore, and there
is no control over the filename used in the save). A later
patch should change vbox to use its implementation for
managedsave, and teach start to use managedsave results.
* src/libxl/libxl_driver.c (libxlDomainSave): Move guts...
(libxlDomainSaveFlags): ...to new function.
(libxlDomainRestore): Move guts...
(libxlDomainRestoreFlags): ...to new function.
* src/test/test_driver.c (testDomainSave, testDomainSaveFlags)
(testDomainRestore, testDomainRestoreFlags): Likewise.
* src/xen/xen_driver.c (xenUnifiedDomainSave)
(xenUnifiedDomainSaveFlags, xenUnifiedDomainRestore)
(xenUnifiedDomainRestoreFlags): Likewise.
* src/qemu/qemu_driver.c (qemudDomainSave, qemudDomainRestore):
Rename and move guts.
(qemuDomainSave, qemuDomainSaveFlags, qemuDomainRestore)
(qemuDomainRestoreFlags): ...here.
(qemudDomainSaveFlag): Rename...
(qemuDomainSaveInternal): ...to this, and update callers.
2011-07-09 02:55:29 +00:00
|
|
|
libxlDomainSaveFlags(virDomainPtr dom, const char *to, const char *dxml,
|
|
|
|
unsigned int flags)
|
2011-05-30 09:53:02 +00:00
|
|
|
{
|
2011-06-02 12:24:30 +00:00
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
2011-05-30 09:53:02 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
save: wire up trivial save/restore flags implementations
For all hypervisors that support save and restore, the new API
now performs the same functions as the old.
VBox is excluded from this list, because its existing domainsave
is broken (there is no corresponding domainrestore, and there
is no control over the filename used in the save). A later
patch should change vbox to use its implementation for
managedsave, and teach start to use managedsave results.
* src/libxl/libxl_driver.c (libxlDomainSave): Move guts...
(libxlDomainSaveFlags): ...to new function.
(libxlDomainRestore): Move guts...
(libxlDomainRestoreFlags): ...to new function.
* src/test/test_driver.c (testDomainSave, testDomainSaveFlags)
(testDomainRestore, testDomainRestoreFlags): Likewise.
* src/xen/xen_driver.c (xenUnifiedDomainSave)
(xenUnifiedDomainSaveFlags, xenUnifiedDomainRestore)
(xenUnifiedDomainRestoreFlags): Likewise.
* src/qemu/qemu_driver.c (qemudDomainSave, qemudDomainRestore):
Rename and move guts.
(qemuDomainSave, qemuDomainSaveFlags, qemuDomainRestore)
(qemuDomainRestoreFlags): ...here.
(qemudDomainSaveFlag): Rename...
(qemuDomainSaveInternal): ...to this, and update callers.
2011-07-09 02:55:29 +00:00
|
|
|
virCheckFlags(0, -1);
|
|
|
|
if (dxml) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("xml modification unsupported"));
|
save: wire up trivial save/restore flags implementations
For all hypervisors that support save and restore, the new API
now performs the same functions as the old.
VBox is excluded from this list, because its existing domainsave
is broken (there is no corresponding domainrestore, and there
is no control over the filename used in the save). A later
patch should change vbox to use its implementation for
managedsave, and teach start to use managedsave results.
* src/libxl/libxl_driver.c (libxlDomainSave): Move guts...
(libxlDomainSaveFlags): ...to new function.
(libxlDomainRestore): Move guts...
(libxlDomainRestoreFlags): ...to new function.
* src/test/test_driver.c (testDomainSave, testDomainSaveFlags)
(testDomainRestore, testDomainRestoreFlags): Likewise.
* src/xen/xen_driver.c (xenUnifiedDomainSave)
(xenUnifiedDomainSaveFlags, xenUnifiedDomainRestore)
(xenUnifiedDomainRestoreFlags): Likewise.
* src/qemu/qemu_driver.c (qemudDomainSave, qemudDomainRestore):
Rename and move guts.
(qemuDomainSave, qemuDomainSaveFlags, qemuDomainRestore)
(qemuDomainRestoreFlags): ...here.
(qemudDomainSaveFlag): Rename...
(qemuDomainSaveInternal): ...to this, and update callers.
2011-07-09 02:55:29 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-05-30 09:53:02 +00:00
|
|
|
libxlDriverLock(driver);
|
2011-06-02 12:24:30 +00:00
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
2011-05-30 09:53:02 +00:00
|
|
|
|
2011-06-02 12:24:30 +00:00
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
2011-05-30 09:53:02 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-06-02 12:24:30 +00:00
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
|
2011-05-30 09:53:02 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-06-02 12:24:30 +00:00
|
|
|
ret = libxlDoDomainSave(driver, vm, to);
|
2011-05-30 09:53:02 +00:00
|
|
|
|
2011-06-02 12:24:30 +00:00
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
return ret;
|
|
|
|
}
|
2011-05-30 09:53:02 +00:00
|
|
|
|
2011-06-02 12:24:30 +00:00
|
|
|
static int
|
save: wire up trivial save/restore flags implementations
For all hypervisors that support save and restore, the new API
now performs the same functions as the old.
VBox is excluded from this list, because its existing domainsave
is broken (there is no corresponding domainrestore, and there
is no control over the filename used in the save). A later
patch should change vbox to use its implementation for
managedsave, and teach start to use managedsave results.
* src/libxl/libxl_driver.c (libxlDomainSave): Move guts...
(libxlDomainSaveFlags): ...to new function.
(libxlDomainRestore): Move guts...
(libxlDomainRestoreFlags): ...to new function.
* src/test/test_driver.c (testDomainSave, testDomainSaveFlags)
(testDomainRestore, testDomainRestoreFlags): Likewise.
* src/xen/xen_driver.c (xenUnifiedDomainSave)
(xenUnifiedDomainSaveFlags, xenUnifiedDomainRestore)
(xenUnifiedDomainRestoreFlags): Likewise.
* src/qemu/qemu_driver.c (qemudDomainSave, qemudDomainRestore):
Rename and move guts.
(qemuDomainSave, qemuDomainSaveFlags, qemuDomainRestore)
(qemuDomainRestoreFlags): ...here.
(qemudDomainSaveFlag): Rename...
(qemuDomainSaveInternal): ...to this, and update callers.
2011-07-09 02:55:29 +00:00
|
|
|
libxlDomainSave(virDomainPtr dom, const char *to)
|
|
|
|
{
|
|
|
|
return libxlDomainSaveFlags(dom, to, NULL, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainRestoreFlags(virConnectPtr conn, const char *from,
|
|
|
|
const char *dxml, unsigned int flags)
|
2011-06-02 12:24:30 +00:00
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
virDomainObjPtr vm = NULL;
|
|
|
|
virDomainDefPtr def = NULL;
|
|
|
|
libxlSavefileHeader hdr;
|
|
|
|
int fd = -1;
|
|
|
|
int ret = -1;
|
2011-05-30 09:53:02 +00:00
|
|
|
|
save: wire up trivial save/restore flags implementations
For all hypervisors that support save and restore, the new API
now performs the same functions as the old.
VBox is excluded from this list, because its existing domainsave
is broken (there is no corresponding domainrestore, and there
is no control over the filename used in the save). A later
patch should change vbox to use its implementation for
managedsave, and teach start to use managedsave results.
* src/libxl/libxl_driver.c (libxlDomainSave): Move guts...
(libxlDomainSaveFlags): ...to new function.
(libxlDomainRestore): Move guts...
(libxlDomainRestoreFlags): ...to new function.
* src/test/test_driver.c (testDomainSave, testDomainSaveFlags)
(testDomainRestore, testDomainRestoreFlags): Likewise.
* src/xen/xen_driver.c (xenUnifiedDomainSave)
(xenUnifiedDomainSaveFlags, xenUnifiedDomainRestore)
(xenUnifiedDomainRestoreFlags): Likewise.
* src/qemu/qemu_driver.c (qemudDomainSave, qemudDomainRestore):
Rename and move guts.
(qemuDomainSave, qemuDomainSaveFlags, qemuDomainRestore)
(qemuDomainRestoreFlags): ...here.
(qemudDomainSaveFlag): Rename...
(qemuDomainSaveInternal): ...to this, and update callers.
2011-07-09 02:55:29 +00:00
|
|
|
virCheckFlags(0, -1);
|
|
|
|
if (dxml) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("xml modification unsupported"));
|
save: wire up trivial save/restore flags implementations
For all hypervisors that support save and restore, the new API
now performs the same functions as the old.
VBox is excluded from this list, because its existing domainsave
is broken (there is no corresponding domainrestore, and there
is no control over the filename used in the save). A later
patch should change vbox to use its implementation for
managedsave, and teach start to use managedsave results.
* src/libxl/libxl_driver.c (libxlDomainSave): Move guts...
(libxlDomainSaveFlags): ...to new function.
(libxlDomainRestore): Move guts...
(libxlDomainRestoreFlags): ...to new function.
* src/test/test_driver.c (testDomainSave, testDomainSaveFlags)
(testDomainRestore, testDomainRestoreFlags): Likewise.
* src/xen/xen_driver.c (xenUnifiedDomainSave)
(xenUnifiedDomainSaveFlags, xenUnifiedDomainRestore)
(xenUnifiedDomainRestoreFlags): Likewise.
* src/qemu/qemu_driver.c (qemudDomainSave, qemudDomainRestore):
Rename and move guts.
(qemuDomainSave, qemuDomainSaveFlags, qemuDomainRestore)
(qemuDomainRestoreFlags): ...here.
(qemudDomainSaveFlag): Rename...
(qemuDomainSaveInternal): ...to this, and update callers.
2011-07-09 02:55:29 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-06-02 12:24:30 +00:00
|
|
|
libxlDriverLock(driver);
|
2011-05-30 09:53:02 +00:00
|
|
|
|
2011-06-02 12:24:30 +00:00
|
|
|
fd = libxlSaveImageOpen(driver, from, &def, &hdr);
|
|
|
|
if (fd < 0)
|
2011-05-30 09:53:02 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(vm = virDomainAssignDef(driver->caps, &driver->domains, def, true)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
def = NULL;
|
|
|
|
|
|
|
|
if ((ret = libxlVmStart(driver, vm, false, fd)) < 0 &&
|
|
|
|
!vm->persistent) {
|
|
|
|
virDomainRemoveInactive(&driver->domains, vm);
|
|
|
|
vm = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
2011-06-02 21:41:13 +00:00
|
|
|
if (VIR_CLOSE(fd) < 0)
|
|
|
|
virReportSystemError(errno, "%s", _("cannot close file"));
|
2011-05-30 09:53:02 +00:00
|
|
|
virDomainDefFree(def);
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
save: wire up trivial save/restore flags implementations
For all hypervisors that support save and restore, the new API
now performs the same functions as the old.
VBox is excluded from this list, because its existing domainsave
is broken (there is no corresponding domainrestore, and there
is no control over the filename used in the save). A later
patch should change vbox to use its implementation for
managedsave, and teach start to use managedsave results.
* src/libxl/libxl_driver.c (libxlDomainSave): Move guts...
(libxlDomainSaveFlags): ...to new function.
(libxlDomainRestore): Move guts...
(libxlDomainRestoreFlags): ...to new function.
* src/test/test_driver.c (testDomainSave, testDomainSaveFlags)
(testDomainRestore, testDomainRestoreFlags): Likewise.
* src/xen/xen_driver.c (xenUnifiedDomainSave)
(xenUnifiedDomainSaveFlags, xenUnifiedDomainRestore)
(xenUnifiedDomainRestoreFlags): Likewise.
* src/qemu/qemu_driver.c (qemudDomainSave, qemudDomainRestore):
Rename and move guts.
(qemuDomainSave, qemuDomainSaveFlags, qemuDomainRestore)
(qemuDomainRestoreFlags): ...here.
(qemudDomainSaveFlag): Rename...
(qemuDomainSaveInternal): ...to this, and update callers.
2011-07-09 02:55:29 +00:00
|
|
|
static int
|
|
|
|
libxlDomainRestore(virConnectPtr conn, const char *from)
|
|
|
|
{
|
|
|
|
return libxlDomainRestoreFlags(conn, from, NULL, 0);
|
|
|
|
}
|
|
|
|
|
2011-05-30 09:53:01 +00:00
|
|
|
static int
|
2011-07-06 20:40:19 +00:00
|
|
|
libxlDomainCoreDump(virDomainPtr dom, const char *to, unsigned int flags)
|
2011-05-30 09:53:01 +00:00
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
libxlDomainObjPrivatePtr priv;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
virDomainEventPtr event = NULL;
|
|
|
|
bool paused = false;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(VIR_DUMP_LIVE | VIR_DUMP_CRASH, -1);
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
|
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
2011-05-30 09:53:01 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
|
2011-05-30 09:53:01 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv = vm->privateData;
|
|
|
|
|
|
|
|
if (!(flags & VIR_DUMP_LIVE) &&
|
|
|
|
virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
|
|
|
|
if (libxl_domain_pause(&priv->ctx, dom->id) != 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Before dumping core, failed to suspend domain '%d'"
|
|
|
|
" with libxenlight"),
|
|
|
|
dom->id);
|
2011-05-30 09:53:01 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_DUMP);
|
|
|
|
paused = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (libxl_domain_core_dump(&priv->ctx, dom->id, to) != 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to dump core of domain '%d' with libxenlight"),
|
|
|
|
dom->id);
|
2011-05-30 09:53:01 +00:00
|
|
|
goto cleanup_unpause;
|
|
|
|
}
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
if (flags & VIR_DUMP_CRASH) {
|
|
|
|
if (libxlVmReap(driver, vm, 1, VIR_DOMAIN_SHUTOFF_CRASHED) != 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to destroy domain '%d'"), dom->id);
|
2011-05-30 09:53:01 +00:00
|
|
|
goto cleanup_unlock;
|
|
|
|
}
|
|
|
|
|
|
|
|
event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
|
|
|
|
VIR_DOMAIN_EVENT_STOPPED_CRASHED);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((flags & VIR_DUMP_CRASH) && !vm->persistent) {
|
|
|
|
virDomainRemoveInactive(&driver->domains, vm);
|
|
|
|
vm = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup_unlock:
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
cleanup_unpause:
|
|
|
|
if (virDomainObjIsActive(vm) && paused) {
|
|
|
|
if (libxl_domain_unpause(&priv->ctx, dom->id) != 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("After dumping core, failed to resume domain '%d' with"
|
|
|
|
" libxenlight"), dom->id);
|
2011-05-30 09:53:01 +00:00
|
|
|
} else {
|
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
|
|
|
|
VIR_DOMAIN_RUNNING_UNPAUSED);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
if (event) {
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
libxlDomainEventQueue(driver, event);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-06-02 12:24:30 +00:00
|
|
|
static int
|
|
|
|
libxlDomainManagedSave(virDomainPtr dom, unsigned int flags)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm = NULL;
|
|
|
|
char *name = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
2011-06-02 12:24:30 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
|
2011-06-02 12:24:30 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2011-08-10 14:51:36 +00:00
|
|
|
if (!vm->persistent) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("cannot do managed save for transient domain"));
|
2011-08-10 14:51:36 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2011-06-02 12:24:30 +00:00
|
|
|
|
|
|
|
name = libxlDomainManagedSavePath(driver, vm);
|
|
|
|
if (name == NULL)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
VIR_INFO("Saving state to %s", name);
|
|
|
|
|
|
|
|
ret = libxlDoDomainSave(driver, vm, name);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
VIR_FREE(name);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-06-11 09:03:27 +00:00
|
|
|
static void
|
|
|
|
libxlDomainManagedSaveLoad(void *payload,
|
|
|
|
const void *n ATTRIBUTE_UNUSED,
|
|
|
|
void *opaque)
|
|
|
|
{
|
|
|
|
virDomainObjPtr vm = payload;
|
|
|
|
libxlDriverPrivatePtr driver = opaque;
|
|
|
|
char *name;
|
|
|
|
|
|
|
|
virDomainObjLock(vm);
|
|
|
|
|
|
|
|
if (!(name = libxlDomainManagedSavePath(driver, vm)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
vm->hasManagedSave = virFileExists(name);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
VIR_FREE(name);
|
|
|
|
}
|
|
|
|
|
2011-06-02 12:24:30 +00:00
|
|
|
static int
|
|
|
|
libxlDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
2011-06-02 12:24:30 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2012-06-11 09:03:27 +00:00
|
|
|
ret = vm->hasManagedSave;
|
2011-06-02 12:24:30 +00:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainManagedSaveRemove(virDomainPtr dom, unsigned int flags)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
char *name = NULL;
|
|
|
|
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
2011-06-02 12:24:30 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
name = libxlDomainManagedSavePath(driver, vm);
|
|
|
|
if (name == NULL)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = unlink(name);
|
2012-06-11 09:03:27 +00:00
|
|
|
vm->hasManagedSave = false;
|
2011-06-02 12:24:30 +00:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(name);
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-03-29 12:31:45 +00:00
|
|
|
static int
|
|
|
|
libxlDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
libxlDomainObjPrivatePtr priv;
|
|
|
|
virDomainDefPtr def;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
libxl_cpumap map;
|
|
|
|
uint8_t *bitmask = NULL;
|
|
|
|
unsigned int maplen;
|
|
|
|
unsigned int i, pos;
|
|
|
|
int max;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(VIR_DOMAIN_VCPU_LIVE |
|
|
|
|
VIR_DOMAIN_VCPU_CONFIG |
|
|
|
|
VIR_DOMAIN_VCPU_MAXIMUM, -1);
|
|
|
|
|
|
|
|
/* At least one of LIVE or CONFIG must be set. MAXIMUM cannot be
|
|
|
|
* mixed with LIVE. */
|
|
|
|
if ((flags & (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) == 0 ||
|
|
|
|
(flags & (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_LIVE)) ==
|
|
|
|
(VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_LIVE)) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("invalid flag combination: (0x%x)"), flags);
|
2011-03-29 12:31:45 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!nvcpus) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s", _("nvcpus is zero"));
|
2011-03-29 12:31:45 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
|
|
|
|
if (!vm) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, "%s", _("no domain with matching uuid"));
|
2011-03-29 12:31:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!virDomainObjIsActive(vm) && (flags & VIR_DOMAIN_VCPU_LIVE)) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("cannot set vcpus on an inactive domain"));
|
2011-03-29 12:31:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!vm->persistent && (flags & VIR_DOMAIN_VCPU_CONFIG)) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("cannot change persistent config of a transient domain"));
|
2011-03-29 12:31:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((max = libxlGetMaxVcpus(dom->conn, NULL)) < 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("could not determine max vcpus for the domain"));
|
2011-03-29 12:31:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(flags & VIR_DOMAIN_VCPU_MAXIMUM) && vm->def->maxvcpus < max) {
|
|
|
|
max = vm->def->maxvcpus;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nvcpus > max) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("requested vcpus is greater than max allowable"
|
|
|
|
" vcpus for the domain: %d > %d"), nvcpus, max);
|
2011-03-29 12:31:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv = vm->privateData;
|
|
|
|
|
|
|
|
if (!(def = virDomainObjGetPersistentDef(driver->caps, vm)))
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-04-05 16:07:57 +00:00
|
|
|
maplen = VIR_CPU_MAPLEN(nvcpus);
|
2011-03-29 12:31:45 +00:00
|
|
|
if (VIR_ALLOC_N(bitmask, maplen) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < nvcpus; ++i) {
|
2011-04-05 16:07:57 +00:00
|
|
|
pos = i / 8;
|
2011-03-29 12:31:45 +00:00
|
|
|
bitmask[pos] |= 1 << (i % 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
map.size = maplen;
|
|
|
|
map.map = bitmask;
|
|
|
|
|
|
|
|
switch (flags) {
|
|
|
|
case VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_CONFIG:
|
|
|
|
def->maxvcpus = nvcpus;
|
|
|
|
if (nvcpus < def->vcpus)
|
|
|
|
def->vcpus = nvcpus;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_VCPU_CONFIG:
|
|
|
|
def->vcpus = nvcpus;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_VCPU_LIVE:
|
|
|
|
if (libxl_set_vcpuonline(&priv->ctx, dom->id, &map) != 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to set vcpus for domain '%d'"
|
|
|
|
" with libxenlight"), dom->id);
|
2011-03-29 12:31:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG:
|
|
|
|
if (libxl_set_vcpuonline(&priv->ctx, dom->id, &map) != 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to set vcpus for domain '%d'"
|
|
|
|
" with libxenlight"), dom->id);
|
2011-03-29 12:31:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
def->vcpus = nvcpus;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_VCPU_CONFIG)
|
|
|
|
ret = virDomainSaveConfig(driver->configDir, def);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(bitmask);
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus)
|
|
|
|
{
|
|
|
|
return libxlDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_VCPU_LIVE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
virDomainDefPtr def;
|
|
|
|
int ret = -1;
|
2011-07-15 23:35:47 +00:00
|
|
|
bool active;
|
2011-03-29 12:31:45 +00:00
|
|
|
|
|
|
|
virCheckFlags(VIR_DOMAIN_VCPU_LIVE |
|
|
|
|
VIR_DOMAIN_VCPU_CONFIG |
|
|
|
|
VIR_DOMAIN_VCPU_MAXIMUM, -1);
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
|
|
|
|
if (!vm) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, "%s", _("no domain with matching uuid"));
|
2011-03-29 12:31:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-07-15 23:35:47 +00:00
|
|
|
active = virDomainObjIsActive(vm);
|
|
|
|
|
|
|
|
if ((flags & (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) == 0) {
|
|
|
|
if (active)
|
|
|
|
flags |= VIR_DOMAIN_VCPU_LIVE;
|
|
|
|
else
|
|
|
|
flags |= VIR_DOMAIN_VCPU_CONFIG;
|
|
|
|
}
|
|
|
|
if ((flags & VIR_DOMAIN_VCPU_LIVE) && (flags & VIR_DOMAIN_VCPU_CONFIG)) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("invalid flag combination: (0x%x)"), flags);
|
2011-07-15 23:35:47 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-03-29 12:31:45 +00:00
|
|
|
if (flags & VIR_DOMAIN_VCPU_LIVE) {
|
2011-07-15 23:35:47 +00:00
|
|
|
if (!active) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("Domain is not running"));
|
2011-03-29 12:31:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
def = vm->def;
|
|
|
|
} else {
|
2011-07-15 23:35:47 +00:00
|
|
|
if (!vm->persistent) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("domain is transient"));
|
2011-07-15 23:35:47 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2011-03-29 12:31:45 +00:00
|
|
|
def = vm->newDef ? vm->newDef : vm->def;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = (flags & VIR_DOMAIN_VCPU_MAXIMUM) ? def->maxvcpus : def->vcpus;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainPinVcpu(virDomainPtr dom, unsigned int vcpu, unsigned char *cpumap,
|
|
|
|
int maplen)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
libxlDomainObjPrivatePtr priv;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
|
|
|
libxl_cpumap map;
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
|
|
|
|
if (!vm) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, "%s", _("no domain with matching uuid"));
|
2011-03-29 12:31:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("cannot pin vcpus on an inactive domain"));
|
2011-03-29 12:31:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv = vm->privateData;
|
|
|
|
|
|
|
|
map.size = maplen;
|
|
|
|
map.map = cpumap;
|
|
|
|
if (libxl_set_vcpuaffinity(&priv->ctx, dom->id, vcpu, &map) != 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to pin vcpu '%d' with libxenlight"), vcpu);
|
2011-03-29 12:31:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2011-04-18 09:16:33 +00:00
|
|
|
|
2012-08-21 09:18:28 +00:00
|
|
|
if (!vm->def->cputune.vcpupin) {
|
|
|
|
if (VIR_ALLOC(vm->def->cputune.vcpupin) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
vm->def->cputune.nvcpupin = 0;
|
|
|
|
}
|
2012-08-30 13:38:37 +00:00
|
|
|
if (virDomainVcpuPinAdd(&vm->def->cputune.vcpupin,
|
2012-08-21 09:18:28 +00:00
|
|
|
&vm->def->cputune.nvcpupin,
|
|
|
|
cpumap,
|
|
|
|
maplen,
|
|
|
|
vcpu) < 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("failed to update or add vcpupin xml"));
|
2011-04-18 09:16:33 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-03-29 12:31:45 +00:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainGetVcpus(virDomainPtr dom, virVcpuInfoPtr info, int maxinfo,
|
|
|
|
unsigned char *cpumaps, int maplen)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
libxlDomainObjPrivatePtr priv;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
|
|
|
libxl_vcpuinfo *vcpuinfo;
|
|
|
|
int maxcpu, hostcpus;
|
|
|
|
unsigned int i;
|
|
|
|
unsigned char *cpumap;
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
|
|
|
|
if (!vm) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, "%s", _("no domain with matching uuid"));
|
2011-03-29 12:31:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
|
2011-03-29 12:31:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv = vm->privateData;
|
|
|
|
if ((vcpuinfo = libxl_list_vcpu(&priv->ctx, dom->id, &maxcpu,
|
|
|
|
&hostcpus)) == NULL) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to list vcpus for domain '%d' with libxenlight"),
|
|
|
|
dom->id);
|
2011-03-29 12:31:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cpumaps && maplen > 0)
|
|
|
|
memset(cpumaps, 0, maplen * maxinfo);
|
|
|
|
for (i = 0; i < maxcpu && i < maxinfo; ++i) {
|
|
|
|
info[i].number = vcpuinfo[i].vcpuid;
|
|
|
|
info[i].cpu = vcpuinfo[i].cpu;
|
|
|
|
info[i].cpuTime = vcpuinfo[i].vcpu_time;
|
|
|
|
if (vcpuinfo[i].running)
|
|
|
|
info[i].state = VIR_VCPU_RUNNING;
|
|
|
|
else if (vcpuinfo[i].blocked)
|
|
|
|
info[i].state = VIR_VCPU_BLOCKED;
|
|
|
|
else
|
|
|
|
info[i].state = VIR_VCPU_OFFLINE;
|
|
|
|
|
|
|
|
if (cpumaps && maplen > 0) {
|
|
|
|
cpumap = VIR_GET_CPUMAP(cpumaps, maplen, i);
|
|
|
|
memcpy(cpumap, vcpuinfo[i].cpumap.map,
|
|
|
|
MIN(maplen, vcpuinfo[i].cpumap.size));
|
|
|
|
}
|
|
|
|
|
|
|
|
libxl_vcpuinfo_destroy(&vcpuinfo[i]);
|
|
|
|
}
|
|
|
|
VIR_FREE(vcpuinfo);
|
|
|
|
|
|
|
|
ret = maxinfo;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
static char *
|
2011-07-06 20:40:19 +00:00
|
|
|
libxlDomainGetXMLDesc(virDomainPtr dom, unsigned int flags)
|
2011-02-10 22:42:34 +00:00
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
char *ret = NULL;
|
|
|
|
|
2011-07-13 22:24:38 +00:00
|
|
|
/* Flags checked by virDomainDefFormat */
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
libxlDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
|
|
|
|
if (!vm) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, "%s",
|
|
|
|
_("no domain with matching uuid"));
|
2011-02-10 22:42:34 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = virDomainDefFormat(vm->def, flags);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-03-29 12:39:18 +00:00
|
|
|
static char *
|
|
|
|
libxlDomainXMLFromNative(virConnectPtr conn, const char * nativeFormat,
|
|
|
|
const char * nativeConfig,
|
2011-07-06 22:17:10 +00:00
|
|
|
unsigned int flags)
|
2011-03-29 12:39:18 +00:00
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
const libxl_version_info *ver_info;
|
|
|
|
virDomainDefPtr def = NULL;
|
|
|
|
virConfPtr conf = NULL;
|
|
|
|
char *xml = NULL;
|
|
|
|
|
2011-07-06 22:17:10 +00:00
|
|
|
virCheckFlags(0, NULL);
|
|
|
|
|
2011-03-29 12:39:18 +00:00
|
|
|
if (STRNEQ(nativeFormat, LIBXL_CONFIG_FORMAT_XM)) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("unsupported config type %s"), nativeFormat);
|
2011-03-29 12:39:18 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((ver_info = libxl_get_version_info(&driver->ctx)) == NULL) {
|
2011-05-09 09:24:09 +00:00
|
|
|
VIR_ERROR(_("cannot get version information from libxenlight"));
|
2011-03-29 12:39:18 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(conf = virConfReadMem(nativeConfig, strlen(nativeConfig), 0)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(def = xenParseXM(conf, ver_info->xen_version_major, driver->caps))) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("parsing xm config failed"));
|
2011-03-29 12:39:18 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
xml = virDomainDefFormat(def, VIR_DOMAIN_XML_INACTIVE);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virDomainDefFree(def);
|
|
|
|
if (conf)
|
|
|
|
virConfFree(conf);
|
|
|
|
return xml;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define MAX_CONFIG_SIZE (1024 * 65)
|
|
|
|
static char *
|
|
|
|
libxlDomainXMLToNative(virConnectPtr conn, const char * nativeFormat,
|
|
|
|
const char * domainXml,
|
2011-07-06 22:17:10 +00:00
|
|
|
unsigned int flags)
|
2011-03-29 12:39:18 +00:00
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
const libxl_version_info *ver_info;
|
|
|
|
virDomainDefPtr def = NULL;
|
|
|
|
virConfPtr conf = NULL;
|
|
|
|
int len = MAX_CONFIG_SIZE;
|
|
|
|
char *ret = NULL;
|
|
|
|
|
2011-07-06 22:17:10 +00:00
|
|
|
virCheckFlags(0, NULL);
|
|
|
|
|
2011-03-29 12:39:18 +00:00
|
|
|
if (STRNEQ(nativeFormat, LIBXL_CONFIG_FORMAT_XM)) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("unsupported config type %s"), nativeFormat);
|
2011-03-29 12:39:18 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((ver_info = libxl_get_version_info(&driver->ctx)) == NULL) {
|
2011-05-09 09:24:09 +00:00
|
|
|
VIR_ERROR(_("cannot get version information from libxenlight"));
|
2011-03-29 12:39:18 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-07-11 17:29:09 +00:00
|
|
|
if (!(def = virDomainDefParseString(driver->caps, domainXml,
|
|
|
|
1 << VIR_DOMAIN_VIRT_XEN, 0)))
|
2011-03-29 12:39:18 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(conf = xenFormatXM(conn, def, ver_info->xen_version_major)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(ret, len) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virConfWriteMem(ret, &len, conf) < 0) {
|
|
|
|
VIR_FREE(ret);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virDomainDefFree(def);
|
|
|
|
if (conf)
|
|
|
|
virConfFree(conf);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
static int
|
|
|
|
libxlListDefinedDomains(virConnectPtr conn,
|
|
|
|
char **const names, int nnames)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
int n;
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
n = virDomainObjListGetInactiveNames(&driver->domains, names, nnames);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlNumDefinedDomains(virConnectPtr conn)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
int n;
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
n = virDomainObjListNumOfDomains(&driver->domains, 0);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainCreateWithFlags(virDomainPtr dom,
|
2011-07-06 22:17:10 +00:00
|
|
|
unsigned int flags)
|
2011-02-10 22:42:34 +00:00
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(VIR_DOMAIN_START_PAUSED, -1);
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
2011-02-10 22:42:34 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virDomainObjIsActive(vm)) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("Domain is already running"));
|
2011-02-10 22:42:34 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-05-30 09:53:02 +00:00
|
|
|
ret = libxlVmStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0, -1);
|
2011-02-10 22:42:34 +00:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainCreate(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
return libxlDomainCreateWithFlags(dom, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static virDomainPtr
|
|
|
|
libxlDomainDefineXML(virConnectPtr conn, const char *xml)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
virDomainDefPtr def = NULL;
|
|
|
|
virDomainObjPtr vm = NULL;
|
|
|
|
virDomainPtr dom = NULL;
|
2011-03-29 12:18:24 +00:00
|
|
|
virDomainEventPtr event = NULL;
|
2011-02-10 22:42:34 +00:00
|
|
|
int dupVM;
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
if (!(def = virDomainDefParseString(driver->caps, xml,
|
2011-07-11 17:29:09 +00:00
|
|
|
1 << VIR_DOMAIN_VIRT_XEN,
|
2011-02-10 22:42:34 +00:00
|
|
|
VIR_DOMAIN_XML_INACTIVE)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if ((dupVM = virDomainObjIsDuplicate(&driver->domains, def, 0)) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(vm = virDomainAssignDef(driver->caps,
|
|
|
|
&driver->domains, def, false)))
|
|
|
|
goto cleanup;
|
|
|
|
def = NULL;
|
|
|
|
vm->persistent = 1;
|
|
|
|
|
|
|
|
if (virDomainSaveConfig(driver->configDir,
|
|
|
|
vm->newDef ? vm->newDef : vm->def) < 0) {
|
|
|
|
virDomainRemoveInactive(&driver->domains, vm);
|
|
|
|
vm = NULL;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
|
|
|
if (dom)
|
|
|
|
dom->id = vm->def->id;
|
|
|
|
|
2011-03-29 12:18:24 +00:00
|
|
|
event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_DEFINED,
|
|
|
|
!dupVM ?
|
|
|
|
VIR_DOMAIN_EVENT_DEFINED_ADDED :
|
|
|
|
VIR_DOMAIN_EVENT_DEFINED_UPDATED);
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
cleanup:
|
|
|
|
virDomainDefFree(def);
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
2011-03-29 12:18:24 +00:00
|
|
|
if (event)
|
|
|
|
libxlDomainEventQueue(driver, event);
|
2011-02-10 22:42:34 +00:00
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2011-07-20 03:05:20 +00:00
|
|
|
libxlDomainUndefineFlags(virDomainPtr dom,
|
|
|
|
unsigned int flags)
|
2011-02-10 22:42:34 +00:00
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
2011-03-29 12:18:24 +00:00
|
|
|
virDomainEventPtr event = NULL;
|
2011-07-20 03:05:20 +00:00
|
|
|
char *name = NULL;
|
2011-02-10 22:42:34 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
2011-07-20 03:05:20 +00:00
|
|
|
virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE, -1);
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
libxlDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
|
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("no domain with matching uuid '%s'"), uuidstr);
|
2011-02-10 22:42:34 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!vm->persistent) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("cannot undefine transient domain"));
|
2011-02-10 22:42:34 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-07-20 03:05:20 +00:00
|
|
|
name = libxlDomainManagedSavePath(driver, vm);
|
|
|
|
if (name == NULL)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virFileExists(name)) {
|
|
|
|
if (flags & VIR_DOMAIN_UNDEFINE_MANAGED_SAVE) {
|
|
|
|
if (unlink(name) < 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Failed to remove domain managed save image"));
|
2011-07-20 03:05:20 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
} else {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("Refusing to undefine while domain managed "
|
|
|
|
"save image exists"));
|
2011-07-20 03:05:20 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
if (virDomainDeleteConfig(driver->configDir,
|
|
|
|
driver->autostartDir,
|
|
|
|
vm) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-03-29 12:18:24 +00:00
|
|
|
event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_UNDEFINED,
|
|
|
|
VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
|
|
|
|
|
2011-08-19 13:46:22 +00:00
|
|
|
if (virDomainObjIsActive(vm)) {
|
|
|
|
vm->persistent = 0;
|
|
|
|
} else {
|
|
|
|
virDomainRemoveInactive(&driver->domains, vm);
|
|
|
|
vm = NULL;
|
|
|
|
}
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
2011-07-20 03:05:20 +00:00
|
|
|
VIR_FREE(name);
|
2011-02-10 22:42:34 +00:00
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
2011-03-29 12:18:24 +00:00
|
|
|
if (event)
|
|
|
|
libxlDomainEventQueue(driver, event);
|
2011-02-10 22:42:34 +00:00
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-07-20 03:05:20 +00:00
|
|
|
static int
|
|
|
|
libxlDomainUndefine(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
return libxlDomainUndefineFlags(dom, 0);
|
|
|
|
}
|
|
|
|
|
2011-05-26 15:27:06 +00:00
|
|
|
static int
|
|
|
|
libxlDomainChangeEjectableMedia(libxlDomainObjPrivatePtr priv,
|
|
|
|
virDomainObjPtr vm, virDomainDiskDefPtr disk)
|
|
|
|
{
|
|
|
|
virDomainDiskDefPtr origdisk = NULL;
|
|
|
|
libxl_device_disk x_disk;
|
|
|
|
int i;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
for (i = 0 ; i < vm->def->ndisks ; i++) {
|
|
|
|
if (vm->def->disks[i]->bus == disk->bus &&
|
|
|
|
STREQ(vm->def->disks[i]->dst, disk->dst)) {
|
|
|
|
origdisk = vm->def->disks[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!origdisk) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("No device with bus '%s' and target '%s'"),
|
|
|
|
virDomainDiskBusTypeToString(disk->bus), disk->dst);
|
2011-05-26 15:27:06 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (origdisk->device != VIR_DOMAIN_DISK_DEVICE_CDROM) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Removable media not supported for %s device"),
|
|
|
|
virDomainDiskDeviceTypeToString(disk->device));
|
2011-05-26 15:27:06 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-05-30 09:53:00 +00:00
|
|
|
if (libxlMakeDisk(vm->def, disk, &x_disk) < 0)
|
2011-05-26 15:27:06 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if ((ret = libxl_cdrom_insert(&priv->ctx, vm->def->id, &x_disk)) < 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("libxenlight failed to change media for disk '%s'"),
|
|
|
|
disk->dst);
|
2011-05-26 15:27:06 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_FREE(origdisk->src);
|
|
|
|
origdisk->src = disk->src;
|
|
|
|
disk->src = NULL;
|
|
|
|
origdisk->type = disk->type;
|
|
|
|
|
|
|
|
|
|
|
|
virDomainDiskDefFree(disk);
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainAttachDeviceDiskLive(libxlDomainObjPrivatePtr priv,
|
|
|
|
virDomainObjPtr vm, virDomainDeviceDefPtr dev)
|
|
|
|
{
|
|
|
|
virDomainDiskDefPtr l_disk = dev->data.disk;
|
|
|
|
libxl_device_disk x_disk;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
switch (l_disk->device) {
|
|
|
|
case VIR_DOMAIN_DISK_DEVICE_CDROM:
|
|
|
|
ret = libxlDomainChangeEjectableMedia(priv, vm, l_disk);
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_DISK_DEVICE_DISK:
|
|
|
|
if (l_disk->bus == VIR_DOMAIN_DISK_BUS_XEN) {
|
snapshot: also support disks by path
I got confused when 'virsh domblkinfo dom disk' required the
path to a disk (which can be ambiguous, since a single file
can back multiple disks), rather than the unambiguous target
device name that I was using in disk snapshots. So, in true
developer fashion, I went for the best of both worlds - all
interfaces that operate on a disk (aka block) now accept
either the target name or the unambiguous path to the backing
file used by the disk.
* src/conf/domain_conf.h (virDomainDiskIndexByName): Add
parameter.
(virDomainDiskPathByName): New prototype.
* src/libvirt_private.syms (domain_conf.h): Export it.
* src/conf/domain_conf.c (virDomainDiskIndexByName): Also allow
searching by path, and decide whether ambiguity is okay.
(virDomainDiskPathByName): New function.
(virDomainDiskRemoveByName, virDomainSnapshotAlignDisks): Update
callers.
* src/qemu/qemu_driver.c (qemudDomainBlockPeek)
(qemuDomainAttachDeviceConfig, qemuDomainUpdateDeviceConfig)
(qemuDomainGetBlockInfo, qemuDiskPathToAlias): Likewise.
* src/qemu/qemu_process.c (qemuProcessFindDomainDiskByPath):
Likewise.
* src/libxl/libxl_driver.c (libxlDomainAttachDeviceDiskLive)
(libxlDomainDetachDeviceDiskLive, libxlDomainAttachDeviceConfig)
(libxlDomainUpdateDeviceConfig): Likewise.
* src/uml/uml_driver.c (umlDomainBlockPeek): Likewise.
* src/xen/xend_internal.c (xenDaemonDomainBlockPeek): Likewise.
* docs/formatsnapshot.html.in: Update documentation.
* tools/virsh.pod (domblkstat, domblkinfo): Likewise.
* docs/schemas/domaincommon.rng (diskTarget): Tighten pattern on
disk targets.
* docs/schemas/domainsnapshot.rng (disksnapshot): Update to match.
* tests/domainsnapshotxml2xmlin/disk_snapshot.xml: Update test.
2011-08-20 02:38:36 +00:00
|
|
|
if (virDomainDiskIndexByName(vm->def, l_disk->dst, true) >= 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("target %s already exists"), l_disk->dst);
|
2011-05-26 15:27:06 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!l_disk->src) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("disk source path is missing"));
|
2011-05-26 15:27:06 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-05-30 09:53:00 +00:00
|
|
|
if (libxlMakeDisk(vm->def, l_disk, &x_disk) < 0)
|
2011-05-26 15:27:06 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if ((ret = libxl_device_disk_add(&priv->ctx, vm->def->id,
|
|
|
|
&x_disk)) < 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("libxenlight failed to attach disk '%s'"),
|
|
|
|
l_disk->dst);
|
2011-05-26 15:27:06 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainDiskInsertPreAlloced(vm->def, l_disk);
|
|
|
|
|
|
|
|
} else {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("disk bus '%s' cannot be hotplugged."),
|
|
|
|
virDomainDiskBusTypeToString(l_disk->bus));
|
2011-05-26 15:27:06 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("disk device type '%s' cannot be hotplugged"),
|
|
|
|
virDomainDiskDeviceTypeToString(l_disk->device));
|
2011-05-26 15:27:06 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainDetachDeviceDiskLive(libxlDomainObjPrivatePtr priv,
|
|
|
|
virDomainObjPtr vm, virDomainDeviceDefPtr dev)
|
|
|
|
{
|
|
|
|
virDomainDiskDefPtr l_disk = NULL;
|
|
|
|
libxl_device_disk x_disk;
|
|
|
|
int i;
|
|
|
|
int wait_secs = 2;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
switch (dev->data.disk->device) {
|
|
|
|
case VIR_DOMAIN_DISK_DEVICE_DISK:
|
|
|
|
if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_XEN) {
|
|
|
|
|
|
|
|
if ((i = virDomainDiskIndexByName(vm->def,
|
snapshot: also support disks by path
I got confused when 'virsh domblkinfo dom disk' required the
path to a disk (which can be ambiguous, since a single file
can back multiple disks), rather than the unambiguous target
device name that I was using in disk snapshots. So, in true
developer fashion, I went for the best of both worlds - all
interfaces that operate on a disk (aka block) now accept
either the target name or the unambiguous path to the backing
file used by the disk.
* src/conf/domain_conf.h (virDomainDiskIndexByName): Add
parameter.
(virDomainDiskPathByName): New prototype.
* src/libvirt_private.syms (domain_conf.h): Export it.
* src/conf/domain_conf.c (virDomainDiskIndexByName): Also allow
searching by path, and decide whether ambiguity is okay.
(virDomainDiskPathByName): New function.
(virDomainDiskRemoveByName, virDomainSnapshotAlignDisks): Update
callers.
* src/qemu/qemu_driver.c (qemudDomainBlockPeek)
(qemuDomainAttachDeviceConfig, qemuDomainUpdateDeviceConfig)
(qemuDomainGetBlockInfo, qemuDiskPathToAlias): Likewise.
* src/qemu/qemu_process.c (qemuProcessFindDomainDiskByPath):
Likewise.
* src/libxl/libxl_driver.c (libxlDomainAttachDeviceDiskLive)
(libxlDomainDetachDeviceDiskLive, libxlDomainAttachDeviceConfig)
(libxlDomainUpdateDeviceConfig): Likewise.
* src/uml/uml_driver.c (umlDomainBlockPeek): Likewise.
* src/xen/xend_internal.c (xenDaemonDomainBlockPeek): Likewise.
* docs/formatsnapshot.html.in: Update documentation.
* tools/virsh.pod (domblkstat, domblkinfo): Likewise.
* docs/schemas/domaincommon.rng (diskTarget): Tighten pattern on
disk targets.
* docs/schemas/domainsnapshot.rng (disksnapshot): Update to match.
* tests/domainsnapshotxml2xmlin/disk_snapshot.xml: Update test.
2011-08-20 02:38:36 +00:00
|
|
|
dev->data.disk->dst,
|
|
|
|
false)) < 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("disk %s not found"), dev->data.disk->dst);
|
2011-05-26 15:27:06 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
l_disk = vm->def->disks[i];
|
|
|
|
|
2011-05-30 09:53:00 +00:00
|
|
|
if (libxlMakeDisk(vm->def, l_disk, &x_disk) < 0)
|
2011-05-26 15:27:06 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if ((ret = libxl_device_disk_del(&priv->ctx, &x_disk,
|
|
|
|
wait_secs)) < 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("libxenlight failed to detach disk '%s'"),
|
|
|
|
l_disk->dst);
|
2011-05-26 15:27:06 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainDiskRemove(vm->def, i);
|
|
|
|
virDomainDiskDefFree(l_disk);
|
|
|
|
|
|
|
|
} else {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("disk bus '%s' cannot be hot unplugged."),
|
|
|
|
virDomainDiskBusTypeToString(dev->data.disk->bus));
|
2011-05-26 15:27:06 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("device type '%s' cannot hot unplugged"),
|
|
|
|
virDomainDiskDeviceTypeToString(dev->data.disk->device));
|
2011-05-26 15:27:06 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainAttachDeviceLive(libxlDomainObjPrivatePtr priv, virDomainObjPtr vm,
|
|
|
|
virDomainDeviceDefPtr dev)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
switch (dev->type) {
|
|
|
|
case VIR_DOMAIN_DEVICE_DISK:
|
|
|
|
ret = libxlDomainAttachDeviceDiskLive(priv, vm, dev);
|
|
|
|
if (!ret)
|
|
|
|
dev->data.disk = NULL;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("device type '%s' cannot be attached"),
|
|
|
|
virDomainDeviceTypeToString(dev->type));
|
2011-05-26 15:27:06 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainAttachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev)
|
|
|
|
{
|
|
|
|
virDomainDiskDefPtr disk;
|
|
|
|
|
|
|
|
switch (dev->type) {
|
|
|
|
case VIR_DOMAIN_DEVICE_DISK:
|
|
|
|
disk = dev->data.disk;
|
snapshot: also support disks by path
I got confused when 'virsh domblkinfo dom disk' required the
path to a disk (which can be ambiguous, since a single file
can back multiple disks), rather than the unambiguous target
device name that I was using in disk snapshots. So, in true
developer fashion, I went for the best of both worlds - all
interfaces that operate on a disk (aka block) now accept
either the target name or the unambiguous path to the backing
file used by the disk.
* src/conf/domain_conf.h (virDomainDiskIndexByName): Add
parameter.
(virDomainDiskPathByName): New prototype.
* src/libvirt_private.syms (domain_conf.h): Export it.
* src/conf/domain_conf.c (virDomainDiskIndexByName): Also allow
searching by path, and decide whether ambiguity is okay.
(virDomainDiskPathByName): New function.
(virDomainDiskRemoveByName, virDomainSnapshotAlignDisks): Update
callers.
* src/qemu/qemu_driver.c (qemudDomainBlockPeek)
(qemuDomainAttachDeviceConfig, qemuDomainUpdateDeviceConfig)
(qemuDomainGetBlockInfo, qemuDiskPathToAlias): Likewise.
* src/qemu/qemu_process.c (qemuProcessFindDomainDiskByPath):
Likewise.
* src/libxl/libxl_driver.c (libxlDomainAttachDeviceDiskLive)
(libxlDomainDetachDeviceDiskLive, libxlDomainAttachDeviceConfig)
(libxlDomainUpdateDeviceConfig): Likewise.
* src/uml/uml_driver.c (umlDomainBlockPeek): Likewise.
* src/xen/xend_internal.c (xenDaemonDomainBlockPeek): Likewise.
* docs/formatsnapshot.html.in: Update documentation.
* tools/virsh.pod (domblkstat, domblkinfo): Likewise.
* docs/schemas/domaincommon.rng (diskTarget): Tighten pattern on
disk targets.
* docs/schemas/domainsnapshot.rng (disksnapshot): Update to match.
* tests/domainsnapshotxml2xmlin/disk_snapshot.xml: Update test.
2011-08-20 02:38:36 +00:00
|
|
|
if (virDomainDiskIndexByName(vmdef, disk->dst, true) >= 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("target %s already exists."), disk->dst);
|
2011-05-26 15:27:06 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (virDomainDiskInsert(vmdef, disk)) {
|
|
|
|
virReportOOMError();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
/* vmdef has the pointer. Generic codes for vmdef will do all jobs */
|
|
|
|
dev->data.disk = NULL;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("persistent attach of device is not supported"));
|
2011-05-26 15:27:06 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainDetachDeviceLive(libxlDomainObjPrivatePtr priv, virDomainObjPtr vm,
|
|
|
|
virDomainDeviceDefPtr dev)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
switch (dev->type) {
|
|
|
|
case VIR_DOMAIN_DEVICE_DISK:
|
|
|
|
ret = libxlDomainDetachDeviceDiskLive(priv, vm, dev);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("device type '%s' cannot be detached"),
|
|
|
|
virDomainDeviceTypeToString(dev->type));
|
2011-05-26 15:27:06 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainDetachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev)
|
|
|
|
{
|
util: eliminate device object leaks related to virDomain*Remove*()
There are several functions in domain_conf.c that remove a device
object from the domain's list of that object type, but don't free the
object or return it to the caller to free. In many cases this isn't a
problem because the caller already had a pointer to the object and
frees it afterward, but in several cases the removed object was just
left floating around with no references to it.
In particular, the function qemuDomainDetachDeviceConfig() calls
functions to locate and remove net (virDomainNetRemoveByMac), disk
(virDomainDiskRemoveByName()), and lease (virDomainLeaseRemove())
devices, but neither it nor its caller qemuDomainModifyDeviceConfig()
ever obtain a pointer to the device being removed, much less free it.
This patch modifies the following "remove" functions to return a
pointer to the device object being removed from the domain device
arrays, to give the caller the option of freeing the device object
using that pointer if needed. In places where the object was
previously leaked, it is now freed:
virDomainDiskRemove
virDomainDiskRemoveByName
virDomainNetRemove
virDomainNetRemoveByMac
virDomainHostdevRemove
virDomainLeaseRemove
virDomainLeaseRemoveAt
The functions that had been leaking:
libxlDomainDetachConfig - leaked a virDomainDiskDef
qemuDomainDetachDeviceConfig - could leak a virDomainDiskDef,
a virDomainNetDef, or a
virDomainLeaseDef
qemuDomainDetachLease - leaked a virDomainLeaseDef
2012-03-06 23:06:14 +00:00
|
|
|
virDomainDiskDefPtr disk, detach;
|
2011-05-26 15:27:06 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
switch (dev->type) {
|
|
|
|
case VIR_DOMAIN_DEVICE_DISK:
|
|
|
|
disk = dev->data.disk;
|
util: eliminate device object leaks related to virDomain*Remove*()
There are several functions in domain_conf.c that remove a device
object from the domain's list of that object type, but don't free the
object or return it to the caller to free. In many cases this isn't a
problem because the caller already had a pointer to the object and
frees it afterward, but in several cases the removed object was just
left floating around with no references to it.
In particular, the function qemuDomainDetachDeviceConfig() calls
functions to locate and remove net (virDomainNetRemoveByMac), disk
(virDomainDiskRemoveByName()), and lease (virDomainLeaseRemove())
devices, but neither it nor its caller qemuDomainModifyDeviceConfig()
ever obtain a pointer to the device being removed, much less free it.
This patch modifies the following "remove" functions to return a
pointer to the device object being removed from the domain device
arrays, to give the caller the option of freeing the device object
using that pointer if needed. In places where the object was
previously leaked, it is now freed:
virDomainDiskRemove
virDomainDiskRemoveByName
virDomainNetRemove
virDomainNetRemoveByMac
virDomainHostdevRemove
virDomainLeaseRemove
virDomainLeaseRemoveAt
The functions that had been leaking:
libxlDomainDetachConfig - leaked a virDomainDiskDef
qemuDomainDetachDeviceConfig - could leak a virDomainDiskDef,
a virDomainNetDef, or a
virDomainLeaseDef
qemuDomainDetachLease - leaked a virDomainLeaseDef
2012-03-06 23:06:14 +00:00
|
|
|
if (!(detach = virDomainDiskRemoveByName(vmdef, disk->dst))) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("no target device %s"), disk->dst);
|
2011-05-26 15:27:06 +00:00
|
|
|
break;
|
|
|
|
}
|
util: eliminate device object leaks related to virDomain*Remove*()
There are several functions in domain_conf.c that remove a device
object from the domain's list of that object type, but don't free the
object or return it to the caller to free. In many cases this isn't a
problem because the caller already had a pointer to the object and
frees it afterward, but in several cases the removed object was just
left floating around with no references to it.
In particular, the function qemuDomainDetachDeviceConfig() calls
functions to locate and remove net (virDomainNetRemoveByMac), disk
(virDomainDiskRemoveByName()), and lease (virDomainLeaseRemove())
devices, but neither it nor its caller qemuDomainModifyDeviceConfig()
ever obtain a pointer to the device being removed, much less free it.
This patch modifies the following "remove" functions to return a
pointer to the device object being removed from the domain device
arrays, to give the caller the option of freeing the device object
using that pointer if needed. In places where the object was
previously leaked, it is now freed:
virDomainDiskRemove
virDomainDiskRemoveByName
virDomainNetRemove
virDomainNetRemoveByMac
virDomainHostdevRemove
virDomainLeaseRemove
virDomainLeaseRemoveAt
The functions that had been leaking:
libxlDomainDetachConfig - leaked a virDomainDiskDef
qemuDomainDetachDeviceConfig - could leak a virDomainDiskDef,
a virDomainNetDef, or a
virDomainLeaseDef
qemuDomainDetachLease - leaked a virDomainLeaseDef
2012-03-06 23:06:14 +00:00
|
|
|
virDomainDiskDefFree(detach);
|
2011-05-26 15:27:06 +00:00
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
default:
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("persistent detach of device is not supported"));
|
2011-05-26 15:27:06 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainUpdateDeviceLive(libxlDomainObjPrivatePtr priv,
|
|
|
|
virDomainObjPtr vm, virDomainDeviceDefPtr dev)
|
|
|
|
{
|
|
|
|
virDomainDiskDefPtr disk;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
switch (dev->type) {
|
|
|
|
case VIR_DOMAIN_DEVICE_DISK:
|
|
|
|
disk = dev->data.disk;
|
|
|
|
switch (disk->device) {
|
|
|
|
case VIR_DOMAIN_DISK_DEVICE_CDROM:
|
|
|
|
ret = libxlDomainChangeEjectableMedia(priv, vm, disk);
|
|
|
|
if (ret == 0)
|
|
|
|
dev->data.disk = NULL;
|
|
|
|
break;
|
|
|
|
default:
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("disk bus '%s' cannot be updated."),
|
|
|
|
virDomainDiskBusTypeToString(disk->bus));
|
2011-05-26 15:27:06 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("device type '%s' cannot be updated"),
|
|
|
|
virDomainDeviceTypeToString(dev->type));
|
2011-05-26 15:27:06 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainUpdateDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev)
|
|
|
|
{
|
|
|
|
virDomainDiskDefPtr orig;
|
|
|
|
virDomainDiskDefPtr disk;
|
|
|
|
int i;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
switch (dev->type) {
|
|
|
|
case VIR_DOMAIN_DEVICE_DISK:
|
|
|
|
disk = dev->data.disk;
|
snapshot: also support disks by path
I got confused when 'virsh domblkinfo dom disk' required the
path to a disk (which can be ambiguous, since a single file
can back multiple disks), rather than the unambiguous target
device name that I was using in disk snapshots. So, in true
developer fashion, I went for the best of both worlds - all
interfaces that operate on a disk (aka block) now accept
either the target name or the unambiguous path to the backing
file used by the disk.
* src/conf/domain_conf.h (virDomainDiskIndexByName): Add
parameter.
(virDomainDiskPathByName): New prototype.
* src/libvirt_private.syms (domain_conf.h): Export it.
* src/conf/domain_conf.c (virDomainDiskIndexByName): Also allow
searching by path, and decide whether ambiguity is okay.
(virDomainDiskPathByName): New function.
(virDomainDiskRemoveByName, virDomainSnapshotAlignDisks): Update
callers.
* src/qemu/qemu_driver.c (qemudDomainBlockPeek)
(qemuDomainAttachDeviceConfig, qemuDomainUpdateDeviceConfig)
(qemuDomainGetBlockInfo, qemuDiskPathToAlias): Likewise.
* src/qemu/qemu_process.c (qemuProcessFindDomainDiskByPath):
Likewise.
* src/libxl/libxl_driver.c (libxlDomainAttachDeviceDiskLive)
(libxlDomainDetachDeviceDiskLive, libxlDomainAttachDeviceConfig)
(libxlDomainUpdateDeviceConfig): Likewise.
* src/uml/uml_driver.c (umlDomainBlockPeek): Likewise.
* src/xen/xend_internal.c (xenDaemonDomainBlockPeek): Likewise.
* docs/formatsnapshot.html.in: Update documentation.
* tools/virsh.pod (domblkstat, domblkinfo): Likewise.
* docs/schemas/domaincommon.rng (diskTarget): Tighten pattern on
disk targets.
* docs/schemas/domainsnapshot.rng (disksnapshot): Update to match.
* tests/domainsnapshotxml2xmlin/disk_snapshot.xml: Update test.
2011-08-20 02:38:36 +00:00
|
|
|
if ((i = virDomainDiskIndexByName(vmdef, disk->dst, false)) < 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("target %s doesn't exist."), disk->dst);
|
2011-05-26 15:27:06 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
orig = vmdef->disks[i];
|
|
|
|
if (!(orig->device == VIR_DOMAIN_DISK_DEVICE_CDROM)) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("this disk doesn't support update"));
|
2011-05-26 15:27:06 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_FREE(orig->src);
|
|
|
|
orig->src = disk->src;
|
|
|
|
orig->type = disk->type;
|
|
|
|
if (disk->driverName) {
|
|
|
|
VIR_FREE(orig->driverName);
|
|
|
|
orig->driverName = disk->driverName;
|
|
|
|
disk->driverName = NULL;
|
|
|
|
}
|
2012-10-15 21:47:42 +00:00
|
|
|
orig->format = disk->format;
|
2011-05-26 15:27:06 +00:00
|
|
|
disk->src = NULL;
|
|
|
|
break;
|
|
|
|
default:
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("persistent update of device is not supported"));
|
2011-05-26 15:27:06 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Actions for libxlDomainModifyDeviceFlags */
|
|
|
|
enum {
|
|
|
|
LIBXL_DEVICE_ATTACH,
|
|
|
|
LIBXL_DEVICE_DETACH,
|
|
|
|
LIBXL_DEVICE_UPDATE,
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainModifyDeviceFlags(virDomainPtr dom, const char *xml,
|
|
|
|
unsigned int flags, int action)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm = NULL;
|
|
|
|
virDomainDefPtr vmdef = NULL;
|
|
|
|
virDomainDeviceDefPtr dev = NULL;
|
|
|
|
libxlDomainObjPrivatePtr priv;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE |
|
|
|
|
VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1);
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
|
|
|
|
if (!vm) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, "%s", _("no domain with matching uuid"));
|
2011-05-26 15:27:06 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virDomainObjIsActive(vm)) {
|
|
|
|
if (flags == VIR_DOMAIN_DEVICE_MODIFY_CURRENT)
|
|
|
|
flags |= VIR_DOMAIN_DEVICE_MODIFY_LIVE;
|
|
|
|
} else {
|
|
|
|
if (flags == VIR_DOMAIN_DEVICE_MODIFY_CURRENT)
|
|
|
|
flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
|
|
|
|
/* check consistency between flags and the vm state */
|
|
|
|
if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("Domain is not running"));
|
2011-05-26 15:27:06 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) && !vm->persistent) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("cannot modify device on transient domain"));
|
2011-05-26 15:27:06 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv = vm->privateData;
|
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
|
|
|
|
if (!(dev = virDomainDeviceDefParse(driver->caps, vm->def, xml,
|
|
|
|
VIR_DOMAIN_XML_INACTIVE)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* Make a copy for updated domain. */
|
|
|
|
if (!(vmdef = virDomainObjCopyPersistentDef(driver->caps, vm)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
switch (action) {
|
|
|
|
case LIBXL_DEVICE_ATTACH:
|
|
|
|
ret = libxlDomainAttachDeviceConfig(vmdef, dev);
|
|
|
|
break;
|
|
|
|
case LIBXL_DEVICE_DETACH:
|
|
|
|
ret = libxlDomainDetachDeviceConfig(vmdef, dev);
|
|
|
|
break;
|
|
|
|
case LIBXL_DEVICE_UPDATE:
|
|
|
|
ret = libxlDomainUpdateDeviceConfig(vmdef, dev);
|
|
|
|
default:
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unknown domain modify action %d"), action);
|
2011-05-26 15:27:06 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) {
|
|
|
|
/* If dev exists it was created to modify the domain config. Free it. */
|
|
|
|
virDomainDeviceDefFree(dev);
|
|
|
|
if (!(dev = virDomainDeviceDefParse(driver->caps, vm->def, xml,
|
|
|
|
VIR_DOMAIN_XML_INACTIVE)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
switch (action) {
|
|
|
|
case LIBXL_DEVICE_ATTACH:
|
|
|
|
ret = libxlDomainAttachDeviceLive(priv, vm, dev);
|
|
|
|
break;
|
|
|
|
case LIBXL_DEVICE_DETACH:
|
|
|
|
ret = libxlDomainDetachDeviceLive(priv, vm, dev);
|
|
|
|
break;
|
|
|
|
case LIBXL_DEVICE_UPDATE:
|
|
|
|
ret = libxlDomainUpdateDeviceLive(priv, vm, dev);
|
|
|
|
default:
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unknown domain modify action %d"), action);
|
2011-05-26 15:27:06 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* update domain status forcibly because the domain status may be
|
|
|
|
* changed even if we attach the device failed.
|
|
|
|
*/
|
|
|
|
if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
|
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Finally, if no error until here, we can save config. */
|
|
|
|
if (!ret && (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG)) {
|
|
|
|
ret = virDomainSaveConfig(driver->configDir, vmdef);
|
|
|
|
if (!ret) {
|
|
|
|
virDomainObjAssignDef(vm, vmdef, false);
|
|
|
|
vmdef = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virDomainDefFree(vmdef);
|
|
|
|
virDomainDeviceDefFree(dev);
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
return libxlDomainModifyDeviceFlags(dom, xml, flags, LIBXL_DEVICE_ATTACH);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainAttachDevice(virDomainPtr dom, const char *xml)
|
|
|
|
{
|
|
|
|
return libxlDomainAttachDeviceFlags(dom, xml,
|
|
|
|
VIR_DOMAIN_DEVICE_MODIFY_LIVE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainDetachDeviceFlags(virDomainPtr dom, const char *xml,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
return libxlDomainModifyDeviceFlags(dom, xml, flags, LIBXL_DEVICE_DETACH);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainDetachDevice(virDomainPtr dom, const char *xml)
|
|
|
|
{
|
|
|
|
return libxlDomainDetachDeviceFlags(dom, xml,
|
|
|
|
VIR_DOMAIN_DEVICE_MODIFY_LIVE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
return libxlDomainModifyDeviceFlags(dom, xml, flags, LIBXL_DEVICE_UPDATE);
|
|
|
|
}
|
|
|
|
|
2011-03-21 09:35:53 +00:00
|
|
|
static unsigned long long
|
|
|
|
libxlNodeGetFreeMemory(virConnectPtr conn)
|
|
|
|
{
|
|
|
|
libxl_physinfo phy_info;
|
|
|
|
const libxl_version_info* ver_info;
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
|
|
|
|
if (libxl_get_physinfo(&driver->ctx, &phy_info)) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("libxl_get_physinfo_info failed"));
|
2011-03-21 09:35:53 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((ver_info = libxl_get_version_info(&driver->ctx)) == NULL) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("libxl_get_version_info failed"));
|
2011-03-21 09:35:53 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return phy_info.free_pages * ver_info->pagesize;
|
|
|
|
}
|
|
|
|
|
2011-03-29 12:18:24 +00:00
|
|
|
static int
|
|
|
|
libxlDomainEventRegister(virConnectPtr conn,
|
|
|
|
virConnectDomainEventCallback callback, void *opaque,
|
|
|
|
virFreeCallback freecb)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
2011-12-13 11:14:46 +00:00
|
|
|
ret = virDomainEventStateRegister(conn,
|
|
|
|
driver->domainEventState,
|
|
|
|
callback, opaque, freecb);
|
2011-03-29 12:18:24 +00:00
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainEventDeregister(virConnectPtr conn,
|
|
|
|
virConnectDomainEventCallback callback)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
2011-05-12 14:47:08 +00:00
|
|
|
ret = virDomainEventStateDeregister(conn,
|
|
|
|
driver->domainEventState,
|
|
|
|
callback);
|
2011-03-29 12:18:24 +00:00
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-03-28 10:49:22 +00:00
|
|
|
static int
|
|
|
|
libxlDomainGetAutostart(virDomainPtr dom, int *autostart)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
|
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
2011-03-28 10:49:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
*autostart = vm->autostart;
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainSetAutostart(virDomainPtr dom, int autostart)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
char *configFile = NULL, *autostartLink = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
|
|
|
|
if (!vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("No domain with matching uuid '%s'"), uuidstr);
|
2011-03-28 10:49:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!vm->persistent) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("cannot set autostart for transient domain"));
|
2011-03-28 10:49:22 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
autostart = (autostart != 0);
|
|
|
|
|
|
|
|
if (vm->autostart != autostart) {
|
|
|
|
if (!(configFile = virDomainConfigFile(driver->configDir, vm->def->name)))
|
|
|
|
goto cleanup;
|
|
|
|
if (!(autostartLink = virDomainConfigFile(driver->autostartDir, vm->def->name)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (autostart) {
|
2011-07-05 21:02:53 +00:00
|
|
|
if (virFileMakePath(driver->autostartDir) < 0) {
|
|
|
|
virReportSystemError(errno,
|
2011-03-28 10:49:22 +00:00
|
|
|
_("cannot create autostart directory %s"),
|
|
|
|
driver->autostartDir);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (symlink(configFile, autostartLink) < 0) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("Failed to create symlink '%s to '%s'"),
|
|
|
|
autostartLink, configFile);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("Failed to delete symlink '%s'"),
|
|
|
|
autostartLink);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
vm->autostart = autostart;
|
|
|
|
}
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(configFile);
|
|
|
|
VIR_FREE(autostartLink);
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-03-29 12:46:55 +00:00
|
|
|
static char *
|
|
|
|
libxlDomainGetSchedulerType(virDomainPtr dom, int *nparams)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
libxlDomainObjPrivatePtr priv;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
char * ret = NULL;
|
|
|
|
int sched_id;
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
|
|
|
|
if (!vm) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, "%s", _("no domain with matching uuid"));
|
2011-03-29 12:46:55 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
|
2011-03-29 12:46:55 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv = vm->privateData;
|
|
|
|
if ((sched_id = libxl_get_sched_id(&priv->ctx)) < 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to get scheduler id for domain '%d'"
|
|
|
|
" with libxenlight"), dom->id);
|
2011-03-29 12:46:55 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-05-18 07:55:32 +00:00
|
|
|
if (nparams)
|
|
|
|
*nparams = 0;
|
2011-03-29 12:46:55 +00:00
|
|
|
switch(sched_id) {
|
|
|
|
case XEN_SCHEDULER_SEDF:
|
|
|
|
ret = strdup("sedf");
|
|
|
|
break;
|
|
|
|
case XEN_SCHEDULER_CREDIT:
|
|
|
|
ret = strdup("credit");
|
2011-05-18 07:55:32 +00:00
|
|
|
if (nparams)
|
|
|
|
*nparams = XEN_SCHED_CREDIT_NPARAM;
|
2011-03-29 12:46:55 +00:00
|
|
|
break;
|
|
|
|
case XEN_SCHEDULER_CREDIT2:
|
|
|
|
ret = strdup("credit2");
|
|
|
|
break;
|
|
|
|
case XEN_SCHEDULER_ARINC653:
|
|
|
|
ret = strdup("arinc653");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ret)
|
|
|
|
virReportOOMError();
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-04-06 08:58:40 +00:00
|
|
|
static int
|
2011-05-17 22:33:53 +00:00
|
|
|
libxlDomainGetSchedulerParametersFlags(virDomainPtr dom,
|
|
|
|
virTypedParameterPtr params,
|
|
|
|
int *nparams,
|
|
|
|
unsigned int flags)
|
2011-04-06 08:58:40 +00:00
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
libxlDomainObjPrivatePtr priv;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
libxl_sched_credit sc_info;
|
|
|
|
int sched_id;
|
|
|
|
int ret = -1;
|
|
|
|
|
2011-05-17 22:33:53 +00:00
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2011-04-06 08:58:40 +00:00
|
|
|
libxlDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
|
|
|
|
if (!vm) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, "%s", _("no domain with matching uuid"));
|
2011-04-06 08:58:40 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
|
2011-04-06 08:58:40 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv = vm->privateData;
|
|
|
|
|
|
|
|
if ((sched_id = libxl_get_sched_id(&priv->ctx)) < 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to get scheduler id for domain '%d'"
|
|
|
|
" with libxenlight"), dom->id);
|
2011-04-06 08:58:40 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sched_id != XEN_SCHEDULER_CREDIT) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Only 'credit' scheduler is supported"));
|
2011-04-06 08:58:40 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (libxl_sched_credit_domain_get(&priv->ctx, dom->id, &sc_info) != 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to get scheduler parameters for domain '%d'"
|
|
|
|
" with libxenlight"), dom->id);
|
2011-04-06 08:58:40 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2012-01-07 12:47:43 +00:00
|
|
|
if (virTypedParameterAssign(¶ms[0], VIR_DOMAIN_SCHEDULER_WEIGHT,
|
|
|
|
VIR_TYPED_PARAM_UINT, sc_info.weight) < 0)
|
2011-04-06 08:58:40 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2011-11-02 17:42:38 +00:00
|
|
|
if (*nparams > 1) {
|
2012-01-07 12:47:43 +00:00
|
|
|
if (virTypedParameterAssign(¶ms[0], VIR_DOMAIN_SCHEDULER_CAP,
|
|
|
|
VIR_TYPED_PARAM_UINT, sc_info.cap) < 0)
|
2011-11-02 17:42:38 +00:00
|
|
|
goto cleanup;
|
2011-04-06 08:58:40 +00:00
|
|
|
}
|
|
|
|
|
2011-11-02 17:42:38 +00:00
|
|
|
if (*nparams > XEN_SCHED_CREDIT_NPARAM)
|
|
|
|
*nparams = XEN_SCHED_CREDIT_NPARAM;
|
2011-04-06 08:58:40 +00:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2011-05-17 22:33:53 +00:00
|
|
|
libxlDomainGetSchedulerParameters(virDomainPtr dom, virTypedParameterPtr params,
|
|
|
|
int *nparams)
|
|
|
|
{
|
|
|
|
return libxlDomainGetSchedulerParametersFlags(dom, params, nparams, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainSetSchedulerParametersFlags(virDomainPtr dom,
|
|
|
|
virTypedParameterPtr params,
|
|
|
|
int nparams,
|
|
|
|
unsigned int flags)
|
2011-04-06 08:58:40 +00:00
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
libxlDomainObjPrivatePtr priv;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
libxl_sched_credit sc_info;
|
|
|
|
int sched_id;
|
|
|
|
int i;
|
|
|
|
int ret = -1;
|
|
|
|
|
2011-05-17 22:33:53 +00:00
|
|
|
virCheckFlags(0, -1);
|
2012-01-07 12:47:43 +00:00
|
|
|
if (virTypedParameterArrayValidate(params, nparams,
|
|
|
|
VIR_DOMAIN_SCHEDULER_WEIGHT,
|
|
|
|
VIR_TYPED_PARAM_UINT,
|
|
|
|
VIR_DOMAIN_SCHEDULER_CAP,
|
|
|
|
VIR_TYPED_PARAM_UINT,
|
|
|
|
NULL) < 0)
|
|
|
|
return -1;
|
2011-05-17 22:33:53 +00:00
|
|
|
|
2011-04-06 08:58:40 +00:00
|
|
|
libxlDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
|
|
|
|
if (!vm) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, "%s", _("no domain with matching uuid"));
|
2011-04-06 08:58:40 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
|
2011-04-06 08:58:40 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv = vm->privateData;
|
|
|
|
|
|
|
|
if ((sched_id = libxl_get_sched_id(&priv->ctx)) < 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to get scheduler id for domain '%d'"
|
|
|
|
" with libxenlight"), dom->id);
|
2011-04-06 08:58:40 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sched_id != XEN_SCHEDULER_CREDIT) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Only 'credit' scheduler is supported"));
|
2011-04-06 08:58:40 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-05-18 09:04:12 +00:00
|
|
|
if (libxl_sched_credit_domain_get(&priv->ctx, dom->id, &sc_info) != 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to get scheduler parameters for domain '%d'"
|
|
|
|
" with libxenlight"), dom->id);
|
2011-04-06 08:58:40 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < nparams; ++i) {
|
2011-05-26 17:39:04 +00:00
|
|
|
virTypedParameterPtr param = ¶ms[i];
|
2011-04-06 08:58:40 +00:00
|
|
|
|
2011-11-01 20:38:42 +00:00
|
|
|
if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_WEIGHT)) {
|
2011-04-06 08:58:40 +00:00
|
|
|
sc_info.weight = params[i].value.ui;
|
2011-11-01 20:38:42 +00:00
|
|
|
} else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_CAP)) {
|
2011-04-06 08:58:40 +00:00
|
|
|
sc_info.cap = params[i].value.ui;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (libxl_sched_credit_domain_set(&priv->ctx, dom->id, &sc_info) != 0) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to set scheduler parameters for domain '%d'"
|
|
|
|
" with libxenlight"), dom->id);
|
2011-04-06 08:58:40 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-05-17 22:33:53 +00:00
|
|
|
static int
|
|
|
|
libxlDomainSetSchedulerParameters(virDomainPtr dom, virTypedParameterPtr params,
|
|
|
|
int nparams)
|
|
|
|
{
|
|
|
|
return libxlDomainSetSchedulerParametersFlags(dom, params, nparams, 0);
|
|
|
|
}
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
static int
|
|
|
|
libxlDomainIsActive(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr obj;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
obj = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
if (!obj) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, NULL);
|
2011-02-10 22:42:34 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
ret = virDomainObjIsActive(obj);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (obj)
|
|
|
|
virDomainObjUnlock(obj);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainIsPersistent(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr obj;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
obj = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
if (!obj) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, NULL);
|
2011-02-10 22:42:34 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
ret = obj->persistent;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (obj)
|
|
|
|
virDomainObjUnlock(obj);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-04-06 08:58:39 +00:00
|
|
|
static int
|
|
|
|
libxlDomainIsUpdated(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
if (!vm) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, NULL);
|
2011-04-06 08:58:39 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
ret = vm->updated;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virDomainObjUnlock(vm);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-03-29 12:18:24 +00:00
|
|
|
static int
|
|
|
|
libxlDomainEventRegisterAny(virConnectPtr conn, virDomainPtr dom, int eventID,
|
|
|
|
virConnectDomainEventGenericCallback callback,
|
|
|
|
void *opaque, virFreeCallback freecb)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
2011-12-13 11:14:46 +00:00
|
|
|
if (virDomainEventStateRegisterID(conn,
|
|
|
|
driver->domainEventState,
|
|
|
|
dom, eventID, callback, opaque,
|
|
|
|
freecb, &ret) < 0)
|
Return count of callbacks when registering callbacks
When registering a callback for a particular event some callers
need to know how many callbacks already exist for that event.
While it is possible to ask for a count, this is not free from
race conditions when threaded. Thus the API for registering
callbacks should return the count of callbacks. Also rename
virDomainEventStateDeregisterAny to virDomainEventStateDeregisterID
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Return count of callbacks when
registering callbacks
* src/libxl/libxl_driver.c, src/libxl/libxl_driver.c,
src/qemu/qemu_driver.c, src/remote/remote_driver.c,
src/remote/remote_driver.c, src/uml/uml_driver.c,
src/vbox/vbox_tmpl.c, src/xen/xen_driver.c: Update
for change in APIs
2011-12-13 23:38:54 +00:00
|
|
|
ret = -1;
|
2011-03-29 12:18:24 +00:00
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainEventDeregisterAny(virConnectPtr conn, int callbackID)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
Return count of callbacks when registering callbacks
When registering a callback for a particular event some callers
need to know how many callbacks already exist for that event.
While it is possible to ask for a count, this is not free from
race conditions when threaded. Thus the API for registering
callbacks should return the count of callbacks. Also rename
virDomainEventStateDeregisterAny to virDomainEventStateDeregisterID
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Return count of callbacks when
registering callbacks
* src/libxl/libxl_driver.c, src/libxl/libxl_driver.c,
src/qemu/qemu_driver.c, src/remote/remote_driver.c,
src/remote/remote_driver.c, src/uml/uml_driver.c,
src/vbox/vbox_tmpl.c, src/xen/xen_driver.c: Update
for change in APIs
2011-12-13 23:38:54 +00:00
|
|
|
ret = virDomainEventStateDeregisterID(conn,
|
|
|
|
driver->domainEventState,
|
|
|
|
callbackID);
|
2011-03-29 12:18:24 +00:00
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2011-09-23 06:56:13 +00:00
|
|
|
static int
|
|
|
|
libxlIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2012-06-11 09:04:57 +00:00
|
|
|
static int
|
|
|
|
libxlListAllDomains(virConnectPtr conn,
|
|
|
|
virDomainPtr **domains,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
int ret = -1;
|
|
|
|
|
2012-08-03 15:48:05 +00:00
|
|
|
virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
|
2012-06-11 09:04:57 +00:00
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
ret = virDomainList(conn, driver->domains.objs, domains, flags);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-09-23 06:56:13 +00:00
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
static virDriver libxlDriver = {
|
Convert all driver struct intializers to C99 style
Change all the driver struct initializers to use the
C99 style, leaving out unused fields. This will make
it possible to add new APIs without changing every
driver. eg change:
qemudDomainResume, /* domainResume */
qemudDomainShutdown, /* domainShutdown */
NULL, /* domainReboot */
qemudDomainDestroy, /* domainDestroy */
to
.domainResume = qemudDomainResume,
.domainShutdown = qemudDomainShutdown,
.domainDestroy = qemudDomainDestroy,
And get rid of any existing C99 style initializersr which
set NULL, eg change
.listPools = vboxStorageListPools,
.numOfDefinedPools = NULL,
.listDefinedPools = NULL,
.findPoolSources = NULL,
.poolLookupByName = vboxStoragePoolLookupByName,
to
.listPools = vboxStorageListPools,
.poolLookupByName = vboxStoragePoolLookupByName,
2011-05-13 10:16:31 +00:00
|
|
|
.no = VIR_DRV_LIBXL,
|
|
|
|
.name = "xenlight",
|
2011-05-13 13:35:01 +00:00
|
|
|
.open = libxlOpen, /* 0.9.0 */
|
|
|
|
.close = libxlClose, /* 0.9.0 */
|
|
|
|
.type = libxlGetType, /* 0.9.0 */
|
|
|
|
.version = libxlGetVersion, /* 0.9.0 */
|
|
|
|
.getHostname = virGetHostname, /* 0.9.0 */
|
|
|
|
.getMaxVcpus = libxlGetMaxVcpus, /* 0.9.0 */
|
|
|
|
.nodeGetInfo = libxlNodeGetInfo, /* 0.9.0 */
|
|
|
|
.getCapabilities = libxlGetCapabilities, /* 0.9.0 */
|
|
|
|
.listDomains = libxlListDomains, /* 0.9.0 */
|
|
|
|
.numOfDomains = libxlNumDomains, /* 0.9.0 */
|
2012-06-11 09:04:57 +00:00
|
|
|
.listAllDomains = libxlListAllDomains, /* 0.9.13 */
|
2011-05-13 13:35:01 +00:00
|
|
|
.domainCreateXML = libxlDomainCreateXML, /* 0.9.0 */
|
|
|
|
.domainLookupByID = libxlDomainLookupByID, /* 0.9.0 */
|
|
|
|
.domainLookupByUUID = libxlDomainLookupByUUID, /* 0.9.0 */
|
|
|
|
.domainLookupByName = libxlDomainLookupByName, /* 0.9.0 */
|
|
|
|
.domainSuspend = libxlDomainSuspend, /* 0.9.0 */
|
|
|
|
.domainResume = libxlDomainResume, /* 0.9.0 */
|
|
|
|
.domainShutdown = libxlDomainShutdown, /* 0.9.0 */
|
2011-10-05 17:31:55 +00:00
|
|
|
.domainShutdownFlags = libxlDomainShutdownFlags, /* 0.9.10 */
|
2011-05-13 13:35:01 +00:00
|
|
|
.domainReboot = libxlDomainReboot, /* 0.9.0 */
|
|
|
|
.domainDestroy = libxlDomainDestroy, /* 0.9.0 */
|
2011-07-20 16:47:46 +00:00
|
|
|
.domainDestroyFlags = libxlDomainDestroyFlags, /* 0.9.4 */
|
2011-05-13 13:35:01 +00:00
|
|
|
.domainGetOSType = libxlDomainGetOSType, /* 0.9.0 */
|
|
|
|
.domainGetMaxMemory = libxlDomainGetMaxMemory, /* 0.9.0 */
|
2011-05-30 09:53:03 +00:00
|
|
|
.domainSetMaxMemory = libxlDomainSetMaxMemory, /* 0.9.2 */
|
2011-05-13 13:35:01 +00:00
|
|
|
.domainSetMemory = libxlDomainSetMemory, /* 0.9.0 */
|
|
|
|
.domainSetMemoryFlags = libxlDomainSetMemoryFlags, /* 0.9.0 */
|
|
|
|
.domainGetInfo = libxlDomainGetInfo, /* 0.9.0 */
|
|
|
|
.domainGetState = libxlDomainGetState, /* 0.9.2 */
|
2011-05-30 09:53:02 +00:00
|
|
|
.domainSave = libxlDomainSave, /* 0.9.2 */
|
save: wire up trivial save/restore flags implementations
For all hypervisors that support save and restore, the new API
now performs the same functions as the old.
VBox is excluded from this list, because its existing domainsave
is broken (there is no corresponding domainrestore, and there
is no control over the filename used in the save). A later
patch should change vbox to use its implementation for
managedsave, and teach start to use managedsave results.
* src/libxl/libxl_driver.c (libxlDomainSave): Move guts...
(libxlDomainSaveFlags): ...to new function.
(libxlDomainRestore): Move guts...
(libxlDomainRestoreFlags): ...to new function.
* src/test/test_driver.c (testDomainSave, testDomainSaveFlags)
(testDomainRestore, testDomainRestoreFlags): Likewise.
* src/xen/xen_driver.c (xenUnifiedDomainSave)
(xenUnifiedDomainSaveFlags, xenUnifiedDomainRestore)
(xenUnifiedDomainRestoreFlags): Likewise.
* src/qemu/qemu_driver.c (qemudDomainSave, qemudDomainRestore):
Rename and move guts.
(qemuDomainSave, qemuDomainSaveFlags, qemuDomainRestore)
(qemuDomainRestoreFlags): ...here.
(qemudDomainSaveFlag): Rename...
(qemuDomainSaveInternal): ...to this, and update callers.
2011-07-09 02:55:29 +00:00
|
|
|
.domainSaveFlags = libxlDomainSaveFlags, /* 0.9.4 */
|
2011-05-30 09:53:02 +00:00
|
|
|
.domainRestore = libxlDomainRestore, /* 0.9.2 */
|
save: wire up trivial save/restore flags implementations
For all hypervisors that support save and restore, the new API
now performs the same functions as the old.
VBox is excluded from this list, because its existing domainsave
is broken (there is no corresponding domainrestore, and there
is no control over the filename used in the save). A later
patch should change vbox to use its implementation for
managedsave, and teach start to use managedsave results.
* src/libxl/libxl_driver.c (libxlDomainSave): Move guts...
(libxlDomainSaveFlags): ...to new function.
(libxlDomainRestore): Move guts...
(libxlDomainRestoreFlags): ...to new function.
* src/test/test_driver.c (testDomainSave, testDomainSaveFlags)
(testDomainRestore, testDomainRestoreFlags): Likewise.
* src/xen/xen_driver.c (xenUnifiedDomainSave)
(xenUnifiedDomainSaveFlags, xenUnifiedDomainRestore)
(xenUnifiedDomainRestoreFlags): Likewise.
* src/qemu/qemu_driver.c (qemudDomainSave, qemudDomainRestore):
Rename and move guts.
(qemuDomainSave, qemuDomainSaveFlags, qemuDomainRestore)
(qemuDomainRestoreFlags): ...here.
(qemudDomainSaveFlag): Rename...
(qemuDomainSaveInternal): ...to this, and update callers.
2011-07-09 02:55:29 +00:00
|
|
|
.domainRestoreFlags = libxlDomainRestoreFlags, /* 0.9.4 */
|
2011-05-30 09:53:01 +00:00
|
|
|
.domainCoreDump = libxlDomainCoreDump, /* 0.9.2 */
|
2011-05-13 13:35:01 +00:00
|
|
|
.domainSetVcpus = libxlDomainSetVcpus, /* 0.9.0 */
|
|
|
|
.domainSetVcpusFlags = libxlDomainSetVcpusFlags, /* 0.9.0 */
|
|
|
|
.domainGetVcpusFlags = libxlDomainGetVcpusFlags, /* 0.9.0 */
|
|
|
|
.domainPinVcpu = libxlDomainPinVcpu, /* 0.9.0 */
|
|
|
|
.domainGetVcpus = libxlDomainGetVcpus, /* 0.9.0 */
|
|
|
|
.domainGetXMLDesc = libxlDomainGetXMLDesc, /* 0.9.0 */
|
|
|
|
.domainXMLFromNative = libxlDomainXMLFromNative, /* 0.9.0 */
|
|
|
|
.domainXMLToNative = libxlDomainXMLToNative, /* 0.9.0 */
|
|
|
|
.listDefinedDomains = libxlListDefinedDomains, /* 0.9.0 */
|
|
|
|
.numOfDefinedDomains = libxlNumDefinedDomains, /* 0.9.0 */
|
|
|
|
.domainCreate = libxlDomainCreate, /* 0.9.0 */
|
|
|
|
.domainCreateWithFlags = libxlDomainCreateWithFlags, /* 0.9.0 */
|
|
|
|
.domainDefineXML = libxlDomainDefineXML, /* 0.9.0 */
|
|
|
|
.domainUndefine = libxlDomainUndefine, /* 0.9.0 */
|
2011-07-20 03:05:20 +00:00
|
|
|
.domainUndefineFlags = libxlDomainUndefineFlags, /* 0.9.4 */
|
2011-05-26 15:27:06 +00:00
|
|
|
.domainAttachDevice = libxlDomainAttachDevice, /* 0.9.2 */
|
|
|
|
.domainAttachDeviceFlags = libxlDomainAttachDeviceFlags, /* 0.9.2 */
|
|
|
|
.domainDetachDevice = libxlDomainDetachDevice, /* 0.9.2 */
|
|
|
|
.domainDetachDeviceFlags = libxlDomainDetachDeviceFlags, /* 0.9.2 */
|
|
|
|
.domainUpdateDeviceFlags = libxlDomainUpdateDeviceFlags, /* 0.9.2 */
|
2011-05-13 13:35:01 +00:00
|
|
|
.domainGetAutostart = libxlDomainGetAutostart, /* 0.9.0 */
|
|
|
|
.domainSetAutostart = libxlDomainSetAutostart, /* 0.9.0 */
|
|
|
|
.domainGetSchedulerType = libxlDomainGetSchedulerType, /* 0.9.0 */
|
|
|
|
.domainGetSchedulerParameters = libxlDomainGetSchedulerParameters, /* 0.9.0 */
|
2011-05-17 22:33:53 +00:00
|
|
|
.domainGetSchedulerParametersFlags = libxlDomainGetSchedulerParametersFlags, /* 0.9.2 */
|
2011-05-13 13:35:01 +00:00
|
|
|
.domainSetSchedulerParameters = libxlDomainSetSchedulerParameters, /* 0.9.0 */
|
2011-05-17 22:33:53 +00:00
|
|
|
.domainSetSchedulerParametersFlags = libxlDomainSetSchedulerParametersFlags, /* 0.9.2 */
|
2011-05-13 13:35:01 +00:00
|
|
|
.nodeGetFreeMemory = libxlNodeGetFreeMemory, /* 0.9.0 */
|
|
|
|
.domainEventRegister = libxlDomainEventRegister, /* 0.9.0 */
|
|
|
|
.domainEventDeregister = libxlDomainEventDeregister, /* 0.9.0 */
|
2011-06-02 12:39:40 +00:00
|
|
|
.domainManagedSave = libxlDomainManagedSave, /* 0.9.2 */
|
|
|
|
.domainHasManagedSaveImage = libxlDomainHasManagedSaveImage, /* 0.9.2 */
|
|
|
|
.domainManagedSaveRemove = libxlDomainManagedSaveRemove, /* 0.9.2 */
|
2011-05-13 13:35:01 +00:00
|
|
|
.domainIsActive = libxlDomainIsActive, /* 0.9.0 */
|
|
|
|
.domainIsPersistent = libxlDomainIsPersistent, /* 0.9.0 */
|
|
|
|
.domainIsUpdated = libxlDomainIsUpdated, /* 0.9.0 */
|
|
|
|
.domainEventRegisterAny = libxlDomainEventRegisterAny, /* 0.9.0 */
|
|
|
|
.domainEventDeregisterAny = libxlDomainEventDeregisterAny, /* 0.9.0 */
|
2011-11-24 13:44:59 +00:00
|
|
|
.isAlive = libxlIsAlive, /* 0.9.8 */
|
2011-02-10 22:42:34 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static virStateDriver libxlStateDriver = {
|
|
|
|
.name = "LIBXL",
|
|
|
|
.initialize = libxlStartup,
|
|
|
|
.cleanup = libxlShutdown,
|
|
|
|
.reload = libxlReload,
|
|
|
|
.active = libxlActive,
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
libxlRegister(void)
|
|
|
|
{
|
|
|
|
if (virRegisterDriver(&libxlDriver) < 0)
|
|
|
|
return -1;
|
|
|
|
if (virRegisterStateDriver(&libxlStateDriver) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|