2013-09-04 00:43:00 -05:00
|
|
|
/*
|
|
|
|
* libxl_driver.c: core driver methods for managing libxenlight domains
|
|
|
|
*
|
|
|
|
* Copyright (C) 2006-2013 Red Hat, Inc.
|
|
|
|
* Copyright (C) 2011-2013 SUSE LINUX Products GmbH, Nuernberg, Germany.
|
|
|
|
* Copyright (C) 2011 Univention GmbH.
|
2011-02-10 16:42:34 -06:00
|
|
|
*
|
|
|
|
* 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 17:30:55 -05:00
|
|
|
* License along with this library. If not, see
|
2012-07-21 05:06:23 -05:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2011-03-29 07:24:05 -05:00
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Jim Fehlig <jfehlig@novell.com>
|
|
|
|
* Markus Groß <gross@univention.de>
|
|
|
|
* Daniel P. Berrange <berrange@redhat.com>
|
2011-02-10 16:42:34 -06:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
2011-03-29 07:31:45 -05:00
|
|
|
#include <math.h>
|
2011-02-10 16:42:34 -06:00
|
|
|
#include <libxl.h>
|
2013-07-12 19:27:18 -05:00
|
|
|
#include <libxl_utils.h>
|
2011-05-30 04:53:02 -05:00
|
|
|
#include <fcntl.h>
|
2013-06-18 21:46:26 -05:00
|
|
|
#include <regex.h>
|
2011-02-10 16:42:34 -06:00
|
|
|
|
|
|
|
#include "internal.h"
|
2012-12-12 11:59:27 -06:00
|
|
|
#include "virlog.h"
|
2012-12-13 12:21:53 -06:00
|
|
|
#include "virerror.h"
|
2012-12-12 10:35:35 -06:00
|
|
|
#include "virconf.h"
|
2011-02-10 16:42:34 -06:00
|
|
|
#include "datatypes.h"
|
2011-07-19 13:32:58 -05:00
|
|
|
#include "virfile.h"
|
2012-12-12 12:06:53 -06:00
|
|
|
#include "viralloc.h"
|
2012-12-13 12:01:25 -06:00
|
|
|
#include "viruuid.h"
|
2012-12-12 10:27:01 -06:00
|
|
|
#include "vircommand.h"
|
2013-08-30 12:18:31 -05:00
|
|
|
#include "libxl_domain.h"
|
2011-02-10 16:42:34 -06:00
|
|
|
#include "libxl_driver.h"
|
|
|
|
#include "libxl_conf.h"
|
2011-03-29 07:39:18 -05:00
|
|
|
#include "xen_xm.h"
|
2012-01-07 06:47:43 -06:00
|
|
|
#include "virtypedparam.h"
|
2012-02-24 12:48:55 -06:00
|
|
|
#include "viruri.h"
|
2013-04-03 05:36:23 -05:00
|
|
|
#include "virstring.h"
|
2013-06-12 10:49:27 -05:00
|
|
|
#include "virsysinfo.h"
|
2013-04-23 05:56:22 -05:00
|
|
|
#include "viraccessapicheck.h"
|
2013-08-30 15:54:50 -05:00
|
|
|
#include "viratomic.h"
|
2011-02-10 16:42:34 -06: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 07:39:18 -05:00
|
|
|
#define LIBXL_CONFIG_FORMAT_XM "xen-xm"
|
|
|
|
|
2011-03-29 07:46:55 -05:00
|
|
|
/* Number of Xen scheduler parameters */
|
|
|
|
#define XEN_SCHED_CREDIT_NPARAM 2
|
|
|
|
|
2013-01-11 07:54:15 -06:00
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
static libxlDriverPrivatePtr libxl_driver = NULL;
|
|
|
|
|
|
|
|
/* Function declarations */
|
2013-01-11 07:54:15 -06:00
|
|
|
static int
|
|
|
|
libxlDomainManagedSaveLoad(virDomainObjPtr vm,
|
2013-01-15 16:44:58 -06:00
|
|
|
void *opaque);
|
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
static int
|
2011-05-30 04:53:02 -05:00
|
|
|
libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm,
|
|
|
|
bool start_paused, int restore_fd);
|
2011-02-10 16:42:34 -06:00
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
|
|
|
|
/* Function definitions */
|
|
|
|
static virDomainObjPtr
|
|
|
|
libxlDomObjFromDomain(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
|
|
|
|
vm = virDomainObjListFindByUUID(driver->domains, dom->uuid);
|
|
|
|
if (!vm) {
|
|
|
|
virUUIDFormat(dom->uuid, uuidstr);
|
|
|
|
virReportError(VIR_ERR_NO_DOMAIN,
|
|
|
|
_("no domain with matching uuid '%s' (%s)"),
|
|
|
|
uuidstr, dom->name);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return vm;
|
|
|
|
}
|
|
|
|
|
2011-03-29 07:18:24 -05:00
|
|
|
static void
|
|
|
|
libxlDomainEventQueue(libxlDriverPrivatePtr driver, virDomainEventPtr event)
|
|
|
|
{
|
2011-05-12 09:47:08 -05:00
|
|
|
virDomainEventStateQueue(driver->domainEventState, event);
|
2011-03-29 07:18:24 -05:00
|
|
|
}
|
|
|
|
|
2013-01-11 07:54:15 -06:00
|
|
|
static int
|
|
|
|
libxlAutostartDomain(virDomainObjPtr vm,
|
2011-03-28 05:49:22 -05:00
|
|
|
void *opaque)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = opaque;
|
|
|
|
virErrorPtr err;
|
2013-01-11 07:54:15 -06:00
|
|
|
int ret = -1;
|
2011-03-28 05:49:22 -05:00
|
|
|
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectLock(vm);
|
2011-03-28 05:49:22 -05:00
|
|
|
virResetLastError();
|
|
|
|
|
|
|
|
if (vm->autostart && !virDomainObjIsActive(vm) &&
|
2011-05-30 04:53:02 -05:00
|
|
|
libxlVmStart(driver, vm, false, -1) < 0) {
|
2011-03-28 05:49:22 -05:00
|
|
|
err = virGetLastError();
|
|
|
|
VIR_ERROR(_("Failed to autostart VM '%s': %s"),
|
|
|
|
vm->def->name,
|
|
|
|
err ? err->message : _("unknown error"));
|
2013-01-11 07:54:15 -06:00
|
|
|
goto cleanup;
|
2011-03-28 05:49:22 -05:00
|
|
|
}
|
|
|
|
|
2013-01-11 07:54:15 -06:00
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
2013-02-28 08:48:16 -06:00
|
|
|
virObjectUnlock(vm);
|
2013-01-11 07:54:15 -06:00
|
|
|
return ret;
|
2011-03-28 05:49:22 -05:00
|
|
|
}
|
|
|
|
|
2011-04-18 04:16:33 -05:00
|
|
|
static int
|
|
|
|
libxlDoNodeGetInfo(libxlDriverPrivatePtr driver, virNodeInfoPtr info)
|
|
|
|
{
|
|
|
|
libxl_physinfo phy_info;
|
2012-12-10 16:28:09 -06:00
|
|
|
virArch hostarch = virArchFromHost();
|
2013-08-30 15:52:14 -05:00
|
|
|
libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
|
|
|
|
int ret = -1;
|
2011-04-18 04:16:33 -05:00
|
|
|
|
2013-08-30 15:52:14 -05:00
|
|
|
if (libxl_get_physinfo(cfg->ctx, &phy_info)) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("libxl_get_physinfo_info failed"));
|
2013-08-30 15:52:14 -05:00
|
|
|
goto cleanup;
|
2011-04-18 04:16:33 -05:00
|
|
|
}
|
|
|
|
|
2012-12-10 16:28:09 -06:00
|
|
|
if (virStrcpyStatic(info->model, virArchToString(hostarch)) == NULL) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("machine type %s too big for destination"),
|
2012-12-10 16:28:09 -06:00
|
|
|
virArchToString(hostarch));
|
2013-08-30 15:52:14 -05:00
|
|
|
goto cleanup;
|
2011-04-18 04:16:33 -05:00
|
|
|
}
|
|
|
|
|
2013-08-30 15:52:14 -05:00
|
|
|
info->memory = phy_info.total_pages * (cfg->verInfo->pagesize / 1024);
|
2011-04-18 04:16:33 -05:00
|
|
|
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;
|
2013-08-30 15:52:14 -05:00
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virObjectUnref(cfg);
|
|
|
|
return ret;
|
2011-04-18 04:16:33 -05:00
|
|
|
}
|
|
|
|
|
2011-06-02 07:24:30 -05:00
|
|
|
static char *
|
|
|
|
libxlDomainManagedSavePath(libxlDriverPrivatePtr driver, virDomainObjPtr vm) {
|
|
|
|
char *ret;
|
2013-08-30 15:52:14 -05:00
|
|
|
libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
|
2011-06-02 07:24:30 -05:00
|
|
|
|
2013-08-30 15:52:14 -05:00
|
|
|
ignore_value(virAsprintf(&ret, "%s/%s.save", cfg->saveDir, vm->def->name));
|
|
|
|
virObjectUnref(cfg);
|
2011-06-02 07:24:30 -05:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-08-30 15:57:42 -05:00
|
|
|
/*
|
|
|
|
* This internal function expects the driver lock to already be held on
|
|
|
|
* entry.
|
|
|
|
*/
|
|
|
|
static int ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5)
|
|
|
|
libxlSaveImageOpen(libxlDriverPrivatePtr driver,
|
|
|
|
libxlDriverConfigPtr cfg,
|
|
|
|
const char *from,
|
|
|
|
virDomainDefPtr *ret_def,
|
|
|
|
libxlSavefileHeaderPtr ret_hdr)
|
2011-06-02 07:24:30 -05:00
|
|
|
{
|
|
|
|
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 14:26:45 -06:00
|
|
|
if ((fd = virFileOpenAs(from, O_RDONLY, 0, -1, -1, 0)) < 0) {
|
util: fix virFileOpenAs return value and resulting error logs
This resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=851411
https://bugzilla.redhat.com/show_bug.cgi?id=955500
The first problem was that virFileOpenAs was returning fd (-1) in one
of the error cases rather than ret (-errno), so the caller thought
that the error was EPERM rather than ENOENT.
The second problem was that some log messages in the general purpose
qemuOpenFile() function would always say "Failed to create" even if
the caller hadn't included O_CREAT (i.e. they were trying to open an
existing file).
This fixes virFileOpenAs to jump down to the error return (which
returns ret instead of fd) in the previously mentioned incorrect
failure case of virFileOpenAs(), removes all error logging from
virFileOpenAs() (since the callers report it), and modifies
qemuOpenFile to appropriately use "open" or "create" in its log
messages.
NB: I seriously considered removing logging from all callers of
virFileOpenAs(), but there is at least one case where the caller
doesn't want virFileOpenAs() to log any errors, because it's just
going to try again (qemuOpenFile()). We can't simply make a silent
variation of virFileOpenAs() though, because qemuOpenFile() can't make
the decision about whether or not it wants to retry until after
virFileOpenAs() has already returned an error code.
Likewise, I also considered changing virFileOpenAs() to return -1 with
errno set on return, and may still do that, but only as a separate
patch, as it obscures the intent of this patch too much.
2013-05-08 14:02:14 -05:00
|
|
|
virReportSystemError(-fd,
|
|
|
|
_("Failed to open domain image file '%s'"), from);
|
2011-06-02 07:24:30 -05:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (saferead(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
"%s", _("failed to read libxl header"));
|
2011-06-02 07:24:30 -05:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (memcmp(hdr.magic, LIBXL_SAVE_MAGIC, sizeof(hdr.magic))) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s", _("image magic is incorrect"));
|
2011-06-02 07:24:30 -05:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hdr.version > LIBXL_SAVE_VERSION) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("image version is not supported (%d > %d)"),
|
|
|
|
hdr.version, LIBXL_SAVE_VERSION);
|
2011-06-02 07:24:30 -05:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hdr.xmlLen <= 0) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("invalid XML length: %d"), hdr.xmlLen);
|
2011-06-02 07:24:30 -05:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2013-07-04 05:10:38 -05:00
|
|
|
if (VIR_ALLOC_N(xml, hdr.xmlLen) < 0)
|
2011-06-02 07:24:30 -05:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (saferead(fd, xml, hdr.xmlLen) != hdr.xmlLen) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("failed to read XML"));
|
2011-06-02 07:24:30 -05:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2013-08-30 15:52:14 -05:00
|
|
|
if (!(def = virDomainDefParseString(xml, cfg->caps, driver->xmlopt,
|
2013-03-28 08:55:55 -05:00
|
|
|
1 << VIR_DOMAIN_VIRT_XEN,
|
2011-06-02 07:24:30 -05: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 16:42:34 -06:00
|
|
|
/*
|
|
|
|
* Cleanup function for domain that has reached shutoff state.
|
|
|
|
*
|
|
|
|
* virDomainObjPtr should be locked on invocation
|
|
|
|
*/
|
|
|
|
static void
|
2011-05-04 04:07:01 -05:00
|
|
|
libxlVmCleanup(libxlDriverPrivatePtr driver,
|
|
|
|
virDomainObjPtr vm,
|
|
|
|
virDomainShutoffReason reason)
|
2011-02-10 16:42:34 -06:00
|
|
|
{
|
|
|
|
libxlDomainObjPrivatePtr priv = vm->privateData;
|
2013-08-30 15:52:14 -05:00
|
|
|
libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
|
2011-02-10 16:42:34 -06:00
|
|
|
int vnc_port;
|
|
|
|
char *file;
|
Convert 'int i' to 'size_t i' in src/libxl/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 09:09:33 -05:00
|
|
|
size_t i;
|
2011-02-10 16:42:34 -06:00
|
|
|
|
2012-11-26 10:28:56 -06:00
|
|
|
if (priv->deathW) {
|
|
|
|
libxl_evdisable_domain_death(priv->ctx, priv->deathW);
|
|
|
|
priv->deathW = NULL;
|
2011-02-10 16:42:34 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
if (vm->persistent) {
|
|
|
|
vm->def->id = -1;
|
2011-05-04 04:07:01 -05:00
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, reason);
|
2011-02-10 16:42:34 -06:00
|
|
|
}
|
|
|
|
|
2013-08-30 15:54:50 -05:00
|
|
|
if (virAtomicIntDecAndTest(&driver->nactive) && driver->inhibitCallback)
|
2012-10-31 14:03:55 -05:00
|
|
|
driver->inhibitCallback(false, driver->inhibitOpaque);
|
|
|
|
|
2011-02-10 16:42:34 -06: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) {
|
2013-01-11 06:09:53 -06:00
|
|
|
if (virPortAllocatorRelease(driver->reservedVNCPorts,
|
|
|
|
vnc_port) < 0)
|
2011-02-10 16:42:34 -06:00
|
|
|
VIR_DEBUG("Could not mark port %d as unused", vnc_port);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-04-18 04:16:33 -05:00
|
|
|
/* Remove any cputune settings */
|
|
|
|
if (vm->def->cputune.nvcpupin) {
|
|
|
|
for (i = 0; i < vm->def->cputune.nvcpupin; ++i) {
|
2013-06-01 16:29:09 -05:00
|
|
|
virBitmapFree(vm->def->cputune.vcpupin[i]->cpumask);
|
2011-04-18 04:16:33 -05:00
|
|
|
VIR_FREE(vm->def->cputune.vcpupin[i]);
|
|
|
|
}
|
|
|
|
VIR_FREE(vm->def->cputune.vcpupin);
|
|
|
|
vm->def->cputune.nvcpupin = 0;
|
|
|
|
}
|
|
|
|
|
2013-08-30 15:52:14 -05:00
|
|
|
if (virAsprintf(&file, "%s/%s.xml", cfg->stateDir, vm->def->name) > 0) {
|
2011-02-10 16:42:34 -06:00
|
|
|
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 10:16:31 -05:00
|
|
|
|
|
|
|
if (vm->newDef) {
|
|
|
|
virDomainDefFree(vm->def);
|
|
|
|
vm->def = vm->newDef;
|
|
|
|
vm->def->id = -1;
|
|
|
|
vm->newDef = NULL;
|
|
|
|
}
|
2013-01-21 11:30:29 -06:00
|
|
|
|
2013-08-30 12:18:31 -05:00
|
|
|
libxlDomainObjRegisteredTimeoutsCleanup(priv);
|
2013-08-30 15:52:14 -05:00
|
|
|
virObjectUnref(cfg);
|
2011-02-10 16:42:34 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Reap a domain from libxenlight.
|
|
|
|
*
|
|
|
|
* virDomainObjPtr should be locked on invocation
|
|
|
|
*/
|
|
|
|
static int
|
2011-05-04 04:07:01 -05:00
|
|
|
libxlVmReap(libxlDriverPrivatePtr driver,
|
|
|
|
virDomainObjPtr vm,
|
|
|
|
virDomainShutoffReason reason)
|
2011-02-10 16:42:34 -06:00
|
|
|
{
|
|
|
|
libxlDomainObjPrivatePtr priv = vm->privateData;
|
|
|
|
|
2012-11-26 10:28:56 -06:00
|
|
|
if (libxl_domain_destroy(priv->ctx, vm->def->id, NULL) < 0) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unable to cleanup domain %d"), vm->def->id);
|
2011-02-10 16:42:34 -06:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-05-04 04:07:01 -05:00
|
|
|
libxlVmCleanup(driver, vm, reason);
|
2011-02-10 16:42:34 -06:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2013-05-16 09:42:21 -05:00
|
|
|
* Handle previously registered event notification from libxenlight.
|
|
|
|
*
|
|
|
|
* Note: Xen 4.3 removed the const from the event handler signature.
|
|
|
|
* Detect which signature to use based on
|
|
|
|
* LIBXL_HAVE_NONCONST_EVENT_OCCURS_EVENT_ARG.
|
2011-02-10 16:42:34 -06:00
|
|
|
*/
|
2013-05-16 09:42:21 -05:00
|
|
|
|
|
|
|
#ifdef LIBXL_HAVE_NONCONST_EVENT_OCCURS_EVENT_ARG
|
|
|
|
# define VIR_LIBXL_EVENT_CONST /* empty */
|
|
|
|
#else
|
|
|
|
# define VIR_LIBXL_EVENT_CONST const
|
|
|
|
#endif
|
|
|
|
|
2013-01-15 16:44:58 -06:00
|
|
|
static void
|
2013-05-16 10:38:56 -05:00
|
|
|
libxlEventHandler(void *data, VIR_LIBXL_EVENT_CONST libxl_event *event)
|
2011-02-10 16:42:34 -06:00
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = libxl_driver;
|
2013-05-16 10:38:56 -05:00
|
|
|
libxlDomainObjPrivatePtr priv = ((virDomainObjPtr)data)->privateData;
|
2013-01-21 11:36:03 -06:00
|
|
|
virDomainObjPtr vm = NULL;
|
2011-03-29 07:18:24 -05:00
|
|
|
virDomainEventPtr dom_event = NULL;
|
2013-01-21 11:36:03 -06:00
|
|
|
libxl_shutdown_reason xl_reason = event->u.domain_shutdown.shutdown_reason;
|
2011-02-10 16:42:34 -06:00
|
|
|
|
2012-11-26 10:28:56 -06:00
|
|
|
if (event->type == LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN) {
|
2011-05-04 04:07:01 -05:00
|
|
|
virDomainShutoffReason reason;
|
|
|
|
|
2013-01-21 11:36:03 -06:00
|
|
|
/*
|
|
|
|
* Similar to the xl implementation, ignore SUSPEND. Any actions needed
|
|
|
|
* after calling libxl_domain_suspend() are handled by it's callers.
|
|
|
|
*/
|
|
|
|
if (xl_reason == LIBXL_SHUTDOWN_REASON_SUSPEND)
|
|
|
|
goto cleanup;
|
|
|
|
|
2013-01-11 10:04:47 -06:00
|
|
|
vm = virDomainObjListFindByID(driver->domains, event->domid);
|
2013-01-21 11:36:03 -06:00
|
|
|
if (!vm)
|
2011-02-10 16:42:34 -06:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-01-21 11:36:03 -06:00
|
|
|
switch (xl_reason) {
|
2012-11-26 10:28:56 -06:00
|
|
|
case LIBXL_SHUTDOWN_REASON_POWEROFF:
|
|
|
|
case LIBXL_SHUTDOWN_REASON_CRASH:
|
2013-01-21 11:36:03 -06:00
|
|
|
if (xl_reason == LIBXL_SHUTDOWN_REASON_CRASH) {
|
2011-03-29 07:18:24 -05:00
|
|
|
dom_event = virDomainEventNewFromObj(vm,
|
|
|
|
VIR_DOMAIN_EVENT_STOPPED,
|
|
|
|
VIR_DOMAIN_EVENT_STOPPED_CRASHED);
|
2011-05-04 04:07:01 -05:00
|
|
|
reason = VIR_DOMAIN_SHUTOFF_CRASHED;
|
|
|
|
} else {
|
|
|
|
reason = VIR_DOMAIN_SHUTOFF_SHUTDOWN;
|
|
|
|
}
|
2012-11-26 10:28:56 -06:00
|
|
|
libxlVmReap(driver, vm, reason);
|
2011-02-10 16:42:34 -06:00
|
|
|
if (!vm->persistent) {
|
2013-01-11 10:04:47 -06:00
|
|
|
virDomainObjListRemove(driver->domains, vm);
|
2011-02-10 16:42:34 -06:00
|
|
|
vm = NULL;
|
|
|
|
}
|
|
|
|
break;
|
2012-11-26 10:28:56 -06:00
|
|
|
case LIBXL_SHUTDOWN_REASON_REBOOT:
|
|
|
|
libxlVmReap(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
|
2011-05-30 04:53:02 -05:00
|
|
|
libxlVmStart(driver, vm, 0, -1);
|
2011-02-10 16:42:34 -06:00
|
|
|
break;
|
|
|
|
default:
|
2013-01-21 11:36:03 -06:00
|
|
|
VIR_INFO("Unhandled shutdown_reason %d", xl_reason);
|
2011-02-10 16:42:34 -06:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2013-08-30 15:57:42 -05:00
|
|
|
if (dom_event)
|
2011-03-29 07:18:24 -05:00
|
|
|
libxlDomainEventQueue(driver, dom_event);
|
2013-05-16 10:38:56 -05:00
|
|
|
/* Cast away any const */
|
|
|
|
libxl_event_free(priv->ctx, (libxl_event *)event);
|
2011-02-10 16:42:34 -06:00
|
|
|
}
|
|
|
|
|
2012-11-26 10:28:56 -06:00
|
|
|
static const struct libxl_event_hooks ev_hooks = {
|
|
|
|
.event_occurs_mask = LIBXL_EVENTMASK_ALL,
|
|
|
|
.event_occurs = libxlEventHandler,
|
|
|
|
.disaster = NULL,
|
|
|
|
};
|
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
/*
|
|
|
|
* Register domain events with libxenlight and insert event handles
|
|
|
|
* in libvirt's event loop.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
libxlCreateDomEvents(virDomainObjPtr vm)
|
|
|
|
{
|
|
|
|
libxlDomainObjPrivatePtr priv = vm->privateData;
|
|
|
|
|
2012-11-26 10:28:56 -06:00
|
|
|
libxl_event_register_callbacks(priv->ctx, &ev_hooks, vm);
|
2011-02-10 16:42:34 -06:00
|
|
|
|
2012-11-26 10:28:56 -06:00
|
|
|
if (libxl_evenable_domain_death(priv->ctx, vm->def->id, 0, &priv->deathW))
|
2011-02-10 16:42:34 -06:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
2013-01-15 16:50:35 -06:00
|
|
|
if (priv->deathW) {
|
2012-11-26 10:28:56 -06:00
|
|
|
libxl_evdisable_domain_death(priv->ctx, priv->deathW);
|
2013-01-15 16:50:35 -06:00
|
|
|
priv->deathW = NULL;
|
|
|
|
}
|
2011-02-10 16:42:34 -06:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-04-18 04:16:33 -05:00
|
|
|
static int
|
2012-12-17 09:01:41 -06:00
|
|
|
libxlDomainSetVcpuAffinities(libxlDriverPrivatePtr driver, virDomainObjPtr vm)
|
2011-04-18 04:16:33 -05:00
|
|
|
{
|
|
|
|
libxlDomainObjPrivatePtr priv = vm->privateData;
|
|
|
|
virDomainDefPtr def = vm->def;
|
2012-11-26 10:28:56 -06:00
|
|
|
libxl_bitmap map;
|
2013-10-30 12:38:08 -05:00
|
|
|
virBitmapPtr cpumask = NULL;
|
2011-04-18 04:16:33 -05:00
|
|
|
uint8_t *cpumap = NULL;
|
|
|
|
virNodeInfo nodeinfo;
|
|
|
|
size_t cpumaplen;
|
Convert 'int i' to 'size_t i' in src/libxl/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 09:09:33 -05:00
|
|
|
int vcpu;
|
|
|
|
size_t i;
|
2011-04-18 04:16:33 -05:00
|
|
|
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;
|
|
|
|
|
2013-07-04 05:10:38 -05:00
|
|
|
if (VIR_ALLOC_N(cpumap, cpumaplen) < 0)
|
2011-04-18 04:16:33 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-10-30 12:38:08 -05:00
|
|
|
cpumask = def->cputune.vcpupin[vcpu]->cpumask;
|
2011-04-18 04:16:33 -05:00
|
|
|
|
2013-10-30 12:38:08 -05:00
|
|
|
for (i = 0; i < virBitmapSize(cpumask); ++i) {
|
|
|
|
bool bit;
|
|
|
|
ignore_value(virBitmapGetBit(cpumask, i, &bit));
|
|
|
|
if (bit)
|
2011-06-07 03:51:51 -05:00
|
|
|
VIR_USE_CPU(cpumap, i);
|
2011-04-18 04:16:33 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
map.size = cpumaplen;
|
|
|
|
map.map = cpumap;
|
|
|
|
|
2012-11-26 10:28:56 -06:00
|
|
|
if (libxl_set_vcpuaffinity(priv->ctx, def->id, vcpu, &map) != 0) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to pin vcpu '%d' with libxenlight"), vcpu);
|
2011-04-18 04:16:33 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_FREE(cpumap);
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(cpumap);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-05-04 05:17:06 -05:00
|
|
|
static int
|
|
|
|
libxlFreeMem(libxlDomainObjPrivatePtr priv, libxl_domain_config *d_config)
|
|
|
|
{
|
|
|
|
uint32_t needed_mem;
|
|
|
|
uint32_t free_mem;
|
Convert 'int i' to 'size_t i' in src/libxl/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 09:09:33 -05:00
|
|
|
size_t i;
|
2011-05-04 05:17:06 -05:00
|
|
|
int ret = -1;
|
|
|
|
int tries = 3;
|
|
|
|
int wait_secs = 10;
|
|
|
|
|
2012-11-26 10:28:56 -06:00
|
|
|
if ((ret = libxl_domain_need_memory(priv->ctx, &d_config->b_info,
|
2011-05-04 05:17:06 -05:00
|
|
|
&needed_mem)) >= 0) {
|
|
|
|
for (i = 0; i < tries; ++i) {
|
2012-11-26 10:28:56 -06:00
|
|
|
if ((ret = libxl_get_free_memory(priv->ctx, &free_mem)) < 0)
|
2011-05-04 05:17:06 -05:00
|
|
|
break;
|
|
|
|
|
|
|
|
if (free_mem >= needed_mem) {
|
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2012-11-26 10:28:56 -06:00
|
|
|
if ((ret = libxl_set_memory_target(priv->ctx, 0,
|
2011-05-04 05:17:06 -05:00
|
|
|
free_mem - needed_mem,
|
|
|
|
/* relative */ 1, 0)) < 0)
|
|
|
|
break;
|
|
|
|
|
2012-11-26 10:28:56 -06:00
|
|
|
ret = libxl_wait_for_free_memory(priv->ctx, 0, needed_mem,
|
2011-05-04 05:17:06 -05:00
|
|
|
wait_secs);
|
|
|
|
if (ret == 0 || ret != ERROR_NOMEM)
|
|
|
|
break;
|
|
|
|
|
2012-11-26 10:28:56 -06:00
|
|
|
if ((ret = libxl_wait_for_memory_target(priv->ctx, 0, 1)) < 0)
|
2011-05-04 05:17:06 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
/*
|
|
|
|
* Start a domain through libxenlight.
|
|
|
|
*
|
|
|
|
* virDomainObjPtr should be locked on invocation
|
|
|
|
*/
|
|
|
|
static int
|
2011-05-30 04:53:02 -05:00
|
|
|
libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm,
|
|
|
|
bool start_paused, int restore_fd)
|
2011-02-10 16:42:34 -06:00
|
|
|
{
|
|
|
|
libxl_domain_config d_config;
|
2011-06-02 07:24:30 -05:00
|
|
|
virDomainDefPtr def = NULL;
|
2011-03-29 07:18:24 -05:00
|
|
|
virDomainEventPtr event = NULL;
|
2011-06-02 07:24:30 -05:00
|
|
|
libxlSavefileHeader hdr;
|
2011-02-10 16:42:34 -06:00
|
|
|
int ret;
|
|
|
|
uint32_t domid = 0;
|
|
|
|
char *dom_xml = NULL;
|
2011-06-02 16:41:13 -05:00
|
|
|
char *managed_save_path = NULL;
|
|
|
|
int managed_save_fd = -1;
|
2011-02-10 16:42:34 -06:00
|
|
|
libxlDomainObjPrivatePtr priv = vm->privateData;
|
2013-08-30 15:52:14 -05:00
|
|
|
libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
|
2013-11-01 02:26:26 -05:00
|
|
|
#ifdef LIBXL_HAVE_DOMAIN_CREATE_RESTORE_PARAMS
|
|
|
|
libxl_domain_restore_params params;
|
|
|
|
#endif
|
2011-02-10 16:42:34 -06:00
|
|
|
|
2013-08-08 14:04:27 -05:00
|
|
|
if (libxlDomainObjPrivateInitCtx(vm) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2011-06-02 07:24:30 -05: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 16:41:13 -05:00
|
|
|
managed_save_path = libxlDomainManagedSavePath(driver, vm);
|
|
|
|
if (managed_save_path == NULL)
|
2011-06-02 07:24:30 -05:00
|
|
|
goto error;
|
|
|
|
|
2011-06-02 16:41:13 -05:00
|
|
|
if (virFileExists(managed_save_path)) {
|
2011-06-02 07:24:30 -05:00
|
|
|
|
2013-08-30 15:57:42 -05:00
|
|
|
managed_save_fd = libxlSaveImageOpen(driver, cfg,
|
|
|
|
managed_save_path,
|
2011-06-02 16:41:13 -05:00
|
|
|
&def, &hdr);
|
|
|
|
if (managed_save_fd < 0)
|
2011-06-02 07:24:30 -05:00
|
|
|
goto error;
|
|
|
|
|
2011-06-02 16:41:13 -05:00
|
|
|
restore_fd = managed_save_fd;
|
|
|
|
|
2011-06-02 07:24:30 -05: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 08:32:10 -05: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 07:24:30 -05:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
Merge virDomainObjListIsDuplicate into virDomainObjListAdd
The duplicate VM checking should be done atomically with
virDomainObjListAdd, so shoud not be a separate function.
Instead just use flags to indicate what kind of checks are
required.
This pair, used in virDomainCreateXML:
if (virDomainObjListIsDuplicate(privconn->domains, def, 1) < 0)
goto cleanup;
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def, false)))
goto cleanup;
Changes to
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def,
VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
NULL)))
goto cleanup;
This pair, used in virDomainRestoreFlags:
if (virDomainObjListIsDuplicate(privconn->domains, def, 1) < 0)
goto cleanup;
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def, true)))
goto cleanup;
Changes to
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def,
VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
NULL)))
goto cleanup;
This pair, used in virDomainDefineXML:
if (virDomainObjListIsDuplicate(privconn->domains, def, 0) < 0)
goto cleanup;
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def, false)))
goto cleanup;
Changes to
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def,
0, NULL)))
goto cleanup;
2013-01-14 08:46:58 -06:00
|
|
|
virDomainObjAssignDef(vm, def, true, NULL);
|
2011-06-02 07:24:30 -05:00
|
|
|
def = NULL;
|
|
|
|
|
2013-08-14 16:33:48 -05:00
|
|
|
if (unlink(managed_save_path) < 0)
|
2011-06-02 16:41:13 -05:00
|
|
|
VIR_WARN("Failed to remove the managed state %s",
|
|
|
|
managed_save_path);
|
2013-08-14 16:33:48 -05:00
|
|
|
|
2012-06-11 04:03:27 -05:00
|
|
|
vm->hasManagedSave = false;
|
2011-06-02 07:24:30 -05:00
|
|
|
}
|
2011-06-02 16:41:13 -05:00
|
|
|
VIR_FREE(managed_save_path);
|
2011-06-02 07:24:30 -05:00
|
|
|
}
|
|
|
|
|
2012-11-26 10:28:56 -06:00
|
|
|
libxl_domain_config_init(&d_config);
|
2011-02-10 16:42:34 -06:00
|
|
|
|
2013-07-24 06:43:43 -05:00
|
|
|
if (libxlBuildDomainConfig(driver, vm, &d_config) < 0)
|
2013-01-15 16:56:35 -06:00
|
|
|
goto error;
|
2011-02-10 16:42:34 -06:00
|
|
|
|
2013-08-30 15:52:14 -05:00
|
|
|
if (cfg->autoballoon && libxlFreeMem(priv, &d_config) < 0) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("libxenlight failed to get free memory for domain '%s'"),
|
|
|
|
d_config.c_info.name);
|
2011-05-04 05:17:06 -05:00
|
|
|
goto error;
|
|
|
|
}
|
2011-02-10 16:42:34 -06:00
|
|
|
|
2012-11-26 10:28:56 -06:00
|
|
|
/* use as synchronous operations => ao_how = NULL and no intermediate reports => ao_progress = NULL */
|
|
|
|
|
2013-11-12 11:41:12 -06:00
|
|
|
if (restore_fd < 0) {
|
2012-11-26 10:28:56 -06:00
|
|
|
ret = libxl_domain_create_new(priv->ctx, &d_config,
|
|
|
|
&domid, NULL, NULL);
|
2013-11-12 11:41:12 -06:00
|
|
|
} else {
|
2013-11-01 02:26:26 -05:00
|
|
|
#ifdef LIBXL_HAVE_DOMAIN_CREATE_RESTORE_PARAMS
|
|
|
|
params.checkpointed_stream = 0;
|
|
|
|
ret = libxl_domain_create_restore(priv->ctx, &d_config, &domid,
|
|
|
|
restore_fd, ¶ms, NULL, NULL);
|
|
|
|
#else
|
2012-11-26 10:28:56 -06:00
|
|
|
ret = libxl_domain_create_restore(priv->ctx, &d_config, &domid,
|
|
|
|
restore_fd, NULL, NULL);
|
2013-11-01 02:26:26 -05:00
|
|
|
#endif
|
2013-11-12 11:41:12 -06:00
|
|
|
}
|
2011-05-30 04:53:02 -05:00
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
if (ret) {
|
2011-05-30 04:53:02 -05:00
|
|
|
if (restore_fd < 0)
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("libxenlight failed to create new domain '%s'"),
|
|
|
|
d_config.c_info.name);
|
2011-05-30 04:53:02 -05:00
|
|
|
else
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("libxenlight failed to restore domain '%s'"),
|
|
|
|
d_config.c_info.name);
|
2011-02-10 16:42:34 -06:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2011-06-02 07:24:30 -05:00
|
|
|
vm->def->id = domid;
|
|
|
|
if ((dom_xml = virDomainDefFormat(vm->def, 0)) == NULL)
|
2011-02-10 16:42:34 -06:00
|
|
|
goto error;
|
|
|
|
|
2012-11-26 10:28:56 -06:00
|
|
|
if (libxl_userdata_store(priv->ctx, domid, "libvirt-xml",
|
2011-02-10 16:42:34 -06:00
|
|
|
(uint8_t *)dom_xml, strlen(dom_xml) + 1)) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("libxenlight failed to store userdata"));
|
2011-02-10 16:42:34 -06:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (libxlCreateDomEvents(vm) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2012-12-17 09:01:41 -06:00
|
|
|
if (libxlDomainSetVcpuAffinities(driver, vm) < 0)
|
2011-04-18 04:16:33 -05:00
|
|
|
goto error;
|
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
if (!start_paused) {
|
2012-11-26 10:28:56 -06:00
|
|
|
libxl_domain_unpause(priv->ctx, domid);
|
2011-05-04 04:07:01 -05:00
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_BOOTED);
|
2011-02-10 16:42:34 -06:00
|
|
|
} else {
|
2011-05-04 04:07:01 -05:00
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
|
2011-02-10 16:42:34 -06:00
|
|
|
}
|
|
|
|
|
2011-03-29 07:18:24 -05:00
|
|
|
|
2013-08-30 15:52:14 -05:00
|
|
|
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
|
2011-02-10 16:42:34 -06:00
|
|
|
goto error;
|
|
|
|
|
2013-08-30 15:54:50 -05:00
|
|
|
if (virAtomicIntInc(&driver->nactive) == 1 && driver->inhibitCallback)
|
2012-10-31 14:03:55 -05:00
|
|
|
driver->inhibitCallback(true, driver->inhibitOpaque);
|
|
|
|
|
2011-03-29 07:18:24 -05:00
|
|
|
event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STARTED,
|
2011-05-30 04:53:02 -05:00
|
|
|
restore_fd < 0 ?
|
|
|
|
VIR_DOMAIN_EVENT_STARTED_BOOTED :
|
|
|
|
VIR_DOMAIN_EVENT_STARTED_RESTORED);
|
2013-02-28 08:48:16 -06:00
|
|
|
if (event)
|
|
|
|
libxlDomainEventQueue(driver, event);
|
2011-03-29 07:18:24 -05:00
|
|
|
|
2012-11-26 10:28:56 -06:00
|
|
|
libxl_domain_config_dispose(&d_config);
|
2011-02-10 16:42:34 -06:00
|
|
|
VIR_FREE(dom_xml);
|
2011-06-02 16:41:13 -05:00
|
|
|
VIR_FORCE_CLOSE(managed_save_fd);
|
2013-08-30 15:52:14 -05:00
|
|
|
virObjectUnref(cfg);
|
2011-02-10 16:42:34 -06:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
if (domid > 0) {
|
2012-11-26 10:28:56 -06:00
|
|
|
libxl_domain_destroy(priv->ctx, domid, NULL);
|
2011-06-02 07:24:30 -05:00
|
|
|
vm->def->id = -1;
|
2011-05-04 04:07:01 -05:00
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_FAILED);
|
2011-02-10 16:42:34 -06:00
|
|
|
}
|
2012-11-26 10:28:56 -06:00
|
|
|
libxl_domain_config_dispose(&d_config);
|
2011-02-10 16:42:34 -06:00
|
|
|
VIR_FREE(dom_xml);
|
2011-06-02 16:41:13 -05:00
|
|
|
VIR_FREE(managed_save_path);
|
2011-06-02 07:24:30 -05:00
|
|
|
virDomainDefFree(def);
|
2011-06-02 16:41:13 -05:00
|
|
|
VIR_FORCE_CLOSE(managed_save_fd);
|
2013-08-30 15:52:14 -05:00
|
|
|
virObjectUnref(cfg);
|
2011-02-10 16:42:34 -06:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Reconnect to running domains that were previously started/created
|
|
|
|
* with libxenlight driver.
|
|
|
|
*/
|
2013-01-11 07:54:15 -06:00
|
|
|
static int
|
|
|
|
libxlReconnectDomain(virDomainObjPtr vm,
|
2011-02-10 16:42:34 -06:00
|
|
|
void *opaque)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = opaque;
|
2013-08-21 12:05:18 -05:00
|
|
|
libxlDomainObjPrivatePtr priv = vm->privateData;
|
2011-02-10 16:42:34 -06:00
|
|
|
int rc;
|
|
|
|
libxl_dominfo d_info;
|
|
|
|
int len;
|
|
|
|
uint8_t *data = NULL;
|
|
|
|
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectLock(vm);
|
2011-02-10 16:42:34 -06:00
|
|
|
|
2013-08-21 12:05:18 -05:00
|
|
|
libxlDomainObjPrivateInitCtx(vm);
|
2011-02-10 16:42:34 -06:00
|
|
|
/* Does domain still exist? */
|
2013-08-21 12:05:18 -05:00
|
|
|
rc = libxl_domain_info(priv->ctx, &d_info, vm->def->id);
|
2011-02-10 16:42:34 -06:00
|
|
|
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? */
|
2013-08-21 12:05:18 -05:00
|
|
|
if (libxl_userdata_retrieve(priv->ctx, vm->def->id,
|
2011-02-10 16:42:34 -06:00
|
|
|
"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 04:07:01 -05:00
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_UNKNOWN);
|
2011-02-10 16:42:34 -06:00
|
|
|
|
2013-08-30 15:54:50 -05:00
|
|
|
if (virAtomicIntInc(&driver->nactive) == 1 && driver->inhibitCallback)
|
2012-10-31 14:03:55 -05:00
|
|
|
driver->inhibitCallback(true, driver->inhibitOpaque);
|
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
/* Recreate domain death et. al. events */
|
|
|
|
libxlCreateDomEvents(vm);
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2013-01-11 07:54:15 -06:00
|
|
|
return 0;
|
2011-02-10 16:42:34 -06:00
|
|
|
|
|
|
|
out:
|
2011-05-04 04:07:01 -05:00
|
|
|
libxlVmCleanup(driver, vm, VIR_DOMAIN_SHUTOFF_UNKNOWN);
|
2011-02-10 16:42:34 -06:00
|
|
|
if (!vm->persistent)
|
2013-06-12 20:54:09 -05:00
|
|
|
virDomainObjListRemoveLocked(driver->domains, vm);
|
2011-02-10 16:42:34 -06:00
|
|
|
else
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2013-01-11 07:54:15 -06:00
|
|
|
|
|
|
|
return -1;
|
2011-02-10 16:42:34 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
libxlReconnectDomains(libxlDriverPrivatePtr driver)
|
|
|
|
{
|
2013-01-11 07:54:15 -06:00
|
|
|
virDomainObjListForEach(driver->domains, libxlReconnectDomain, driver);
|
2011-02-10 16:42:34 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-04-23 07:50:18 -05:00
|
|
|
libxlStateCleanup(void)
|
2011-02-10 16:42:34 -06:00
|
|
|
{
|
|
|
|
if (!libxl_driver)
|
|
|
|
return -1;
|
|
|
|
|
2013-08-30 15:52:14 -05:00
|
|
|
virObjectUnref(libxl_driver->config);
|
2013-03-31 13:03:42 -05:00
|
|
|
virObjectUnref(libxl_driver->xmlopt);
|
2013-01-11 07:54:15 -06:00
|
|
|
virObjectUnref(libxl_driver->domains);
|
2013-01-11 06:09:53 -06:00
|
|
|
virObjectUnref(libxl_driver->reservedVNCPorts);
|
2011-02-10 16:42:34 -06:00
|
|
|
|
2011-05-13 12:21:59 -05:00
|
|
|
virDomainEventStateFree(libxl_driver->domainEventState);
|
2013-06-12 10:49:27 -05:00
|
|
|
virSysinfoDefFree(libxl_driver->hostsysinfo);
|
2011-03-29 07:18:24 -05:00
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
virMutexDestroy(&libxl_driver->lock);
|
|
|
|
VIR_FREE(libxl_driver);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-08-30 13:34:48 -05:00
|
|
|
static bool
|
|
|
|
libxlDriverShouldLoad(bool privileged)
|
2012-10-31 14:03:55 -05:00
|
|
|
{
|
2013-08-30 13:34:48 -05:00
|
|
|
bool ret = false;
|
2011-02-10 16:42:34 -06:00
|
|
|
virCommandPtr cmd;
|
2013-08-30 13:34:48 -05:00
|
|
|
int status;
|
2011-02-10 16:42:34 -06:00
|
|
|
|
2013-08-30 13:34:48 -05:00
|
|
|
/* Don't load if non-root */
|
2011-02-10 16:42:34 -06:00
|
|
|
if (!privileged) {
|
2011-05-09 04:24:09 -05:00
|
|
|
VIR_INFO("Not running privileged, disabling libxenlight driver");
|
2013-08-30 13:34:48 -05:00
|
|
|
return ret;
|
2011-02-10 16:42:34 -06:00
|
|
|
}
|
|
|
|
|
2013-08-30 13:34:48 -05:00
|
|
|
/* Don't load if not running on a Xen control domain (dom0) */
|
|
|
|
if (!virFileExists("/proc/xen/capabilities")) {
|
|
|
|
VIR_INFO("No Xen capabilities detected, probably not running "
|
|
|
|
"in a Xen Dom0. Disabling libxenlight driver");
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Don't load if legacy xen toolstack (xend) is in use */
|
2011-02-10 16:42:34 -06:00
|
|
|
cmd = virCommandNewArgList("/usr/sbin/xend", "status", NULL);
|
|
|
|
if (virCommandRun(cmd, &status) == 0 && status == 0) {
|
2011-05-09 04:24:09 -05:00
|
|
|
VIR_INFO("Legacy xen tool stack seems to be in use, disabling "
|
2011-02-10 16:42:34 -06:00
|
|
|
"libxenlight driver.");
|
2013-08-30 13:34:48 -05:00
|
|
|
} else {
|
|
|
|
ret = true;
|
2011-02-10 16:42:34 -06:00
|
|
|
}
|
|
|
|
virCommandFree(cmd);
|
|
|
|
|
2013-08-30 13:34:48 -05:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlStateInitialize(bool privileged,
|
|
|
|
virStateInhibitCallback callback ATTRIBUTE_UNUSED,
|
|
|
|
void *opaque ATTRIBUTE_UNUSED)
|
|
|
|
{
|
2013-08-30 15:52:14 -05:00
|
|
|
libxlDriverConfigPtr cfg;
|
2013-08-30 13:34:48 -05:00
|
|
|
char ebuf[1024];
|
|
|
|
|
|
|
|
if (!libxlDriverShouldLoad(privileged))
|
|
|
|
return 0;
|
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
if (VIR_ALLOC(libxl_driver) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (virMutexInit(&libxl_driver->lock) < 0) {
|
2013-08-30 13:34:48 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("cannot initialize mutex"));
|
2011-02-10 16:42:34 -06:00
|
|
|
VIR_FREE(libxl_driver);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Allocate bitmap for vnc port reservation */
|
2013-01-11 06:09:53 -06:00
|
|
|
if (!(libxl_driver->reservedVNCPorts =
|
2013-10-31 06:46:28 -05:00
|
|
|
virPortAllocatorNew(_("VNC"),
|
|
|
|
LIBXL_VNC_PORT_MIN,
|
2013-01-11 06:09:53 -06:00
|
|
|
LIBXL_VNC_PORT_MAX)))
|
|
|
|
goto error;
|
2011-02-10 16:42:34 -06:00
|
|
|
|
2013-01-11 10:04:47 -06:00
|
|
|
if (!(libxl_driver->domains = virDomainObjListNew()))
|
|
|
|
goto error;
|
2011-02-10 16:42:34 -06:00
|
|
|
|
2013-08-30 15:52:14 -05:00
|
|
|
if (!(cfg = libxlDriverConfigNew()))
|
2013-06-07 08:20:35 -05:00
|
|
|
goto error;
|
2011-02-10 16:42:34 -06:00
|
|
|
|
2013-08-30 15:52:14 -05:00
|
|
|
libxl_driver->config = cfg;
|
|
|
|
if (virFileMakePath(cfg->logDir) < 0) {
|
2013-08-30 13:34:48 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("failed to create log dir '%s': %s"),
|
2013-08-30 15:52:14 -05:00
|
|
|
cfg->logDir,
|
2013-08-30 13:34:48 -05:00
|
|
|
virStrerror(errno, ebuf, sizeof(ebuf)));
|
2011-02-10 16:42:34 -06:00
|
|
|
goto error;
|
|
|
|
}
|
2013-08-30 15:52:14 -05:00
|
|
|
if (virFileMakePath(cfg->stateDir) < 0) {
|
2013-08-30 13:34:48 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("failed to create state dir '%s': %s"),
|
2013-08-30 15:52:14 -05:00
|
|
|
cfg->stateDir,
|
2013-08-30 13:34:48 -05:00
|
|
|
virStrerror(errno, ebuf, sizeof(ebuf)));
|
2011-02-10 16:42:34 -06:00
|
|
|
goto error;
|
|
|
|
}
|
2013-08-30 15:52:14 -05:00
|
|
|
if (virFileMakePath(cfg->libDir) < 0) {
|
2013-08-30 13:34:48 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("failed to create lib dir '%s': %s"),
|
2013-08-30 15:52:14 -05:00
|
|
|
cfg->libDir,
|
2013-08-30 13:34:48 -05:00
|
|
|
virStrerror(errno, ebuf, sizeof(ebuf)));
|
2011-02-10 16:42:34 -06:00
|
|
|
goto error;
|
|
|
|
}
|
2013-08-30 15:52:14 -05:00
|
|
|
if (virFileMakePath(cfg->saveDir) < 0) {
|
2013-08-30 13:34:48 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("failed to create save dir '%s': %s"),
|
2013-08-30 15:52:14 -05:00
|
|
|
cfg->saveDir,
|
2013-08-30 13:34:48 -05:00
|
|
|
virStrerror(errno, ebuf, sizeof(ebuf)));
|
2011-02-10 16:42:34 -06:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2013-06-12 10:49:27 -05:00
|
|
|
/* read the host sysinfo */
|
2013-09-04 17:59:59 -05:00
|
|
|
libxl_driver->hostsysinfo = virSysinfoRead();
|
2013-06-12 10:49:27 -05:00
|
|
|
|
2011-12-13 18:25:58 -06:00
|
|
|
libxl_driver->domainEventState = virDomainEventStateNew();
|
2011-05-13 12:21:59 -05:00
|
|
|
if (!libxl_driver->domainEventState)
|
2011-03-29 07:18:24 -05:00
|
|
|
goto error;
|
|
|
|
|
2013-08-30 15:52:14 -05:00
|
|
|
if ((cfg->caps = libxlMakeCapabilities(cfg->ctx)) == NULL) {
|
2013-08-30 13:34:48 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("cannot create capabilities for libxenlight"));
|
2011-02-10 16:42:34 -06:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2013-03-15 09:44:12 -05:00
|
|
|
if (!(libxl_driver->xmlopt = virDomainXMLOptionNew(&libxlDomainDefParserConfig,
|
2013-02-19 10:29:39 -06:00
|
|
|
&libxlDomainXMLPrivateDataCallbacks,
|
|
|
|
NULL)))
|
2013-03-05 09:17:24 -06:00
|
|
|
goto error;
|
2011-02-10 16:42:34 -06:00
|
|
|
|
|
|
|
/* Load running domains first. */
|
2013-01-11 10:04:47 -06:00
|
|
|
if (virDomainObjListLoadAllConfigs(libxl_driver->domains,
|
2013-08-30 15:52:14 -05:00
|
|
|
cfg->stateDir,
|
|
|
|
cfg->autostartDir,
|
2013-03-28 08:55:55 -05:00
|
|
|
1,
|
2013-08-30 15:52:14 -05:00
|
|
|
cfg->caps,
|
2013-03-28 08:55:55 -05:00
|
|
|
libxl_driver->xmlopt,
|
|
|
|
1 << VIR_DOMAIN_VIRT_XEN,
|
2013-01-11 10:04:47 -06:00
|
|
|
NULL, NULL) < 0)
|
2011-02-10 16:42:34 -06:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
libxlReconnectDomains(libxl_driver);
|
|
|
|
|
|
|
|
/* Then inactive persistent configs */
|
2013-01-11 10:04:47 -06:00
|
|
|
if (virDomainObjListLoadAllConfigs(libxl_driver->domains,
|
2013-08-30 15:52:14 -05:00
|
|
|
cfg->configDir,
|
|
|
|
cfg->autostartDir,
|
2013-03-28 08:55:55 -05:00
|
|
|
0,
|
2013-08-30 15:52:14 -05:00
|
|
|
cfg->caps,
|
2013-03-28 08:55:55 -05:00
|
|
|
libxl_driver->xmlopt,
|
|
|
|
1 << VIR_DOMAIN_VIRT_XEN,
|
2013-01-11 10:04:47 -06:00
|
|
|
NULL, NULL) < 0)
|
2011-02-10 16:42:34 -06:00
|
|
|
goto error;
|
|
|
|
|
2013-01-11 07:54:15 -06:00
|
|
|
virDomainObjListForEach(libxl_driver->domains, libxlDomainManagedSaveLoad,
|
|
|
|
libxl_driver);
|
2012-06-11 04:03:27 -05:00
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
2013-04-23 07:50:18 -05:00
|
|
|
libxlStateCleanup();
|
2013-08-30 15:52:14 -05:00
|
|
|
return -1;
|
2011-02-10 16:42:34 -06:00
|
|
|
}
|
|
|
|
|
2013-07-25 07:03:38 -05:00
|
|
|
static void
|
|
|
|
libxlStateAutoStart(void)
|
|
|
|
{
|
|
|
|
if (!libxl_driver)
|
|
|
|
return;
|
|
|
|
|
|
|
|
virDomainObjListForEach(libxl_driver->domains, libxlAutostartDomain,
|
|
|
|
libxl_driver);
|
|
|
|
}
|
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
static int
|
2013-04-23 07:50:18 -05:00
|
|
|
libxlStateReload(void)
|
2011-02-10 16:42:34 -06:00
|
|
|
{
|
2013-08-30 15:52:14 -05:00
|
|
|
libxlDriverConfigPtr cfg;
|
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
if (!libxl_driver)
|
|
|
|
return 0;
|
|
|
|
|
2013-08-30 15:52:14 -05:00
|
|
|
cfg = libxlDriverConfigGet(libxl_driver);
|
|
|
|
|
2013-01-11 10:04:47 -06:00
|
|
|
virDomainObjListLoadAllConfigs(libxl_driver->domains,
|
2013-08-30 15:52:14 -05:00
|
|
|
cfg->configDir,
|
|
|
|
cfg->autostartDir,
|
2013-03-28 08:55:55 -05:00
|
|
|
1,
|
2013-08-30 15:52:14 -05:00
|
|
|
cfg->caps,
|
2013-03-28 08:55:55 -05:00
|
|
|
libxl_driver->xmlopt,
|
|
|
|
1 << VIR_DOMAIN_VIRT_XEN,
|
2013-01-11 10:04:47 -06:00
|
|
|
NULL, libxl_driver);
|
|
|
|
|
2013-01-11 07:54:15 -06:00
|
|
|
virDomainObjListForEach(libxl_driver->domains, libxlAutostartDomain,
|
|
|
|
libxl_driver);
|
2011-03-28 05:49:22 -05:00
|
|
|
|
2013-08-30 15:52:14 -05:00
|
|
|
virObjectUnref(cfg);
|
2011-02-10 16:42:34 -06:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static virDrvOpenStatus
|
2013-04-23 07:50:18 -05:00
|
|
|
libxlConnectOpen(virConnectPtr conn,
|
|
|
|
virConnectAuthPtr auth ATTRIBUTE_UNUSED,
|
|
|
|
unsigned int flags)
|
2011-02-10 16:42:34 -06:00
|
|
|
{
|
2011-07-06 17:17:10 -05:00
|
|
|
virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
|
|
|
|
|
2011-02-10 16:42:34 -06: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 07:16:54 -05:00
|
|
|
if (!(conn->uri = virURIParse("xen:///")))
|
2011-02-10 16:42:34 -06: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 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("libxenlight state driver is not active"));
|
2011-02-10 16:42:34 -06: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 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unexpected Xen URI path '%s', try xen:///"),
|
|
|
|
NULLSTR(conn->uri->path));
|
2011-02-10 16:42:34 -06:00
|
|
|
return VIR_DRV_OPEN_ERROR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virConnectOpenEnsureACL(conn) < 0)
|
|
|
|
return VIR_DRV_OPEN_ERROR;
|
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
conn->privateData = libxl_driver;
|
|
|
|
|
|
|
|
return VIR_DRV_OPEN_SUCCESS;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
2013-04-23 07:50:18 -05:00
|
|
|
libxlConnectClose(virConnectPtr conn ATTRIBUTE_UNUSED)
|
2011-02-10 16:42:34 -06:00
|
|
|
{
|
|
|
|
conn->privateData = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *
|
2013-04-23 05:56:22 -05:00
|
|
|
libxlConnectGetType(virConnectPtr conn)
|
2011-02-10 16:42:34 -06:00
|
|
|
{
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virConnectGetTypeEnsureACL(conn) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
2013-05-17 10:17:03 -05:00
|
|
|
return "Xen";
|
2011-02-10 16:42:34 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-04-23 07:50:18 -05:00
|
|
|
libxlConnectGetVersion(virConnectPtr conn, unsigned long *version)
|
2011-02-10 16:42:34 -06:00
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
2013-08-30 15:52:14 -05:00
|
|
|
libxlDriverConfigPtr cfg;
|
2011-02-10 16:42:34 -06:00
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virConnectGetVersionEnsureACL(conn) < 0)
|
|
|
|
return 0;
|
|
|
|
|
2013-08-30 15:52:14 -05:00
|
|
|
cfg = libxlDriverConfigGet(driver);
|
|
|
|
*version = cfg->version;
|
|
|
|
virObjectUnref(cfg);
|
2011-02-10 16:42:34 -06:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-04-26 11:39:11 -05:00
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
static char *libxlConnectGetHostname(virConnectPtr conn)
|
2013-04-26 11:39:11 -05:00
|
|
|
{
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virConnectGetHostnameEnsureACL(conn) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
2013-04-26 11:39:11 -05:00
|
|
|
return virGetHostname();
|
|
|
|
}
|
|
|
|
|
2013-06-12 10:49:27 -05:00
|
|
|
static char *
|
|
|
|
libxlConnectGetSysinfo(virConnectPtr conn, unsigned int flags)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
|
|
|
|
|
|
|
virCheckFlags(0, NULL);
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virConnectGetSysinfoEnsureACL(conn) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
2013-06-12 10:49:27 -05:00
|
|
|
if (!driver->hostsysinfo) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Host SMBIOS information is not available"));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virSysinfoFormat(&buf, driver->hostsysinfo) < 0)
|
|
|
|
return NULL;
|
|
|
|
if (virBufferError(&buf)) {
|
|
|
|
virReportOOMError();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return virBufferContentAndReset(&buf);
|
|
|
|
}
|
2013-04-26 11:39:11 -05:00
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
static int
|
2013-04-23 07:50:18 -05:00
|
|
|
libxlConnectGetMaxVcpus(virConnectPtr conn, const char *type ATTRIBUTE_UNUSED)
|
2011-02-10 16:42:34 -06:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
2013-08-30 15:52:14 -05:00
|
|
|
libxlDriverConfigPtr cfg;
|
2011-02-10 16:42:34 -06:00
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virConnectGetMaxVcpusEnsureACL(conn) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2013-08-30 15:52:14 -05:00
|
|
|
cfg = libxlDriverConfigGet(driver);
|
|
|
|
ret = libxl_get_max_cpus(cfg->ctx);
|
2011-02-10 16:42:34 -06:00
|
|
|
/* libxl_get_max_cpus() will return 0 if there were any failures,
|
|
|
|
e.g. xc_physinfo() failing */
|
|
|
|
if (ret == 0)
|
2013-08-30 15:52:14 -05:00
|
|
|
ret = -1;
|
2011-02-10 16:42:34 -06:00
|
|
|
|
2013-08-30 15:52:14 -05:00
|
|
|
virObjectUnref(cfg);
|
2011-02-10 16:42:34 -06:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info)
|
|
|
|
{
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virNodeGetInfoEnsureACL(conn) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2011-04-18 04:16:33 -05:00
|
|
|
return libxlDoNodeGetInfo(conn->privateData, info);
|
2011-02-10 16:42:34 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
2013-04-23 07:50:18 -05:00
|
|
|
libxlConnectGetCapabilities(virConnectPtr conn)
|
2011-02-10 16:42:34 -06:00
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
char *xml;
|
2013-08-30 15:52:14 -05:00
|
|
|
libxlDriverConfigPtr cfg;
|
2011-02-10 16:42:34 -06:00
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virConnectGetCapabilitiesEnsureACL(conn) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
2013-08-30 15:52:14 -05:00
|
|
|
cfg = libxlDriverConfigGet(driver);
|
|
|
|
if ((xml = virCapabilitiesFormatXML(cfg->caps)) == NULL)
|
2011-02-10 16:42:34 -06:00
|
|
|
virReportOOMError();
|
|
|
|
|
2013-08-30 15:52:14 -05:00
|
|
|
virObjectUnref(cfg);
|
2011-02-10 16:42:34 -06:00
|
|
|
return xml;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-04-23 07:50:18 -05:00
|
|
|
libxlConnectListDomains(virConnectPtr conn, int *ids, int nids)
|
2011-02-10 16:42:34 -06:00
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
int n;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virConnectListDomainsEnsureACL(conn) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2013-06-24 11:49:47 -05:00
|
|
|
n = virDomainObjListGetActiveIDs(driver->domains, ids, nids,
|
|
|
|
virConnectListDomainsCheckACL, conn);
|
2011-02-10 16:42:34 -06:00
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-04-23 07:50:18 -05:00
|
|
|
libxlConnectNumOfDomains(virConnectPtr conn)
|
2011-02-10 16:42:34 -06:00
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
int n;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virConnectNumOfDomainsEnsureACL(conn) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2013-06-24 11:49:47 -05:00
|
|
|
n = virDomainObjListNumOfDomains(driver->domains, true,
|
|
|
|
virConnectNumOfDomainsCheckACL, conn);
|
2011-02-10 16:42:34 -06:00
|
|
|
|
|
|
|
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;
|
2013-08-30 15:52:14 -05:00
|
|
|
libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
|
2011-02-10 16:42:34 -06:00
|
|
|
|
|
|
|
virCheckFlags(VIR_DOMAIN_START_PAUSED, NULL);
|
|
|
|
|
2013-08-30 15:52:14 -05:00
|
|
|
if (!(def = virDomainDefParseString(xml, cfg->caps, driver->xmlopt,
|
2013-03-28 08:55:55 -05:00
|
|
|
1 << VIR_DOMAIN_VIRT_XEN,
|
2011-02-10 16:42:34 -06:00
|
|
|
VIR_DOMAIN_XML_INACTIVE)))
|
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainCreateXMLEnsureACL(conn, def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2013-03-28 08:55:55 -05:00
|
|
|
if (!(vm = virDomainObjListAdd(driver->domains, def,
|
2013-03-31 13:03:42 -05:00
|
|
|
driver->xmlopt,
|
Merge virDomainObjListIsDuplicate into virDomainObjListAdd
The duplicate VM checking should be done atomically with
virDomainObjListAdd, so shoud not be a separate function.
Instead just use flags to indicate what kind of checks are
required.
This pair, used in virDomainCreateXML:
if (virDomainObjListIsDuplicate(privconn->domains, def, 1) < 0)
goto cleanup;
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def, false)))
goto cleanup;
Changes to
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def,
VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
NULL)))
goto cleanup;
This pair, used in virDomainRestoreFlags:
if (virDomainObjListIsDuplicate(privconn->domains, def, 1) < 0)
goto cleanup;
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def, true)))
goto cleanup;
Changes to
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def,
VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
NULL)))
goto cleanup;
This pair, used in virDomainDefineXML:
if (virDomainObjListIsDuplicate(privconn->domains, def, 0) < 0)
goto cleanup;
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def, false)))
goto cleanup;
Changes to
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def,
0, NULL)))
goto cleanup;
2013-01-14 08:46:58 -06:00
|
|
|
VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
|
|
|
|
NULL)))
|
2011-02-10 16:42:34 -06:00
|
|
|
goto cleanup;
|
|
|
|
def = NULL;
|
|
|
|
|
2011-05-30 04:53:02 -05:00
|
|
|
if (libxlVmStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0,
|
|
|
|
-1) < 0) {
|
2013-01-11 10:04:47 -06:00
|
|
|
virDomainObjListRemove(driver->domains, vm);
|
2011-02-10 16:42:34 -06:00
|
|
|
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)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2013-08-30 15:52:14 -05:00
|
|
|
virObjectUnref(cfg);
|
2011-02-10 16:42:34 -06:00
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
|
|
|
static virDomainPtr
|
|
|
|
libxlDomainLookupByID(virConnectPtr conn, int id)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
virDomainPtr dom = NULL;
|
|
|
|
|
2013-01-11 10:04:47 -06:00
|
|
|
vm = virDomainObjListFindByID(driver->domains, id);
|
2011-02-10 16:42:34 -06:00
|
|
|
if (!vm) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, NULL);
|
2011-02-10 16:42:34 -06:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainLookupByIDEnsureACL(conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
|
|
|
if (dom)
|
|
|
|
dom->id = vm->def->id;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2011-02-10 16:42:34 -06:00
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
|
|
|
static virDomainPtr
|
|
|
|
libxlDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
virDomainPtr dom = NULL;
|
|
|
|
|
2013-01-11 10:04:47 -06:00
|
|
|
vm = virDomainObjListFindByUUID(driver->domains, uuid);
|
2011-02-10 16:42:34 -06:00
|
|
|
if (!vm) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, NULL);
|
2011-02-10 16:42:34 -06:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainLookupByUUIDEnsureACL(conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
|
|
|
if (dom)
|
|
|
|
dom->id = vm->def->id;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2011-02-10 16:42:34 -06:00
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
|
|
|
static virDomainPtr
|
|
|
|
libxlDomainLookupByName(virConnectPtr conn, const char *name)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
virDomainPtr dom = NULL;
|
|
|
|
|
2013-01-11 10:04:47 -06:00
|
|
|
vm = virDomainObjListFindByName(driver->domains, name);
|
2011-02-10 16:42:34 -06:00
|
|
|
if (!vm) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, NULL);
|
2011-02-10 16:42:34 -06:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainLookupByNameEnsureACL(conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
|
|
|
if (dom)
|
|
|
|
dom->id = vm->def->id;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2011-02-10 16:42:34 -06:00
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
2011-03-29 07:55:38 -05:00
|
|
|
static int
|
|
|
|
libxlDomainSuspend(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
2013-08-30 15:52:14 -05:00
|
|
|
libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
|
2011-03-29 07:55:38 -05:00
|
|
|
virDomainObjPtr vm;
|
|
|
|
libxlDomainObjPrivatePtr priv;
|
|
|
|
virDomainEventPtr event = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-03-29 07:55:38 -05:00
|
|
|
goto cleanup;
|
2013-04-23 05:56:22 -05:00
|
|
|
|
|
|
|
if (virDomainSuspendEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-03-29 07:55:38 -05:00
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
|
2011-03-29 07:55:38 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv = vm->privateData;
|
|
|
|
|
2011-05-04 04:07:01 -05:00
|
|
|
if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_PAUSED) {
|
2012-11-26 10:28:56 -06:00
|
|
|
if (libxl_domain_pause(priv->ctx, dom->id) != 0) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to suspend domain '%d' with libxenlight"),
|
|
|
|
dom->id);
|
2011-03-29 07:55:38 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-05-04 04:07:01 -05:00
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
|
2011-03-29 07:55:38 -05:00
|
|
|
|
|
|
|
event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_SUSPENDED,
|
|
|
|
VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
|
|
|
|
}
|
|
|
|
|
2013-08-30 15:52:14 -05:00
|
|
|
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
|
2011-03-29 07:55:38 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2013-08-30 15:57:42 -05:00
|
|
|
if (event)
|
2011-03-29 07:55:38 -05:00
|
|
|
libxlDomainEventQueue(driver, event);
|
2013-08-30 15:52:14 -05:00
|
|
|
virObjectUnref(cfg);
|
2011-03-29 07:55:38 -05:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainResume(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
2013-08-30 15:52:14 -05:00
|
|
|
libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
|
2011-03-29 07:55:38 -05:00
|
|
|
virDomainObjPtr vm;
|
|
|
|
libxlDomainObjPrivatePtr priv;
|
|
|
|
virDomainEventPtr event = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-03-29 07:55:38 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainResumeEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-03-29 07:55:38 -05:00
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
|
2011-03-29 07:55:38 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv = vm->privateData;
|
|
|
|
|
2011-05-04 04:07:01 -05:00
|
|
|
if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
|
2012-11-26 10:28:56 -06:00
|
|
|
if (libxl_domain_unpause(priv->ctx, dom->id) != 0) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to resume domain '%d' with libxenlight"),
|
|
|
|
dom->id);
|
2011-03-29 07:55:38 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-05-04 04:07:01 -05:00
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
|
|
|
|
VIR_DOMAIN_RUNNING_UNPAUSED);
|
2011-03-29 07:55:38 -05:00
|
|
|
|
|
|
|
event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_RESUMED,
|
|
|
|
VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
|
|
|
|
}
|
|
|
|
|
2013-08-30 15:52:14 -05:00
|
|
|
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
|
2011-03-29 07:55:38 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2013-08-30 15:57:42 -05:00
|
|
|
if (event)
|
2011-03-29 07:55:38 -05:00
|
|
|
libxlDomainEventQueue(driver, event);
|
2013-08-30 15:52:14 -05:00
|
|
|
virObjectUnref(cfg);
|
2011-03-29 07:55:38 -05:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
static int
|
2011-10-05 12:31:55 -05:00
|
|
|
libxlDomainShutdownFlags(virDomainPtr dom, unsigned int flags)
|
2011-02-10 16:42:34 -06:00
|
|
|
{
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
|
|
|
libxlDomainObjPrivatePtr priv;
|
|
|
|
|
2011-10-05 12:31:55 -05:00
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-02-10 16:42:34 -06:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainShutdownFlagsEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("Domain is not running"));
|
2011-02-10 16:42:34 -06:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv = vm->privateData;
|
2012-11-26 10:28:56 -06:00
|
|
|
if (libxl_domain_shutdown(priv->ctx, dom->id) != 0) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to shutdown domain '%d' with libxenlight"),
|
|
|
|
dom->id);
|
2011-02-10 16:42:34 -06:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vm is marked shutoff (or removed from domains list if not persistent)
|
|
|
|
* in shutdown event handler.
|
|
|
|
*/
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2011-02-10 16:42:34 -06:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-10-05 12:31:55 -05:00
|
|
|
static int
|
|
|
|
libxlDomainShutdown(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
return libxlDomainShutdownFlags(dom, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
static int
|
2011-07-06 17:17:10 -05:00
|
|
|
libxlDomainReboot(virDomainPtr dom, unsigned int flags)
|
2011-02-10 16:42:34 -06:00
|
|
|
{
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
|
|
|
libxlDomainObjPrivatePtr priv;
|
|
|
|
|
2011-07-06 17:17:10 -05:00
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-02-10 16:42:34 -06:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainRebootEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("Domain is not running"));
|
2011-02-10 16:42:34 -06:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv = vm->privateData;
|
2012-11-26 10:28:56 -06:00
|
|
|
if (libxl_domain_reboot(priv->ctx, dom->id) != 0) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to reboot domain '%d' with libxenlight"),
|
|
|
|
dom->id);
|
2011-02-10 16:42:34 -06:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2011-02-10 16:42:34 -06:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2011-07-20 11:47:46 -05:00
|
|
|
libxlDomainDestroyFlags(virDomainPtr dom,
|
|
|
|
unsigned int flags)
|
2011-02-10 16:42:34 -06:00
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
2011-03-29 07:18:24 -05:00
|
|
|
virDomainEventPtr event = NULL;
|
2011-02-10 16:42:34 -06:00
|
|
|
|
2011-07-20 11:47:46 -05:00
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-02-10 16:42:34 -06:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainDestroyFlagsEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("Domain is not running"));
|
2011-02-10 16:42:34 -06:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-11-19 16:32:34 -06:00
|
|
|
event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
|
2011-03-29 07:18:24 -05:00
|
|
|
VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
|
|
|
|
|
2012-11-26 10:28:56 -06:00
|
|
|
if (libxlVmReap(driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED) != 0) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to destroy domain '%d'"), dom->id);
|
2011-02-10 16:42:34 -06:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!vm->persistent) {
|
2013-01-11 10:04:47 -06:00
|
|
|
virDomainObjListRemove(driver->domains, vm);
|
2011-02-10 16:42:34 -06:00
|
|
|
vm = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2011-03-29 07:18:24 -05:00
|
|
|
if (event)
|
|
|
|
libxlDomainEventQueue(driver, event);
|
2011-02-10 16:42:34 -06:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-07-20 11:47:46 -05:00
|
|
|
static int
|
|
|
|
libxlDomainDestroy(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
return libxlDomainDestroyFlags(dom, 0);
|
|
|
|
}
|
|
|
|
|
2011-03-29 07:49:43 -05:00
|
|
|
static char *
|
|
|
|
libxlDomainGetOSType(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
char *type = NULL;
|
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-03-29 07:49:43 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainGetOSTypeEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (VIR_STRDUP(type, vm->def->os.type) < 0)
|
|
|
|
goto cleanup;
|
2011-03-29 07:49:43 -05:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2011-03-29 07:49:43 -05:00
|
|
|
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-02 18:47:16 -06:00
|
|
|
static unsigned long long
|
2011-03-21 04:35:53 -05:00
|
|
|
libxlDomainGetMaxMemory(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
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-02 18:47:16 -06:00
|
|
|
unsigned long long ret = 0;
|
2011-03-21 04:35:53 -05:00
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-03-21 04:35:53 -05:00
|
|
|
goto cleanup;
|
2013-04-23 05:56:22 -05:00
|
|
|
|
|
|
|
if (virDomainGetMaxMemoryEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-03-21 04:35:53 -05:00
|
|
|
ret = vm->def->mem.max_balloon;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2011-03-21 04:35:53 -05:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2011-05-30 04:53:03 -05:00
|
|
|
libxlDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem,
|
2011-03-21 04:35:53 -05:00
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
2013-08-30 15:52:14 -05:00
|
|
|
libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
|
2011-03-21 04:35:53 -05:00
|
|
|
libxlDomainObjPrivatePtr priv;
|
|
|
|
virDomainObjPtr vm;
|
2011-05-30 04:53:03 -05:00
|
|
|
virDomainDefPtr persistentDef = NULL;
|
|
|
|
bool isActive;
|
2011-03-21 04:35:53 -05:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(VIR_DOMAIN_MEM_LIVE |
|
2011-05-30 04:53:03 -05:00
|
|
|
VIR_DOMAIN_MEM_CONFIG |
|
|
|
|
VIR_DOMAIN_MEM_MAXIMUM, -1);
|
2011-03-21 04:35:53 -05:00
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-03-21 04:35:53 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainSetMemoryFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-05-30 04:53:03 -05: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 04:35:53 -05:00
|
|
|
}
|
|
|
|
|
2011-05-30 04:53:03 -05:00
|
|
|
if (!isActive && (flags & VIR_DOMAIN_MEM_LIVE)) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("cannot set memory on an inactive domain"));
|
2011-03-21 04:35:53 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_MEM_CONFIG) {
|
|
|
|
if (!vm->persistent) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("cannot change persistent config of a transient domain"));
|
2011-03-21 04:35:53 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2013-08-30 15:52:14 -05:00
|
|
|
if (!(persistentDef = virDomainObjGetPersistentDef(cfg->caps,
|
2013-03-31 13:03:42 -05:00
|
|
|
driver->xmlopt,
|
2013-03-05 09:17:24 -06:00
|
|
|
vm)))
|
2011-03-21 04:35:53 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-05-30 04:53:03 -05:00
|
|
|
if (flags & VIR_DOMAIN_MEM_MAXIMUM) {
|
|
|
|
/* resize the maximum memory */
|
2011-03-21 04:35:53 -05:00
|
|
|
|
2011-05-30 04:53:03 -05:00
|
|
|
if (flags & VIR_DOMAIN_MEM_LIVE) {
|
|
|
|
priv = vm->privateData;
|
2012-11-26 10:28:56 -06:00
|
|
|
if (libxl_domain_setmaxmem(priv->ctx, dom->id, newmem) < 0) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to set maximum memory for domain '%d'"
|
|
|
|
" with libxenlight"), dom->id);
|
2011-05-30 04:53:03 -05: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;
|
2013-08-30 15:52:14 -05:00
|
|
|
ret = virDomainSaveConfig(cfg->configDir, persistentDef);
|
2011-03-21 04:35:53 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-05-30 04:53:03 -05:00
|
|
|
} else {
|
|
|
|
/* resize the current memory */
|
2011-03-21 04:35:53 -05:00
|
|
|
|
2011-05-30 04:53:03 -05:00
|
|
|
if (newmem > vm->def->mem.max_balloon) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("cannot set memory higher than max memory"));
|
2011-05-30 04:53:03 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_MEM_LIVE) {
|
|
|
|
priv = vm->privateData;
|
2012-11-26 10:28:56 -06:00
|
|
|
if (libxl_set_memory_target(priv->ctx, dom->id, newmem, 0,
|
2011-05-30 04:53:03 -05:00
|
|
|
/* force */ 1) < 0) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to set memory for domain '%d'"
|
|
|
|
" with libxenlight"), dom->id);
|
2011-05-30 04:53:03 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_MEM_CONFIG) {
|
|
|
|
sa_assert(persistentDef);
|
|
|
|
persistentDef->mem.cur_balloon = newmem;
|
2013-08-30 15:52:14 -05:00
|
|
|
ret = virDomainSaveConfig(cfg->configDir, persistentDef);
|
2011-05-30 04:53:03 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2011-03-21 04:35:53 -05:00
|
|
|
}
|
|
|
|
|
2011-05-30 04:53:03 -05:00
|
|
|
ret = 0;
|
|
|
|
|
2011-03-21 04:35:53 -05:00
|
|
|
cleanup:
|
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2013-08-30 15:52:14 -05:00
|
|
|
virObjectUnref(cfg);
|
2011-03-21 04:35:53 -05:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainSetMemory(virDomainPtr dom, unsigned long memory)
|
|
|
|
{
|
|
|
|
return libxlDomainSetMemoryFlags(dom, memory, VIR_DOMAIN_MEM_LIVE);
|
|
|
|
}
|
|
|
|
|
2011-05-30 04:53:03 -05:00
|
|
|
static int
|
|
|
|
libxlDomainSetMaxMemory(virDomainPtr dom, unsigned long memory)
|
|
|
|
{
|
|
|
|
return libxlDomainSetMemoryFlags(dom, memory, VIR_DOMAIN_MEM_MAXIMUM);
|
|
|
|
}
|
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
static int
|
|
|
|
libxlDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
|
|
|
|
{
|
|
|
|
virDomainObjPtr vm;
|
2011-03-21 04:35:51 -05:00
|
|
|
libxl_dominfo d_info;
|
2013-08-30 15:36:22 -05:00
|
|
|
libxlDomainObjPrivatePtr priv;
|
2011-02-10 16:42:34 -06:00
|
|
|
int ret = -1;
|
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-02-10 16:42:34 -06:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainGetInfoEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2013-08-30 15:36:22 -05:00
|
|
|
priv = vm->privateData;
|
2011-03-21 04:35:51 -05:00
|
|
|
if (!virDomainObjIsActive(vm)) {
|
|
|
|
info->cpuTime = 0;
|
|
|
|
info->memory = vm->def->mem.cur_balloon;
|
2011-06-02 07:16:32 -05:00
|
|
|
info->maxMem = vm->def->mem.max_balloon;
|
2011-03-21 04:35:51 -05:00
|
|
|
} else {
|
2013-08-30 15:36:22 -05:00
|
|
|
if (libxl_domain_info(priv->ctx, &d_info, dom->id) != 0) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("libxl_domain_info failed for domain '%d'"), dom->id);
|
2011-03-21 04:35:51 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
info->cpuTime = d_info.cpu_time;
|
|
|
|
info->memory = d_info.current_memkb;
|
2011-06-02 07:16:32 -05:00
|
|
|
info->maxMem = d_info.max_memkb;
|
2011-03-21 04:35:51 -05:00
|
|
|
}
|
|
|
|
|
2011-05-04 04:07:01 -05:00
|
|
|
info->state = virDomainObjGetState(vm, NULL);
|
2011-02-10 16:42:34 -06:00
|
|
|
info->nrVirtCpu = vm->def->vcpus;
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2011-02-10 16:42:34 -06:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-05-02 04:35:29 -05:00
|
|
|
static int
|
|
|
|
libxlDomainGetState(virDomainPtr dom,
|
|
|
|
int *state,
|
|
|
|
int *reason,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-05-02 04:35:29 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainGetStateEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-05-04 04:07:01 -05:00
|
|
|
*state = virDomainObjGetState(vm, reason);
|
2011-05-02 04:35:29 -05:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2011-05-02 04:35:29 -05:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-06-02 07:24:30 -05:00
|
|
|
/* This internal function expects the driver lock to already be held on
|
|
|
|
* entry and the vm must be active. */
|
2011-05-30 04:53:02 -05:00
|
|
|
static int
|
2011-06-02 07:24:30 -05:00
|
|
|
libxlDoDomainSave(libxlDriverPrivatePtr driver, virDomainObjPtr vm,
|
|
|
|
const char *to)
|
2011-05-30 04:53:02 -05:00
|
|
|
{
|
2011-06-02 07:24:30 -05:00
|
|
|
libxlDomainObjPrivatePtr priv = vm->privateData;
|
2011-05-30 04:53:02 -05:00
|
|
|
libxlSavefileHeader hdr;
|
|
|
|
virDomainEventPtr event = NULL;
|
|
|
|
char *xml = NULL;
|
|
|
|
uint32_t xml_len;
|
2013-02-28 08:48:16 -06:00
|
|
|
int fd = -1;
|
2011-05-30 04:53:02 -05:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("Domain '%d' has to be running because libxenlight will"
|
|
|
|
" suspend it"), vm->def->id);
|
2011-05-30 04:53:02 -05: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 14:26:45 -06:00
|
|
|
-1, -1, 0)) < 0) {
|
2011-05-30 04:53:02 -05: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 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
|
|
|
|
_("Failed to write save file header"));
|
2011-05-30 04:53:02 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (safewrite(fd, xml, xml_len) != xml_len) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
|
|
|
|
_("Failed to write xml description"));
|
2011-05-30 04:53:02 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2012-11-26 10:28:56 -06:00
|
|
|
if (libxl_domain_suspend(priv->ctx, vm->def->id, fd, 0, NULL) != 0) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to save domain '%d' with libxenlight"),
|
|
|
|
vm->def->id);
|
2011-05-30 04:53:02 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
|
|
|
|
VIR_DOMAIN_EVENT_STOPPED_SAVED);
|
|
|
|
|
2012-11-26 10:28:56 -06:00
|
|
|
if (libxlVmReap(driver, vm, VIR_DOMAIN_SHUTOFF_SAVED) != 0) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to destroy domain '%d'"), vm->def->id);
|
2011-05-30 04:53:02 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2012-06-11 04:03:27 -05:00
|
|
|
vm->hasManagedSave = true;
|
2011-05-30 04:53:02 -05:00
|
|
|
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-08 21:55:29 -05:00
|
|
|
libxlDomainSaveFlags(virDomainPtr dom, const char *to, const char *dxml,
|
|
|
|
unsigned int flags)
|
2011-05-30 04:53:02 -05:00
|
|
|
{
|
2011-06-02 07:24:30 -05:00
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
2011-05-30 04:53:02 -05: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-08 21:55:29 -05:00
|
|
|
virCheckFlags(0, -1);
|
|
|
|
if (dxml) {
|
2012-07-18 08:32:10 -05: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-08 21:55:29 -05:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-05-30 04:53:02 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainSaveFlagsEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-06-02 07:24:30 -05:00
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
|
2011-05-30 04:53:02 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-01-21 11:32:34 -06:00
|
|
|
if (libxlDoDomainSave(driver, vm, to) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!vm->persistent) {
|
2013-01-11 10:04:47 -06:00
|
|
|
virDomainObjListRemove(driver->domains, vm);
|
2013-01-21 11:32:34 -06:00
|
|
|
vm = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
2011-05-30 04:53:02 -05:00
|
|
|
|
2011-06-02 07:24:30 -05:00
|
|
|
cleanup:
|
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2011-06-02 07:24:30 -05:00
|
|
|
return ret;
|
|
|
|
}
|
2011-05-30 04:53:02 -05:00
|
|
|
|
2011-06-02 07:24:30 -05: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-08 21:55:29 -05: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 07:24:30 -05:00
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
2013-08-30 15:57:42 -05:00
|
|
|
libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
|
2011-06-02 07:24:30 -05:00
|
|
|
virDomainObjPtr vm = NULL;
|
|
|
|
virDomainDefPtr def = NULL;
|
|
|
|
libxlSavefileHeader hdr;
|
|
|
|
int fd = -1;
|
|
|
|
int ret = -1;
|
2011-05-30 04:53:02 -05:00
|
|
|
|
2013-06-12 20:54:11 -05:00
|
|
|
virCheckFlags(VIR_DOMAIN_SAVE_PAUSED, -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-08 21:55:29 -05:00
|
|
|
if (dxml) {
|
2012-07-18 08:32:10 -05: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-08 21:55:29 -05:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-08-30 15:57:42 -05:00
|
|
|
/* Lock the driver until domain def is read from the saved
|
|
|
|
image and a virDomainObj is created and locked.
|
|
|
|
*/
|
2011-06-02 07:24:30 -05:00
|
|
|
libxlDriverLock(driver);
|
2011-05-30 04:53:02 -05:00
|
|
|
|
2013-08-30 15:57:42 -05:00
|
|
|
fd = libxlSaveImageOpen(driver, cfg, from, &def, &hdr);
|
2011-06-02 07:24:30 -05:00
|
|
|
if (fd < 0)
|
2013-08-30 15:57:42 -05:00
|
|
|
goto cleanup_unlock;
|
2011-05-30 04:53:02 -05:00
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainRestoreFlagsEnsureACL(conn, def) < 0)
|
2013-08-30 15:57:42 -05:00
|
|
|
goto cleanup_unlock;
|
2013-04-23 05:56:22 -05:00
|
|
|
|
2013-03-28 08:55:55 -05:00
|
|
|
if (!(vm = virDomainObjListAdd(driver->domains, def,
|
2013-03-31 13:03:42 -05:00
|
|
|
driver->xmlopt,
|
Merge virDomainObjListIsDuplicate into virDomainObjListAdd
The duplicate VM checking should be done atomically with
virDomainObjListAdd, so shoud not be a separate function.
Instead just use flags to indicate what kind of checks are
required.
This pair, used in virDomainCreateXML:
if (virDomainObjListIsDuplicate(privconn->domains, def, 1) < 0)
goto cleanup;
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def, false)))
goto cleanup;
Changes to
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def,
VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
NULL)))
goto cleanup;
This pair, used in virDomainRestoreFlags:
if (virDomainObjListIsDuplicate(privconn->domains, def, 1) < 0)
goto cleanup;
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def, true)))
goto cleanup;
Changes to
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def,
VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
NULL)))
goto cleanup;
This pair, used in virDomainDefineXML:
if (virDomainObjListIsDuplicate(privconn->domains, def, 0) < 0)
goto cleanup;
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def, false)))
goto cleanup;
Changes to
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def,
0, NULL)))
goto cleanup;
2013-01-14 08:46:58 -06:00
|
|
|
VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
|
|
|
|
VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
|
|
|
|
NULL)))
|
2013-08-30 15:57:42 -05:00
|
|
|
goto cleanup_unlock;
|
2011-05-30 04:53:02 -05:00
|
|
|
|
2013-08-30 15:57:42 -05:00
|
|
|
libxlDriverUnlock(driver);
|
2011-05-30 04:53:02 -05:00
|
|
|
def = NULL;
|
|
|
|
|
2013-06-12 20:54:11 -05:00
|
|
|
ret = libxlVmStart(driver, vm, (flags & VIR_DOMAIN_SAVE_PAUSED) != 0, fd);
|
|
|
|
if (ret < 0 && !vm->persistent) {
|
2013-01-11 10:04:47 -06:00
|
|
|
virDomainObjListRemove(driver->domains, vm);
|
2011-05-30 04:53:02 -05:00
|
|
|
vm = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
2011-06-02 16:41:13 -05:00
|
|
|
if (VIR_CLOSE(fd) < 0)
|
|
|
|
virReportSystemError(errno, "%s", _("cannot close file"));
|
2011-05-30 04:53:02 -05:00
|
|
|
virDomainDefFree(def);
|
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2013-08-30 15:57:42 -05:00
|
|
|
virObjectUnref(cfg);
|
2011-05-30 04:53:02 -05:00
|
|
|
return ret;
|
2013-08-30 15:57:42 -05:00
|
|
|
|
|
|
|
cleanup_unlock:
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
goto cleanup;
|
2011-05-30 04:53:02 -05: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-08 21:55:29 -05:00
|
|
|
static int
|
|
|
|
libxlDomainRestore(virConnectPtr conn, const char *from)
|
|
|
|
{
|
|
|
|
return libxlDomainRestoreFlags(conn, from, NULL, 0);
|
|
|
|
}
|
|
|
|
|
2011-05-30 04:53:01 -05:00
|
|
|
static int
|
2011-07-06 15:40:19 -05:00
|
|
|
libxlDomainCoreDump(virDomainPtr dom, const char *to, unsigned int flags)
|
2011-05-30 04:53:01 -05: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);
|
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-05-30 04:53:01 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainCoreDumpEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-05-30 04:53:01 -05:00
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
|
2011-05-30 04:53:01 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv = vm->privateData;
|
|
|
|
|
|
|
|
if (!(flags & VIR_DUMP_LIVE) &&
|
|
|
|
virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
|
2012-11-26 10:28:56 -06:00
|
|
|
if (libxl_domain_pause(priv->ctx, dom->id) != 0) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Before dumping core, failed to suspend domain '%d'"
|
|
|
|
" with libxenlight"),
|
|
|
|
dom->id);
|
2011-05-30 04:53:01 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_DUMP);
|
|
|
|
paused = true;
|
|
|
|
}
|
|
|
|
|
2012-11-26 10:28:56 -06:00
|
|
|
if (libxl_domain_core_dump(priv->ctx, dom->id, to, NULL) != 0) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to dump core of domain '%d' with libxenlight"),
|
|
|
|
dom->id);
|
2011-05-30 04:53:01 -05:00
|
|
|
goto cleanup_unpause;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & VIR_DUMP_CRASH) {
|
2012-11-26 10:28:56 -06:00
|
|
|
if (libxlVmReap(driver, vm, VIR_DOMAIN_SHUTOFF_CRASHED) != 0) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to destroy domain '%d'"), dom->id);
|
2013-08-30 15:57:42 -05:00
|
|
|
goto cleanup_unpause;
|
2011-05-30 04:53:01 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
|
|
|
|
VIR_DOMAIN_EVENT_STOPPED_CRASHED);
|
2013-09-04 15:27:20 -05:00
|
|
|
if (!vm->persistent) {
|
|
|
|
virDomainObjListRemove(driver->domains, vm);
|
|
|
|
vm = NULL;
|
|
|
|
}
|
2011-05-30 04:53:01 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup_unpause:
|
2013-09-04 15:27:20 -05:00
|
|
|
if (vm && virDomainObjIsActive(vm) && paused) {
|
2012-11-26 10:28:56 -06:00
|
|
|
if (libxl_domain_unpause(priv->ctx, dom->id) != 0) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("After dumping core, failed to resume domain '%d' with"
|
|
|
|
" libxenlight"), dom->id);
|
2011-05-30 04:53:01 -05:00
|
|
|
} else {
|
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
|
|
|
|
VIR_DOMAIN_RUNNING_UNPAUSED);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2013-08-30 15:57:42 -05:00
|
|
|
if (event)
|
2011-05-30 04:53:01 -05:00
|
|
|
libxlDomainEventQueue(driver, event);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-06-02 07:24:30 -05: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);
|
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-06-02 07:24:30 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainManagedSaveEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-06-02 07:24:30 -05:00
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
|
2011-06-02 07:24:30 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2011-08-10 09:51:36 -05:00
|
|
|
if (!vm->persistent) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("cannot do managed save for transient domain"));
|
2011-08-10 09:51:36 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2011-06-02 07:24:30 -05:00
|
|
|
|
|
|
|
name = libxlDomainManagedSavePath(driver, vm);
|
|
|
|
if (name == NULL)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
VIR_INFO("Saving state to %s", name);
|
|
|
|
|
2013-01-21 11:32:34 -06:00
|
|
|
if (libxlDoDomainSave(driver, vm, name) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!vm->persistent) {
|
2013-01-11 10:04:47 -06:00
|
|
|
virDomainObjListRemove(driver->domains, vm);
|
2013-01-21 11:32:34 -06:00
|
|
|
vm = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
2011-06-02 07:24:30 -05:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2011-06-02 07:24:30 -05:00
|
|
|
VIR_FREE(name);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-01-11 07:54:15 -06:00
|
|
|
static int
|
|
|
|
libxlDomainManagedSaveLoad(virDomainObjPtr vm,
|
2012-06-11 04:03:27 -05:00
|
|
|
void *opaque)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = opaque;
|
|
|
|
char *name;
|
2013-01-11 07:54:15 -06:00
|
|
|
int ret = -1;
|
2012-06-11 04:03:27 -05:00
|
|
|
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectLock(vm);
|
2012-06-11 04:03:27 -05:00
|
|
|
|
|
|
|
if (!(name = libxlDomainManagedSavePath(driver, vm)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
vm->hasManagedSave = virFileExists(name);
|
|
|
|
|
2013-01-11 07:54:15 -06:00
|
|
|
ret = 0;
|
2012-06-11 04:03:27 -05:00
|
|
|
cleanup:
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2012-06-11 04:03:27 -05:00
|
|
|
VIR_FREE(name);
|
2013-01-11 07:54:15 -06:00
|
|
|
return ret;
|
2012-06-11 04:03:27 -05:00
|
|
|
}
|
|
|
|
|
2011-06-02 07:24:30 -05:00
|
|
|
static int
|
|
|
|
libxlDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
|
|
|
|
{
|
|
|
|
virDomainObjPtr vm = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-06-02 07:24:30 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainHasManagedSaveImageEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2012-06-11 04:03:27 -05:00
|
|
|
ret = vm->hasManagedSave;
|
2011-06-02 07:24:30 -05:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2011-06-02 07:24:30 -05:00
|
|
|
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);
|
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-06-02 07:24:30 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainManagedSaveRemoveEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-06-02 07:24:30 -05:00
|
|
|
name = libxlDomainManagedSavePath(driver, vm);
|
|
|
|
if (name == NULL)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = unlink(name);
|
2012-06-11 04:03:27 -05:00
|
|
|
vm->hasManagedSave = false;
|
2011-06-02 07:24:30 -05:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(name);
|
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2011-06-02 07:24:30 -05:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-03-29 07:31:45 -05:00
|
|
|
static int
|
|
|
|
libxlDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
2013-08-30 15:52:14 -05:00
|
|
|
libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
|
2011-03-29 07:31:45 -05:00
|
|
|
libxlDomainObjPrivatePtr priv;
|
|
|
|
virDomainDefPtr def;
|
|
|
|
virDomainObjPtr vm;
|
2012-11-26 10:28:56 -06:00
|
|
|
libxl_bitmap map;
|
2011-03-29 07:31:45 -05:00
|
|
|
uint8_t *bitmask = NULL;
|
|
|
|
unsigned int maplen;
|
Convert 'int i' to 'size_t i' in src/libxl/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 09:09:33 -05:00
|
|
|
size_t i;
|
|
|
|
unsigned int pos;
|
2011-03-29 07:31:45 -05:00
|
|
|
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 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("invalid flag combination: (0x%x)"), flags);
|
2011-03-29 07:31:45 -05:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!nvcpus) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s", _("nvcpus is zero"));
|
2011-03-29 07:31:45 -05:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-03-29 07:31:45 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainSetVcpusFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-03-29 07:31:45 -05:00
|
|
|
if (!virDomainObjIsActive(vm) && (flags & VIR_DOMAIN_VCPU_LIVE)) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("cannot set vcpus on an inactive domain"));
|
2011-03-29 07:31:45 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!vm->persistent && (flags & VIR_DOMAIN_VCPU_CONFIG)) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("cannot change persistent config of a transient domain"));
|
2011-03-29 07:31:45 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-04-23 07:50:18 -05:00
|
|
|
if ((max = libxlConnectGetMaxVcpus(dom->conn, NULL)) < 0) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("could not determine max vcpus for the domain"));
|
2011-03-29 07:31:45 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(flags & VIR_DOMAIN_VCPU_MAXIMUM) && vm->def->maxvcpus < max) {
|
|
|
|
max = vm->def->maxvcpus;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nvcpus > max) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("requested vcpus is greater than max allowable"
|
|
|
|
" vcpus for the domain: %d > %d"), nvcpus, max);
|
2011-03-29 07:31:45 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv = vm->privateData;
|
|
|
|
|
2013-08-30 15:52:14 -05:00
|
|
|
if (!(def = virDomainObjGetPersistentDef(cfg->caps, driver->xmlopt, vm)))
|
2011-03-29 07:31:45 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
2011-04-05 11:07:57 -05:00
|
|
|
maplen = VIR_CPU_MAPLEN(nvcpus);
|
2013-07-04 05:10:38 -05:00
|
|
|
if (VIR_ALLOC_N(bitmask, maplen) < 0)
|
2011-03-29 07:31:45 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
for (i = 0; i < nvcpus; ++i) {
|
2011-04-05 11:07:57 -05:00
|
|
|
pos = i / 8;
|
2011-03-29 07:31:45 -05: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:
|
2012-11-26 10:28:56 -06:00
|
|
|
if (libxl_set_vcpuonline(priv->ctx, dom->id, &map) != 0) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to set vcpus for domain '%d'"
|
|
|
|
" with libxenlight"), dom->id);
|
2011-03-29 07:31:45 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG:
|
2012-11-26 10:28:56 -06:00
|
|
|
if (libxl_set_vcpuonline(priv->ctx, dom->id, &map) != 0) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to set vcpus for domain '%d'"
|
|
|
|
" with libxenlight"), dom->id);
|
2011-03-29 07:31:45 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
def->vcpus = nvcpus;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_VCPU_CONFIG)
|
2013-08-30 15:52:14 -05:00
|
|
|
ret = virDomainSaveConfig(cfg->configDir, def);
|
2011-03-29 07:31:45 -05:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(bitmask);
|
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2013-08-30 15:52:14 -05:00
|
|
|
virObjectUnref(cfg);
|
2011-03-29 07:31:45 -05:00
|
|
|
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)
|
|
|
|
{
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
virDomainDefPtr def;
|
|
|
|
int ret = -1;
|
2011-07-15 18:35:47 -05:00
|
|
|
bool active;
|
2011-03-29 07:31:45 -05:00
|
|
|
|
|
|
|
virCheckFlags(VIR_DOMAIN_VCPU_LIVE |
|
|
|
|
VIR_DOMAIN_VCPU_CONFIG |
|
|
|
|
VIR_DOMAIN_VCPU_MAXIMUM, -1);
|
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-03-29 07:31:45 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainGetVcpusFlagsEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-07-15 18:35:47 -05: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 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("invalid flag combination: (0x%x)"), flags);
|
2011-07-15 18:35:47 -05:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-03-29 07:31:45 -05:00
|
|
|
if (flags & VIR_DOMAIN_VCPU_LIVE) {
|
2011-07-15 18:35:47 -05:00
|
|
|
if (!active) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("Domain is not running"));
|
2011-03-29 07:31:45 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
def = vm->def;
|
|
|
|
} else {
|
2011-07-15 18:35:47 -05:00
|
|
|
if (!vm->persistent) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("domain is transient"));
|
2011-07-15 18:35:47 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2011-03-29 07:31:45 -05:00
|
|
|
def = vm->newDef ? vm->newDef : vm->def;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = (flags & VIR_DOMAIN_VCPU_MAXIMUM) ? def->maxvcpus : def->vcpus;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2011-03-29 07:31:45 -05:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainPinVcpu(virDomainPtr dom, unsigned int vcpu, unsigned char *cpumap,
|
|
|
|
int maplen)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
2013-08-30 15:52:14 -05:00
|
|
|
libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
|
2011-03-29 07:31:45 -05:00
|
|
|
libxlDomainObjPrivatePtr priv;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
2012-11-26 10:28:56 -06:00
|
|
|
libxl_bitmap map;
|
2011-03-29 07:31:45 -05:00
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-03-29 07:31:45 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainPinVcpuEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-03-29 07:31:45 -05:00
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("cannot pin vcpus on an inactive domain"));
|
2011-03-29 07:31:45 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv = vm->privateData;
|
|
|
|
|
|
|
|
map.size = maplen;
|
|
|
|
map.map = cpumap;
|
2012-11-26 10:28:56 -06:00
|
|
|
if (libxl_set_vcpuaffinity(priv->ctx, dom->id, vcpu, &map) != 0) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to pin vcpu '%d' with libxenlight"), vcpu);
|
2011-03-29 07:31:45 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2011-04-18 04:16:33 -05:00
|
|
|
|
2012-08-21 04:18:28 -05:00
|
|
|
if (!vm->def->cputune.vcpupin) {
|
2013-07-04 05:10:38 -05:00
|
|
|
if (VIR_ALLOC(vm->def->cputune.vcpupin) < 0)
|
2012-08-21 04:18:28 -05:00
|
|
|
goto cleanup;
|
|
|
|
vm->def->cputune.nvcpupin = 0;
|
|
|
|
}
|
2012-08-30 08:38:37 -05:00
|
|
|
if (virDomainVcpuPinAdd(&vm->def->cputune.vcpupin,
|
2012-08-21 04:18:28 -05:00
|
|
|
&vm->def->cputune.nvcpupin,
|
|
|
|
cpumap,
|
|
|
|
maplen,
|
|
|
|
vcpu) < 0) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("failed to update or add vcpupin xml"));
|
2011-04-18 04:16:33 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-08-30 15:52:14 -05:00
|
|
|
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
|
2011-04-18 04:16:33 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
2011-03-29 07:31:45 -05:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2013-08-30 15:52:14 -05:00
|
|
|
virObjectUnref(cfg);
|
2011-03-29 07:31:45 -05:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainGetVcpus(virDomainPtr dom, virVcpuInfoPtr info, int maxinfo,
|
|
|
|
unsigned char *cpumaps, int maplen)
|
|
|
|
{
|
|
|
|
libxlDomainObjPrivatePtr priv;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
|
|
|
libxl_vcpuinfo *vcpuinfo;
|
|
|
|
int maxcpu, hostcpus;
|
Convert 'int i' to 'size_t i' in src/libxl/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 09:09:33 -05:00
|
|
|
size_t i;
|
2011-03-29 07:31:45 -05:00
|
|
|
unsigned char *cpumap;
|
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-03-29 07:31:45 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainGetVcpusEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-03-29 07:31:45 -05:00
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
|
2011-03-29 07:31:45 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv = vm->privateData;
|
2012-11-26 10:28:56 -06:00
|
|
|
if ((vcpuinfo = libxl_list_vcpu(priv->ctx, dom->id, &maxcpu,
|
2011-03-29 07:31:45 -05:00
|
|
|
&hostcpus)) == NULL) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to list vcpus for domain '%d' with libxenlight"),
|
|
|
|
dom->id);
|
2011-03-29 07:31:45 -05: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));
|
|
|
|
}
|
|
|
|
|
2012-11-26 10:28:56 -06:00
|
|
|
libxl_vcpuinfo_dispose(&vcpuinfo[i]);
|
2011-03-29 07:31:45 -05:00
|
|
|
}
|
|
|
|
VIR_FREE(vcpuinfo);
|
|
|
|
|
|
|
|
ret = maxinfo;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2011-03-29 07:31:45 -05:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
static char *
|
2011-07-06 15:40:19 -05:00
|
|
|
libxlDomainGetXMLDesc(virDomainPtr dom, unsigned int flags)
|
2011-02-10 16:42:34 -06:00
|
|
|
{
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
char *ret = NULL;
|
|
|
|
|
2011-07-13 17:24:38 -05:00
|
|
|
/* Flags checked by virDomainDefFormat */
|
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-02-10 16:42:34 -06:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainGetXMLDescEnsureACL(dom->conn, vm->def, flags) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
ret = virDomainDefFormat(vm->def, flags);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2011-02-10 16:42:34 -06:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-03-29 07:39:18 -05:00
|
|
|
static char *
|
2013-04-23 07:50:18 -05:00
|
|
|
libxlConnectDomainXMLFromNative(virConnectPtr conn, const char * nativeFormat,
|
|
|
|
const char * nativeConfig,
|
|
|
|
unsigned int flags)
|
2011-03-29 07:39:18 -05:00
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
2013-08-30 15:52:14 -05:00
|
|
|
libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
|
2011-03-29 07:39:18 -05:00
|
|
|
virDomainDefPtr def = NULL;
|
|
|
|
virConfPtr conf = NULL;
|
|
|
|
char *xml = NULL;
|
|
|
|
|
2011-07-06 17:17:10 -05:00
|
|
|
virCheckFlags(0, NULL);
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virConnectDomainXMLFromNativeEnsureACL(conn) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-03-29 07:39:18 -05:00
|
|
|
if (STRNEQ(nativeFormat, LIBXL_CONFIG_FORMAT_XM)) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("unsupported config type %s"), nativeFormat);
|
2011-03-29 07:39:18 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(conf = virConfReadMem(nativeConfig, strlen(nativeConfig), 0)))
|
|
|
|
goto cleanup;
|
|
|
|
|
2013-08-30 15:32:10 -05:00
|
|
|
if (!(def = xenParseXM(conf,
|
2013-08-30 15:52:14 -05:00
|
|
|
cfg->verInfo->xen_version_major,
|
|
|
|
cfg->caps))) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("parsing xm config failed"));
|
2011-03-29 07:39:18 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
xml = virDomainDefFormat(def, VIR_DOMAIN_XML_INACTIVE);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virDomainDefFree(def);
|
|
|
|
if (conf)
|
|
|
|
virConfFree(conf);
|
2013-08-30 15:52:14 -05:00
|
|
|
virObjectUnref(cfg);
|
2011-03-29 07:39:18 -05:00
|
|
|
return xml;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define MAX_CONFIG_SIZE (1024 * 65)
|
|
|
|
static char *
|
2013-04-23 07:50:18 -05:00
|
|
|
libxlConnectDomainXMLToNative(virConnectPtr conn, const char * nativeFormat,
|
|
|
|
const char * domainXml,
|
|
|
|
unsigned int flags)
|
2011-03-29 07:39:18 -05:00
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
2013-08-30 15:52:14 -05:00
|
|
|
libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
|
2011-03-29 07:39:18 -05:00
|
|
|
virDomainDefPtr def = NULL;
|
|
|
|
virConfPtr conf = NULL;
|
|
|
|
int len = MAX_CONFIG_SIZE;
|
|
|
|
char *ret = NULL;
|
|
|
|
|
2011-07-06 17:17:10 -05:00
|
|
|
virCheckFlags(0, NULL);
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virConnectDomainXMLToNativeEnsureACL(conn) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-03-29 07:39:18 -05:00
|
|
|
if (STRNEQ(nativeFormat, LIBXL_CONFIG_FORMAT_XM)) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("unsupported config type %s"), nativeFormat);
|
2011-03-29 07:39:18 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-03-28 08:55:55 -05:00
|
|
|
if (!(def = virDomainDefParseString(domainXml,
|
2013-08-30 15:52:14 -05:00
|
|
|
cfg->caps, driver->xmlopt,
|
2011-07-11 12:29:09 -05:00
|
|
|
1 << VIR_DOMAIN_VIRT_XEN, 0)))
|
2011-03-29 07:39:18 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-08-30 15:52:14 -05:00
|
|
|
if (!(conf = xenFormatXM(conn, def, cfg->verInfo->xen_version_major)))
|
2011-03-29 07:39:18 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-07-04 05:10:38 -05:00
|
|
|
if (VIR_ALLOC_N(ret, len) < 0)
|
2011-03-29 07:39:18 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virConfWriteMem(ret, &len, conf) < 0) {
|
|
|
|
VIR_FREE(ret);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virDomainDefFree(def);
|
|
|
|
if (conf)
|
|
|
|
virConfFree(conf);
|
2013-08-30 15:52:14 -05:00
|
|
|
virObjectUnref(cfg);
|
2011-03-29 07:39:18 -05:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
static int
|
2013-04-23 07:50:18 -05:00
|
|
|
libxlConnectListDefinedDomains(virConnectPtr conn,
|
|
|
|
char **const names, int nnames)
|
2011-02-10 16:42:34 -06:00
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
int n;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virConnectListDefinedDomainsEnsureACL(conn) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2013-06-24 11:49:47 -05:00
|
|
|
n = virDomainObjListGetInactiveNames(driver->domains, names, nnames,
|
|
|
|
virConnectListDefinedDomainsCheckACL, conn);
|
2011-02-10 16:42:34 -06:00
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-04-23 07:50:18 -05:00
|
|
|
libxlConnectNumOfDefinedDomains(virConnectPtr conn)
|
2011-02-10 16:42:34 -06:00
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
int n;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virConnectNumOfDefinedDomainsEnsureACL(conn) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2013-06-24 11:49:47 -05:00
|
|
|
n = virDomainObjListNumOfDomains(driver->domains, false,
|
2013-07-04 09:55:53 -05:00
|
|
|
virConnectNumOfDefinedDomainsCheckACL,
|
|
|
|
conn);
|
2011-02-10 16:42:34 -06:00
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainCreateWithFlags(virDomainPtr dom,
|
2011-07-06 17:17:10 -05:00
|
|
|
unsigned int flags)
|
2011-02-10 16:42:34 -06:00
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(VIR_DOMAIN_START_PAUSED, -1);
|
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-02-10 16:42:34 -06:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainCreateWithFlagsEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
if (virDomainObjIsActive(vm)) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("Domain is already running"));
|
2011-02-10 16:42:34 -06:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-05-30 04:53:02 -05:00
|
|
|
ret = libxlVmStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0, -1);
|
2011-02-10 16:42:34 -06:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2011-02-10 16:42:34 -06:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainCreate(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
return libxlDomainCreateWithFlags(dom, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static virDomainPtr
|
|
|
|
libxlDomainDefineXML(virConnectPtr conn, const char *xml)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
2013-08-30 15:52:14 -05:00
|
|
|
libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
|
2011-02-10 16:42:34 -06:00
|
|
|
virDomainDefPtr def = NULL;
|
|
|
|
virDomainObjPtr vm = NULL;
|
|
|
|
virDomainPtr dom = NULL;
|
2011-03-29 07:18:24 -05:00
|
|
|
virDomainEventPtr event = NULL;
|
Merge virDomainObjListIsDuplicate into virDomainObjListAdd
The duplicate VM checking should be done atomically with
virDomainObjListAdd, so shoud not be a separate function.
Instead just use flags to indicate what kind of checks are
required.
This pair, used in virDomainCreateXML:
if (virDomainObjListIsDuplicate(privconn->domains, def, 1) < 0)
goto cleanup;
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def, false)))
goto cleanup;
Changes to
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def,
VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
NULL)))
goto cleanup;
This pair, used in virDomainRestoreFlags:
if (virDomainObjListIsDuplicate(privconn->domains, def, 1) < 0)
goto cleanup;
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def, true)))
goto cleanup;
Changes to
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def,
VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
NULL)))
goto cleanup;
This pair, used in virDomainDefineXML:
if (virDomainObjListIsDuplicate(privconn->domains, def, 0) < 0)
goto cleanup;
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def, false)))
goto cleanup;
Changes to
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def,
0, NULL)))
goto cleanup;
2013-01-14 08:46:58 -06:00
|
|
|
virDomainDefPtr oldDef = NULL;
|
2011-02-10 16:42:34 -06:00
|
|
|
|
2013-08-30 15:57:42 -05:00
|
|
|
/* Lock the driver until the virDomainObj is created and locked */
|
2011-02-10 16:42:34 -06:00
|
|
|
libxlDriverLock(driver);
|
2013-08-30 15:52:14 -05:00
|
|
|
if (!(def = virDomainDefParseString(xml, cfg->caps, driver->xmlopt,
|
2011-07-11 12:29:09 -05:00
|
|
|
1 << VIR_DOMAIN_VIRT_XEN,
|
2011-02-10 16:42:34 -06:00
|
|
|
VIR_DOMAIN_XML_INACTIVE)))
|
2013-08-30 15:57:42 -05:00
|
|
|
goto cleanup_unlock;
|
2011-02-10 16:42:34 -06:00
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainDefineXMLEnsureACL(conn, def) < 0)
|
2013-08-30 15:57:42 -05:00
|
|
|
goto cleanup_unlock;
|
2013-04-23 05:56:22 -05:00
|
|
|
|
2013-03-28 08:55:55 -05:00
|
|
|
if (!(vm = virDomainObjListAdd(driver->domains, def,
|
2013-03-31 13:03:42 -05:00
|
|
|
driver->xmlopt,
|
Merge virDomainObjListIsDuplicate into virDomainObjListAdd
The duplicate VM checking should be done atomically with
virDomainObjListAdd, so shoud not be a separate function.
Instead just use flags to indicate what kind of checks are
required.
This pair, used in virDomainCreateXML:
if (virDomainObjListIsDuplicate(privconn->domains, def, 1) < 0)
goto cleanup;
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def, false)))
goto cleanup;
Changes to
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def,
VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
NULL)))
goto cleanup;
This pair, used in virDomainRestoreFlags:
if (virDomainObjListIsDuplicate(privconn->domains, def, 1) < 0)
goto cleanup;
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def, true)))
goto cleanup;
Changes to
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def,
VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
NULL)))
goto cleanup;
This pair, used in virDomainDefineXML:
if (virDomainObjListIsDuplicate(privconn->domains, def, 0) < 0)
goto cleanup;
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def, false)))
goto cleanup;
Changes to
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def,
0, NULL)))
goto cleanup;
2013-01-14 08:46:58 -06:00
|
|
|
0,
|
|
|
|
&oldDef)))
|
2013-08-30 15:57:42 -05:00
|
|
|
goto cleanup_unlock;
|
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
def = NULL;
|
|
|
|
vm->persistent = 1;
|
2013-08-30 15:57:42 -05:00
|
|
|
libxlDriverUnlock(driver);
|
2011-02-10 16:42:34 -06:00
|
|
|
|
2013-08-30 15:52:14 -05:00
|
|
|
if (virDomainSaveConfig(cfg->configDir,
|
2011-02-10 16:42:34 -06:00
|
|
|
vm->newDef ? vm->newDef : vm->def) < 0) {
|
2013-01-11 10:04:47 -06:00
|
|
|
virDomainObjListRemove(driver->domains, vm);
|
2011-02-10 16:42:34 -06:00
|
|
|
vm = NULL;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
|
|
|
if (dom)
|
|
|
|
dom->id = vm->def->id;
|
|
|
|
|
2011-03-29 07:18:24 -05:00
|
|
|
event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_DEFINED,
|
Merge virDomainObjListIsDuplicate into virDomainObjListAdd
The duplicate VM checking should be done atomically with
virDomainObjListAdd, so shoud not be a separate function.
Instead just use flags to indicate what kind of checks are
required.
This pair, used in virDomainCreateXML:
if (virDomainObjListIsDuplicate(privconn->domains, def, 1) < 0)
goto cleanup;
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def, false)))
goto cleanup;
Changes to
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def,
VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
NULL)))
goto cleanup;
This pair, used in virDomainRestoreFlags:
if (virDomainObjListIsDuplicate(privconn->domains, def, 1) < 0)
goto cleanup;
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def, true)))
goto cleanup;
Changes to
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def,
VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
NULL)))
goto cleanup;
This pair, used in virDomainDefineXML:
if (virDomainObjListIsDuplicate(privconn->domains, def, 0) < 0)
goto cleanup;
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def, false)))
goto cleanup;
Changes to
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def,
0, NULL)))
goto cleanup;
2013-01-14 08:46:58 -06:00
|
|
|
!oldDef ?
|
2011-03-29 07:18:24 -05:00
|
|
|
VIR_DOMAIN_EVENT_DEFINED_ADDED :
|
|
|
|
VIR_DOMAIN_EVENT_DEFINED_UPDATED);
|
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
cleanup:
|
|
|
|
virDomainDefFree(def);
|
Merge virDomainObjListIsDuplicate into virDomainObjListAdd
The duplicate VM checking should be done atomically with
virDomainObjListAdd, so shoud not be a separate function.
Instead just use flags to indicate what kind of checks are
required.
This pair, used in virDomainCreateXML:
if (virDomainObjListIsDuplicate(privconn->domains, def, 1) < 0)
goto cleanup;
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def, false)))
goto cleanup;
Changes to
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def,
VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
NULL)))
goto cleanup;
This pair, used in virDomainRestoreFlags:
if (virDomainObjListIsDuplicate(privconn->domains, def, 1) < 0)
goto cleanup;
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def, true)))
goto cleanup;
Changes to
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def,
VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
NULL)))
goto cleanup;
This pair, used in virDomainDefineXML:
if (virDomainObjListIsDuplicate(privconn->domains, def, 0) < 0)
goto cleanup;
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def, false)))
goto cleanup;
Changes to
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def,
0, NULL)))
goto cleanup;
2013-01-14 08:46:58 -06:00
|
|
|
virDomainDefFree(oldDef);
|
2011-02-10 16:42:34 -06:00
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2011-03-29 07:18:24 -05:00
|
|
|
if (event)
|
|
|
|
libxlDomainEventQueue(driver, event);
|
2013-08-30 15:52:14 -05:00
|
|
|
virObjectUnref(cfg);
|
2011-02-10 16:42:34 -06:00
|
|
|
return dom;
|
2013-08-30 15:57:42 -05:00
|
|
|
|
|
|
|
cleanup_unlock:
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
goto cleanup;
|
2011-02-10 16:42:34 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2011-07-19 22:05:20 -05:00
|
|
|
libxlDomainUndefineFlags(virDomainPtr dom,
|
|
|
|
unsigned int flags)
|
2011-02-10 16:42:34 -06:00
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
2013-08-30 15:52:14 -05:00
|
|
|
libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
|
2011-02-10 16:42:34 -06:00
|
|
|
virDomainObjPtr vm;
|
2011-03-29 07:18:24 -05:00
|
|
|
virDomainEventPtr event = NULL;
|
2011-07-19 22:05:20 -05:00
|
|
|
char *name = NULL;
|
2011-02-10 16:42:34 -06:00
|
|
|
int ret = -1;
|
|
|
|
|
2011-07-19 22:05:20 -05:00
|
|
|
virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE, -1);
|
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-02-10 16:42:34 -06:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainUndefineFlagsEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
if (!vm->persistent) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("cannot undefine transient domain"));
|
2011-02-10 16:42:34 -06:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-07-19 22:05:20 -05: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 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Failed to remove domain managed save image"));
|
2011-07-19 22:05:20 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
} else {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("Refusing to undefine while domain managed "
|
|
|
|
"save image exists"));
|
2011-07-19 22:05:20 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-30 15:52:14 -05:00
|
|
|
if (virDomainDeleteConfig(cfg->configDir, cfg->autostartDir, vm) < 0)
|
2011-02-10 16:42:34 -06:00
|
|
|
goto cleanup;
|
|
|
|
|
2011-03-29 07:18:24 -05:00
|
|
|
event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_UNDEFINED,
|
|
|
|
VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
|
|
|
|
|
2011-08-19 08:46:22 -05:00
|
|
|
if (virDomainObjIsActive(vm)) {
|
|
|
|
vm->persistent = 0;
|
|
|
|
} else {
|
2013-01-11 10:04:47 -06:00
|
|
|
virDomainObjListRemove(driver->domains, vm);
|
2011-08-19 08:46:22 -05:00
|
|
|
vm = NULL;
|
|
|
|
}
|
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
2011-07-19 22:05:20 -05:00
|
|
|
VIR_FREE(name);
|
2011-02-10 16:42:34 -06:00
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2011-03-29 07:18:24 -05:00
|
|
|
if (event)
|
|
|
|
libxlDomainEventQueue(driver, event);
|
2013-08-30 15:52:14 -05:00
|
|
|
virObjectUnref(cfg);
|
2011-02-10 16:42:34 -06:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-07-19 22:05:20 -05:00
|
|
|
static int
|
|
|
|
libxlDomainUndefine(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
return libxlDomainUndefineFlags(dom, 0);
|
|
|
|
}
|
|
|
|
|
2011-05-26 10:27:06 -05:00
|
|
|
static int
|
|
|
|
libxlDomainChangeEjectableMedia(libxlDomainObjPrivatePtr priv,
|
|
|
|
virDomainObjPtr vm, virDomainDiskDefPtr disk)
|
|
|
|
{
|
|
|
|
virDomainDiskDefPtr origdisk = NULL;
|
|
|
|
libxl_device_disk x_disk;
|
Convert 'int i' to 'size_t i' in src/libxl/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 09:09:33 -05:00
|
|
|
size_t i;
|
2011-05-26 10:27:06 -05:00
|
|
|
int ret = -1;
|
|
|
|
|
2013-05-21 02:21:16 -05:00
|
|
|
for (i = 0; i < vm->def->ndisks; i++) {
|
2011-05-26 10:27:06 -05:00
|
|
|
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 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("No device with bus '%s' and target '%s'"),
|
|
|
|
virDomainDiskBusTypeToString(disk->bus), disk->dst);
|
2011-05-26 10:27:06 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (origdisk->device != VIR_DOMAIN_DISK_DEVICE_CDROM) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Removable media not supported for %s device"),
|
|
|
|
virDomainDiskDeviceTypeToString(disk->device));
|
2011-05-26 10:27:06 -05:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-11-26 10:28:56 -06:00
|
|
|
if (libxlMakeDisk(disk, &x_disk) < 0)
|
2011-05-26 10:27:06 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
2012-11-26 10:28:56 -06:00
|
|
|
if ((ret = libxl_cdrom_insert(priv->ctx, vm->def->id, &x_disk, NULL)) < 0) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("libxenlight failed to change media for disk '%s'"),
|
|
|
|
disk->dst);
|
2011-05-26 10:27:06 -05: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-19 21:38:36 -05:00
|
|
|
if (virDomainDiskIndexByName(vm->def, l_disk->dst, true) >= 0) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("target %s already exists"), l_disk->dst);
|
2011-05-26 10:27:06 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!l_disk->src) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("disk source path is missing"));
|
2011-05-26 10:27:06 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-07-04 05:10:38 -05:00
|
|
|
if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0)
|
2011-05-26 10:27:06 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
2012-11-26 10:28:56 -06:00
|
|
|
if (libxlMakeDisk(l_disk, &x_disk) < 0)
|
2011-05-26 10:27:06 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
2012-11-26 10:28:56 -06:00
|
|
|
if ((ret = libxl_device_disk_add(priv->ctx, vm->def->id,
|
|
|
|
&x_disk, NULL)) < 0) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("libxenlight failed to attach disk '%s'"),
|
|
|
|
l_disk->dst);
|
2011-05-26 10:27:06 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainDiskInsertPreAlloced(vm->def, l_disk);
|
|
|
|
|
|
|
|
} else {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("disk bus '%s' cannot be hotplugged."),
|
|
|
|
virDomainDiskBusTypeToString(l_disk->bus));
|
2011-05-26 10:27:06 -05:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("disk device type '%s' cannot be hotplugged"),
|
|
|
|
virDomainDiskDeviceTypeToString(l_disk->device));
|
2011-05-26 10:27:06 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainDetachDeviceDiskLive(libxlDomainObjPrivatePtr priv,
|
|
|
|
virDomainObjPtr vm, virDomainDeviceDefPtr dev)
|
|
|
|
{
|
|
|
|
virDomainDiskDefPtr l_disk = NULL;
|
|
|
|
libxl_device_disk x_disk;
|
Convert 'int i' to 'size_t i' in src/libxl/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 09:09:33 -05:00
|
|
|
int idx;
|
2011-05-26 10:27:06 -05:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
switch (dev->data.disk->device) {
|
|
|
|
case VIR_DOMAIN_DISK_DEVICE_DISK:
|
|
|
|
if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_XEN) {
|
|
|
|
|
Convert 'int i' to 'size_t i' in src/libxl/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 09:09:33 -05:00
|
|
|
if ((idx = virDomainDiskIndexByName(vm->def,
|
|
|
|
dev->data.disk->dst,
|
|
|
|
false)) < 0) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("disk %s not found"), dev->data.disk->dst);
|
2011-05-26 10:27:06 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
Convert 'int i' to 'size_t i' in src/libxl/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 09:09:33 -05:00
|
|
|
l_disk = vm->def->disks[idx];
|
2011-05-26 10:27:06 -05:00
|
|
|
|
2012-11-26 10:28:56 -06:00
|
|
|
if (libxlMakeDisk(l_disk, &x_disk) < 0)
|
2011-05-26 10:27:06 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
2012-11-26 10:28:56 -06:00
|
|
|
if ((ret = libxl_device_disk_remove(priv->ctx, vm->def->id,
|
|
|
|
&x_disk, NULL)) < 0) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("libxenlight failed to detach disk '%s'"),
|
|
|
|
l_disk->dst);
|
2011-05-26 10:27:06 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
Convert 'int i' to 'size_t i' in src/libxl/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 09:09:33 -05:00
|
|
|
virDomainDiskRemove(vm->def, idx);
|
2011-05-26 10:27:06 -05:00
|
|
|
virDomainDiskDefFree(l_disk);
|
|
|
|
|
|
|
|
} else {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("disk bus '%s' cannot be hot unplugged."),
|
|
|
|
virDomainDiskBusTypeToString(dev->data.disk->bus));
|
2011-05-26 10:27:06 -05:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("device type '%s' cannot hot unplugged"),
|
|
|
|
virDomainDiskDeviceTypeToString(dev->data.disk->device));
|
2011-05-26 10:27:06 -05: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 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("device type '%s' cannot be attached"),
|
|
|
|
virDomainDeviceTypeToString(dev->type));
|
2011-05-26 10:27:06 -05: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-19 21:38:36 -05:00
|
|
|
if (virDomainDiskIndexByName(vmdef, disk->dst, true) >= 0) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("target %s already exists."), disk->dst);
|
2011-05-26 10:27:06 -05:00
|
|
|
return -1;
|
|
|
|
}
|
2013-07-04 05:10:38 -05:00
|
|
|
if (virDomainDiskInsert(vmdef, disk))
|
2011-05-26 10:27:06 -05:00
|
|
|
return -1;
|
|
|
|
/* vmdef has the pointer. Generic codes for vmdef will do all jobs */
|
|
|
|
dev->data.disk = NULL;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("persistent attach of device is not supported"));
|
2011-05-26 10:27:06 -05: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 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("device type '%s' cannot be detached"),
|
|
|
|
virDomainDeviceTypeToString(dev->type));
|
2011-05-26 10:27:06 -05: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 17:06:14 -06:00
|
|
|
virDomainDiskDefPtr disk, detach;
|
2011-05-26 10:27:06 -05: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 17:06:14 -06:00
|
|
|
if (!(detach = virDomainDiskRemoveByName(vmdef, disk->dst))) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("no target device %s"), disk->dst);
|
2011-05-26 10:27:06 -05: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 17:06:14 -06:00
|
|
|
virDomainDiskDefFree(detach);
|
2011-05-26 10:27:06 -05:00
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
default:
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("persistent detach of device is not supported"));
|
2011-05-26 10:27:06 -05: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 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("disk bus '%s' cannot be updated."),
|
|
|
|
virDomainDiskBusTypeToString(disk->bus));
|
2011-05-26 10:27:06 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("device type '%s' cannot be updated"),
|
|
|
|
virDomainDeviceTypeToString(dev->type));
|
2011-05-26 10:27:06 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainUpdateDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev)
|
|
|
|
{
|
|
|
|
virDomainDiskDefPtr orig;
|
|
|
|
virDomainDiskDefPtr disk;
|
Convert 'int i' to 'size_t i' in src/libxl/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 09:09:33 -05:00
|
|
|
int idx;
|
2011-05-26 10:27:06 -05:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
switch (dev->type) {
|
|
|
|
case VIR_DOMAIN_DEVICE_DISK:
|
|
|
|
disk = dev->data.disk;
|
Convert 'int i' to 'size_t i' in src/libxl/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 09:09:33 -05:00
|
|
|
if ((idx = virDomainDiskIndexByName(vmdef, disk->dst, false)) < 0) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("target %s doesn't exist."), disk->dst);
|
2011-05-26 10:27:06 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
Convert 'int i' to 'size_t i' in src/libxl/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 09:09:33 -05:00
|
|
|
orig = vmdef->disks[idx];
|
2011-05-26 10:27:06 -05:00
|
|
|
if (!(orig->device == VIR_DOMAIN_DISK_DEVICE_CDROM)) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("this disk doesn't support update"));
|
2011-05-26 10:27:06 -05: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 16:47:42 -05:00
|
|
|
orig->format = disk->format;
|
2011-05-26 10:27:06 -05:00
|
|
|
disk->src = NULL;
|
|
|
|
break;
|
|
|
|
default:
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("persistent update of device is not supported"));
|
2011-05-26 10:27:06 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2013-04-29 10:59:42 -05:00
|
|
|
libxlDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
|
|
|
|
unsigned int flags)
|
2011-05-26 10:27:06 -05:00
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
2013-08-30 15:52:14 -05:00
|
|
|
libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
|
2011-05-26 10:27:06 -05:00
|
|
|
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);
|
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-05-26 10:27:06 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainAttachDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-05-26 10:27:06 -05:00
|
|
|
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 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("Domain is not running"));
|
2011-05-26 10:27:06 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) && !vm->persistent) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("cannot modify device on transient domain"));
|
2011-05-26 10:27:06 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv = vm->privateData;
|
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
|
2013-03-28 08:55:55 -05:00
|
|
|
if (!(dev = virDomainDeviceDefParse(xml, vm->def,
|
2013-08-30 15:52:14 -05:00
|
|
|
cfg->caps, driver->xmlopt,
|
2011-05-26 10:27:06 -05:00
|
|
|
VIR_DOMAIN_XML_INACTIVE)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* Make a copy for updated domain. */
|
2013-08-30 15:52:14 -05:00
|
|
|
if (!(vmdef = virDomainObjCopyPersistentDef(vm, cfg->caps,
|
2013-03-28 08:55:55 -05:00
|
|
|
driver->xmlopt)))
|
2011-05-26 10:27:06 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-29 10:59:42 -05:00
|
|
|
if ((ret = libxlDomainAttachDeviceConfig(vmdef, dev)) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
} else {
|
2011-05-26 10:27:06 -05:00
|
|
|
ret = 0;
|
2013-04-29 10:59:42 -05:00
|
|
|
}
|
2011-05-26 10:27:06 -05:00
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) {
|
|
|
|
/* If dev exists it was created to modify the domain config. Free it. */
|
|
|
|
virDomainDeviceDefFree(dev);
|
2013-03-28 08:55:55 -05:00
|
|
|
if (!(dev = virDomainDeviceDefParse(xml, vm->def,
|
2013-08-30 15:52:14 -05:00
|
|
|
cfg->caps, driver->xmlopt,
|
2011-05-26 10:27:06 -05:00
|
|
|
VIR_DOMAIN_XML_INACTIVE)))
|
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-29 10:59:42 -05:00
|
|
|
if ((ret = libxlDomainAttachDeviceLive(priv, vm, dev)) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-05-26 10:27:06 -05:00
|
|
|
/*
|
|
|
|
* update domain status forcibly because the domain status may be
|
|
|
|
* changed even if we attach the device failed.
|
|
|
|
*/
|
2013-08-30 15:52:14 -05:00
|
|
|
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
|
2011-05-26 10:27:06 -05:00
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Finally, if no error until here, we can save config. */
|
|
|
|
if (!ret && (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG)) {
|
2013-08-30 15:52:14 -05:00
|
|
|
ret = virDomainSaveConfig(cfg->configDir, vmdef);
|
2011-05-26 10:27:06 -05:00
|
|
|
if (!ret) {
|
Merge virDomainObjListIsDuplicate into virDomainObjListAdd
The duplicate VM checking should be done atomically with
virDomainObjListAdd, so shoud not be a separate function.
Instead just use flags to indicate what kind of checks are
required.
This pair, used in virDomainCreateXML:
if (virDomainObjListIsDuplicate(privconn->domains, def, 1) < 0)
goto cleanup;
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def, false)))
goto cleanup;
Changes to
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def,
VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
NULL)))
goto cleanup;
This pair, used in virDomainRestoreFlags:
if (virDomainObjListIsDuplicate(privconn->domains, def, 1) < 0)
goto cleanup;
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def, true)))
goto cleanup;
Changes to
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def,
VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
NULL)))
goto cleanup;
This pair, used in virDomainDefineXML:
if (virDomainObjListIsDuplicate(privconn->domains, def, 0) < 0)
goto cleanup;
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def, false)))
goto cleanup;
Changes to
if (!(dom = virDomainObjListAdd(privconn->domains,
privconn->caps,
def,
0, NULL)))
goto cleanup;
2013-01-14 08:46:58 -06:00
|
|
|
virDomainObjAssignDef(vm, vmdef, false, NULL);
|
2011-05-26 10:27:06 -05:00
|
|
|
vmdef = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virDomainDefFree(vmdef);
|
|
|
|
virDomainDeviceDefFree(dev);
|
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2013-08-30 15:52:14 -05:00
|
|
|
virObjectUnref(cfg);
|
2011-05-26 10:27:06 -05:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2013-04-29 10:59:42 -05:00
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
2013-08-30 15:52:14 -05:00
|
|
|
libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
|
2013-04-29 10:59:42 -05:00
|
|
|
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);
|
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2013-04-29 10:59:42 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainDetachDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-29 10:59:42 -05:00
|
|
|
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) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("Domain is not running"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) && !vm->persistent) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("cannot modify device on transient domain"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv = vm->privateData;
|
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
|
|
|
|
if (!(dev = virDomainDeviceDefParse(xml, vm->def,
|
2013-08-30 15:52:14 -05:00
|
|
|
cfg->caps, driver->xmlopt,
|
2013-04-29 10:59:42 -05:00
|
|
|
VIR_DOMAIN_XML_INACTIVE)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* Make a copy for updated domain. */
|
2013-08-30 15:52:14 -05:00
|
|
|
if (!(vmdef = virDomainObjCopyPersistentDef(vm, cfg->caps,
|
2013-04-29 10:59:42 -05:00
|
|
|
driver->xmlopt)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if ((ret = libxlDomainDetachDeviceConfig(vmdef, dev)) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
} 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(xml, vm->def,
|
2013-08-30 15:52:14 -05:00
|
|
|
cfg->caps, driver->xmlopt,
|
2013-04-29 10:59:42 -05:00
|
|
|
VIR_DOMAIN_XML_INACTIVE)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if ((ret = libxlDomainDetachDeviceLive(priv, vm, dev)) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* update domain status forcibly because the domain status may be
|
|
|
|
* changed even if we attach the device failed.
|
|
|
|
*/
|
2013-08-30 15:52:14 -05:00
|
|
|
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
|
2013-04-29 10:59:42 -05:00
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Finally, if no error until here, we can save config. */
|
|
|
|
if (!ret && (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG)) {
|
2013-08-30 15:52:14 -05:00
|
|
|
ret = virDomainSaveConfig(cfg->configDir, vmdef);
|
2013-04-29 10:59:42 -05:00
|
|
|
if (!ret) {
|
|
|
|
virDomainObjAssignDef(vm, vmdef, false, NULL);
|
|
|
|
vmdef = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virDomainDefFree(vmdef);
|
|
|
|
virDomainDeviceDefFree(dev);
|
|
|
|
if (vm)
|
|
|
|
virObjectUnlock(vm);
|
2013-08-30 15:52:14 -05:00
|
|
|
virObjectUnref(cfg);
|
2013-04-29 10:59:42 -05:00
|
|
|
return ret;
|
2011-05-26 10:27:06 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2013-04-29 10:59:42 -05:00
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
2013-08-30 15:52:14 -05:00
|
|
|
libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
|
2013-04-29 10:59:42 -05:00
|
|
|
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);
|
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2013-04-29 10:59:42 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainUpdateDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-29 10:59:42 -05:00
|
|
|
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) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("Domain is not running"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) && !vm->persistent) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("cannot modify device on transient domain"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv = vm->privateData;
|
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
|
|
|
|
if (!(dev = virDomainDeviceDefParse(xml, vm->def,
|
2013-08-30 15:52:14 -05:00
|
|
|
cfg->caps, driver->xmlopt,
|
2013-04-29 10:59:42 -05:00
|
|
|
VIR_DOMAIN_XML_INACTIVE)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* Make a copy for updated domain. */
|
2013-08-30 15:52:14 -05:00
|
|
|
if (!(vmdef = virDomainObjCopyPersistentDef(vm, cfg->caps,
|
2013-04-29 10:59:42 -05:00
|
|
|
driver->xmlopt)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if ((ret = libxlDomainUpdateDeviceConfig(vmdef, dev)) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
} 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(xml, vm->def,
|
2013-08-30 15:52:14 -05:00
|
|
|
cfg->caps, driver->xmlopt,
|
2013-04-29 10:59:42 -05:00
|
|
|
VIR_DOMAIN_XML_INACTIVE)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if ((ret = libxlDomainUpdateDeviceLive(priv, vm, dev)) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* update domain status forcibly because the domain status may be
|
|
|
|
* changed even if we attach the device failed.
|
|
|
|
*/
|
2013-08-30 15:52:14 -05:00
|
|
|
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
|
2013-04-29 10:59:42 -05:00
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Finally, if no error until here, we can save config. */
|
|
|
|
if (!ret && (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG)) {
|
2013-08-30 15:52:14 -05:00
|
|
|
ret = virDomainSaveConfig(cfg->configDir, vmdef);
|
2013-04-29 10:59:42 -05:00
|
|
|
if (!ret) {
|
|
|
|
virDomainObjAssignDef(vm, vmdef, false, NULL);
|
|
|
|
vmdef = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virDomainDefFree(vmdef);
|
|
|
|
virDomainDeviceDefFree(dev);
|
|
|
|
if (vm)
|
|
|
|
virObjectUnlock(vm);
|
2013-08-30 15:52:14 -05:00
|
|
|
virObjectUnref(cfg);
|
2013-04-29 10:59:42 -05:00
|
|
|
return ret;
|
2011-05-26 10:27:06 -05:00
|
|
|
}
|
|
|
|
|
2011-03-21 04:35:53 -05:00
|
|
|
static unsigned long long
|
|
|
|
libxlNodeGetFreeMemory(virConnectPtr conn)
|
|
|
|
{
|
|
|
|
libxl_physinfo phy_info;
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
2013-08-30 15:52:14 -05:00
|
|
|
libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
|
|
|
|
unsigned long long ret = 0;
|
2011-03-21 04:35:53 -05:00
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virNodeGetFreeMemoryEnsureACL(conn) < 0)
|
2013-08-30 15:52:14 -05:00
|
|
|
goto cleanup;
|
2013-04-23 05:56:22 -05:00
|
|
|
|
2013-08-30 15:52:14 -05:00
|
|
|
if (libxl_get_physinfo(cfg->ctx, &phy_info)) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("libxl_get_physinfo_info failed"));
|
2013-08-30 15:52:14 -05:00
|
|
|
goto cleanup;
|
2011-03-21 04:35:53 -05:00
|
|
|
}
|
|
|
|
|
2013-08-30 15:52:14 -05:00
|
|
|
ret = phy_info.free_pages * cfg->verInfo->pagesize;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virObjectUnref(cfg);
|
|
|
|
return ret;
|
2011-03-21 04:35:53 -05:00
|
|
|
}
|
|
|
|
|
2013-06-28 09:32:52 -05:00
|
|
|
static int
|
|
|
|
libxlNodeGetCellsFreeMemory(virConnectPtr conn,
|
|
|
|
unsigned long long *freeMems,
|
|
|
|
int startCell,
|
|
|
|
int maxCells)
|
|
|
|
{
|
|
|
|
int n, lastCell, numCells;
|
|
|
|
int ret = -1, nr_nodes = 0;
|
|
|
|
libxl_numainfo *numa_info = NULL;
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
2013-08-30 15:52:14 -05:00
|
|
|
libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
|
2013-06-28 09:32:52 -05:00
|
|
|
|
|
|
|
if (virNodeGetCellsFreeMemoryEnsureACL(conn) < 0)
|
2013-08-30 15:52:14 -05:00
|
|
|
goto cleanup;
|
2013-06-28 09:32:52 -05:00
|
|
|
|
2013-08-30 15:52:14 -05:00
|
|
|
numa_info = libxl_get_numainfo(cfg->ctx, &nr_nodes);
|
2013-06-28 09:32:52 -05:00
|
|
|
if (numa_info == NULL || nr_nodes == 0) {
|
2013-08-09 04:05:58 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("libxl_get_numainfo failed"));
|
|
|
|
goto cleanup;
|
2013-06-28 09:32:52 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Check/sanitize the cell range */
|
2013-08-09 04:05:58 -05:00
|
|
|
if (startCell >= nr_nodes) {
|
2013-06-28 09:32:52 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("start cell %d out of range (0-%d)"),
|
2013-08-09 04:05:58 -05:00
|
|
|
startCell, nr_nodes - 1);
|
2013-06-28 09:32:52 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
lastCell = startCell + maxCells - 1;
|
2013-08-09 04:05:58 -05:00
|
|
|
if (lastCell >= nr_nodes)
|
|
|
|
lastCell = nr_nodes - 1;
|
2013-06-28 09:32:52 -05:00
|
|
|
|
|
|
|
for (numCells = 0, n = startCell; n <= lastCell; n++) {
|
|
|
|
if (numa_info[n].size == LIBXL_NUMAINFO_INVALID_ENTRY)
|
|
|
|
freeMems[numCells++] = 0;
|
|
|
|
else
|
|
|
|
freeMems[numCells++] = numa_info[n].free;
|
|
|
|
}
|
2013-08-14 16:33:48 -05:00
|
|
|
|
2013-06-28 09:32:52 -05:00
|
|
|
ret = numCells;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
libxl_numainfo_list_free(numa_info, nr_nodes);
|
2013-08-30 15:52:14 -05:00
|
|
|
virObjectUnref(cfg);
|
2013-06-28 09:32:52 -05:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-03-29 07:18:24 -05:00
|
|
|
static int
|
2013-04-23 07:50:18 -05:00
|
|
|
libxlConnectDomainEventRegister(virConnectPtr conn,
|
|
|
|
virConnectDomainEventCallback callback, void *opaque,
|
|
|
|
virFreeCallback freecb)
|
2011-03-29 07:18:24 -05:00
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
int ret;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virConnectDomainEventRegisterEnsureACL(conn) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2011-12-13 05:14:46 -06:00
|
|
|
ret = virDomainEventStateRegister(conn,
|
|
|
|
driver->domainEventState,
|
|
|
|
callback, opaque, freecb);
|
2011-03-29 07:18:24 -05:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2013-04-23 07:50:18 -05:00
|
|
|
libxlConnectDomainEventDeregister(virConnectPtr conn,
|
|
|
|
virConnectDomainEventCallback callback)
|
2011-03-29 07:18:24 -05:00
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
int ret;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virConnectDomainEventDeregisterEnsureACL(conn) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2011-05-12 09:47:08 -05:00
|
|
|
ret = virDomainEventStateDeregister(conn,
|
|
|
|
driver->domainEventState,
|
|
|
|
callback);
|
2011-03-29 07:18:24 -05:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-03-28 05:49:22 -05:00
|
|
|
static int
|
|
|
|
libxlDomainGetAutostart(virDomainPtr dom, int *autostart)
|
|
|
|
{
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-03-28 05:49:22 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainGetAutostartEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-03-28 05:49:22 -05:00
|
|
|
*autostart = vm->autostart;
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2011-03-28 05:49:22 -05:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainSetAutostart(virDomainPtr dom, int autostart)
|
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = dom->conn->privateData;
|
2013-08-30 15:52:14 -05:00
|
|
|
libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
|
2011-03-28 05:49:22 -05:00
|
|
|
virDomainObjPtr vm;
|
|
|
|
char *configFile = NULL, *autostartLink = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-03-28 05:49:22 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainSetAutostartEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-03-28 05:49:22 -05:00
|
|
|
if (!vm->persistent) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("cannot set autostart for transient domain"));
|
2011-03-28 05:49:22 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
autostart = (autostart != 0);
|
|
|
|
|
|
|
|
if (vm->autostart != autostart) {
|
2013-08-30 15:52:14 -05:00
|
|
|
if (!(configFile = virDomainConfigFile(cfg->configDir, vm->def->name)))
|
2011-03-28 05:49:22 -05:00
|
|
|
goto cleanup;
|
2013-08-30 15:52:14 -05:00
|
|
|
if (!(autostartLink = virDomainConfigFile(cfg->autostartDir, vm->def->name)))
|
2011-03-28 05:49:22 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (autostart) {
|
2013-08-30 15:52:14 -05:00
|
|
|
if (virFileMakePath(cfg->autostartDir) < 0) {
|
2011-07-05 16:02:53 -05:00
|
|
|
virReportSystemError(errno,
|
2011-03-28 05:49:22 -05:00
|
|
|
_("cannot create autostart directory %s"),
|
2013-08-30 15:52:14 -05:00
|
|
|
cfg->autostartDir);
|
2011-03-28 05:49:22 -05:00
|
|
|
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)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2013-08-30 15:52:14 -05:00
|
|
|
virObjectUnref(cfg);
|
2011-03-28 05:49:22 -05:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-03-29 07:46:55 -05:00
|
|
|
static char *
|
|
|
|
libxlDomainGetSchedulerType(virDomainPtr dom, int *nparams)
|
|
|
|
{
|
|
|
|
libxlDomainObjPrivatePtr priv;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
char * ret = NULL;
|
2013-05-03 07:42:47 -05:00
|
|
|
const char *name = NULL;
|
2012-11-26 10:28:56 -06:00
|
|
|
libxl_scheduler sched_id;
|
2011-03-29 07:46:55 -05:00
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-03-29 07:46:55 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainGetSchedulerTypeEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-03-29 07:46:55 -05:00
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
|
2011-03-29 07:46:55 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv = vm->privateData;
|
2012-11-26 10:28:56 -06:00
|
|
|
sched_id = libxl_get_scheduler(priv->ctx);
|
2011-03-29 07:46:55 -05:00
|
|
|
|
2011-05-18 02:55:32 -05:00
|
|
|
if (nparams)
|
|
|
|
*nparams = 0;
|
2012-10-17 04:23:12 -05:00
|
|
|
switch (sched_id) {
|
2012-11-26 10:28:56 -06:00
|
|
|
case LIBXL_SCHEDULER_SEDF:
|
2013-05-03 07:42:47 -05:00
|
|
|
name = "sedf";
|
2011-03-29 07:46:55 -05:00
|
|
|
break;
|
2012-11-26 10:28:56 -06:00
|
|
|
case LIBXL_SCHEDULER_CREDIT:
|
2013-05-03 07:42:47 -05:00
|
|
|
name = "credit";
|
2011-05-18 02:55:32 -05:00
|
|
|
if (nparams)
|
|
|
|
*nparams = XEN_SCHED_CREDIT_NPARAM;
|
2011-03-29 07:46:55 -05:00
|
|
|
break;
|
2012-11-26 10:28:56 -06:00
|
|
|
case LIBXL_SCHEDULER_CREDIT2:
|
2013-05-03 07:42:47 -05:00
|
|
|
name = "credit2";
|
2011-03-29 07:46:55 -05:00
|
|
|
break;
|
2012-11-26 10:28:56 -06:00
|
|
|
case LIBXL_SCHEDULER_ARINC653:
|
2013-05-03 07:42:47 -05:00
|
|
|
name = "arinc653";
|
2011-03-29 07:46:55 -05:00
|
|
|
break;
|
|
|
|
default:
|
2012-11-26 10:28:56 -06:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to get scheduler id for domain '%d'"
|
|
|
|
" with libxenlight"), dom->id);
|
2011-03-29 07:46:55 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-05-03 07:42:47 -05:00
|
|
|
ignore_value(VIR_STRDUP(ret, name));
|
2011-03-29 07:46:55 -05:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2011-03-29 07:46:55 -05:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-04-06 03:58:40 -05:00
|
|
|
static int
|
2011-05-17 17:33:53 -05:00
|
|
|
libxlDomainGetSchedulerParametersFlags(virDomainPtr dom,
|
|
|
|
virTypedParameterPtr params,
|
|
|
|
int *nparams,
|
|
|
|
unsigned int flags)
|
2011-04-06 03:58:40 -05:00
|
|
|
{
|
|
|
|
libxlDomainObjPrivatePtr priv;
|
|
|
|
virDomainObjPtr vm;
|
2012-11-26 10:28:56 -06:00
|
|
|
libxl_domain_sched_params sc_info;
|
|
|
|
libxl_scheduler sched_id;
|
2011-04-06 03:58:40 -05:00
|
|
|
int ret = -1;
|
|
|
|
|
2013-07-12 19:27:10 -05:00
|
|
|
virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
|
|
|
|
|
|
|
|
/* We don't return strings, and thus trivially support this flag. */
|
|
|
|
flags &= ~VIR_TYPED_PARAM_STRING_OKAY;
|
2011-05-17 17:33:53 -05:00
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-04-06 03:58:40 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainGetSchedulerParametersFlagsEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-04-06 03:58:40 -05:00
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-11-26 10:28:56 -06:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("Domain is not running"));
|
2011-04-06 03:58:40 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv = vm->privateData;
|
|
|
|
|
2012-11-26 10:28:56 -06:00
|
|
|
sched_id = libxl_get_scheduler(priv->ctx);
|
2011-04-06 03:58:40 -05:00
|
|
|
|
2012-11-26 10:28:56 -06:00
|
|
|
if (sched_id != LIBXL_SCHEDULER_CREDIT) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Only 'credit' scheduler is supported"));
|
2011-04-06 03:58:40 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2012-11-26 10:28:56 -06:00
|
|
|
if (libxl_domain_sched_params_get(priv->ctx, dom->id, &sc_info) != 0) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to get scheduler parameters for domain '%d'"
|
|
|
|
" with libxenlight"), dom->id);
|
2011-04-06 03:58:40 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2012-01-07 06:47:43 -06:00
|
|
|
if (virTypedParameterAssign(¶ms[0], VIR_DOMAIN_SCHEDULER_WEIGHT,
|
|
|
|
VIR_TYPED_PARAM_UINT, sc_info.weight) < 0)
|
2011-04-06 03:58:40 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
2011-11-02 12:42:38 -05:00
|
|
|
if (*nparams > 1) {
|
2012-01-07 06:47:43 -06:00
|
|
|
if (virTypedParameterAssign(¶ms[0], VIR_DOMAIN_SCHEDULER_CAP,
|
|
|
|
VIR_TYPED_PARAM_UINT, sc_info.cap) < 0)
|
2011-11-02 12:42:38 -05:00
|
|
|
goto cleanup;
|
2011-04-06 03:58:40 -05:00
|
|
|
}
|
|
|
|
|
2011-11-02 12:42:38 -05:00
|
|
|
if (*nparams > XEN_SCHED_CREDIT_NPARAM)
|
|
|
|
*nparams = XEN_SCHED_CREDIT_NPARAM;
|
2011-04-06 03:58:40 -05:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2011-04-06 03:58:40 -05:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2011-05-17 17:33:53 -05: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 03:58:40 -05:00
|
|
|
{
|
|
|
|
libxlDomainObjPrivatePtr priv;
|
|
|
|
virDomainObjPtr vm;
|
2012-11-26 10:28:56 -06:00
|
|
|
libxl_domain_sched_params sc_info;
|
2011-04-06 03:58:40 -05:00
|
|
|
int sched_id;
|
Convert 'int i' to 'size_t i' in src/libxl/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 09:09:33 -05:00
|
|
|
size_t i;
|
2011-04-06 03:58:40 -05:00
|
|
|
int ret = -1;
|
|
|
|
|
2011-05-17 17:33:53 -05:00
|
|
|
virCheckFlags(0, -1);
|
2013-05-03 08:34:10 -05:00
|
|
|
if (virTypedParamsValidate(params, nparams,
|
|
|
|
VIR_DOMAIN_SCHEDULER_WEIGHT,
|
|
|
|
VIR_TYPED_PARAM_UINT,
|
|
|
|
VIR_DOMAIN_SCHEDULER_CAP,
|
|
|
|
VIR_TYPED_PARAM_UINT,
|
|
|
|
NULL) < 0)
|
2012-01-07 06:47:43 -06:00
|
|
|
return -1;
|
2011-05-17 17:33:53 -05:00
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-04-06 03:58:40 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virDomainSetSchedulerParametersFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-04-06 03:58:40 -05:00
|
|
|
if (!virDomainObjIsActive(vm)) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
|
2011-04-06 03:58:40 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv = vm->privateData;
|
|
|
|
|
2012-11-26 10:28:56 -06:00
|
|
|
sched_id = libxl_get_scheduler(priv->ctx);
|
2011-04-06 03:58:40 -05:00
|
|
|
|
2012-11-26 10:28:56 -06:00
|
|
|
if (sched_id != LIBXL_SCHEDULER_CREDIT) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Only 'credit' scheduler is supported"));
|
2011-04-06 03:58:40 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2012-11-26 10:28:56 -06:00
|
|
|
if (libxl_domain_sched_params_get(priv->ctx, dom->id, &sc_info) != 0) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to get scheduler parameters for domain '%d'"
|
|
|
|
" with libxenlight"), dom->id);
|
2011-04-06 03:58:40 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < nparams; ++i) {
|
2011-05-26 12:39:04 -05:00
|
|
|
virTypedParameterPtr param = ¶ms[i];
|
2011-04-06 03:58:40 -05:00
|
|
|
|
2013-08-14 16:33:48 -05:00
|
|
|
if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_WEIGHT))
|
2011-04-06 03:58:40 -05:00
|
|
|
sc_info.weight = params[i].value.ui;
|
2013-08-14 16:33:48 -05:00
|
|
|
else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_CAP))
|
2011-04-06 03:58:40 -05:00
|
|
|
sc_info.cap = params[i].value.ui;
|
|
|
|
}
|
|
|
|
|
2012-11-26 10:28:56 -06:00
|
|
|
if (libxl_domain_sched_params_set(priv->ctx, dom->id, &sc_info) != 0) {
|
2012-07-18 08:32:10 -05:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to set scheduler parameters for domain '%d'"
|
|
|
|
" with libxenlight"), dom->id);
|
2011-04-06 03:58:40 -05:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2011-04-06 03:58:40 -05:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-07-25 22:30:50 -05:00
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainOpenConsole(virDomainPtr dom,
|
|
|
|
const char *dev_name,
|
|
|
|
virStreamPtr st,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
virDomainObjPtr vm = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
virDomainChrDefPtr chr = NULL;
|
|
|
|
libxlDomainObjPrivatePtr priv;
|
|
|
|
char *console = NULL;
|
|
|
|
|
|
|
|
virCheckFlags(VIR_DOMAIN_CONSOLE_FORCE, -1);
|
|
|
|
|
|
|
|
if (dev_name) {
|
|
|
|
/* XXX support device aliases in future */
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Named device aliases are not supported"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2013-07-25 22:30:50 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virDomainOpenConsoleEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!virDomainObjIsActive(vm)) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("domain is not running"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv = vm->privateData;
|
|
|
|
|
|
|
|
if (vm->def->nserials)
|
|
|
|
chr = vm->def->serials[0];
|
|
|
|
|
|
|
|
if (!chr) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("cannot find character device %s"),
|
|
|
|
NULLSTR(dev_name));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (chr->source.type != VIR_DOMAIN_CHR_TYPE_PTY) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("character device %s is not using a PTY"),
|
|
|
|
NULLSTR(dev_name));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = libxl_primary_console_get_tty(priv->ctx, vm->def->id, &console);
|
|
|
|
if (ret)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (VIR_STRDUP(chr->source.data.file.path, console) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* handle mutually exclusive access to console devices */
|
|
|
|
ret = virChrdevOpen(priv->devs,
|
|
|
|
&chr->source,
|
|
|
|
st,
|
|
|
|
(flags & VIR_DOMAIN_CONSOLE_FORCE) != 0);
|
|
|
|
|
|
|
|
if (ret == 1) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
|
|
|
|
_("Active console session exists for this domain"));
|
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(console);
|
|
|
|
if (vm)
|
|
|
|
virObjectUnlock(vm);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-05-17 17:33:53 -05:00
|
|
|
static int
|
|
|
|
libxlDomainSetSchedulerParameters(virDomainPtr dom, virTypedParameterPtr params,
|
|
|
|
int nparams)
|
|
|
|
{
|
|
|
|
return libxlDomainSetSchedulerParametersFlags(dom, params, nparams, 0);
|
|
|
|
}
|
|
|
|
|
2013-07-12 19:27:18 -05:00
|
|
|
/* NUMA node affinity information is available through libxl
|
|
|
|
* starting from Xen 4.3. */
|
|
|
|
#ifdef LIBXL_HAVE_DOMAIN_NODEAFFINITY
|
|
|
|
|
|
|
|
/* Number of Xen NUMA parameters */
|
|
|
|
# define LIBXL_NUMA_NPARAM 2
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainGetNumaParameters(virDomainPtr dom,
|
|
|
|
virTypedParameterPtr params,
|
|
|
|
int *nparams,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
libxlDomainObjPrivatePtr priv;
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
libxl_bitmap nodemap;
|
|
|
|
virBitmapPtr nodes = NULL;
|
|
|
|
char *nodeset = NULL;
|
|
|
|
int rc, ret = -1;
|
|
|
|
size_t i, j;
|
|
|
|
|
|
|
|
/* In Xen 4.3, it is possible to query the NUMA node affinity of a domain
|
|
|
|
* via libxl, but not to change it. We therefore only allow AFFECT_LIVE. */
|
|
|
|
virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
|
|
|
|
VIR_TYPED_PARAM_STRING_OKAY, -1);
|
|
|
|
|
|
|
|
/* We blindly return a string, and let libvirt.c and remote_driver.c do
|
|
|
|
* the filtering on behalf of older clients that can't parse it. */
|
|
|
|
flags &= ~VIR_TYPED_PARAM_STRING_OKAY;
|
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2013-07-12 19:27:18 -05:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virDomainGetNumaParametersEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!virDomainObjIsActive(vm)) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("Domain is not running"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv = vm->privateData;
|
|
|
|
|
|
|
|
libxl_bitmap_init(&nodemap);
|
|
|
|
|
|
|
|
if ((*nparams) == 0) {
|
|
|
|
*nparams = LIBXL_NUMA_NPARAM;
|
|
|
|
ret = 0;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < LIBXL_NUMA_NPARAM && i < *nparams; i++) {
|
|
|
|
virMemoryParameterPtr param = ¶ms[i];
|
|
|
|
|
|
|
|
switch (i) {
|
|
|
|
case 0:
|
|
|
|
/* NUMA mode */
|
|
|
|
|
|
|
|
/* Xen implements something that is really close to numactl's
|
|
|
|
* 'interleave' policy (see `man 8 numactl' for details). */
|
|
|
|
if (virTypedParameterAssign(param, VIR_DOMAIN_NUMA_MODE,
|
|
|
|
VIR_TYPED_PARAM_INT,
|
|
|
|
VIR_DOMAIN_NUMATUNE_MEM_INTERLEAVE) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
/* Node affinity */
|
|
|
|
|
|
|
|
/* Let's allocate both libxl and libvirt bitmaps */
|
|
|
|
if (libxl_node_bitmap_alloc(priv->ctx, &nodemap, 0) ||
|
|
|
|
!(nodes = virBitmapNew(libxl_get_max_nodes(priv->ctx)))) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = libxl_domain_get_nodeaffinity(priv->ctx,
|
|
|
|
vm->def->id,
|
|
|
|
&nodemap);
|
|
|
|
if (rc != 0) {
|
|
|
|
virReportSystemError(-rc, "%s",
|
|
|
|
_("unable to get numa affinity"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* First, we convert libxl_bitmap into virBitmap. After that,
|
|
|
|
* we format virBitmap as a string that can be returned. */
|
|
|
|
virBitmapClearAll(nodes);
|
|
|
|
libxl_for_each_set_bit(j, nodemap) {
|
|
|
|
if (virBitmapSetBit(nodes, j)) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Node %zu out of range"), j);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nodeset = virBitmapFormat(nodes);
|
|
|
|
if (!nodeset && VIR_STRDUP(nodeset, "") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virTypedParameterAssign(param, VIR_DOMAIN_NUMA_NODESET,
|
|
|
|
VIR_TYPED_PARAM_STRING, nodeset) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
nodeset = NULL;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*nparams > LIBXL_NUMA_NPARAM)
|
|
|
|
*nparams = LIBXL_NUMA_NPARAM;
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(nodeset);
|
|
|
|
virBitmapFree(nodes);
|
|
|
|
libxl_bitmap_dispose(&nodemap);
|
|
|
|
if (vm)
|
|
|
|
virObjectUnlock(vm);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
static int
|
|
|
|
libxlDomainIsActive(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
virDomainObjPtr obj;
|
|
|
|
int ret = -1;
|
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(obj = libxlDomObjFromDomain(dom)))
|
2011-02-10 16:42:34 -06:00
|
|
|
goto cleanup;
|
2013-04-23 05:56:22 -05:00
|
|
|
|
|
|
|
if (virDomainIsActiveEnsureACL(dom->conn, obj->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
ret = virDomainObjIsActive(obj);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (obj)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(obj);
|
2011-02-10 16:42:34 -06:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainIsPersistent(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
virDomainObjPtr obj;
|
|
|
|
int ret = -1;
|
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(obj = libxlDomObjFromDomain(dom)))
|
2011-02-10 16:42:34 -06:00
|
|
|
goto cleanup;
|
2013-04-23 05:56:22 -05:00
|
|
|
|
|
|
|
if (virDomainIsPersistentEnsureACL(dom->conn, obj->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
ret = obj->persistent;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (obj)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(obj);
|
2011-02-10 16:42:34 -06:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-04-06 03:58:39 -05:00
|
|
|
static int
|
|
|
|
libxlDomainIsUpdated(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
int ret = -1;
|
|
|
|
|
2013-08-30 15:58:31 -05:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-04-06 03:58:39 -05:00
|
|
|
goto cleanup;
|
2013-04-23 05:56:22 -05:00
|
|
|
|
|
|
|
if (virDomainIsUpdatedEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-04-06 03:58:39 -05:00
|
|
|
ret = vm->updated;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
2013-01-09 15:00:32 -06:00
|
|
|
virObjectUnlock(vm);
|
2011-04-06 03:58:39 -05:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-03-29 07:18:24 -05:00
|
|
|
static int
|
2013-04-23 07:50:18 -05:00
|
|
|
libxlConnectDomainEventRegisterAny(virConnectPtr conn, virDomainPtr dom, int eventID,
|
|
|
|
virConnectDomainEventGenericCallback callback,
|
|
|
|
void *opaque, virFreeCallback freecb)
|
2011-03-29 07:18:24 -05:00
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
int ret;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virConnectDomainEventRegisterAnyEnsureACL(conn) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2011-12-13 05:14:46 -06: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 17:38:54 -06:00
|
|
|
ret = -1;
|
2011-03-29 07:18:24 -05:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2013-04-23 07:50:18 -05:00
|
|
|
libxlConnectDomainEventDeregisterAny(virConnectPtr conn, int callbackID)
|
2011-03-29 07:18:24 -05:00
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
int ret;
|
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virConnectDomainEventDeregisterAnyEnsureACL(conn) < 0)
|
|
|
|
return -1;
|
|
|
|
|
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 17:38:54 -06:00
|
|
|
ret = virDomainEventStateDeregisterID(conn,
|
|
|
|
driver->domainEventState,
|
|
|
|
callbackID);
|
2011-03-29 07:18:24 -05:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-02-10 16:42:34 -06:00
|
|
|
|
2011-09-23 01:56:13 -05:00
|
|
|
static int
|
2013-04-23 07:50:18 -05:00
|
|
|
libxlConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
|
2011-09-23 01:56:13 -05:00
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2012-06-11 04:04:57 -05:00
|
|
|
static int
|
2013-04-23 07:50:18 -05:00
|
|
|
libxlConnectListAllDomains(virConnectPtr conn,
|
|
|
|
virDomainPtr **domains,
|
|
|
|
unsigned int flags)
|
2012-06-11 04:04:57 -05:00
|
|
|
{
|
|
|
|
libxlDriverPrivatePtr driver = conn->privateData;
|
|
|
|
int ret = -1;
|
|
|
|
|
2012-08-03 10:48:05 -05:00
|
|
|
virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
|
2012-06-11 04:04:57 -05:00
|
|
|
|
2013-04-23 05:56:22 -05:00
|
|
|
if (virConnectListAllDomainsEnsureACL(conn) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2013-06-24 11:49:47 -05:00
|
|
|
ret = virDomainObjListExport(driver->domains, conn, domains,
|
|
|
|
virConnectListAllDomainsCheckACL, flags);
|
2012-06-11 04:04:57 -05:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-07-12 19:27:10 -05:00
|
|
|
/* Which features are supported by this driver? */
|
|
|
|
static int
|
|
|
|
libxlConnectSupportsFeature(virConnectPtr conn, int feature)
|
|
|
|
{
|
|
|
|
if (virConnectSupportsFeatureEnsureACL(conn) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
switch (feature) {
|
|
|
|
case VIR_DRV_FEATURE_TYPED_PARAM_STRING:
|
|
|
|
return 1;
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2012-06-11 04:04:57 -05:00
|
|
|
|
2011-09-23 01:56:13 -05:00
|
|
|
|
2011-02-10 16:42:34 -06: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 05:16:31 -05:00
|
|
|
.no = VIR_DRV_LIBXL,
|
|
|
|
.name = "xenlight",
|
2013-04-23 07:50:18 -05:00
|
|
|
.connectOpen = libxlConnectOpen, /* 0.9.0 */
|
|
|
|
.connectClose = libxlConnectClose, /* 0.9.0 */
|
|
|
|
.connectGetType = libxlConnectGetType, /* 0.9.0 */
|
|
|
|
.connectGetVersion = libxlConnectGetVersion, /* 0.9.0 */
|
2013-04-26 11:39:11 -05:00
|
|
|
.connectGetHostname = libxlConnectGetHostname, /* 0.9.0 */
|
2013-06-25 08:25:29 -05:00
|
|
|
.connectGetSysinfo = libxlConnectGetSysinfo, /* 1.1.0 */
|
2013-04-23 07:50:18 -05:00
|
|
|
.connectGetMaxVcpus = libxlConnectGetMaxVcpus, /* 0.9.0 */
|
2011-05-13 08:35:01 -05:00
|
|
|
.nodeGetInfo = libxlNodeGetInfo, /* 0.9.0 */
|
2013-04-23 07:50:18 -05:00
|
|
|
.connectGetCapabilities = libxlConnectGetCapabilities, /* 0.9.0 */
|
|
|
|
.connectListDomains = libxlConnectListDomains, /* 0.9.0 */
|
|
|
|
.connectNumOfDomains = libxlConnectNumOfDomains, /* 0.9.0 */
|
|
|
|
.connectListAllDomains = libxlConnectListAllDomains, /* 0.9.13 */
|
2011-05-13 08:35:01 -05: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 12:31:55 -05:00
|
|
|
.domainShutdownFlags = libxlDomainShutdownFlags, /* 0.9.10 */
|
2011-05-13 08:35:01 -05:00
|
|
|
.domainReboot = libxlDomainReboot, /* 0.9.0 */
|
|
|
|
.domainDestroy = libxlDomainDestroy, /* 0.9.0 */
|
2011-07-20 11:47:46 -05:00
|
|
|
.domainDestroyFlags = libxlDomainDestroyFlags, /* 0.9.4 */
|
2011-05-13 08:35:01 -05:00
|
|
|
.domainGetOSType = libxlDomainGetOSType, /* 0.9.0 */
|
|
|
|
.domainGetMaxMemory = libxlDomainGetMaxMemory, /* 0.9.0 */
|
2011-05-30 04:53:03 -05:00
|
|
|
.domainSetMaxMemory = libxlDomainSetMaxMemory, /* 0.9.2 */
|
2011-05-13 08:35:01 -05:00
|
|
|
.domainSetMemory = libxlDomainSetMemory, /* 0.9.0 */
|
|
|
|
.domainSetMemoryFlags = libxlDomainSetMemoryFlags, /* 0.9.0 */
|
|
|
|
.domainGetInfo = libxlDomainGetInfo, /* 0.9.0 */
|
|
|
|
.domainGetState = libxlDomainGetState, /* 0.9.2 */
|
2011-05-30 04:53:02 -05: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-08 21:55:29 -05:00
|
|
|
.domainSaveFlags = libxlDomainSaveFlags, /* 0.9.4 */
|
2011-05-30 04:53:02 -05: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-08 21:55:29 -05:00
|
|
|
.domainRestoreFlags = libxlDomainRestoreFlags, /* 0.9.4 */
|
2011-05-30 04:53:01 -05:00
|
|
|
.domainCoreDump = libxlDomainCoreDump, /* 0.9.2 */
|
2011-05-13 08:35:01 -05: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 */
|
2013-04-23 07:50:18 -05:00
|
|
|
.connectDomainXMLFromNative = libxlConnectDomainXMLFromNative, /* 0.9.0 */
|
|
|
|
.connectDomainXMLToNative = libxlConnectDomainXMLToNative, /* 0.9.0 */
|
|
|
|
.connectListDefinedDomains = libxlConnectListDefinedDomains, /* 0.9.0 */
|
|
|
|
.connectNumOfDefinedDomains = libxlConnectNumOfDefinedDomains, /* 0.9.0 */
|
2011-05-13 08:35:01 -05:00
|
|
|
.domainCreate = libxlDomainCreate, /* 0.9.0 */
|
|
|
|
.domainCreateWithFlags = libxlDomainCreateWithFlags, /* 0.9.0 */
|
|
|
|
.domainDefineXML = libxlDomainDefineXML, /* 0.9.0 */
|
|
|
|
.domainUndefine = libxlDomainUndefine, /* 0.9.0 */
|
2011-07-19 22:05:20 -05:00
|
|
|
.domainUndefineFlags = libxlDomainUndefineFlags, /* 0.9.4 */
|
2011-05-26 10:27:06 -05: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 08:35:01 -05:00
|
|
|
.domainGetAutostart = libxlDomainGetAutostart, /* 0.9.0 */
|
|
|
|
.domainSetAutostart = libxlDomainSetAutostart, /* 0.9.0 */
|
|
|
|
.domainGetSchedulerType = libxlDomainGetSchedulerType, /* 0.9.0 */
|
|
|
|
.domainGetSchedulerParameters = libxlDomainGetSchedulerParameters, /* 0.9.0 */
|
2011-05-17 17:33:53 -05:00
|
|
|
.domainGetSchedulerParametersFlags = libxlDomainGetSchedulerParametersFlags, /* 0.9.2 */
|
2011-05-13 08:35:01 -05:00
|
|
|
.domainSetSchedulerParameters = libxlDomainSetSchedulerParameters, /* 0.9.0 */
|
2011-05-17 17:33:53 -05:00
|
|
|
.domainSetSchedulerParametersFlags = libxlDomainSetSchedulerParametersFlags, /* 0.9.2 */
|
2013-07-12 19:27:18 -05:00
|
|
|
#ifdef LIBXL_HAVE_DOMAIN_NODEAFFINITY
|
|
|
|
.domainGetNumaParameters = libxlDomainGetNumaParameters, /* 1.1.1 */
|
|
|
|
#endif
|
2011-05-13 08:35:01 -05:00
|
|
|
.nodeGetFreeMemory = libxlNodeGetFreeMemory, /* 0.9.0 */
|
2013-06-28 09:32:52 -05:00
|
|
|
.nodeGetCellsFreeMemory = libxlNodeGetCellsFreeMemory, /* 1.1.1 */
|
2013-04-23 07:50:18 -05:00
|
|
|
.connectDomainEventRegister = libxlConnectDomainEventRegister, /* 0.9.0 */
|
|
|
|
.connectDomainEventDeregister = libxlConnectDomainEventDeregister, /* 0.9.0 */
|
2011-06-02 07:39:40 -05:00
|
|
|
.domainManagedSave = libxlDomainManagedSave, /* 0.9.2 */
|
|
|
|
.domainHasManagedSaveImage = libxlDomainHasManagedSaveImage, /* 0.9.2 */
|
|
|
|
.domainManagedSaveRemove = libxlDomainManagedSaveRemove, /* 0.9.2 */
|
2013-07-25 22:30:50 -05:00
|
|
|
.domainOpenConsole = libxlDomainOpenConsole, /* 1.1.2 */
|
2011-05-13 08:35:01 -05:00
|
|
|
.domainIsActive = libxlDomainIsActive, /* 0.9.0 */
|
|
|
|
.domainIsPersistent = libxlDomainIsPersistent, /* 0.9.0 */
|
|
|
|
.domainIsUpdated = libxlDomainIsUpdated, /* 0.9.0 */
|
2013-04-23 07:50:18 -05:00
|
|
|
.connectDomainEventRegisterAny = libxlConnectDomainEventRegisterAny, /* 0.9.0 */
|
|
|
|
.connectDomainEventDeregisterAny = libxlConnectDomainEventDeregisterAny, /* 0.9.0 */
|
|
|
|
.connectIsAlive = libxlConnectIsAlive, /* 0.9.8 */
|
2013-07-12 19:27:10 -05:00
|
|
|
.connectSupportsFeature = libxlConnectSupportsFeature, /* 1.1.1 */
|
2011-02-10 16:42:34 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
static virStateDriver libxlStateDriver = {
|
|
|
|
.name = "LIBXL",
|
2013-04-23 07:50:18 -05:00
|
|
|
.stateInitialize = libxlStateInitialize,
|
2013-07-25 07:03:38 -05:00
|
|
|
.stateAutoStart = libxlStateAutoStart,
|
2013-04-23 07:50:18 -05:00
|
|
|
.stateCleanup = libxlStateCleanup,
|
|
|
|
.stateReload = libxlStateReload,
|
2011-02-10 16:42:34 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
libxlRegister(void)
|
|
|
|
{
|
|
|
|
if (virRegisterDriver(&libxlDriver) < 0)
|
|
|
|
return -1;
|
|
|
|
if (virRegisterStateDriver(&libxlStateDriver) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|