2013-09-03 23:43:00 -06:00
|
|
|
/*
|
|
|
|
* libxl_driver.c: core driver methods for managing libxenlight domains
|
|
|
|
*
|
2015-05-08 12:55:00 -04:00
|
|
|
* Copyright (C) 2006-2015 Red Hat, Inc.
|
2015-02-02 14:12:58 -07:00
|
|
|
* Copyright (C) 2011-2015 SUSE LINUX Products GmbH, Nuernberg, Germany.
|
2013-09-03 23:43:00 -06:00
|
|
|
* Copyright (C) 2011 Univention GmbH.
|
2011-02-10 15:42:34 -07: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 16:30:55 -06:00
|
|
|
* License along with this library. If not, see
|
2012-07-21 18:06:23 +08:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2011-02-10 15:42:34 -07:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <libxl.h>
|
2013-07-13 02:27:18 +02:00
|
|
|
#include <libxl_utils.h>
|
2016-07-26 00:45:14 +01:00
|
|
|
#include <xenstore.h>
|
2011-05-30 11:53:02 +02:00
|
|
|
#include <fcntl.h>
|
2011-02-10 15:42:34 -07:00
|
|
|
|
|
|
|
#include "internal.h"
|
2012-12-12 17:59:27 +00:00
|
|
|
#include "virlog.h"
|
2012-12-13 18:21:53 +00:00
|
|
|
#include "virerror.h"
|
2012-12-12 16:35:35 +00:00
|
|
|
#include "virconf.h"
|
2011-02-10 15:42:34 -07:00
|
|
|
#include "datatypes.h"
|
2011-07-19 12:32:58 -06:00
|
|
|
#include "virfile.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.h"
|
2012-12-13 18:01:25 +00:00
|
|
|
#include "viruuid.h"
|
2016-07-11 13:55:53 +02:00
|
|
|
#include "virhook.h"
|
2012-12-12 16:27:01 +00:00
|
|
|
#include "vircommand.h"
|
2021-03-25 17:26:03 +01:00
|
|
|
#include "libxl_api_wrapper.h"
|
2013-08-30 11:18:31 -06:00
|
|
|
#include "libxl_domain.h"
|
2011-02-10 15:42:34 -07:00
|
|
|
#include "libxl_driver.h"
|
|
|
|
#include "libxl_conf.h"
|
2016-03-04 11:35:20 -07:00
|
|
|
#include "libxl_capabilities.h"
|
2014-05-08 15:56:51 -06:00
|
|
|
#include "libxl_migration.h"
|
2011-03-29 20:39:18 +08:00
|
|
|
#include "xen_xm.h"
|
2014-12-15 21:30:06 -07:00
|
|
|
#include "xen_xl.h"
|
2012-01-07 05:47:43 -07:00
|
|
|
#include "virtypedparam.h"
|
2012-02-24 19:48:55 +01:00
|
|
|
#include "viruri.h"
|
2013-04-03 12:36:23 +02:00
|
|
|
#include "virstring.h"
|
2013-06-12 09:49:27 -06:00
|
|
|
#include "virsysinfo.h"
|
2013-04-23 11:56:22 +01:00
|
|
|
#include "viraccessapicheck.h"
|
2014-03-06 17:46:11 +08:00
|
|
|
#include "virhostdev.h"
|
2019-05-23 11:34:08 +01:00
|
|
|
#include "virpidfile.h"
|
2015-04-14 14:38:46 -06:00
|
|
|
#include "locking/domain_lock.h"
|
2016-11-18 23:51:15 +01:00
|
|
|
#include "virnetdevtap.h"
|
2016-07-20 20:08:48 +01:00
|
|
|
#include "cpu/cpu.h"
|
2020-02-16 22:59:28 +01:00
|
|
|
#include "virutil.h"
|
2020-12-10 21:38:07 -03:00
|
|
|
#include "domain_validate.h"
|
2021-01-04 09:54:26 -03:00
|
|
|
#include "domain_driver.h"
|
2011-02-10 15:42:34 -07:00
|
|
|
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_LIBXL
|
|
|
|
|
2014-02-28 12:16:17 +00:00
|
|
|
VIR_LOG_INIT("libxl.libxl_driver");
|
|
|
|
|
2011-02-10 15:42:34 -07:00
|
|
|
#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
|
|
|
|
|
2015-11-13 13:14:41 +00:00
|
|
|
#define LIBXL_NB_TOTAL_CPU_STAT_PARAM 1
|
2016-07-26 00:45:14 +01:00
|
|
|
#define LIBXL_NB_TOTAL_BLK_STAT_PARAM 6
|
2015-11-13 13:14:41 +00:00
|
|
|
|
2014-03-17 12:14:11 +00:00
|
|
|
#define HYPERVISOR_CAPABILITIES "/proc/xen/capabilities"
|
2015-05-24 18:42:41 +03:00
|
|
|
#define HYPERVISOR_XENSTORED "/dev/xen/xenstored"
|
2014-03-17 12:14:11 +00:00
|
|
|
|
2020-01-29 12:05:15 +01:00
|
|
|
/* Number of Xen scheduler parameters. credit and credit2 both support 2 */
|
2011-03-29 20:46:55 +08:00
|
|
|
#define XEN_SCHED_CREDIT_NPARAM 2
|
|
|
|
|
2017-11-03 13:09:47 +01:00
|
|
|
#define LIBXL_CHECK_DOM0_GOTO(name, label) \
|
|
|
|
do { \
|
|
|
|
if (STREQ_NULLABLE(name, "Domain-0")) { \
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s", \
|
2015-06-22 11:36:59 -06:00
|
|
|
_("Domain-0 does not support requested operation")); \
|
2017-11-03 13:09:47 +01:00
|
|
|
goto label; \
|
|
|
|
} \
|
2015-06-22 11:36:59 -06:00
|
|
|
} while (0)
|
|
|
|
|
2013-01-11 13:54:15 +00:00
|
|
|
|
2021-03-11 08:16:13 +01:00
|
|
|
static libxlDriverPrivate *libxl_driver;
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2015-02-02 14:12:58 -07:00
|
|
|
/* Object used to store info related to libxl event registrations */
|
|
|
|
typedef struct _libxlOSEventHookInfo libxlOSEventHookInfo;
|
|
|
|
struct _libxlOSEventHookInfo {
|
|
|
|
libxl_ctx *ctx;
|
|
|
|
void *xl_priv;
|
|
|
|
int id;
|
|
|
|
};
|
|
|
|
|
2016-07-26 00:45:14 +01:00
|
|
|
/* Object used to store disk statistics across multiple xen backends */
|
|
|
|
typedef struct _libxlBlockStats libxlBlockStats;
|
|
|
|
struct _libxlBlockStats {
|
|
|
|
long long rd_req;
|
|
|
|
long long rd_bytes;
|
|
|
|
long long wr_req;
|
|
|
|
long long wr_bytes;
|
|
|
|
long long f_req;
|
|
|
|
|
|
|
|
char *backend;
|
|
|
|
union {
|
|
|
|
struct {
|
|
|
|
long long ds_req;
|
|
|
|
long long oo_req;
|
|
|
|
} vbd;
|
|
|
|
} u;
|
|
|
|
};
|
|
|
|
|
2011-02-10 15:42:34 -07:00
|
|
|
/* Function declarations */
|
2013-01-11 13:54:15 +00:00
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDomainManagedSaveLoad(virDomainObj *vm,
|
2013-01-15 15:44:58 -07:00
|
|
|
void *opaque);
|
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
|
|
|
|
/* Function definitions */
|
2015-02-02 14:12:58 -07:00
|
|
|
static void
|
|
|
|
libxlOSEventHookInfoFree(void *obj)
|
|
|
|
{
|
2021-02-03 14:40:15 -05:00
|
|
|
g_free(obj);
|
2015-02-02 14:12:58 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-10-14 14:45:33 +02:00
|
|
|
libxlFDEventCallback(int watch G_GNUC_UNUSED,
|
2015-02-02 14:12:58 -07:00
|
|
|
int fd,
|
|
|
|
int vir_events,
|
|
|
|
void *fd_info)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlOSEventHookInfo *info = fd_info;
|
2015-02-02 14:12:58 -07:00
|
|
|
int events = 0;
|
|
|
|
|
|
|
|
if (vir_events & VIR_EVENT_HANDLE_READABLE)
|
|
|
|
events |= POLLIN;
|
|
|
|
if (vir_events & VIR_EVENT_HANDLE_WRITABLE)
|
|
|
|
events |= POLLOUT;
|
|
|
|
if (vir_events & VIR_EVENT_HANDLE_ERROR)
|
|
|
|
events |= POLLERR;
|
|
|
|
if (vir_events & VIR_EVENT_HANDLE_HANGUP)
|
|
|
|
events |= POLLHUP;
|
|
|
|
|
|
|
|
libxl_osevent_occurred_fd(info->ctx, info->xl_priv, fd, 0, events);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlFDRegisterEventHook(void *priv,
|
|
|
|
int fd,
|
|
|
|
void **hndp,
|
|
|
|
short events,
|
|
|
|
void *xl_priv)
|
|
|
|
{
|
|
|
|
int vir_events = VIR_EVENT_HANDLE_ERROR;
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlOSEventHookInfo *info;
|
2015-02-02 14:12:58 -07:00
|
|
|
|
2020-09-23 20:43:09 +02:00
|
|
|
info = g_new0(libxlOSEventHookInfo, 1);
|
2015-02-02 14:12:58 -07:00
|
|
|
|
|
|
|
info->ctx = priv;
|
|
|
|
info->xl_priv = xl_priv;
|
|
|
|
|
|
|
|
if (events & POLLIN)
|
|
|
|
vir_events |= VIR_EVENT_HANDLE_READABLE;
|
|
|
|
if (events & POLLOUT)
|
|
|
|
vir_events |= VIR_EVENT_HANDLE_WRITABLE;
|
|
|
|
|
|
|
|
info->id = virEventAddHandle(fd, vir_events, libxlFDEventCallback,
|
|
|
|
info, libxlOSEventHookInfoFree);
|
|
|
|
if (info->id < 0) {
|
|
|
|
VIR_FREE(info);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
*hndp = info;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2019-10-14 14:45:33 +02:00
|
|
|
libxlFDModifyEventHook(void *priv G_GNUC_UNUSED,
|
|
|
|
int fd G_GNUC_UNUSED,
|
2015-02-02 14:12:58 -07:00
|
|
|
void **hndp,
|
|
|
|
short events)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlOSEventHookInfo *info = *hndp;
|
2015-02-02 14:12:58 -07:00
|
|
|
int vir_events = VIR_EVENT_HANDLE_ERROR;
|
|
|
|
|
|
|
|
if (events & POLLIN)
|
|
|
|
vir_events |= VIR_EVENT_HANDLE_READABLE;
|
|
|
|
if (events & POLLOUT)
|
|
|
|
vir_events |= VIR_EVENT_HANDLE_WRITABLE;
|
|
|
|
|
|
|
|
virEventUpdateHandle(info->id, vir_events);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-10-14 14:45:33 +02:00
|
|
|
libxlFDDeregisterEventHook(void *priv G_GNUC_UNUSED,
|
|
|
|
int fd G_GNUC_UNUSED,
|
2015-02-02 14:12:58 -07:00
|
|
|
void *hnd)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlOSEventHookInfo *info = hnd;
|
2015-02-02 14:12:58 -07:00
|
|
|
|
|
|
|
virEventRemoveHandle(info->id);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-10-14 14:45:33 +02:00
|
|
|
libxlTimerCallback(int timer G_GNUC_UNUSED, void *timer_info)
|
2015-02-02 14:12:58 -07:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlOSEventHookInfo *info = timer_info;
|
2015-02-02 14:12:58 -07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* libxl expects the event to be deregistered when calling
|
|
|
|
* libxl_osevent_occurred_timeout, but we dont want the event info
|
|
|
|
* destroyed. Disable the timeout and only remove it after returning
|
|
|
|
* from libxl.
|
|
|
|
*/
|
|
|
|
virEventUpdateTimeout(info->id, -1);
|
|
|
|
libxl_osevent_occurred_timeout(info->ctx, info->xl_priv);
|
|
|
|
virEventRemoveTimeout(info->id);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlTimeoutRegisterEventHook(void *priv,
|
|
|
|
void **hndp,
|
|
|
|
struct timeval abs_t,
|
|
|
|
void *xl_priv)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlOSEventHookInfo *info;
|
2019-12-20 16:19:30 +00:00
|
|
|
gint64 now_us;
|
|
|
|
gint64 abs_us;
|
|
|
|
gint64 res_ms;
|
2015-02-02 14:12:58 -07:00
|
|
|
int timeout;
|
|
|
|
|
2020-09-23 20:43:09 +02:00
|
|
|
info = g_new0(libxlOSEventHookInfo, 1);
|
2015-02-02 14:12:58 -07:00
|
|
|
|
|
|
|
info->ctx = priv;
|
|
|
|
info->xl_priv = xl_priv;
|
|
|
|
|
2019-12-20 16:19:30 +00:00
|
|
|
now_us = g_get_real_time();
|
|
|
|
abs_us = (abs_t.tv_sec * (1000LL*1000LL)) + abs_t.tv_usec;
|
|
|
|
if (now_us >= abs_us) {
|
2015-02-02 14:12:58 -07:00
|
|
|
timeout = 0;
|
|
|
|
} else {
|
2019-12-20 16:19:30 +00:00
|
|
|
res_ms = (abs_us - now_us) / 1000;
|
|
|
|
if (res_ms > INT_MAX)
|
|
|
|
timeout = INT_MAX;
|
|
|
|
else
|
|
|
|
timeout = res_ms;
|
2015-02-02 14:12:58 -07:00
|
|
|
}
|
|
|
|
info->id = virEventAddTimeout(timeout, libxlTimerCallback,
|
|
|
|
info, libxlOSEventHookInfoFree);
|
|
|
|
if (info->id < 0) {
|
|
|
|
VIR_FREE(info);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
*hndp = info;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Note: There are two changes wrt timeouts starting with xen-unstable
|
|
|
|
* changeset 26469:
|
|
|
|
*
|
|
|
|
* 1. Timeout modify callbacks will only be invoked with an abs_t of {0,0},
|
|
|
|
* i.e. make the timeout fire immediately. Prior to this commit, timeout
|
|
|
|
* modify callbacks were never invoked.
|
|
|
|
*
|
|
|
|
* 2. Timeout deregister hooks will no longer be called.
|
|
|
|
*/
|
|
|
|
static int
|
2019-10-14 14:45:33 +02:00
|
|
|
libxlTimeoutModifyEventHook(void *priv G_GNUC_UNUSED,
|
2015-02-02 14:12:58 -07:00
|
|
|
void **hndp,
|
2019-10-14 14:45:33 +02:00
|
|
|
struct timeval abs_t G_GNUC_UNUSED)
|
2015-02-02 14:12:58 -07:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlOSEventHookInfo *info = *hndp;
|
2015-02-02 14:12:58 -07:00
|
|
|
|
|
|
|
/* Make the timeout fire */
|
|
|
|
virEventUpdateTimeout(info->id, 0);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-10-14 14:45:33 +02:00
|
|
|
libxlTimeoutDeregisterEventHook(void *priv G_GNUC_UNUSED,
|
2015-02-02 14:12:58 -07:00
|
|
|
void *hnd)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlOSEventHookInfo *info = hnd;
|
2015-02-02 14:12:58 -07:00
|
|
|
|
|
|
|
virEventRemoveTimeout(info->id);
|
|
|
|
}
|
|
|
|
|
2021-03-11 08:16:13 +01:00
|
|
|
static virDomainObj *
|
2013-08-30 14:58:31 -06:00
|
|
|
libxlDomObjFromDomain(virDomainPtr dom)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainObj *vm;
|
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
2013-08-30 14:58:31 -06:00
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
|
2018-03-09 10:47:46 -05:00
|
|
|
vm = virDomainObjListFindByUUID(driver->domains, dom->uuid);
|
2013-08-30 14:58:31 -06:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-01-11 13:54:15 +00:00
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlAutostartDomain(virDomainObj *vm,
|
2011-03-28 12:49:22 +02:00
|
|
|
void *opaque)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = opaque;
|
2013-01-11 13:54:15 +00:00
|
|
|
int ret = -1;
|
2011-03-28 12:49:22 +02:00
|
|
|
|
2016-06-12 18:30:00 +08:00
|
|
|
virObjectRef(vm);
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectLock(vm);
|
2011-03-28 12:49:22 +02:00
|
|
|
virResetLastError();
|
|
|
|
|
2016-06-12 18:30:00 +08:00
|
|
|
if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
|
|
|
|
goto cleanup;
|
2015-03-01 18:24:26 -07:00
|
|
|
|
2011-03-28 12:49:22 +02:00
|
|
|
if (vm->autostart && !virDomainObjIsActive(vm) &&
|
libxl: support Xen migration stream V2 in save/restore
Xen 4.6 introduced a new migration stream commonly referred to as
"migration V2". Xen 4.6 and newer always produce this new stream,
whereas Xen 4.5 and older always produce the legacy stream.
Support for migration stream V2 can be detected at build time with
LIBXL_HAVE_SRM_V2 from libxl.h. The legacy and V2 streams are not
compatible, but a V2 host can accept and convert a legacy stream.
Commit e7440656 changed the libxl driver to use the lowest libxl
API version possible (version 0x040200) to ensure the driver
builds against older Xen releases. The old 4.2 restore API does
not support specifying a stream version and assumes a legacy
stream, even if the incoming stream is migration V2. Thinking it
has been given a legacy stream, libxl will fail to convert an
incoming stream that is already V2, which causes the entire
restore operation to fail. Xen's libvirt-related OSSTest has been
failing since commit e7440656 landed in libvirt.git master. One
of the more recent failures can be seen here
http://lists.xenproject.org/archives/html/xen-devel/2016-05/msg00071.html
This patch changes the call to libxl_domain_create_restore() to
include the stream version if LIBXL_HAVE_SRM_V2 is defined. The
version field of the libxlSavefileHeader struct is also updated
to '2' when LIBXL_HAVE_SRM_V2 is defined, ensuring the stream
version in the header matches the actual stream version produced
by Xen. Along with bumping the libxl API requirement to 0x040400,
this patch fixes save/restore on a migration V2 Xen host.
Oddly, migration has never used the libxlSavefileHeader. It
handles passing configuration in the Begin and Prepare phases,
and then calls libxl directly to transfer domain state/memory
in the Perform phase. A subsequent patch will add stream
version handling in the Begin and Prepare phase handshaking,
which will fix the migration related OSSTest failures.
Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2016-05-02 12:00:39 -06:00
|
|
|
libxlDomainStartNew(driver, vm, false) < 0) {
|
2016-05-23 20:35:57 +02:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to autostart VM '%s': %s"),
|
|
|
|
vm->def->name, virGetLastErrorMessage());
|
2015-03-01 18:24:26 -07:00
|
|
|
goto endjob;
|
2011-03-28 12:49:22 +02:00
|
|
|
}
|
|
|
|
|
2013-01-11 13:54:15 +00:00
|
|
|
ret = 0;
|
2015-03-01 18:24:26 -07:00
|
|
|
|
|
|
|
endjob:
|
2016-06-12 18:30:00 +08:00
|
|
|
libxlDomainObjEndJob(driver, vm);
|
|
|
|
cleanup:
|
|
|
|
virDomainObjEndAPI(&vm);
|
2015-03-01 18:24:26 -07:00
|
|
|
|
2013-01-11 13:54:15 +00:00
|
|
|
return ret;
|
2011-03-28 12:49:22 +02:00
|
|
|
}
|
|
|
|
|
2019-02-01 17:11:22 +00:00
|
|
|
|
|
|
|
static void
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlReconnectNotifyNets(virDomainDef *def)
|
2019-02-01 17:11:22 +00:00
|
|
|
{
|
|
|
|
size_t i;
|
2021-01-08 00:31:05 -05:00
|
|
|
g_autoptr(virConnect) conn = NULL;
|
2019-02-01 17:11:22 +00:00
|
|
|
|
|
|
|
for (i = 0; i < def->nnets; i++) {
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainNetDef *net = def->nets[i];
|
2019-02-01 17:11:22 +00:00
|
|
|
/* keep others from trying to use the macvtap device name, but
|
|
|
|
* don't return error if this happens, since that causes the
|
|
|
|
* domain to be unceremoniously killed, which would be *very*
|
|
|
|
* impolite.
|
|
|
|
*/
|
|
|
|
if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_DIRECT)
|
2020-12-14 09:50:34 +08:00
|
|
|
virNetDevReserveName(net->ifname);
|
2019-02-01 17:11:22 +00:00
|
|
|
|
2021-01-08 00:36:31 -05:00
|
|
|
if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK && !conn)
|
|
|
|
conn = virGetConnectNetwork();
|
|
|
|
|
|
|
|
virDomainNetNotifyActualDevice(conn, def, net);
|
2019-02-01 17:11:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-02-10 15:42:34 -07:00
|
|
|
/*
|
|
|
|
* Reconnect to running domains that were previously started/created
|
|
|
|
* with libxenlight driver.
|
|
|
|
*/
|
2013-01-11 13:54:15 +00:00
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlReconnectDomain(virDomainObj *vm,
|
2011-02-10 15:42:34 -07:00
|
|
|
void *opaque)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = opaque;
|
|
|
|
libxlDomainObjPrivate *priv = vm->privateData;
|
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
2011-02-10 15:42:34 -07:00
|
|
|
int rc;
|
|
|
|
libxl_dominfo d_info;
|
|
|
|
int len;
|
|
|
|
uint8_t *data = NULL;
|
2021-03-11 08:16:13 +01:00
|
|
|
virHostdevManager *hostdev_mgr = driver->hostdevMgr;
|
2016-05-19 16:14:33 +08:00
|
|
|
unsigned int hostdev_flags = VIR_HOSTDEV_SP_PCI;
|
2016-07-27 14:46:41 +02:00
|
|
|
int ret = -1;
|
2016-05-19 16:14:33 +08:00
|
|
|
|
|
|
|
#ifdef LIBXL_HAVE_PVUSB
|
|
|
|
hostdev_flags |= VIR_HOSTDEV_SP_USB;
|
|
|
|
#endif
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2016-07-27 14:46:41 +02:00
|
|
|
virObjectRef(vm);
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectLock(vm);
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2016-01-21 10:21:10 +00:00
|
|
|
libxl_dominfo_init(&d_info);
|
|
|
|
|
2011-02-10 15:42:34 -07:00
|
|
|
/* Does domain still exist? */
|
2015-02-11 16:40:07 -07:00
|
|
|
rc = libxl_domain_info(cfg->ctx, &d_info, vm->def->id);
|
2011-02-10 15:42:34 -07:00
|
|
|
if (rc == ERROR_INVAL) {
|
2016-07-27 14:46:41 +02:00
|
|
|
goto error;
|
2011-02-10 15:42:34 -07:00
|
|
|
} else if (rc != 0) {
|
|
|
|
VIR_DEBUG("libxl_domain_info failed (code %d), ignoring domain %d",
|
|
|
|
rc, vm->def->id);
|
2016-07-27 14:46:41 +02:00
|
|
|
goto error;
|
2011-02-10 15:42:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Is this a domain that was under libvirt control? */
|
2015-02-11 16:40:07 -07:00
|
|
|
if (libxl_userdata_retrieve(cfg->ctx, vm->def->id,
|
2011-02-10 15:42:34 -07:00
|
|
|
"libvirt-xml", &data, &len)) {
|
|
|
|
VIR_DEBUG("libxl_userdata_retrieve failed, ignoring domain %d", vm->def->id);
|
2016-07-27 14:46:41 +02:00
|
|
|
goto error;
|
2011-02-10 15:42:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Update domid in case it changed (e.g. reboot) while we were gone? */
|
|
|
|
vm->def->id = d_info.domid;
|
2014-03-06 17:46:11 +08:00
|
|
|
|
2017-01-09 16:20:50 +01:00
|
|
|
libxlLoggerOpenFile(cfg->logger, vm->def->id, vm->def->name, NULL);
|
|
|
|
|
2014-03-06 17:46:11 +08:00
|
|
|
/* Update hostdev state */
|
2020-05-04 15:20:37 -06:00
|
|
|
if (virHostdevUpdateActiveDomainDevices(hostdev_mgr, LIBXL_DRIVER_INTERNAL_NAME,
|
2016-05-19 16:14:33 +08:00
|
|
|
vm->def, hostdev_flags) < 0)
|
2016-07-27 14:46:41 +02:00
|
|
|
goto error;
|
2014-03-06 17:46:11 +08:00
|
|
|
|
2018-09-07 21:29:56 +02:00
|
|
|
if (d_info.shutdown &&
|
|
|
|
d_info.shutdown_reason == LIBXL_SHUTDOWN_REASON_SUSPEND)
|
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_PMSUSPENDED,
|
|
|
|
VIR_DOMAIN_PMSUSPENDED_UNKNOWN);
|
|
|
|
else if (d_info.paused)
|
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_PAUSED,
|
|
|
|
VIR_DOMAIN_PAUSED_UNKNOWN);
|
|
|
|
else
|
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
|
|
|
|
VIR_DOMAIN_RUNNING_UNKNOWN);
|
|
|
|
|
2020-01-31 17:04:24 +01:00
|
|
|
if (g_atomic_int_add(&driver->nactive, 1) == 0 && driver->inhibitCallback)
|
2012-10-31 19:03:55 +00:00
|
|
|
driver->inhibitCallback(true, driver->inhibitOpaque);
|
|
|
|
|
2015-02-12 12:02:27 -07:00
|
|
|
/* Enable domain death events */
|
2015-02-11 16:40:07 -07:00
|
|
|
libxl_evenable_domain_death(cfg->ctx, vm->def->id, 0, &priv->deathW);
|
2015-02-12 12:02:27 -07:00
|
|
|
|
2019-02-01 17:11:22 +00:00
|
|
|
libxlReconnectNotifyNets(vm->def);
|
|
|
|
|
2019-11-27 12:53:10 +00:00
|
|
|
if (virDomainObjSave(vm, driver->xmlopt, cfg->stateDir) < 0)
|
2019-02-01 17:40:41 +00:00
|
|
|
VIR_WARN("Cannot update XML for running Xen guest %s", vm->def->name);
|
|
|
|
|
2016-07-11 13:55:53 +02:00
|
|
|
/* now that we know it's reconnected call the hook if present */
|
|
|
|
if (virHookPresent(VIR_HOOK_DRIVER_LIBXL) &&
|
|
|
|
STRNEQ("Domain-0", vm->def->name)) {
|
2019-11-27 11:57:34 +00:00
|
|
|
char *xml = virDomainDefFormat(vm->def, driver->xmlopt, 0);
|
2016-07-11 13:55:53 +02:00
|
|
|
int hookret;
|
|
|
|
|
|
|
|
/* we can't stop the operation even if the script raised an error */
|
|
|
|
hookret = virHookCall(VIR_HOOK_DRIVER_LIBXL, vm->def->name,
|
|
|
|
VIR_HOOK_LIBXL_OP_RECONNECT, VIR_HOOK_SUBOP_BEGIN,
|
|
|
|
NULL, xml, NULL);
|
|
|
|
VIR_FREE(xml);
|
|
|
|
if (hookret < 0) {
|
|
|
|
/* Stop the domain if the hook failed */
|
|
|
|
if (virDomainObjIsActive(vm)) {
|
|
|
|
libxlDomainDestroyInternal(driver, vm);
|
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_FAILED);
|
|
|
|
}
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-27 14:46:41 +02:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
2016-01-21 10:21:10 +00:00
|
|
|
libxl_dominfo_dispose(&d_info);
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(vm);
|
2016-07-27 14:46:41 +02:00
|
|
|
virObjectUnref(vm);
|
2015-02-11 16:40:07 -07:00
|
|
|
virObjectUnref(cfg);
|
2016-07-27 14:46:41 +02:00
|
|
|
return ret;
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2016-07-27 14:46:41 +02:00
|
|
|
error:
|
2015-07-07 12:29:24 -06:00
|
|
|
libxlDomainCleanup(driver, vm);
|
2018-04-23 10:40:48 -04:00
|
|
|
if (!vm->persistent)
|
2013-06-13 03:54:09 +02:00
|
|
|
virDomainObjListRemoveLocked(driver->domains, vm);
|
2016-07-27 14:46:41 +02:00
|
|
|
goto cleanup;
|
2011-02-10 15:42:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlReconnectDomains(libxlDriverPrivate *driver)
|
2011-02-10 15:42:34 -07:00
|
|
|
{
|
2019-09-06 13:59:59 +02:00
|
|
|
virDomainObjListForEach(driver->domains, true, libxlReconnectDomain, driver);
|
2011-02-10 15:42:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-04-23 13:50:18 +01:00
|
|
|
libxlStateCleanup(void)
|
2011-02-10 15:42:34 -07:00
|
|
|
{
|
|
|
|
if (!libxl_driver)
|
|
|
|
return -1;
|
|
|
|
|
2014-03-06 17:46:11 +08:00
|
|
|
virObjectUnref(libxl_driver->hostdevMgr);
|
2013-03-31 20:03:42 +02:00
|
|
|
virObjectUnref(libxl_driver->xmlopt);
|
2013-01-11 13:54:15 +00:00
|
|
|
virObjectUnref(libxl_driver->domains);
|
2018-02-06 12:09:06 +03:00
|
|
|
virPortAllocatorRangeFree(libxl_driver->reservedGraphicsPorts);
|
|
|
|
virPortAllocatorRangeFree(libxl_driver->migrationPorts);
|
2015-04-14 14:38:46 -06:00
|
|
|
virLockManagerPluginUnref(libxl_driver->lockManager);
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2016-10-11 09:48:36 +02:00
|
|
|
virObjectUnref(libxl_driver->domainEventState);
|
2013-06-12 09:49:27 -06:00
|
|
|
virSysinfoDefFree(libxl_driver->hostsysinfo);
|
2011-03-29 20:18:24 +08:00
|
|
|
|
2019-05-23 11:34:08 +01:00
|
|
|
if (libxl_driver->lockFD != -1)
|
|
|
|
virPidFileRelease(libxl_driver->config->stateDir, "driver", libxl_driver->lockFD);
|
|
|
|
|
|
|
|
virObjectUnref(libxl_driver->config);
|
2011-02-10 15:42:34 -07:00
|
|
|
virMutexDestroy(&libxl_driver->lock);
|
|
|
|
VIR_FREE(libxl_driver);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-08-30 12:34:48 -06:00
|
|
|
static bool
|
|
|
|
libxlDriverShouldLoad(bool privileged)
|
2012-10-31 19:03:55 +00:00
|
|
|
{
|
2013-08-30 12:34:48 -06:00
|
|
|
/* Don't load if non-root */
|
2011-02-10 15:42:34 -07:00
|
|
|
if (!privileged) {
|
2011-05-09 17:24:09 +08:00
|
|
|
VIR_INFO("Not running privileged, disabling libxenlight driver");
|
2019-07-10 11:43:04 +01:00
|
|
|
return false;
|
2011-02-10 15:42:34 -07:00
|
|
|
}
|
|
|
|
|
2015-05-24 18:42:41 +03:00
|
|
|
if (virFileExists(HYPERVISOR_CAPABILITIES)) {
|
|
|
|
int status;
|
2021-02-16 18:37:09 -07:00
|
|
|
g_autofree char *output = NULL;
|
2015-05-24 18:42:41 +03:00
|
|
|
/*
|
|
|
|
* Don't load if not running on a Xen control domain (dom0). It is not
|
|
|
|
* sufficient to check for the file to exist as any guest can mount
|
|
|
|
* xenfs to /proc/xen.
|
|
|
|
*/
|
|
|
|
status = virFileReadAll(HYPERVISOR_CAPABILITIES, 10, &output);
|
|
|
|
if (status >= 0)
|
|
|
|
status = strncmp(output, "control_d", 9);
|
|
|
|
if (status) {
|
|
|
|
VIR_INFO("No Xen capabilities detected, probably not running "
|
|
|
|
"in a Xen Dom0. Disabling libxenlight driver");
|
|
|
|
|
2019-07-10 11:43:04 +01:00
|
|
|
return false;
|
2015-05-24 18:42:41 +03:00
|
|
|
}
|
|
|
|
} else if (!virFileExists(HYPERVISOR_XENSTORED)) {
|
|
|
|
VIR_INFO("Disabling driver as neither " HYPERVISOR_CAPABILITIES
|
|
|
|
" nor " HYPERVISOR_XENSTORED " exist");
|
2019-07-10 11:43:04 +01:00
|
|
|
return false;
|
2013-08-30 12:34:48 -06:00
|
|
|
}
|
|
|
|
|
2019-07-10 11:43:04 +01:00
|
|
|
return true;
|
2013-08-30 12:34:48 -06:00
|
|
|
}
|
|
|
|
|
2015-02-02 14:12:58 -07:00
|
|
|
/* Callbacks wrapping libvirt's event loop interface */
|
|
|
|
static const libxl_osevent_hooks libxl_osevent_callbacks = {
|
|
|
|
.fd_register = libxlFDRegisterEventHook,
|
|
|
|
.fd_modify = libxlFDModifyEventHook,
|
|
|
|
.fd_deregister = libxlFDDeregisterEventHook,
|
|
|
|
.timeout_register = libxlTimeoutRegisterEventHook,
|
|
|
|
.timeout_modify = libxlTimeoutModifyEventHook,
|
|
|
|
.timeout_deregister = libxlTimeoutDeregisterEventHook,
|
|
|
|
};
|
|
|
|
|
2015-02-02 16:19:34 -07:00
|
|
|
static const libxl_childproc_hooks libxl_child_hooks = {
|
|
|
|
#ifdef LIBXL_HAVE_SIGCHLD_OWNER_SELECTIVE_REAP
|
|
|
|
.chldowner = libxl_sigchld_owner_libxl_always_selective_reap,
|
|
|
|
#else
|
|
|
|
.chldowner = libxl_sigchld_owner_libxl,
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
2015-02-12 11:37:46 -07:00
|
|
|
const struct libxl_event_hooks ev_hooks = {
|
|
|
|
.event_occurs_mask = LIBXL_EVENTMASK_ALL,
|
|
|
|
.event_occurs = libxlDomainEventHandler,
|
|
|
|
.disaster = NULL,
|
|
|
|
};
|
|
|
|
|
2015-06-22 11:36:59 -06:00
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlAddDom0(libxlDriverPrivate *driver)
|
2015-06-22 11:36:59 -06:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
|
|
|
virDomainDef *def = NULL;
|
|
|
|
virDomainObj *vm = NULL;
|
2015-06-22 11:36:59 -06:00
|
|
|
libxl_dominfo d_info;
|
2017-01-31 17:10:34 -07:00
|
|
|
unsigned long long maxmem;
|
2015-06-22 11:36:59 -06:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
libxl_dominfo_init(&d_info);
|
|
|
|
|
|
|
|
/* Ensure we have a dom0 */
|
|
|
|
if (libxl_domain_info(cfg->ctx, &d_info, 0) != 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("unable to get Domain-0 information from libxenlight"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2020-09-11 11:35:47 -06:00
|
|
|
/*
|
|
|
|
* On a driver reload dom0 will already exist. On host restart it must
|
|
|
|
* created.
|
|
|
|
*/
|
|
|
|
if ((vm = virDomainObjListFindByID(driver->domains, 0)) == NULL) {
|
|
|
|
if (!(def = virDomainDefNew()))
|
|
|
|
goto cleanup;
|
2015-06-22 11:36:59 -06:00
|
|
|
|
2020-09-11 11:35:47 -06:00
|
|
|
def->id = 0;
|
|
|
|
def->virtType = VIR_DOMAIN_VIRT_XEN;
|
|
|
|
def->name = g_strdup("Domain-0");
|
2015-06-22 11:36:59 -06:00
|
|
|
|
2020-09-11 11:35:47 -06:00
|
|
|
def->os.type = VIR_DOMAIN_OSTYPE_XEN;
|
2015-06-22 11:36:59 -06:00
|
|
|
|
2020-09-11 11:35:47 -06:00
|
|
|
if (virUUIDParse("00000000-0000-0000-0000-000000000000", def->uuid) < 0)
|
|
|
|
goto cleanup;
|
2015-06-22 11:36:59 -06:00
|
|
|
|
2020-09-11 11:35:47 -06:00
|
|
|
if (!(vm = virDomainObjListAdd(driver->domains, def,
|
|
|
|
driver->xmlopt,
|
|
|
|
0,
|
|
|
|
NULL)))
|
|
|
|
goto cleanup;
|
|
|
|
|
2020-09-24 10:39:13 -06:00
|
|
|
def = NULL;
|
2020-09-11 11:35:47 -06:00
|
|
|
vm->persistent = 1;
|
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_BOOTED);
|
|
|
|
}
|
2015-06-22 11:36:59 -06:00
|
|
|
|
2016-06-29 14:55:24 +02:00
|
|
|
if (virDomainDefSetVcpusMax(vm->def, d_info.vcpu_max_id + 1, driver->xmlopt))
|
2015-10-16 16:10:27 +02:00
|
|
|
goto cleanup;
|
|
|
|
|
2015-10-22 10:52:05 +02:00
|
|
|
if (virDomainDefSetVcpus(vm->def, d_info.vcpu_online) < 0)
|
|
|
|
goto cleanup;
|
2015-06-22 11:36:59 -06:00
|
|
|
vm->def->mem.cur_balloon = d_info.current_memkb;
|
2017-01-31 17:10:34 -07:00
|
|
|
if (libxlDriverGetDom0MaxmemConf(cfg, &maxmem) < 0)
|
|
|
|
maxmem = d_info.current_memkb;
|
|
|
|
virDomainDefSetMemoryTotal(vm->def, maxmem);
|
2015-06-22 11:36:59 -06:00
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
libxl_dominfo_dispose(&d_info);
|
|
|
|
virDomainDefFree(def);
|
2018-04-23 10:40:48 -04:00
|
|
|
virDomainObjEndAPI(&vm);
|
2015-06-22 11:36:59 -06:00
|
|
|
virObjectUnref(cfg);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-08-30 12:34:48 -06:00
|
|
|
static int
|
|
|
|
libxlStateInitialize(bool privileged,
|
2019-05-17 12:30:45 +01:00
|
|
|
const char *root,
|
2020-01-18 03:37:42 +01:00
|
|
|
virStateInhibitCallback callback,
|
|
|
|
void *opaque)
|
2013-08-30 12:34:48 -06:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverConfig *cfg;
|
2020-02-22 13:02:27 +01:00
|
|
|
g_autofree char *driverConf = NULL;
|
2019-10-05 09:15:24 +02:00
|
|
|
bool autostart = true;
|
2013-08-30 12:34:48 -06:00
|
|
|
|
2019-05-17 12:30:45 +01:00
|
|
|
if (root != NULL) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("Driver does not support embedded mode"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-08-30 12:34:48 -06:00
|
|
|
if (!libxlDriverShouldLoad(privileged))
|
2019-07-23 13:05:18 +01:00
|
|
|
return VIR_DRV_STATE_INIT_SKIPPED;
|
2013-08-30 12:34:48 -06:00
|
|
|
|
2020-09-23 20:43:09 +02:00
|
|
|
libxl_driver = g_new0(libxlDriverPrivate, 1);
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2019-05-23 11:34:08 +01:00
|
|
|
libxl_driver->lockFD = -1;
|
2011-02-10 15:42:34 -07:00
|
|
|
if (virMutexInit(&libxl_driver->lock) < 0) {
|
2013-08-30 12:34:48 -06:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("cannot initialize mutex"));
|
2011-02-10 15:42:34 -07:00
|
|
|
VIR_FREE(libxl_driver);
|
2019-07-23 13:05:18 +01:00
|
|
|
return VIR_DRV_STATE_INIT_ERROR;
|
2011-02-10 15:42:34 -07:00
|
|
|
}
|
|
|
|
|
2020-01-18 03:37:42 +01:00
|
|
|
libxl_driver->inhibitCallback = callback;
|
|
|
|
libxl_driver->inhibitOpaque = opaque;
|
|
|
|
|
2011-02-10 15:42:34 -07:00
|
|
|
/* Allocate bitmap for vnc port reservation */
|
2015-04-27 18:53:04 -06:00
|
|
|
if (!(libxl_driver->reservedGraphicsPorts =
|
2018-02-06 12:09:06 +03:00
|
|
|
virPortAllocatorRangeNew(_("VNC"),
|
|
|
|
LIBXL_VNC_PORT_MIN,
|
2018-02-06 12:09:09 +03:00
|
|
|
LIBXL_VNC_PORT_MAX)))
|
2013-01-11 12:09:53 +00:00
|
|
|
goto error;
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2014-05-08 15:56:51 -06:00
|
|
|
/* Allocate bitmap for migration port reservation */
|
|
|
|
if (!(libxl_driver->migrationPorts =
|
2018-02-06 12:09:06 +03:00
|
|
|
virPortAllocatorRangeNew(_("migration"),
|
|
|
|
LIBXL_MIGRATION_PORT_MIN,
|
2018-02-06 12:09:09 +03:00
|
|
|
LIBXL_MIGRATION_PORT_MAX)))
|
2014-05-08 15:56:51 -06:00
|
|
|
goto error;
|
|
|
|
|
2013-01-11 16:04:47 +00:00
|
|
|
if (!(libxl_driver->domains = virDomainObjListNew()))
|
|
|
|
goto error;
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2014-03-06 17:46:11 +08:00
|
|
|
if (!(libxl_driver->hostdevMgr = virHostdevManagerGetDefault()))
|
|
|
|
goto error;
|
|
|
|
|
2013-08-30 14:52:14 -06:00
|
|
|
if (!(cfg = libxlDriverConfigNew()))
|
2013-06-07 15:20:35 +02:00
|
|
|
goto error;
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2020-04-03 15:51:48 -06:00
|
|
|
if (libxlDriverConfigInit(cfg) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2019-10-22 15:26:14 +02:00
|
|
|
driverConf = g_strdup_printf("%s/libxl.conf", cfg->configBaseDir);
|
2013-09-09 09:15:15 -06:00
|
|
|
|
|
|
|
if (libxlDriverConfigLoadFile(cfg, driverConf) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2015-02-02 14:12:58 -07:00
|
|
|
/* Register the callbacks providing access to libvirt's event loop */
|
|
|
|
libxl_osevent_register_hooks(cfg->ctx, &libxl_osevent_callbacks, cfg->ctx);
|
|
|
|
|
2015-02-02 16:19:34 -07:00
|
|
|
/* Setup child process handling. See $xen-src/tools/libxl/libxl_event.h */
|
|
|
|
libxl_childproc_setmode(cfg->ctx, &libxl_child_hooks, cfg->ctx);
|
|
|
|
|
2015-02-12 11:37:46 -07:00
|
|
|
/* Register callback to handle domain events */
|
|
|
|
libxl_event_register_callbacks(cfg->ctx, &ev_hooks, libxl_driver);
|
|
|
|
|
2013-08-30 14:52:14 -06:00
|
|
|
libxl_driver->config = cfg;
|
2021-02-26 09:37:10 +01:00
|
|
|
if (g_mkdir_with_parents(cfg->stateDir, 0777) < 0) {
|
2013-08-30 12:34:48 -06:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("failed to create state dir '%s': %s"),
|
2013-08-30 14:52:14 -06:00
|
|
|
cfg->stateDir,
|
2020-02-26 18:57:34 +01:00
|
|
|
g_strerror(errno));
|
2011-02-10 15:42:34 -07:00
|
|
|
goto error;
|
|
|
|
}
|
2021-02-26 09:37:10 +01:00
|
|
|
if (g_mkdir_with_parents(cfg->libDir, 0777) < 0) {
|
2013-08-30 12:34:48 -06:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("failed to create lib dir '%s': %s"),
|
2013-08-30 14:52:14 -06:00
|
|
|
cfg->libDir,
|
2020-02-26 18:57:34 +01:00
|
|
|
g_strerror(errno));
|
2011-02-10 15:42:34 -07:00
|
|
|
goto error;
|
|
|
|
}
|
2021-02-26 09:37:10 +01:00
|
|
|
if (g_mkdir_with_parents(cfg->saveDir, 0777) < 0) {
|
2013-08-30 12:34:48 -06:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("failed to create save dir '%s': %s"),
|
2013-08-30 14:52:14 -06:00
|
|
|
cfg->saveDir,
|
2020-02-26 18:57:34 +01:00
|
|
|
g_strerror(errno));
|
2011-02-10 15:42:34 -07:00
|
|
|
goto error;
|
|
|
|
}
|
2021-02-26 09:37:10 +01:00
|
|
|
if (g_mkdir_with_parents(cfg->autoDumpDir, 0777) < 0) {
|
2014-02-19 16:09:36 -07:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("failed to create dump dir '%s': %s"),
|
|
|
|
cfg->autoDumpDir,
|
2020-02-26 18:57:34 +01:00
|
|
|
g_strerror(errno));
|
2014-02-19 16:09:36 -07:00
|
|
|
goto error;
|
|
|
|
}
|
2021-02-26 09:37:10 +01:00
|
|
|
if (g_mkdir_with_parents(cfg->channelDir, 0777) < 0) {
|
libxl: channels support
And allow libxl to handle channel element which creates a Xen
console visible to the guest as a low-bandwitdh communication
channel. If type is PTY we also fetch the tty after boot using
libxl_channel_getinfo to fetch the tty path. On socket case,
we autogenerate a path if not specified in the XML. Path autogenerated
is slightly different from qemu driver: qemu stores also on
"channels/target" but it creates then a directory per domain with
each channel target name. libxl doesn't appear to have a clear
definition of private files associated with each domain, so for
simplicity we do it slightly different. On qemu each autogenerated
channel goes like:
channels/target/<domain-name>/<target name>
Whereas for libxl:
channels/target/<domain-name>-<target name>
Should note that if path is not specified it won't persist,
existing only on live XML, unless user had initially specified it.
Since support for libxl channels only came on Xen >= 4.5 we therefore
need to conditionally compile it with LIBXL_HAVE_DEVICE_CHANNEL.
After this patch and having a qemu guest agent:
$ cat domain.xml | grep -a1 channel | head -n 5 | tail -n 4
<channel type='unix'>
<source mode='bind' path='/tmp/channel'/>
<target type='xen' name='org.qemu.guest_agent.0'/>
</channel>
$ virsh create domain.xml
$ echo '{"execute":"guest-network-get-interfaces"}' | socat
stdio,ignoreeof unix-connect:/tmp/channel
{"execute":"guest-network-get-interfaces"}
{"return": [{"name": "lo", "ip-addresses": [{"ip-address-type": "ipv4",
"ip-address": "127.0.0.1", "prefix": 8}, {"ip-address-type": "ipv6",
"ip-address": "::1", "prefix": 128}], "hardware-address":
"00:00:00:00:00:00"}, {"name": "eth0", "ip-addresses":
[{"ip-address-type": "ipv4", "ip-address": "10.100.0.6", "prefix": 24},
{"ip-address-type": "ipv6", "ip-address": "fe80::216:3eff:fe40:88eb",
"prefix": 64}], "hardware-address": "00:16:3e:40:88:eb"}, {"name":
"sit0"}]}
Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2016-09-26 18:33:16 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("failed to create channel dir '%s': %s"),
|
|
|
|
cfg->channelDir,
|
2020-02-26 18:57:34 +01:00
|
|
|
g_strerror(errno));
|
libxl: channels support
And allow libxl to handle channel element which creates a Xen
console visible to the guest as a low-bandwitdh communication
channel. If type is PTY we also fetch the tty after boot using
libxl_channel_getinfo to fetch the tty path. On socket case,
we autogenerate a path if not specified in the XML. Path autogenerated
is slightly different from qemu driver: qemu stores also on
"channels/target" but it creates then a directory per domain with
each channel target name. libxl doesn't appear to have a clear
definition of private files associated with each domain, so for
simplicity we do it slightly different. On qemu each autogenerated
channel goes like:
channels/target/<domain-name>/<target name>
Whereas for libxl:
channels/target/<domain-name>-<target name>
Should note that if path is not specified it won't persist,
existing only on live XML, unless user had initially specified it.
Since support for libxl channels only came on Xen >= 4.5 we therefore
need to conditionally compile it with LIBXL_HAVE_DEVICE_CHANNEL.
After this patch and having a qemu guest agent:
$ cat domain.xml | grep -a1 channel | head -n 5 | tail -n 4
<channel type='unix'>
<source mode='bind' path='/tmp/channel'/>
<target type='xen' name='org.qemu.guest_agent.0'/>
</channel>
$ virsh create domain.xml
$ echo '{"execute":"guest-network-get-interfaces"}' | socat
stdio,ignoreeof unix-connect:/tmp/channel
{"execute":"guest-network-get-interfaces"}
{"return": [{"name": "lo", "ip-addresses": [{"ip-address-type": "ipv4",
"ip-address": "127.0.0.1", "prefix": 8}, {"ip-address-type": "ipv6",
"ip-address": "::1", "prefix": 128}], "hardware-address":
"00:00:00:00:00:00"}, {"name": "eth0", "ip-addresses":
[{"ip-address-type": "ipv4", "ip-address": "10.100.0.6", "prefix": 24},
{"ip-address-type": "ipv6", "ip-address": "fe80::216:3eff:fe40:88eb",
"prefix": 64}], "hardware-address": "00:16:3e:40:88:eb"}, {"name":
"sit0"}]}
Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2016-09-26 18:33:16 +01:00
|
|
|
goto error;
|
|
|
|
}
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2019-05-23 11:34:08 +01:00
|
|
|
if ((libxl_driver->lockFD =
|
2019-07-11 15:57:34 +01:00
|
|
|
virPidFileAcquire(cfg->stateDir, "driver", false, getpid())) < 0)
|
2019-05-23 11:34:08 +01:00
|
|
|
goto error;
|
|
|
|
|
2015-04-14 14:38:46 -06:00
|
|
|
if (!(libxl_driver->lockManager =
|
|
|
|
virLockManagerPluginNew(cfg->lockManagerName ?
|
|
|
|
cfg->lockManagerName : "nop",
|
|
|
|
"libxl",
|
|
|
|
cfg->configBaseDir,
|
|
|
|
0)))
|
|
|
|
goto error;
|
|
|
|
|
2013-06-12 09:49:27 -06:00
|
|
|
/* read the host sysinfo */
|
2013-09-04 16:59:59 -06:00
|
|
|
libxl_driver->hostsysinfo = virSysinfoRead();
|
2013-06-12 09:49:27 -06:00
|
|
|
|
2013-11-21 11:43:10 +01:00
|
|
|
libxl_driver->domainEventState = virObjectEventStateNew();
|
2011-05-13 11:21:59 -06:00
|
|
|
if (!libxl_driver->domainEventState)
|
2011-03-29 20:18:24 +08:00
|
|
|
goto error;
|
|
|
|
|
2013-08-30 14:52:14 -06:00
|
|
|
if ((cfg->caps = libxlMakeCapabilities(cfg->ctx)) == NULL) {
|
2013-08-30 12:34:48 -06:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("cannot create capabilities for libxenlight"));
|
2011-02-10 15:42:34 -07:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2019-12-03 10:49:49 +00:00
|
|
|
if (!(libxl_driver->xmlopt = libxlCreateXMLConf(libxl_driver)))
|
2013-03-05 16:17:24 +01:00
|
|
|
goto error;
|
2011-02-10 15:42:34 -07:00
|
|
|
|
|
|
|
/* Load running domains first. */
|
2013-01-11 16:04:47 +00:00
|
|
|
if (virDomainObjListLoadAllConfigs(libxl_driver->domains,
|
2013-08-30 14:52:14 -06:00
|
|
|
cfg->stateDir,
|
|
|
|
cfg->autostartDir,
|
2017-11-08 15:17:33 +01:00
|
|
|
true,
|
2013-03-28 14:55:55 +01:00
|
|
|
libxl_driver->xmlopt,
|
2013-01-11 16:04:47 +00:00
|
|
|
NULL, NULL) < 0)
|
2011-02-10 15:42:34 -07:00
|
|
|
goto error;
|
|
|
|
|
2020-09-11 11:35:47 -06:00
|
|
|
/* Add Domain-0 */
|
|
|
|
if (libxlAddDom0(libxl_driver) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2011-02-10 15:42:34 -07:00
|
|
|
libxlReconnectDomains(libxl_driver);
|
|
|
|
|
|
|
|
/* Then inactive persistent configs */
|
2013-01-11 16:04:47 +00:00
|
|
|
if (virDomainObjListLoadAllConfigs(libxl_driver->domains,
|
2013-08-30 14:52:14 -06:00
|
|
|
cfg->configDir,
|
|
|
|
cfg->autostartDir,
|
2017-11-08 15:17:33 +01:00
|
|
|
false,
|
2013-03-28 14:55:55 +01:00
|
|
|
libxl_driver->xmlopt,
|
2013-01-11 16:04:47 +00:00
|
|
|
NULL, NULL) < 0)
|
2011-02-10 15:42:34 -07:00
|
|
|
goto error;
|
|
|
|
|
2019-10-05 09:15:24 +02:00
|
|
|
if (virDriverShouldAutostart(cfg->stateDir, &autostart) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (autostart) {
|
|
|
|
virDomainObjListForEach(libxl_driver->domains, false,
|
|
|
|
libxlAutostartDomain,
|
|
|
|
libxl_driver);
|
|
|
|
}
|
2019-03-01 15:16:45 +01:00
|
|
|
|
2019-09-06 13:59:59 +02:00
|
|
|
virDomainObjListForEach(libxl_driver->domains, false,
|
|
|
|
libxlDomainManagedSaveLoad,
|
2013-01-11 13:54:15 +00:00
|
|
|
libxl_driver);
|
2012-06-11 11:03:27 +02:00
|
|
|
|
2019-07-23 13:05:18 +01:00
|
|
|
return VIR_DRV_STATE_INIT_COMPLETE;
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
error:
|
2013-04-23 13:50:18 +01:00
|
|
|
libxlStateCleanup();
|
2019-07-23 13:05:18 +01:00
|
|
|
return VIR_DRV_STATE_INIT_ERROR;
|
2011-02-10 15:42:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-04-23 13:50:18 +01:00
|
|
|
libxlStateReload(void)
|
2011-02-10 15:42:34 -07:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverConfig *cfg;
|
2013-08-30 14:52:14 -06:00
|
|
|
|
2011-02-10 15:42:34 -07:00
|
|
|
if (!libxl_driver)
|
|
|
|
return 0;
|
|
|
|
|
2013-08-30 14:52:14 -06:00
|
|
|
cfg = libxlDriverConfigGet(libxl_driver);
|
|
|
|
|
2013-01-11 16:04:47 +00:00
|
|
|
virDomainObjListLoadAllConfigs(libxl_driver->domains,
|
2013-08-30 14:52:14 -06:00
|
|
|
cfg->configDir,
|
|
|
|
cfg->autostartDir,
|
2017-11-08 15:17:33 +01:00
|
|
|
true,
|
2013-03-28 14:55:55 +01:00
|
|
|
libxl_driver->xmlopt,
|
2013-01-11 16:04:47 +00:00
|
|
|
NULL, libxl_driver);
|
|
|
|
|
2019-09-06 13:59:59 +02:00
|
|
|
virDomainObjListForEach(libxl_driver->domains, false,
|
|
|
|
libxlAutostartDomain,
|
2013-01-11 13:54:15 +00:00
|
|
|
libxl_driver);
|
2011-03-28 12:49:22 +02:00
|
|
|
|
2013-08-30 14:52:14 -06:00
|
|
|
virObjectUnref(cfg);
|
2011-02-10 15:42:34 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-03-27 17:24:44 +01:00
|
|
|
static int
|
|
|
|
libxlConnectURIProbe(char **uri)
|
|
|
|
{
|
|
|
|
if (libxl_driver == NULL)
|
|
|
|
return 0;
|
|
|
|
|
2019-10-20 12:41:35 +02:00
|
|
|
*uri = g_strdup("xen:///system");
|
|
|
|
return 1;
|
2018-03-27 17:24:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-02-10 15:42:34 -07:00
|
|
|
static virDrvOpenStatus
|
2013-04-23 13:50:18 +01:00
|
|
|
libxlConnectOpen(virConnectPtr conn,
|
2019-10-14 14:45:33 +02:00
|
|
|
virConnectAuthPtr auth G_GNUC_UNUSED,
|
2021-03-11 08:16:13 +01:00
|
|
|
virConf *conf G_GNUC_UNUSED,
|
2013-04-23 13:50:18 +01:00
|
|
|
unsigned int flags)
|
2011-02-10 15:42:34 -07:00
|
|
|
{
|
2011-07-06 16:17:10 -06:00
|
|
|
virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
|
|
|
|
|
2018-03-28 12:49:29 +01:00
|
|
|
/* Error if xen or libxl scheme specified but driver not started. */
|
|
|
|
if (libxl_driver == NULL) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("libxenlight state driver is not active"));
|
|
|
|
return VIR_DRV_OPEN_ERROR;
|
|
|
|
}
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2018-03-28 12:49:29 +01:00
|
|
|
/* /session isn't supported in libxenlight */
|
2018-03-28 14:25:23 +01:00
|
|
|
if (STRNEQ(conn->uri->path, "") &&
|
2018-03-28 12:49:29 +01:00
|
|
|
STRNEQ(conn->uri->path, "/") &&
|
|
|
|
STRNEQ(conn->uri->path, "/system")) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unexpected Xen URI path '%s', try xen:///system"),
|
2018-03-28 14:25:23 +01:00
|
|
|
conn->uri->path);
|
2018-03-28 12:49:29 +01:00
|
|
|
return VIR_DRV_OPEN_ERROR;
|
2011-02-10 15:42:34 -07:00
|
|
|
}
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virConnectOpenEnsureACL(conn) < 0)
|
|
|
|
return VIR_DRV_OPEN_ERROR;
|
|
|
|
|
2011-02-10 15:42:34 -07:00
|
|
|
conn->privateData = libxl_driver;
|
|
|
|
|
|
|
|
return VIR_DRV_OPEN_SUCCESS;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
2019-10-14 14:45:33 +02:00
|
|
|
libxlConnectClose(virConnectPtr conn G_GNUC_UNUSED)
|
2011-02-10 15:42:34 -07:00
|
|
|
{
|
|
|
|
conn->privateData = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *
|
2013-04-23 11:56:22 +01:00
|
|
|
libxlConnectGetType(virConnectPtr conn)
|
2011-02-10 15:42:34 -07:00
|
|
|
{
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virConnectGetTypeEnsureACL(conn) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
2020-05-04 14:51:32 -06:00
|
|
|
return LIBXL_DRIVER_EXTERNAL_NAME;
|
2011-02-10 15:42:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-04-23 13:50:18 +01:00
|
|
|
libxlConnectGetVersion(virConnectPtr conn, unsigned long *version)
|
2011-02-10 15:42:34 -07:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = conn->privateData;
|
|
|
|
libxlDriverConfig *cfg;
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virConnectGetVersionEnsureACL(conn) < 0)
|
|
|
|
return 0;
|
|
|
|
|
2013-08-30 14:52:14 -06:00
|
|
|
cfg = libxlDriverConfigGet(driver);
|
|
|
|
*version = cfg->version;
|
|
|
|
virObjectUnref(cfg);
|
2011-02-10 15:42:34 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-04-26 17:39:11 +01:00
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
static char *libxlConnectGetHostname(virConnectPtr conn)
|
2013-04-26 17:39:11 +01:00
|
|
|
{
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virConnectGetHostnameEnsureACL(conn) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
2013-04-26 17:39:11 +01:00
|
|
|
return virGetHostname();
|
|
|
|
}
|
|
|
|
|
2013-06-12 09:49:27 -06:00
|
|
|
static char *
|
|
|
|
libxlConnectGetSysinfo(virConnectPtr conn, unsigned int flags)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = conn->privateData;
|
2020-07-02 18:21:30 -04:00
|
|
|
g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
|
2013-06-12 09:49:27 -06:00
|
|
|
|
|
|
|
virCheckFlags(0, NULL);
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virConnectGetSysinfoEnsureACL(conn) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
2013-06-12 09:49:27 -06: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;
|
|
|
|
return virBufferContentAndReset(&buf);
|
|
|
|
}
|
2013-04-26 17:39:11 +01:00
|
|
|
|
2011-02-10 15:42:34 -07:00
|
|
|
static int
|
2019-10-14 14:45:33 +02:00
|
|
|
libxlConnectGetMaxVcpus(virConnectPtr conn, const char *type G_GNUC_UNUSED)
|
2011-02-10 15:42:34 -07:00
|
|
|
{
|
|
|
|
int ret;
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = conn->privateData;
|
|
|
|
libxlDriverConfig *cfg;
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virConnectGetMaxVcpusEnsureACL(conn) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2013-08-30 14:52:14 -06:00
|
|
|
cfg = libxlDriverConfigGet(driver);
|
|
|
|
ret = libxl_get_max_cpus(cfg->ctx);
|
2021-05-03 12:56:11 +02:00
|
|
|
if (ret < 0)
|
2013-08-30 14:52:14 -06:00
|
|
|
ret = -1;
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2013-08-30 14:52:14 -06:00
|
|
|
virObjectUnref(cfg);
|
2011-02-10 15:42:34 -07:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info)
|
|
|
|
{
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virNodeGetInfoEnsureACL(conn) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2014-02-26 13:44:09 -07:00
|
|
|
return libxlDriverNodeGetInfo(conn->privateData, info);
|
2011-02-10 15:42:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
2013-04-23 13:50:18 +01:00
|
|
|
libxlConnectGetCapabilities(virConnectPtr conn)
|
2011-02-10 15:42:34 -07:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = conn->privateData;
|
2011-02-10 15:42:34 -07:00
|
|
|
char *xml;
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverConfig *cfg;
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virConnectGetCapabilitiesEnsureACL(conn) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
2013-08-30 14:52:14 -06:00
|
|
|
cfg = libxlDriverConfigGet(driver);
|
2014-06-27 09:55:44 +02:00
|
|
|
xml = virCapabilitiesFormatXML(cfg->caps);
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2013-08-30 14:52:14 -06:00
|
|
|
virObjectUnref(cfg);
|
2011-02-10 15:42:34 -07:00
|
|
|
return xml;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-04-23 13:50:18 +01:00
|
|
|
libxlConnectListDomains(virConnectPtr conn, int *ids, int nids)
|
2011-02-10 15:42:34 -07:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = conn->privateData;
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virConnectListDomainsEnsureACL(conn) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2019-10-17 10:10:10 +02:00
|
|
|
return virDomainObjListGetActiveIDs(driver->domains, ids, nids,
|
|
|
|
virConnectListDomainsCheckACL, conn);
|
2011-02-10 15:42:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-04-23 13:50:18 +01:00
|
|
|
libxlConnectNumOfDomains(virConnectPtr conn)
|
2011-02-10 15:42:34 -07:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = conn->privateData;
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virConnectNumOfDomainsEnsureACL(conn) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2019-10-17 10:10:10 +02:00
|
|
|
return virDomainObjListNumOfDomains(driver->domains, true,
|
|
|
|
virConnectNumOfDomainsCheckACL, conn);
|
2011-02-10 15:42:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static virDomainPtr
|
|
|
|
libxlDomainCreateXML(virConnectPtr conn, const char *xml,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = conn->privateData;
|
|
|
|
virDomainDef *def;
|
|
|
|
virDomainObj *vm = NULL;
|
2011-02-10 15:42:34 -07:00
|
|
|
virDomainPtr dom = NULL;
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
2014-11-18 17:34:42 +00:00
|
|
|
unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2014-11-18 17:34:42 +00:00
|
|
|
virCheckFlags(VIR_DOMAIN_START_PAUSED |
|
|
|
|
VIR_DOMAIN_START_VALIDATE, NULL);
|
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_START_VALIDATE)
|
2016-05-24 17:20:20 +02:00
|
|
|
parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2019-11-27 12:29:21 +00:00
|
|
|
if (!(def = virDomainDefParseString(xml, driver->xmlopt,
|
2016-09-22 17:14:17 +02:00
|
|
|
NULL, parse_flags)))
|
2011-02-10 15:42:34 -07:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virDomainCreateXMLEnsureACL(conn, def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2013-03-28 14:55:55 +01:00
|
|
|
if (!(vm = virDomainObjListAdd(driver->domains, def,
|
2013-03-31 20:03:42 +02:00
|
|
|
driver->xmlopt,
|
2015-09-22 16:57:52 +02:00
|
|
|
VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
|
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 14:46:58 +00:00
|
|
|
VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
|
|
|
|
NULL)))
|
2011-02-10 15:42:34 -07:00
|
|
|
goto cleanup;
|
|
|
|
def = NULL;
|
|
|
|
|
2015-03-01 18:24:26 -07:00
|
|
|
if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0) {
|
2018-04-23 10:40:48 -04:00
|
|
|
if (!vm->persistent)
|
2015-03-01 18:24:26 -07:00
|
|
|
virDomainObjListRemove(driver->domains, vm);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
libxl: support Xen migration stream V2 in save/restore
Xen 4.6 introduced a new migration stream commonly referred to as
"migration V2". Xen 4.6 and newer always produce this new stream,
whereas Xen 4.5 and older always produce the legacy stream.
Support for migration stream V2 can be detected at build time with
LIBXL_HAVE_SRM_V2 from libxl.h. The legacy and V2 streams are not
compatible, but a V2 host can accept and convert a legacy stream.
Commit e7440656 changed the libxl driver to use the lowest libxl
API version possible (version 0x040200) to ensure the driver
builds against older Xen releases. The old 4.2 restore API does
not support specifying a stream version and assumes a legacy
stream, even if the incoming stream is migration V2. Thinking it
has been given a legacy stream, libxl will fail to convert an
incoming stream that is already V2, which causes the entire
restore operation to fail. Xen's libvirt-related OSSTest has been
failing since commit e7440656 landed in libvirt.git master. One
of the more recent failures can be seen here
http://lists.xenproject.org/archives/html/xen-devel/2016-05/msg00071.html
This patch changes the call to libxl_domain_create_restore() to
include the stream version if LIBXL_HAVE_SRM_V2 is defined. The
version field of the libxlSavefileHeader struct is also updated
to '2' when LIBXL_HAVE_SRM_V2 is defined, ensuring the stream
version in the header matches the actual stream version produced
by Xen. Along with bumping the libxl API requirement to 0x040400,
this patch fixes save/restore on a migration V2 Xen host.
Oddly, migration has never used the libxlSavefileHeader. It
handles passing configuration in the Begin and Prepare phases,
and then calls libxl directly to transfer domain state/memory
in the Perform phase. A subsequent patch will add stream
version handling in the Begin and Prepare phase handshaking,
which will fix the migration related OSSTest failures.
Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2016-05-02 12:00:39 -06:00
|
|
|
if (libxlDomainStartNew(driver, vm,
|
|
|
|
(flags & VIR_DOMAIN_START_PAUSED) != 0) < 0) {
|
2018-04-23 10:40:48 -04:00
|
|
|
if (!vm->persistent)
|
2015-06-24 15:14:41 -06:00
|
|
|
virDomainObjListRemove(driver->domains, vm);
|
2015-03-01 18:24:26 -07:00
|
|
|
goto endjob;
|
2011-02-10 15:42:34 -07:00
|
|
|
}
|
|
|
|
|
2017-03-28 17:08:03 +02:00
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid, vm->def->id);
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2015-03-01 18:24:26 -07:00
|
|
|
endjob:
|
2016-06-12 18:30:00 +08:00
|
|
|
libxlDomainObjEndJob(driver, vm);
|
2015-03-01 18:24:26 -07:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2011-02-10 15:42:34 -07:00
|
|
|
virDomainDefFree(def);
|
2016-06-12 18:30:00 +08:00
|
|
|
virDomainObjEndAPI(&vm);
|
2013-08-30 14:52:14 -06:00
|
|
|
virObjectUnref(cfg);
|
2011-02-10 15:42:34 -07:00
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
|
|
|
static virDomainPtr
|
|
|
|
libxlDomainLookupByID(virConnectPtr conn, int id)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = conn->privateData;
|
|
|
|
virDomainObj *vm;
|
2011-02-10 15:42:34 -07:00
|
|
|
virDomainPtr dom = NULL;
|
|
|
|
|
2018-03-09 10:59:28 -05:00
|
|
|
vm = virDomainObjListFindByID(driver->domains, id);
|
2011-02-10 15:42:34 -07:00
|
|
|
if (!vm) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, NULL);
|
2011-02-10 15:42:34 -07:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virDomainLookupByIDEnsureACL(conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2017-03-28 17:08:03 +02:00
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid, vm->def->id);
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2018-03-09 11:48:00 -05:00
|
|
|
virDomainObjEndAPI(&vm);
|
2011-02-10 15:42:34 -07:00
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
|
|
|
static virDomainPtr
|
|
|
|
libxlDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = conn->privateData;
|
|
|
|
virDomainObj *vm;
|
2011-02-10 15:42:34 -07:00
|
|
|
virDomainPtr dom = NULL;
|
|
|
|
|
2018-03-09 10:47:46 -05:00
|
|
|
vm = virDomainObjListFindByUUID(driver->domains, uuid);
|
2011-02-10 15:42:34 -07:00
|
|
|
if (!vm) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, NULL);
|
2011-02-10 15:42:34 -07:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virDomainLookupByUUIDEnsureACL(conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2017-03-28 17:08:03 +02:00
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid, vm->def->id);
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2018-03-09 11:48:00 -05:00
|
|
|
virDomainObjEndAPI(&vm);
|
2011-02-10 15:42:34 -07:00
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
|
|
|
static virDomainPtr
|
|
|
|
libxlDomainLookupByName(virConnectPtr conn, const char *name)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = conn->privateData;
|
|
|
|
virDomainObj *vm;
|
2011-02-10 15:42:34 -07:00
|
|
|
virDomainPtr dom = NULL;
|
|
|
|
|
2013-01-11 16:04:47 +00:00
|
|
|
vm = virDomainObjListFindByName(driver->domains, name);
|
2011-02-10 15:42:34 -07:00
|
|
|
if (!vm) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, NULL);
|
2011-02-10 15:42:34 -07:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virDomainLookupByNameEnsureACL(conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2017-03-28 17:08:03 +02:00
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid, vm->def->id);
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2015-04-23 18:00:01 +02:00
|
|
|
virDomainObjEndAPI(&vm);
|
2011-02-10 15:42:34 -07:00
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
2011-03-29 20:55:38 +08:00
|
|
|
static int
|
|
|
|
libxlDomainSuspend(virDomainPtr dom)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
|
|
|
virDomainObj *vm;
|
|
|
|
virObjectEvent *event = NULL;
|
2011-03-29 20:55:38 +08:00
|
|
|
int ret = -1;
|
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-03-29 20:55:38 +08:00
|
|
|
goto cleanup;
|
2013-04-23 11:56:22 +01:00
|
|
|
|
2015-06-22 11:36:59 -06:00
|
|
|
LIBXL_CHECK_DOM0_GOTO(vm->def->name, cleanup);
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virDomainSuspendEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2014-02-06 16:21:50 -07:00
|
|
|
if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2018-04-17 22:13:29 +00:00
|
|
|
if (virDomainObjCheckActive(vm) < 0)
|
2014-02-06 16:21:50 -07:00
|
|
|
goto endjob;
|
2011-03-29 20:55:38 +08:00
|
|
|
|
2011-05-04 11:07:01 +02:00
|
|
|
if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_PAUSED) {
|
2021-03-25 17:26:05 +01:00
|
|
|
if (libxlDomainPauseWrapper(cfg->ctx, vm->def->id) != 0) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to suspend domain '%d' with libxenlight"),
|
2014-03-27 17:55:02 +01:00
|
|
|
vm->def->id);
|
2014-02-06 16:21:50 -07:00
|
|
|
goto endjob;
|
2011-03-29 20:55:38 +08:00
|
|
|
}
|
|
|
|
|
2011-05-04 11:07:01 +02:00
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
|
2011-03-29 20:55:38 +08:00
|
|
|
|
2013-11-21 18:03:26 +01:00
|
|
|
event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_SUSPENDED,
|
2011-03-29 20:55:38 +08:00
|
|
|
VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
|
|
|
|
}
|
|
|
|
|
2019-11-27 12:53:10 +00:00
|
|
|
if (virDomainObjSave(vm, driver->xmlopt, cfg->stateDir) < 0)
|
2014-02-06 16:21:50 -07:00
|
|
|
goto endjob;
|
2011-03-29 20:55:38 +08:00
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
endjob:
|
2016-06-12 18:30:00 +08:00
|
|
|
libxlDomainObjEndJob(driver, vm);
|
2014-02-06 16:21:50 -07:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2016-06-12 18:30:00 +08:00
|
|
|
virDomainObjEndAPI(&vm);
|
2018-06-12 13:33:01 -04:00
|
|
|
virObjectEventStateQueue(driver->domainEventState, event);
|
2013-08-30 14:52:14 -06:00
|
|
|
virObjectUnref(cfg);
|
2011-03-29 20:55:38 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainResume(virDomainPtr dom)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
|
|
|
virDomainObj *vm;
|
|
|
|
virObjectEvent *event = NULL;
|
2011-03-29 20:55:38 +08:00
|
|
|
int ret = -1;
|
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-03-29 20:55:38 +08:00
|
|
|
goto cleanup;
|
|
|
|
|
2015-06-22 11:36:59 -06:00
|
|
|
LIBXL_CHECK_DOM0_GOTO(vm->def->name, cleanup);
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virDomainResumeEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2014-02-06 16:21:50 -07:00
|
|
|
if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2018-04-17 22:13:29 +00:00
|
|
|
if (virDomainObjCheckActive(vm) < 0)
|
2014-02-06 16:21:50 -07:00
|
|
|
goto endjob;
|
2011-03-29 20:55:38 +08:00
|
|
|
|
2011-05-04 11:07:01 +02:00
|
|
|
if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
|
2021-03-25 17:26:06 +01:00
|
|
|
if (libxlDomainUnpauseWrapper(cfg->ctx, vm->def->id) != 0) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to resume domain '%d' with libxenlight"),
|
2014-03-27 17:55:02 +01:00
|
|
|
vm->def->id);
|
2014-02-06 16:21:50 -07:00
|
|
|
goto endjob;
|
2011-03-29 20:55:38 +08:00
|
|
|
}
|
|
|
|
|
2011-05-04 11:07:01 +02:00
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
|
|
|
|
VIR_DOMAIN_RUNNING_UNPAUSED);
|
2011-03-29 20:55:38 +08:00
|
|
|
|
2013-11-21 18:03:26 +01:00
|
|
|
event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_RESUMED,
|
2011-03-29 20:55:38 +08:00
|
|
|
VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
|
|
|
|
}
|
|
|
|
|
2019-11-27 12:53:10 +00:00
|
|
|
if (virDomainObjSave(vm, driver->xmlopt, cfg->stateDir) < 0)
|
2014-02-06 16:21:50 -07:00
|
|
|
goto endjob;
|
2011-03-29 20:55:38 +08:00
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
endjob:
|
2016-06-12 18:30:00 +08:00
|
|
|
libxlDomainObjEndJob(driver, vm);
|
2014-02-06 16:21:50 -07:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2016-06-12 18:30:00 +08:00
|
|
|
virDomainObjEndAPI(&vm);
|
2018-06-12 13:33:01 -04:00
|
|
|
virObjectEventStateQueue(driver->domainEventState, event);
|
2013-08-30 14:52:14 -06:00
|
|
|
virObjectUnref(cfg);
|
2011-03-29 20:55:38 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-02-10 15:42:34 -07:00
|
|
|
static int
|
2011-10-05 18:31:55 +01:00
|
|
|
libxlDomainShutdownFlags(virDomainPtr dom, unsigned int flags)
|
2011-02-10 15:42:34 -07:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
|
|
|
virDomainObj *vm;
|
2011-02-10 15:42:34 -07:00
|
|
|
int ret = -1;
|
|
|
|
|
2014-05-01 12:11:51 -06:00
|
|
|
virCheckFlags(VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN |
|
|
|
|
VIR_DOMAIN_SHUTDOWN_PARAVIRT, -1);
|
|
|
|
if (flags == 0)
|
|
|
|
flags = VIR_DOMAIN_SHUTDOWN_PARAVIRT |
|
|
|
|
VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN;
|
2011-10-05 18:31:55 +01:00
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-02-10 15:42:34 -07:00
|
|
|
goto cleanup;
|
|
|
|
|
2015-06-22 11:36:59 -06:00
|
|
|
LIBXL_CHECK_DOM0_GOTO(vm->def->name, cleanup);
|
|
|
|
|
api: require write permission for guest agent interaction
I noticed that we allow virDomainGetVcpusFlags even for read-only
connections, but that with a flag, it can require guest agent
interaction. It is feasible that a malicious guest could
intentionally abuse the replies it sends over the guest agent
connection to possibly trigger a bug in libvirt's JSON parser,
or withhold an answer so as to prevent the use of the agent
in a later command such as a shutdown request. Although we
don't know of any such exploits now (and therefore don't mind
posting this patch publicly without trying to get a CVE assigned),
it is better to err on the side of caution and explicitly require
full access to any domain where the API requires guest interaction
to operate correctly.
I audited all commands that are marked as conditionally using a
guest agent. Note that at least virDomainFSTrim is documented
as needing a guest agent, but that such use is unconditional
depending on the hypervisor (so the existing domain:fs_trim ACL
should be sufficient there, rather than also requirng domain:write).
But when designing future APIs, such as the plans for obtaining
a domain's IP addresses, we should copy the approach of this patch
in making interaction with the guest be specified via a flag, and
use that flag to also require stricter access checks.
* src/libvirt.c (virDomainGetVcpusFlags): Forbid guest interaction
on read-only connection.
(virDomainShutdownFlags, virDomainReboot): Improve docs on agent
interaction.
* src/remote/remote_protocol.x
(REMOTE_PROC_DOMAIN_SNAPSHOT_CREATE_XML)
(REMOTE_PROC_DOMAIN_SET_VCPUS_FLAGS)
(REMOTE_PROC_DOMAIN_GET_VCPUS_FLAGS, REMOTE_PROC_DOMAIN_REBOOT)
(REMOTE_PROC_DOMAIN_SHUTDOWN_FLAGS): Require domain:write for any
conditional use of a guest agent.
* src/xen/xen_driver.c: Fix clients.
* src/libxl/libxl_driver.c: Likewise.
* src/uml/uml_driver.c: Likewise.
* src/qemu/qemu_driver.c: Likewise.
* src/lxc/lxc_driver.c: Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-21 10:37:29 -07:00
|
|
|
if (virDomainShutdownFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
|
2013-04-23 11:56:22 +01:00
|
|
|
goto cleanup;
|
|
|
|
|
2018-04-17 22:13:29 +00:00
|
|
|
if (virDomainObjCheckActive(vm) < 0)
|
2011-02-10 15:42:34 -07:00
|
|
|
goto cleanup;
|
|
|
|
|
2014-05-01 12:11:51 -06:00
|
|
|
if (flags & VIR_DOMAIN_SHUTDOWN_PARAVIRT) {
|
2021-03-25 17:26:03 +01:00
|
|
|
ret = libxlDomainShutdownWrapper(cfg->ctx, vm->def->id);
|
2014-05-01 12:11:51 -06:00
|
|
|
if (ret == 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (ret != ERROR_NOPARAVIRT) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to shutdown domain '%d' with libxenlight"),
|
|
|
|
vm->def->id);
|
|
|
|
ret = -1;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN) {
|
2021-03-25 17:26:10 +01:00
|
|
|
ret = libxlSendTriggerWrapper(cfg->ctx, vm->def->id,
|
|
|
|
LIBXL_TRIGGER_POWER, 0);
|
2014-05-01 12:11:51 -06:00
|
|
|
if (ret == 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to shutdown domain '%d' with libxenlight"),
|
2014-03-27 17:55:02 +01:00
|
|
|
vm->def->id);
|
2014-05-01 12:11:51 -06:00
|
|
|
ret = -1;
|
2011-02-10 15:42:34 -07:00
|
|
|
}
|
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2018-03-09 11:47:59 -05:00
|
|
|
virDomainObjEndAPI(&vm);
|
2015-02-11 16:40:07 -07:00
|
|
|
virObjectUnref(cfg);
|
2011-02-10 15:42:34 -07:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-10-05 18:31:55 +01:00
|
|
|
static int
|
|
|
|
libxlDomainShutdown(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
return libxlDomainShutdownFlags(dom, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-02-10 15:42:34 -07:00
|
|
|
static int
|
2011-07-06 16:17:10 -06:00
|
|
|
libxlDomainReboot(virDomainPtr dom, unsigned int flags)
|
2011-02-10 15:42:34 -07:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
|
|
|
virDomainObj *vm;
|
2011-02-10 15:42:34 -07:00
|
|
|
int ret = -1;
|
|
|
|
|
2014-05-01 15:00:47 -06:00
|
|
|
virCheckFlags(VIR_DOMAIN_REBOOT_PARAVIRT, -1);
|
|
|
|
if (flags == 0)
|
|
|
|
flags = VIR_DOMAIN_REBOOT_PARAVIRT;
|
2011-07-06 16:17:10 -06:00
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-02-10 15:42:34 -07:00
|
|
|
goto cleanup;
|
|
|
|
|
2015-06-22 11:36:59 -06:00
|
|
|
LIBXL_CHECK_DOM0_GOTO(vm->def->name, cleanup);
|
|
|
|
|
api: require write permission for guest agent interaction
I noticed that we allow virDomainGetVcpusFlags even for read-only
connections, but that with a flag, it can require guest agent
interaction. It is feasible that a malicious guest could
intentionally abuse the replies it sends over the guest agent
connection to possibly trigger a bug in libvirt's JSON parser,
or withhold an answer so as to prevent the use of the agent
in a later command such as a shutdown request. Although we
don't know of any such exploits now (and therefore don't mind
posting this patch publicly without trying to get a CVE assigned),
it is better to err on the side of caution and explicitly require
full access to any domain where the API requires guest interaction
to operate correctly.
I audited all commands that are marked as conditionally using a
guest agent. Note that at least virDomainFSTrim is documented
as needing a guest agent, but that such use is unconditional
depending on the hypervisor (so the existing domain:fs_trim ACL
should be sufficient there, rather than also requirng domain:write).
But when designing future APIs, such as the plans for obtaining
a domain's IP addresses, we should copy the approach of this patch
in making interaction with the guest be specified via a flag, and
use that flag to also require stricter access checks.
* src/libvirt.c (virDomainGetVcpusFlags): Forbid guest interaction
on read-only connection.
(virDomainShutdownFlags, virDomainReboot): Improve docs on agent
interaction.
* src/remote/remote_protocol.x
(REMOTE_PROC_DOMAIN_SNAPSHOT_CREATE_XML)
(REMOTE_PROC_DOMAIN_SET_VCPUS_FLAGS)
(REMOTE_PROC_DOMAIN_GET_VCPUS_FLAGS, REMOTE_PROC_DOMAIN_REBOOT)
(REMOTE_PROC_DOMAIN_SHUTDOWN_FLAGS): Require domain:write for any
conditional use of a guest agent.
* src/xen/xen_driver.c: Fix clients.
* src/libxl/libxl_driver.c: Likewise.
* src/uml/uml_driver.c: Likewise.
* src/qemu/qemu_driver.c: Likewise.
* src/lxc/lxc_driver.c: Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-21 10:37:29 -07:00
|
|
|
if (virDomainRebootEnsureACL(dom->conn, vm->def, flags) < 0)
|
2013-04-23 11:56:22 +01:00
|
|
|
goto cleanup;
|
|
|
|
|
2018-04-17 22:13:29 +00:00
|
|
|
if (virDomainObjCheckActive(vm) < 0)
|
2011-02-10 15:42:34 -07:00
|
|
|
goto cleanup;
|
|
|
|
|
2014-05-01 15:00:47 -06:00
|
|
|
if (flags & VIR_DOMAIN_REBOOT_PARAVIRT) {
|
2021-03-25 17:26:04 +01:00
|
|
|
ret = libxlDomainRebootWrapper(cfg->ctx, vm->def->id);
|
2014-05-01 15:00:47 -06:00
|
|
|
if (ret == 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to reboot domain '%d' with libxenlight"),
|
2014-03-27 17:55:02 +01:00
|
|
|
vm->def->id);
|
2014-05-01 15:00:47 -06:00
|
|
|
ret = -1;
|
2011-02-10 15:42:34 -07:00
|
|
|
}
|
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2018-03-09 11:47:59 -05:00
|
|
|
virDomainObjEndAPI(&vm);
|
2015-02-11 16:40:07 -07:00
|
|
|
virObjectUnref(cfg);
|
2011-02-10 15:42:34 -07:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2011-07-20 18:47:46 +02:00
|
|
|
libxlDomainDestroyFlags(virDomainPtr dom,
|
|
|
|
unsigned int flags)
|
2011-02-10 15:42:34 -07:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
|
|
|
virDomainObj *vm;
|
2011-02-10 15:42:34 -07:00
|
|
|
int ret = -1;
|
2021-03-11 08:16:13 +01:00
|
|
|
virObjectEvent *event = NULL;
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2011-07-20 18:47:46 +02:00
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-02-10 15:42:34 -07:00
|
|
|
goto cleanup;
|
|
|
|
|
2015-06-22 11:36:59 -06:00
|
|
|
LIBXL_CHECK_DOM0_GOTO(vm->def->name, cleanup);
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virDomainDestroyFlagsEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2015-03-01 16:22:07 -07:00
|
|
|
if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2018-04-17 22:13:29 +00:00
|
|
|
if (virDomainObjCheckActive(vm) < 0)
|
2015-03-01 16:22:07 -07:00
|
|
|
goto endjob;
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2015-03-03 17:54:50 -07:00
|
|
|
if (libxlDomainDestroyInternal(driver, vm) < 0) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2014-03-27 17:55:02 +01:00
|
|
|
_("Failed to destroy domain '%d'"), vm->def->id);
|
2015-03-01 16:22:07 -07:00
|
|
|
goto endjob;
|
2011-02-10 15:42:34 -07:00
|
|
|
}
|
|
|
|
|
2015-07-07 12:29:24 -06:00
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF,
|
|
|
|
VIR_DOMAIN_SHUTOFF_DESTROYED);
|
|
|
|
|
|
|
|
event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
|
|
|
|
VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
|
|
|
|
|
|
|
|
libxlDomainCleanup(driver, vm);
|
2018-04-23 10:40:48 -04:00
|
|
|
if (!vm->persistent)
|
2015-03-01 16:22:07 -07:00
|
|
|
virDomainObjListRemove(driver->domains, vm);
|
2011-02-10 15:42:34 -07:00
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2015-03-01 16:22:07 -07:00
|
|
|
endjob:
|
2016-06-12 18:30:00 +08:00
|
|
|
libxlDomainObjEndJob(driver, vm);
|
2015-03-01 16:22:07 -07:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2016-06-12 18:30:00 +08:00
|
|
|
virDomainObjEndAPI(&vm);
|
2018-06-12 13:33:01 -04:00
|
|
|
virObjectEventStateQueue(driver->domainEventState, event);
|
2015-02-11 16:40:07 -07:00
|
|
|
virObjectUnref(cfg);
|
2011-02-10 15:42:34 -07:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-07-20 18:47:46 +02:00
|
|
|
static int
|
|
|
|
libxlDomainDestroy(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
return libxlDomainDestroyFlags(dom, 0);
|
|
|
|
}
|
|
|
|
|
2018-09-07 21:29:55 +02:00
|
|
|
#ifdef LIBXL_HAVE_DOMAIN_SUSPEND_ONLY
|
|
|
|
static int
|
|
|
|
libxlDomainPMSuspendForDuration(virDomainPtr dom,
|
|
|
|
unsigned int target,
|
|
|
|
unsigned long long duration,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainObj *vm;
|
2018-09-07 21:29:55 +02:00
|
|
|
int ret = -1;
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
|
|
|
virObjectEvent *event = NULL;
|
2018-09-07 21:29:55 +02:00
|
|
|
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
if (target != VIR_NODE_SUSPEND_TARGET_MEM) {
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
|
|
|
|
_("PMSuspend type %d not supported by libxenlight driver"),
|
|
|
|
target);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (duration != 0) {
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
|
|
|
_("Duration not supported. Use 0 for now"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virDomainPMSuspendForDurationEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2019-09-06 16:12:55 +02:00
|
|
|
if (virDomainObjCheckActive(vm) < 0)
|
2018-09-07 21:29:55 +02:00
|
|
|
goto endjob;
|
|
|
|
|
2021-03-11 08:16:13 +01:00
|
|
|
/* Unlock virDomainObj *to not deadlock with even handler, which will try
|
2018-09-07 21:29:55 +02:00
|
|
|
* to send lifecycle event
|
|
|
|
*/
|
|
|
|
virObjectUnlock(vm);
|
|
|
|
ret = libxl_domain_suspend_only(cfg->ctx, vm->def->id, NULL);
|
|
|
|
virObjectLock(vm);
|
|
|
|
|
|
|
|
if (ret < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to suspend domain '%d'"), vm->def->id);
|
|
|
|
goto endjob;
|
|
|
|
}
|
|
|
|
|
2019-08-13 13:53:59 -06:00
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_PMSUSPENDED, VIR_DOMAIN_PMSUSPENDED_UNKNOWN);
|
|
|
|
event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_PMSUSPENDED,
|
|
|
|
VIR_DOMAIN_EVENT_PMSUSPENDED_MEMORY);
|
|
|
|
|
2018-09-07 21:29:55 +02:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
endjob:
|
|
|
|
libxlDomainObjEndJob(driver, vm);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virDomainObjEndAPI(&vm);
|
2019-08-13 13:53:59 -06:00
|
|
|
virObjectEventStateQueue(driver->domainEventState, event);
|
2018-09-07 21:29:55 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainPMWakeup(virDomainPtr dom, unsigned int flags)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
virDomainObj *vm;
|
2018-09-07 21:29:55 +02:00
|
|
|
int ret = -1;
|
2021-03-11 08:16:13 +01:00
|
|
|
virObjectEvent *event = NULL;
|
|
|
|
libxlDomainObjPrivate *priv;
|
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
2018-09-07 21:29:55 +02:00
|
|
|
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virDomainPMWakeupEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_PMSUSPENDED) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("Domain is not suspended"));
|
|
|
|
goto endjob;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
priv = vm->privateData;
|
|
|
|
if (libxl_domain_resume(cfg->ctx, vm->def->id, 1, NULL) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to resume domain '%d'"), vm->def->id);
|
|
|
|
goto endjob;
|
|
|
|
}
|
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_WAKEUP);
|
2020-07-09 12:42:21 +08:00
|
|
|
/* re-enable death event - libxl reports it only once */
|
2018-09-07 21:29:55 +02:00
|
|
|
if (priv->deathW)
|
|
|
|
libxl_evdisable_domain_death(cfg->ctx, priv->deathW);
|
|
|
|
if (libxl_evenable_domain_death(cfg->ctx, vm->def->id, 0, &priv->deathW))
|
|
|
|
goto destroy_dom;
|
|
|
|
|
|
|
|
event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STARTED,
|
|
|
|
VIR_DOMAIN_EVENT_STARTED_WAKEUP);
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
goto endjob;
|
|
|
|
|
|
|
|
destroy_dom:
|
|
|
|
libxlDomainDestroyInternal(driver, vm);
|
|
|
|
vm->def->id = -1;
|
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_FAILED);
|
2018-12-08 03:45:59 +01:00
|
|
|
event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
|
|
|
|
VIR_DOMAIN_EVENT_STOPPED_FAILED);
|
|
|
|
libxlDomainCleanup(driver, vm);
|
2018-09-07 21:29:55 +02:00
|
|
|
|
|
|
|
endjob:
|
|
|
|
libxlDomainObjEndJob(driver, vm);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virDomainObjEndAPI(&vm);
|
|
|
|
virObjectEventStateQueue(driver->domainEventState, event);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-03-29 20:49:43 +08:00
|
|
|
static char *
|
|
|
|
libxlDomainGetOSType(virDomainPtr dom)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainObj *vm;
|
2011-03-29 20:49:43 +08:00
|
|
|
char *type = NULL;
|
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-03-29 20:49:43 +08:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virDomainGetOSTypeEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2019-10-20 13:49:46 +02:00
|
|
|
type = g_strdup(virDomainOSTypeToString(vm->def->os.type));
|
2011-03-29 20:49:43 +08:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2018-03-09 11:47:59 -05:00
|
|
|
virDomainObjEndAPI(&vm);
|
2011-03-29 20:49:43 +08: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 17:47:16 -07:00
|
|
|
static unsigned long long
|
2011-03-21 10:35:53 +01:00
|
|
|
libxlDomainGetMaxMemory(virDomainPtr dom)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainObj *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 17:47:16 -07:00
|
|
|
unsigned long long ret = 0;
|
2011-03-21 10:35:53 +01:00
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-03-21 10:35:53 +01:00
|
|
|
goto cleanup;
|
2013-04-23 11:56:22 +01:00
|
|
|
|
|
|
|
if (virDomainGetMaxMemoryEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2016-06-15 15:34:04 +02:00
|
|
|
ret = virDomainDefGetMemoryTotal(vm->def);
|
2011-03-21 10:35:53 +01:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2018-03-09 11:47:59 -05:00
|
|
|
virDomainObjEndAPI(&vm);
|
2011-03-21 10:35:53 +01:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-07-01 16:27:31 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Helper method for --current, --live, and --config options, and check
|
|
|
|
* whether domain is active or can get persistent domain configuration.
|
|
|
|
*
|
|
|
|
* Return 0 if success, also change the flags and get the persistent
|
|
|
|
* domain configuration if needed. Return -1 on error.
|
|
|
|
*/
|
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainLiveConfigHelperMethod(virCaps *caps G_GNUC_UNUSED,
|
|
|
|
virDomainXMLOption *xmlopt,
|
|
|
|
virDomainObj *dom,
|
2016-07-01 16:27:31 +02:00
|
|
|
unsigned int *flags,
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainDef **persistentDef)
|
2016-07-01 16:27:31 +02:00
|
|
|
{
|
|
|
|
if (virDomainObjUpdateModificationImpact(dom, flags) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (*flags & VIR_DOMAIN_AFFECT_CONFIG) {
|
2019-11-27 12:41:59 +00:00
|
|
|
if (!(*persistentDef = virDomainObjGetPersistentDef(xmlopt, dom, NULL))) {
|
2016-07-01 16:27:31 +02:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Get persistent config failed"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-03-21 10:35:53 +01:00
|
|
|
static int
|
2011-05-30 11:53:03 +02:00
|
|
|
libxlDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem,
|
2011-03-21 10:35:53 +01:00
|
|
|
unsigned int flags)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
|
|
|
virDomainObj *vm;
|
|
|
|
virDomainDef *persistentDef = NULL;
|
2011-03-21 10:35:53 +01:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(VIR_DOMAIN_MEM_LIVE |
|
2011-05-30 11:53:03 +02:00
|
|
|
VIR_DOMAIN_MEM_CONFIG |
|
|
|
|
VIR_DOMAIN_MEM_MAXIMUM, -1);
|
2011-03-21 10:35:53 +01:00
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-03-21 10:35:53 +01:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virDomainSetMemoryFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2014-02-06 16:10:25 -07:00
|
|
|
if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2016-02-24 11:38:37 +03:00
|
|
|
if (virDomainLiveConfigHelperMethod(cfg->caps, driver->xmlopt, vm, &flags,
|
|
|
|
&persistentDef) < 0)
|
2014-02-06 16:10:25 -07:00
|
|
|
goto endjob;
|
2011-03-21 10:35:53 +01:00
|
|
|
|
2011-05-30 11:53:03 +02:00
|
|
|
if (flags & VIR_DOMAIN_MEM_MAXIMUM) {
|
|
|
|
/* resize the maximum memory */
|
2011-03-21 10:35:53 +01:00
|
|
|
|
2011-05-30 11:53:03 +02:00
|
|
|
if (flags & VIR_DOMAIN_MEM_LIVE) {
|
2015-02-11 16:40:07 -07:00
|
|
|
if (libxl_domain_setmaxmem(cfg->ctx, vm->def->id, newmem) < 0) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to set maximum memory for domain '%d'"
|
2014-03-27 17:55:02 +01:00
|
|
|
" with libxenlight"), vm->def->id);
|
2014-02-06 16:10:25 -07:00
|
|
|
goto endjob;
|
2011-05-30 11:53:03 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_MEM_CONFIG) {
|
|
|
|
/* Help clang 2.8 decipher the logic flow. */
|
|
|
|
sa_assert(persistentDef);
|
2015-09-16 14:25:42 +02:00
|
|
|
virDomainDefSetMemoryTotal(persistentDef, newmem);
|
2011-05-30 11:53:03 +02:00
|
|
|
if (persistentDef->mem.cur_balloon > newmem)
|
|
|
|
persistentDef->mem.cur_balloon = newmem;
|
2019-11-27 12:53:10 +00:00
|
|
|
ret = virDomainDefSave(persistentDef, driver->xmlopt, cfg->configDir);
|
2014-02-06 16:10:25 -07:00
|
|
|
goto endjob;
|
2011-03-21 10:35:53 +01:00
|
|
|
}
|
|
|
|
|
2011-05-30 11:53:03 +02:00
|
|
|
} else {
|
|
|
|
/* resize the current memory */
|
2011-03-21 10:35:53 +01:00
|
|
|
|
2016-06-15 15:34:04 +02:00
|
|
|
if (newmem > virDomainDefGetMemoryTotal(vm->def)) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("cannot set memory higher than max memory"));
|
2014-02-06 16:10:25 -07:00
|
|
|
goto endjob;
|
2011-05-30 11:53:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_MEM_LIVE) {
|
2014-02-06 16:10:25 -07:00
|
|
|
int res;
|
|
|
|
|
|
|
|
/* Unlock virDomainObj while ballooning memory */
|
|
|
|
virObjectUnlock(vm);
|
2021-03-25 17:26:11 +01:00
|
|
|
res = libxlSetMemoryTargetWrapper(cfg->ctx, vm->def->id, newmem, 0,
|
|
|
|
/* force */ 1);
|
2014-02-06 16:10:25 -07:00
|
|
|
virObjectLock(vm);
|
|
|
|
if (res < 0) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to set memory for domain '%d'"
|
2014-03-27 17:55:02 +01:00
|
|
|
" with libxenlight"), vm->def->id);
|
2014-02-06 16:10:25 -07:00
|
|
|
goto endjob;
|
2011-05-30 11:53:03 +02:00
|
|
|
}
|
2019-01-10 15:18:36 -07:00
|
|
|
vm->def->mem.cur_balloon = newmem;
|
2011-05-30 11:53:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_MEM_CONFIG) {
|
|
|
|
sa_assert(persistentDef);
|
|
|
|
persistentDef->mem.cur_balloon = newmem;
|
2019-11-27 12:53:10 +00:00
|
|
|
ret = virDomainDefSave(persistentDef, driver->xmlopt, cfg->configDir);
|
2014-02-06 16:10:25 -07:00
|
|
|
goto endjob;
|
2011-05-30 11:53:03 +02:00
|
|
|
}
|
2011-03-21 10:35:53 +01:00
|
|
|
}
|
|
|
|
|
2011-05-30 11:53:03 +02:00
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
endjob:
|
2016-06-12 18:30:00 +08:00
|
|
|
libxlDomainObjEndJob(driver, vm);
|
2014-02-06 16:10:25 -07:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2016-06-12 18:30:00 +08:00
|
|
|
virDomainObjEndAPI(&vm);
|
2013-08-30 14:52:14 -06:00
|
|
|
virObjectUnref(cfg);
|
2011-03-21 10:35:53 +01:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainSetMemory(virDomainPtr dom, unsigned long memory)
|
|
|
|
{
|
|
|
|
return libxlDomainSetMemoryFlags(dom, memory, VIR_DOMAIN_MEM_LIVE);
|
|
|
|
}
|
|
|
|
|
2011-05-30 11:53:03 +02:00
|
|
|
static int
|
|
|
|
libxlDomainSetMaxMemory(virDomainPtr dom, unsigned long memory)
|
|
|
|
{
|
|
|
|
return libxlDomainSetMemoryFlags(dom, memory, VIR_DOMAIN_MEM_MAXIMUM);
|
|
|
|
}
|
|
|
|
|
2011-02-10 15:42:34 -07:00
|
|
|
static int
|
|
|
|
libxlDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
|
|
|
virDomainObj *vm;
|
2011-03-21 10:35:51 +01:00
|
|
|
libxl_dominfo d_info;
|
2011-02-10 15:42:34 -07:00
|
|
|
int ret = -1;
|
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-02-10 15:42:34 -07:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virDomainGetInfoEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2017-01-16 10:51:40 -07:00
|
|
|
info->maxMem = virDomainDefGetMemoryTotal(vm->def);
|
2011-03-21 10:35:51 +01:00
|
|
|
if (!virDomainObjIsActive(vm)) {
|
|
|
|
info->cpuTime = 0;
|
|
|
|
info->memory = vm->def->mem.cur_balloon;
|
|
|
|
} else {
|
2016-01-21 10:21:10 +00:00
|
|
|
libxl_dominfo_init(&d_info);
|
|
|
|
|
2015-02-11 16:40:07 -07:00
|
|
|
if (libxl_domain_info(cfg->ctx, &d_info, vm->def->id) != 0) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2014-03-27 17:55:02 +01:00
|
|
|
_("libxl_domain_info failed for domain '%d'"),
|
|
|
|
vm->def->id);
|
2011-03-21 10:35:51 +01:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
info->cpuTime = d_info.cpu_time;
|
|
|
|
info->memory = d_info.current_memkb;
|
2016-01-21 10:21:10 +00:00
|
|
|
|
|
|
|
libxl_dominfo_dispose(&d_info);
|
2011-03-21 10:35:51 +01:00
|
|
|
}
|
|
|
|
|
2011-05-04 11:07:01 +02:00
|
|
|
info->state = virDomainObjGetState(vm, NULL);
|
2015-10-22 14:59:03 +02:00
|
|
|
info->nrVirtCpu = virDomainDefGetVcpus(vm->def);
|
2011-02-10 15:42:34 -07:00
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2018-03-09 11:47:59 -05:00
|
|
|
virDomainObjEndAPI(&vm);
|
2015-02-11 16:40:07 -07:00
|
|
|
virObjectUnref(cfg);
|
2011-02-10 15:42:34 -07:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-05-02 11:35:29 +02:00
|
|
|
static int
|
|
|
|
libxlDomainGetState(virDomainPtr dom,
|
|
|
|
int *state,
|
|
|
|
int *reason,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainObj *vm;
|
2011-05-02 11:35:29 +02:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-05-02 11:35:29 +02:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virDomainGetStateEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-05-04 11:07:01 +02:00
|
|
|
*state = virDomainObjGetState(vm, reason);
|
2011-05-02 11:35:29 +02:00
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2018-03-09 11:47:59 -05:00
|
|
|
virDomainObjEndAPI(&vm);
|
2011-05-02 11:35:29 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-02-06 18:02:06 -07:00
|
|
|
/*
|
2021-03-11 08:16:13 +01:00
|
|
|
* virDomainObj *must be locked on invocation
|
2014-02-06 18:02:06 -07:00
|
|
|
*/
|
2011-05-30 11:53:02 +02:00
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDoDomainSave(libxlDriverPrivate *driver,
|
|
|
|
virDomainObj *vm,
|
2018-05-14 14:45:05 -06:00
|
|
|
const char *to,
|
|
|
|
bool managed)
|
2011-05-30 11:53:02 +02:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
2011-05-30 11:53:02 +02:00
|
|
|
libxlSavefileHeader hdr;
|
2021-03-11 08:16:13 +01:00
|
|
|
virObjectEvent *event = NULL;
|
2021-02-16 18:37:09 -07:00
|
|
|
g_autofree char *xml = NULL;
|
2011-05-30 11:53:02 +02:00
|
|
|
uint32_t xml_len;
|
2013-02-28 09:48:16 -05:00
|
|
|
int fd = -1;
|
2011-05-30 11:53:02 +02:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("Domain '%d' has to be running because libxenlight will"
|
|
|
|
" suspend it"), vm->def->id);
|
2011-05-30 11:53:02 +02: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 15:26:45 -05:00
|
|
|
-1, -1, 0)) < 0) {
|
2011-05-30 11:53:02 +02:00
|
|
|
virReportSystemError(-fd,
|
|
|
|
_("Failed to create domain save file '%s'"), to);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2019-11-27 11:57:34 +00:00
|
|
|
if ((xml = virDomainDefFormat(vm->def, driver->xmlopt, 0)) == NULL)
|
2011-05-30 11:53:02 +02:00
|
|
|
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 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
|
|
|
|
_("Failed to write save file header"));
|
2011-05-30 11:53:02 +02:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (safewrite(fd, xml, xml_len) != xml_len) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
|
|
|
|
_("Failed to write xml description"));
|
2011-05-30 11:53:02 +02:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2014-02-06 16:34:58 -07:00
|
|
|
/* Unlock virDomainObj while saving domain */
|
|
|
|
virObjectUnlock(vm);
|
2015-02-11 16:40:07 -07:00
|
|
|
ret = libxl_domain_suspend(cfg->ctx, vm->def->id, fd, 0, NULL);
|
2014-02-06 16:34:58 -07:00
|
|
|
virObjectLock(vm);
|
|
|
|
|
|
|
|
if (ret != 0) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to save domain '%d' with libxenlight"),
|
|
|
|
vm->def->id);
|
2014-02-06 16:34:58 -07:00
|
|
|
ret = -1;
|
2011-05-30 11:53:02 +02:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2015-07-07 12:29:24 -06:00
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF,
|
|
|
|
VIR_DOMAIN_SHUTOFF_SAVED);
|
|
|
|
|
2013-11-21 18:03:26 +01:00
|
|
|
event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
|
2011-05-30 11:53:02 +02:00
|
|
|
VIR_DOMAIN_EVENT_STOPPED_SAVED);
|
|
|
|
|
2015-03-03 17:54:50 -07:00
|
|
|
if (libxlDomainDestroyInternal(driver, vm) < 0) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to destroy domain '%d'"), vm->def->id);
|
2011-05-30 11:53:02 +02:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2015-07-07 12:29:24 -06:00
|
|
|
libxlDomainCleanup(driver, vm);
|
2018-05-14 14:45:05 -06:00
|
|
|
vm->hasManagedSave = managed;
|
2011-05-30 11:53:02 +02:00
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2011-05-30 11:53:02 +02:00
|
|
|
if (VIR_CLOSE(fd) < 0)
|
|
|
|
virReportSystemError(errno, "%s", _("cannot close file"));
|
2018-06-12 13:33:01 -04:00
|
|
|
virObjectEventStateQueue(driver->domainEventState, event);
|
2015-02-11 16:40:07 -07:00
|
|
|
virObjectUnref(cfg);
|
2011-05-30 11:53:02 +02:00
|
|
|
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 20:55:29 -06:00
|
|
|
libxlDomainSaveFlags(virDomainPtr dom, const char *to, const char *dxml,
|
|
|
|
unsigned int flags)
|
2011-05-30 11:53:02 +02:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
virDomainObj *vm;
|
2011-05-30 11:53:02 +02:00
|
|
|
int ret = -1;
|
|
|
|
|
2014-06-24 11:10:49 -06:00
|
|
|
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
|
|
|
|
virReportUnsupportedError();
|
|
|
|
return -1;
|
|
|
|
#endif
|
|
|
|
|
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 20:55:29 -06:00
|
|
|
virCheckFlags(0, -1);
|
|
|
|
if (dxml) {
|
2012-07-18 14:32:10 +01: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 20:55:29 -06:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-05-30 11:53:02 +02:00
|
|
|
goto cleanup;
|
|
|
|
|
2015-06-22 11:36:59 -06:00
|
|
|
LIBXL_CHECK_DOM0_GOTO(vm->def->name, cleanup);
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virDomainSaveFlagsEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2014-02-06 16:34:58 -07:00
|
|
|
if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2018-04-17 22:13:29 +00:00
|
|
|
if (virDomainObjCheckActive(vm) < 0)
|
2014-02-06 16:34:58 -07:00
|
|
|
goto endjob;
|
2011-05-30 11:53:02 +02:00
|
|
|
|
2018-05-14 14:45:05 -06:00
|
|
|
if (libxlDoDomainSave(driver, vm, to, false) < 0)
|
2014-02-06 16:34:58 -07:00
|
|
|
goto endjob;
|
2013-01-21 10:32:34 -07:00
|
|
|
|
2014-02-06 16:34:58 -07:00
|
|
|
if (!vm->persistent)
|
2018-04-23 10:40:48 -04:00
|
|
|
virDomainObjListRemove(driver->domains, vm);
|
2013-01-21 10:32:34 -07:00
|
|
|
|
|
|
|
ret = 0;
|
2011-05-30 11:53:02 +02:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
endjob:
|
2016-06-12 18:30:00 +08:00
|
|
|
libxlDomainObjEndJob(driver, vm);
|
2014-02-06 16:34:58 -07:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2016-06-12 18:30:00 +08:00
|
|
|
virDomainObjEndAPI(&vm);
|
2011-06-02 20:24:30 +08:00
|
|
|
return ret;
|
|
|
|
}
|
2011-05-30 11:53:02 +02:00
|
|
|
|
2011-06-02 20:24:30 +08: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 20:55:29 -06: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 20:24:30 +08:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = conn->privateData;
|
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
|
|
|
virDomainObj *vm = NULL;
|
|
|
|
virDomainDef *def = NULL;
|
2011-06-02 20:24:30 +08:00
|
|
|
libxlSavefileHeader hdr;
|
|
|
|
int fd = -1;
|
|
|
|
int ret = -1;
|
2011-05-30 11:53:02 +02:00
|
|
|
|
2014-06-24 11:10:49 -06:00
|
|
|
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
|
|
|
|
virReportUnsupportedError();
|
|
|
|
return -1;
|
|
|
|
#endif
|
|
|
|
|
2013-06-13 03:54:11 +02: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 20:55:29 -06:00
|
|
|
if (dxml) {
|
2012-07-18 14:32:10 +01: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 20:55:29 -06:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-02-25 21:28:51 -07:00
|
|
|
fd = libxlDomainSaveImageOpen(driver, cfg, from, &def, &hdr);
|
2011-06-02 20:24:30 +08:00
|
|
|
if (fd < 0)
|
2015-03-01 18:24:26 -07:00
|
|
|
goto cleanup;
|
2011-05-30 11:53:02 +02:00
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virDomainRestoreFlagsEnsureACL(conn, def) < 0)
|
2015-03-01 18:33:48 -07:00
|
|
|
goto cleanup;
|
2013-04-23 11:56:22 +01:00
|
|
|
|
2013-03-28 14:55:55 +01:00
|
|
|
if (!(vm = virDomainObjListAdd(driver->domains, def,
|
2013-03-31 20:03:42 +02: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 14:46:58 +00:00
|
|
|
VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
|
|
|
|
VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
|
|
|
|
NULL)))
|
2015-03-01 18:33:48 -07:00
|
|
|
goto cleanup;
|
2011-05-30 11:53:02 +02:00
|
|
|
def = NULL;
|
|
|
|
|
2015-03-01 18:24:26 -07:00
|
|
|
if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0) {
|
2018-04-23 10:40:48 -04:00
|
|
|
if (!vm->persistent)
|
2015-03-01 18:24:26 -07:00
|
|
|
virDomainObjListRemove(driver->domains, vm);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
libxl: support Xen migration stream V2 in save/restore
Xen 4.6 introduced a new migration stream commonly referred to as
"migration V2". Xen 4.6 and newer always produce this new stream,
whereas Xen 4.5 and older always produce the legacy stream.
Support for migration stream V2 can be detected at build time with
LIBXL_HAVE_SRM_V2 from libxl.h. The legacy and V2 streams are not
compatible, but a V2 host can accept and convert a legacy stream.
Commit e7440656 changed the libxl driver to use the lowest libxl
API version possible (version 0x040200) to ensure the driver
builds against older Xen releases. The old 4.2 restore API does
not support specifying a stream version and assumes a legacy
stream, even if the incoming stream is migration V2. Thinking it
has been given a legacy stream, libxl will fail to convert an
incoming stream that is already V2, which causes the entire
restore operation to fail. Xen's libvirt-related OSSTest has been
failing since commit e7440656 landed in libvirt.git master. One
of the more recent failures can be seen here
http://lists.xenproject.org/archives/html/xen-devel/2016-05/msg00071.html
This patch changes the call to libxl_domain_create_restore() to
include the stream version if LIBXL_HAVE_SRM_V2 is defined. The
version field of the libxlSavefileHeader struct is also updated
to '2' when LIBXL_HAVE_SRM_V2 is defined, ensuring the stream
version in the header matches the actual stream version produced
by Xen. Along with bumping the libxl API requirement to 0x040400,
this patch fixes save/restore on a migration V2 Xen host.
Oddly, migration has never used the libxlSavefileHeader. It
handles passing configuration in the Begin and Prepare phases,
and then calls libxl directly to transfer domain state/memory
in the Perform phase. A subsequent patch will add stream
version handling in the Begin and Prepare phase handshaking,
which will fix the migration related OSSTest failures.
Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2016-05-02 12:00:39 -06:00
|
|
|
ret = libxlDomainStartRestore(driver, vm,
|
|
|
|
(flags & VIR_DOMAIN_SAVE_PAUSED) != 0,
|
|
|
|
fd, hdr.version);
|
2018-04-23 10:40:48 -04:00
|
|
|
if (ret < 0 && !vm->persistent)
|
2013-01-11 16:04:47 +00:00
|
|
|
virDomainObjListRemove(driver->domains, vm);
|
2015-03-01 18:24:26 -07:00
|
|
|
|
2016-06-12 18:30:00 +08:00
|
|
|
libxlDomainObjEndJob(driver, vm);
|
2011-05-30 11:53:02 +02:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2011-06-02 15:41:13 -06:00
|
|
|
if (VIR_CLOSE(fd) < 0)
|
|
|
|
virReportSystemError(errno, "%s", _("cannot close file"));
|
2011-05-30 11:53:02 +02:00
|
|
|
virDomainDefFree(def);
|
2016-06-12 18:30:00 +08:00
|
|
|
virDomainObjEndAPI(&vm);
|
2013-08-30 14:57:42 -06:00
|
|
|
virObjectUnref(cfg);
|
2011-05-30 11:53:02 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
save: wire up trivial save/restore flags implementations
For all hypervisors that support save and restore, the new API
now performs the same functions as the old.
VBox is excluded from this list, because its existing domainsave
is broken (there is no corresponding domainrestore, and there
is no control over the filename used in the save). A later
patch should change vbox to use its implementation for
managedsave, and teach start to use managedsave results.
* src/libxl/libxl_driver.c (libxlDomainSave): Move guts...
(libxlDomainSaveFlags): ...to new function.
(libxlDomainRestore): Move guts...
(libxlDomainRestoreFlags): ...to new function.
* src/test/test_driver.c (testDomainSave, testDomainSaveFlags)
(testDomainRestore, testDomainRestoreFlags): Likewise.
* src/xen/xen_driver.c (xenUnifiedDomainSave)
(xenUnifiedDomainSaveFlags, xenUnifiedDomainRestore)
(xenUnifiedDomainRestoreFlags): Likewise.
* src/qemu/qemu_driver.c (qemudDomainSave, qemudDomainRestore):
Rename and move guts.
(qemuDomainSave, qemuDomainSaveFlags, qemuDomainRestore)
(qemuDomainRestoreFlags): ...here.
(qemudDomainSaveFlag): Rename...
(qemuDomainSaveInternal): ...to this, and update callers.
2011-07-08 20:55:29 -06:00
|
|
|
static int
|
|
|
|
libxlDomainRestore(virConnectPtr conn, const char *from)
|
|
|
|
{
|
|
|
|
return libxlDomainRestoreFlags(conn, from, NULL, 0);
|
|
|
|
}
|
|
|
|
|
2011-05-30 11:53:01 +02:00
|
|
|
static int
|
2011-07-06 14:40:19 -06:00
|
|
|
libxlDomainCoreDump(virDomainPtr dom, const char *to, unsigned int flags)
|
2011-05-30 11:53:01 +02:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
|
|
|
virDomainObj *vm;
|
|
|
|
virObjectEvent *event = NULL;
|
2011-05-30 11:53:01 +02:00
|
|
|
bool paused = false;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(VIR_DUMP_LIVE | VIR_DUMP_CRASH, -1);
|
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-05-30 11:53:01 +02:00
|
|
|
goto cleanup;
|
|
|
|
|
2015-06-22 11:36:59 -06:00
|
|
|
LIBXL_CHECK_DOM0_GOTO(vm->def->name, cleanup);
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virDomainCoreDumpEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2014-02-06 16:54:39 -07:00
|
|
|
if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2018-04-17 22:13:29 +00:00
|
|
|
if (virDomainObjCheckActive(vm) < 0)
|
2014-02-06 16:54:39 -07:00
|
|
|
goto endjob;
|
2011-05-30 11:53:01 +02:00
|
|
|
|
|
|
|
if (!(flags & VIR_DUMP_LIVE) &&
|
|
|
|
virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
|
2021-03-25 17:26:05 +01:00
|
|
|
if (libxlDomainPauseWrapper(cfg->ctx, vm->def->id) != 0) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Before dumping core, failed to suspend domain '%d'"
|
|
|
|
" with libxenlight"),
|
2014-03-27 17:55:02 +01:00
|
|
|
vm->def->id);
|
2014-02-06 16:54:39 -07:00
|
|
|
goto endjob;
|
2011-05-30 11:53:01 +02:00
|
|
|
}
|
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_DUMP);
|
|
|
|
paused = true;
|
|
|
|
}
|
|
|
|
|
2014-02-06 16:54:39 -07:00
|
|
|
/* Unlock virDomainObj while dumping core */
|
|
|
|
virObjectUnlock(vm);
|
2015-02-11 16:40:07 -07:00
|
|
|
ret = libxl_domain_core_dump(cfg->ctx, vm->def->id, to, NULL);
|
2014-02-06 16:54:39 -07:00
|
|
|
virObjectLock(vm);
|
|
|
|
if (ret != 0) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to dump core of domain '%d' with libxenlight"),
|
2014-03-27 17:55:02 +01:00
|
|
|
vm->def->id);
|
2014-02-06 16:54:39 -07:00
|
|
|
ret = -1;
|
|
|
|
goto unpause;
|
2011-05-30 11:53:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & VIR_DUMP_CRASH) {
|
2015-03-03 17:54:50 -07:00
|
|
|
if (libxlDomainDestroyInternal(driver, vm) < 0) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2014-03-27 17:55:02 +01:00
|
|
|
_("Failed to destroy domain '%d'"), vm->def->id);
|
2014-02-06 16:54:39 -07:00
|
|
|
goto unpause;
|
2011-05-30 11:53:01 +02:00
|
|
|
}
|
|
|
|
|
2015-07-07 12:29:24 -06:00
|
|
|
libxlDomainCleanup(driver, vm);
|
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF,
|
|
|
|
VIR_DOMAIN_SHUTOFF_CRASHED);
|
2013-11-21 18:03:26 +01:00
|
|
|
event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
|
2011-05-30 11:53:01 +02:00
|
|
|
VIR_DOMAIN_EVENT_STOPPED_CRASHED);
|
2014-02-06 16:54:39 -07:00
|
|
|
if (!vm->persistent)
|
2018-04-23 10:40:48 -04:00
|
|
|
virDomainObjListRemove(driver->domains, vm);
|
2011-05-30 11:53:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
unpause:
|
2014-02-06 16:54:39 -07:00
|
|
|
if (virDomainObjIsActive(vm) && paused) {
|
2021-03-25 17:26:06 +01:00
|
|
|
if (libxlDomainUnpauseWrapper(cfg->ctx, vm->def->id) != 0) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("After dumping core, failed to resume domain '%d' with"
|
2014-03-27 17:55:02 +01:00
|
|
|
" libxenlight"), vm->def->id);
|
2011-05-30 11:53:01 +02:00
|
|
|
} else {
|
|
|
|
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
|
|
|
|
VIR_DOMAIN_RUNNING_UNPAUSED);
|
|
|
|
}
|
|
|
|
}
|
2014-02-06 16:54:39 -07:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
endjob:
|
2016-06-12 18:30:00 +08:00
|
|
|
libxlDomainObjEndJob(driver, vm);
|
2014-02-06 16:54:39 -07:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2016-06-12 18:30:00 +08:00
|
|
|
virDomainObjEndAPI(&vm);
|
2018-06-12 13:33:01 -04:00
|
|
|
virObjectEventStateQueue(driver->domainEventState, event);
|
2015-02-11 16:40:07 -07:00
|
|
|
virObjectUnref(cfg);
|
2011-05-30 11:53:01 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-06-02 20:24:30 +08:00
|
|
|
static int
|
|
|
|
libxlDomainManagedSave(virDomainPtr dom, unsigned int flags)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
virDomainObj *vm = NULL;
|
2021-02-16 18:37:09 -07:00
|
|
|
g_autofree char *name = NULL;
|
2011-06-02 20:24:30 +08:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-06-02 20:24:30 +08:00
|
|
|
goto cleanup;
|
|
|
|
|
2015-06-22 11:36:59 -06:00
|
|
|
LIBXL_CHECK_DOM0_GOTO(vm->def->name, cleanup);
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virDomainManagedSaveEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2014-02-06 16:34:58 -07:00
|
|
|
if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2018-04-17 22:13:29 +00:00
|
|
|
if (virDomainObjCheckActive(vm) < 0)
|
2014-02-06 16:34:58 -07:00
|
|
|
goto endjob;
|
2011-08-10 08:51:36 -06:00
|
|
|
if (!vm->persistent) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("cannot do managed save for transient domain"));
|
2014-02-06 16:34:58 -07:00
|
|
|
goto endjob;
|
2011-08-10 08:51:36 -06:00
|
|
|
}
|
2011-06-02 20:24:30 +08:00
|
|
|
|
|
|
|
name = libxlDomainManagedSavePath(driver, vm);
|
|
|
|
if (name == NULL)
|
2014-02-06 16:34:58 -07:00
|
|
|
goto endjob;
|
2011-06-02 20:24:30 +08:00
|
|
|
|
|
|
|
VIR_INFO("Saving state to %s", name);
|
|
|
|
|
2018-05-14 14:45:05 -06:00
|
|
|
if (libxlDoDomainSave(driver, vm, name, true) < 0)
|
2014-02-06 16:34:58 -07:00
|
|
|
goto endjob;
|
2013-01-21 10:32:34 -07:00
|
|
|
|
2014-02-06 16:34:58 -07:00
|
|
|
if (!vm->persistent)
|
2018-04-23 10:40:48 -04:00
|
|
|
virDomainObjListRemove(driver->domains, vm);
|
2013-01-21 10:32:34 -07:00
|
|
|
|
|
|
|
ret = 0;
|
2011-06-02 20:24:30 +08:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
endjob:
|
2016-06-12 18:30:00 +08:00
|
|
|
libxlDomainObjEndJob(driver, vm);
|
2014-02-06 16:34:58 -07:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2016-06-12 18:30:00 +08:00
|
|
|
virDomainObjEndAPI(&vm);
|
2011-06-02 20:24:30 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-01-11 13:54:15 +00:00
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDomainManagedSaveLoad(virDomainObj *vm,
|
2012-06-11 11:03:27 +02:00
|
|
|
void *opaque)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = opaque;
|
2012-06-11 11:03:27 +02:00
|
|
|
char *name;
|
2013-01-11 13:54:15 +00:00
|
|
|
int ret = -1;
|
2012-06-11 11:03:27 +02:00
|
|
|
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectLock(vm);
|
2012-06-11 11:03:27 +02:00
|
|
|
|
|
|
|
if (!(name = libxlDomainManagedSavePath(driver, vm)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
vm->hasManagedSave = virFileExists(name);
|
|
|
|
|
2013-01-11 13:54:15 +00:00
|
|
|
ret = 0;
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(vm);
|
2012-06-11 11:03:27 +02:00
|
|
|
VIR_FREE(name);
|
2013-01-11 13:54:15 +00:00
|
|
|
return ret;
|
2012-06-11 11:03:27 +02:00
|
|
|
}
|
|
|
|
|
2011-06-02 20:24:30 +08:00
|
|
|
static int
|
|
|
|
libxlDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainObj *vm = NULL;
|
2011-06-02 20:24:30 +08:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-06-02 20:24:30 +08:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virDomainHasManagedSaveImageEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2012-06-11 11:03:27 +02:00
|
|
|
ret = vm->hasManagedSave;
|
2011-06-02 20:24:30 +08:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2018-03-09 11:47:59 -05:00
|
|
|
virDomainObjEndAPI(&vm);
|
2011-06-02 20:24:30 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainManagedSaveRemove(virDomainPtr dom, unsigned int flags)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
virDomainObj *vm = NULL;
|
2011-06-02 20:24:30 +08:00
|
|
|
int ret = -1;
|
2021-02-16 18:37:09 -07:00
|
|
|
g_autofree char *name = NULL;
|
2011-06-02 20:24:30 +08:00
|
|
|
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-06-02 20:24:30 +08:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virDomainManagedSaveRemoveEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-06-02 20:24:30 +08:00
|
|
|
name = libxlDomainManagedSavePath(driver, vm);
|
|
|
|
if (name == NULL)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = unlink(name);
|
2012-06-11 11:03:27 +02:00
|
|
|
vm->hasManagedSave = false;
|
2011-06-02 20:24:30 +08:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2018-03-09 11:47:59 -05:00
|
|
|
virDomainObjEndAPI(&vm);
|
2011-06-02 20:24:30 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-03-29 20:31:45 +08:00
|
|
|
static int
|
|
|
|
libxlDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
|
|
|
virDomainDef *def;
|
|
|
|
virDomainObj *vm;
|
2012-11-26 09:28:56 -07:00
|
|
|
libxl_bitmap map;
|
2011-03-29 20:31:45 +08: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 15:09:33 +01:00
|
|
|
size_t i;
|
|
|
|
unsigned int pos;
|
2011-03-29 20:31:45 +08: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 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("invalid flag combination: (0x%x)"), flags);
|
2011-03-29 20:31:45 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!nvcpus) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s", _("nvcpus is zero"));
|
2011-03-29 20:31:45 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-03-29 20:31:45 +08:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virDomainSetVcpusFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2014-02-06 17:16:14 -07:00
|
|
|
if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-03-29 20:31:45 +08:00
|
|
|
if (!virDomainObjIsActive(vm) && (flags & VIR_DOMAIN_VCPU_LIVE)) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("cannot set vcpus on an inactive domain"));
|
2014-02-06 17:16:14 -07:00
|
|
|
goto endjob;
|
2011-03-29 20:31:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!vm->persistent && (flags & VIR_DOMAIN_VCPU_CONFIG)) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("cannot change persistent config of a transient domain"));
|
2014-02-06 17:16:14 -07:00
|
|
|
goto endjob;
|
2011-03-29 20:31:45 +08:00
|
|
|
}
|
|
|
|
|
2013-04-23 13:50:18 +01:00
|
|
|
if ((max = libxlConnectGetMaxVcpus(dom->conn, NULL)) < 0) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("could not determine max vcpus for the domain"));
|
2014-02-06 17:16:14 -07:00
|
|
|
goto endjob;
|
2011-03-29 20:31:45 +08:00
|
|
|
}
|
|
|
|
|
2015-10-19 19:21:24 +02:00
|
|
|
if (!(flags & VIR_DOMAIN_VCPU_MAXIMUM) && virDomainDefGetVcpusMax(vm->def) < max)
|
|
|
|
max = virDomainDefGetVcpusMax(vm->def);
|
2011-03-29 20:31:45 +08:00
|
|
|
|
|
|
|
if (nvcpus > max) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("requested vcpus is greater than max allowable"
|
|
|
|
" vcpus for the domain: %d > %d"), nvcpus, max);
|
2014-02-06 17:16:14 -07:00
|
|
|
goto endjob;
|
2011-03-29 20:31:45 +08:00
|
|
|
}
|
|
|
|
|
2019-11-27 12:41:59 +00:00
|
|
|
if (!(def = virDomainObjGetPersistentDef(driver->xmlopt, vm, NULL)))
|
2014-02-06 17:16:14 -07:00
|
|
|
goto endjob;
|
2011-03-29 20:31:45 +08:00
|
|
|
|
2011-04-05 10:07:57 -06:00
|
|
|
maplen = VIR_CPU_MAPLEN(nvcpus);
|
2020-09-23 20:43:09 +02:00
|
|
|
bitmask = g_new0(uint8_t, maplen);
|
2011-03-29 20:31:45 +08:00
|
|
|
|
|
|
|
for (i = 0; i < nvcpus; ++i) {
|
2011-04-05 10:07:57 -06:00
|
|
|
pos = i / 8;
|
2011-03-29 20:31:45 +08:00
|
|
|
bitmask[pos] |= 1 << (i % 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
map.size = maplen;
|
|
|
|
map.map = bitmask;
|
|
|
|
|
|
|
|
switch (flags) {
|
|
|
|
case VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_CONFIG:
|
2016-06-29 14:55:24 +02:00
|
|
|
if (virDomainDefSetVcpusMax(def, nvcpus, driver->xmlopt) < 0)
|
2015-10-16 16:10:27 +02:00
|
|
|
goto cleanup;
|
2011-03-29 20:31:45 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_VCPU_CONFIG:
|
2015-10-22 10:52:05 +02:00
|
|
|
if (virDomainDefSetVcpus(def, nvcpus) < 0)
|
|
|
|
goto cleanup;
|
2011-03-29 20:31:45 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_VCPU_LIVE:
|
2021-03-25 17:26:09 +01:00
|
|
|
if (libxlSetVcpuonlineWrapper(cfg->ctx, vm->def->id, &map) != 0) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to set vcpus for domain '%d'"
|
2014-03-27 17:55:02 +01:00
|
|
|
" with libxenlight"), vm->def->id);
|
2014-02-06 17:16:14 -07:00
|
|
|
goto endjob;
|
2011-03-29 20:31:45 +08:00
|
|
|
}
|
2015-10-22 10:52:05 +02:00
|
|
|
if (virDomainDefSetVcpus(vm->def, nvcpus) < 0)
|
|
|
|
goto endjob;
|
2011-03-29 20:31:45 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG:
|
2021-03-25 17:26:09 +01:00
|
|
|
if (libxlSetVcpuonlineWrapper(cfg->ctx, vm->def->id, &map) != 0) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to set vcpus for domain '%d'"
|
2014-03-27 17:55:02 +01:00
|
|
|
" with libxenlight"), vm->def->id);
|
2014-02-06 17:16:14 -07:00
|
|
|
goto endjob;
|
2011-03-29 20:31:45 +08:00
|
|
|
}
|
2015-10-22 10:52:05 +02:00
|
|
|
if (virDomainDefSetVcpus(vm->def, nvcpus) < 0 ||
|
|
|
|
virDomainDefSetVcpus(def, nvcpus) < 0)
|
|
|
|
goto endjob;
|
2011-03-29 20:31:45 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2015-06-29 10:46:36 -06:00
|
|
|
if (flags & VIR_DOMAIN_VCPU_LIVE) {
|
2019-11-27 12:53:10 +00:00
|
|
|
if (virDomainObjSave(vm, driver->xmlopt, cfg->stateDir) < 0) {
|
2015-06-29 10:46:36 -06:00
|
|
|
VIR_WARN("Unable to save status on vm %s after changing vcpus",
|
|
|
|
vm->def->name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (flags & VIR_DOMAIN_VCPU_CONFIG) {
|
2019-11-27 12:53:10 +00:00
|
|
|
if (virDomainDefSave(def, driver->xmlopt, cfg->configDir) < 0) {
|
2015-06-29 10:46:36 -06:00
|
|
|
VIR_WARN("Unable to save configuration of vm %s after changing vcpus",
|
|
|
|
vm->def->name);
|
|
|
|
}
|
|
|
|
}
|
2011-03-29 20:31:45 +08:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
endjob:
|
2016-06-12 18:30:00 +08:00
|
|
|
libxlDomainObjEndJob(driver, vm);
|
2014-02-06 17:16:14 -07:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2011-03-29 20:31:45 +08:00
|
|
|
VIR_FREE(bitmask);
|
2016-06-12 18:30:00 +08:00
|
|
|
virDomainObjEndAPI(&vm);
|
|
|
|
virObjectUnref(cfg);
|
2011-03-29 20:31:45 +08: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)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainObj *vm;
|
|
|
|
virDomainDef *def;
|
2011-03-29 20:31:45 +08:00
|
|
|
int ret = -1;
|
2011-07-15 17:35:47 -06:00
|
|
|
bool active;
|
2011-03-29 20:31:45 +08:00
|
|
|
|
|
|
|
virCheckFlags(VIR_DOMAIN_VCPU_LIVE |
|
|
|
|
VIR_DOMAIN_VCPU_CONFIG |
|
|
|
|
VIR_DOMAIN_VCPU_MAXIMUM, -1);
|
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-03-29 20:31:45 +08:00
|
|
|
goto cleanup;
|
|
|
|
|
api: require write permission for guest agent interaction
I noticed that we allow virDomainGetVcpusFlags even for read-only
connections, but that with a flag, it can require guest agent
interaction. It is feasible that a malicious guest could
intentionally abuse the replies it sends over the guest agent
connection to possibly trigger a bug in libvirt's JSON parser,
or withhold an answer so as to prevent the use of the agent
in a later command such as a shutdown request. Although we
don't know of any such exploits now (and therefore don't mind
posting this patch publicly without trying to get a CVE assigned),
it is better to err on the side of caution and explicitly require
full access to any domain where the API requires guest interaction
to operate correctly.
I audited all commands that are marked as conditionally using a
guest agent. Note that at least virDomainFSTrim is documented
as needing a guest agent, but that such use is unconditional
depending on the hypervisor (so the existing domain:fs_trim ACL
should be sufficient there, rather than also requirng domain:write).
But when designing future APIs, such as the plans for obtaining
a domain's IP addresses, we should copy the approach of this patch
in making interaction with the guest be specified via a flag, and
use that flag to also require stricter access checks.
* src/libvirt.c (virDomainGetVcpusFlags): Forbid guest interaction
on read-only connection.
(virDomainShutdownFlags, virDomainReboot): Improve docs on agent
interaction.
* src/remote/remote_protocol.x
(REMOTE_PROC_DOMAIN_SNAPSHOT_CREATE_XML)
(REMOTE_PROC_DOMAIN_SET_VCPUS_FLAGS)
(REMOTE_PROC_DOMAIN_GET_VCPUS_FLAGS, REMOTE_PROC_DOMAIN_REBOOT)
(REMOTE_PROC_DOMAIN_SHUTDOWN_FLAGS): Require domain:write for any
conditional use of a guest agent.
* src/xen/xen_driver.c: Fix clients.
* src/libxl/libxl_driver.c: Likewise.
* src/uml/uml_driver.c: Likewise.
* src/qemu/qemu_driver.c: Likewise.
* src/lxc/lxc_driver.c: Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-21 10:37:29 -07:00
|
|
|
if (virDomainGetVcpusFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
|
2013-04-23 11:56:22 +01:00
|
|
|
goto cleanup;
|
|
|
|
|
2011-07-15 17:35:47 -06: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 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("invalid flag combination: (0x%x)"), flags);
|
2011-07-15 17:35:47 -06:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-03-29 20:31:45 +08:00
|
|
|
if (flags & VIR_DOMAIN_VCPU_LIVE) {
|
2011-07-15 17:35:47 -06:00
|
|
|
if (!active) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("Domain is not running"));
|
2011-03-29 20:31:45 +08:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
def = vm->def;
|
|
|
|
} else {
|
2011-07-15 17:35:47 -06:00
|
|
|
if (!vm->persistent) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("domain is transient"));
|
2011-07-15 17:35:47 -06:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2011-03-29 20:31:45 +08:00
|
|
|
def = vm->newDef ? vm->newDef : vm->def;
|
|
|
|
}
|
|
|
|
|
2015-10-19 19:21:24 +02:00
|
|
|
if (flags & VIR_DOMAIN_VCPU_MAXIMUM)
|
|
|
|
ret = virDomainDefGetVcpusMax(def);
|
|
|
|
else
|
2015-10-22 14:59:03 +02:00
|
|
|
ret = virDomainDefGetVcpus(def);
|
2011-03-29 20:31:45 +08:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2018-03-09 11:47:59 -05:00
|
|
|
virDomainObjEndAPI(&vm);
|
2011-03-29 20:31:45 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-01-06 12:19:31 -07:00
|
|
|
static int
|
|
|
|
libxlDomainGetMaxVcpus(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
return libxlDomainGetVcpusFlags(dom, (VIR_DOMAIN_AFFECT_LIVE |
|
|
|
|
VIR_DOMAIN_VCPU_MAXIMUM));
|
|
|
|
}
|
|
|
|
|
2011-03-29 20:31:45 +08:00
|
|
|
static int
|
2013-12-20 16:01:39 +01:00
|
|
|
libxlDomainPinVcpuFlags(virDomainPtr dom, unsigned int vcpu,
|
|
|
|
unsigned char *cpumap, int maplen,
|
|
|
|
unsigned int flags)
|
2011-03-29 20:31:45 +08:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
|
|
|
virDomainDef *targetDef = NULL;
|
|
|
|
virBitmap *pcpumap = NULL;
|
|
|
|
virDomainVcpuDef *vcpuinfo;
|
|
|
|
virDomainObj *vm;
|
2011-03-29 20:31:45 +08:00
|
|
|
int ret = -1;
|
2013-12-20 16:01:39 +01:00
|
|
|
|
|
|
|
virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
|
|
|
|
VIR_DOMAIN_AFFECT_CONFIG, -1);
|
2011-03-29 20:31:45 +08:00
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-03-29 20:31:45 +08:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-12-20 16:01:39 +01:00
|
|
|
if (virDomainPinVcpuFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
|
2013-04-23 11:56:22 +01:00
|
|
|
goto cleanup;
|
|
|
|
|
2014-02-06 17:16:14 -07:00
|
|
|
if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2013-12-20 16:01:39 +01:00
|
|
|
if (virDomainLiveConfigHelperMethod(cfg->caps, driver->xmlopt, vm,
|
|
|
|
&flags, &targetDef) < 0)
|
2014-02-06 17:16:14 -07:00
|
|
|
goto endjob;
|
2013-12-20 16:01:39 +01:00
|
|
|
|
2014-11-13 15:27:11 +01:00
|
|
|
if (flags & VIR_DOMAIN_AFFECT_LIVE)
|
2013-12-20 16:01:39 +01:00
|
|
|
targetDef = vm->def;
|
|
|
|
|
|
|
|
/* Make sure coverity knows targetDef is valid at this point. */
|
|
|
|
sa_assert(targetDef);
|
|
|
|
|
2013-12-20 16:01:46 +01:00
|
|
|
pcpumap = virBitmapNewData(cpumap, maplen);
|
|
|
|
if (!pcpumap)
|
2014-02-06 17:16:14 -07:00
|
|
|
goto endjob;
|
2013-12-20 16:01:46 +01:00
|
|
|
|
2016-01-29 10:20:44 +01:00
|
|
|
if (!(vcpuinfo = virDomainDefGetVcpu(targetDef, vcpu)) ||
|
|
|
|
!vcpuinfo->online) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("vcpu '%u' is not active"), vcpu);
|
|
|
|
goto endjob;
|
|
|
|
}
|
|
|
|
|
2013-12-20 16:01:39 +01:00
|
|
|
if (flags & VIR_DOMAIN_AFFECT_LIVE) {
|
|
|
|
libxl_bitmap map = { .size = maplen, .map = cpumap };
|
2018-03-27 11:50:14 -06:00
|
|
|
if (libxl_set_vcpuaffinity(cfg->ctx, vm->def->id, vcpu, &map, NULL) != 0) {
|
2013-12-20 16:01:39 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to pin vcpu '%d' with libxenlight"),
|
|
|
|
vcpu);
|
2014-02-06 17:16:14 -07:00
|
|
|
goto endjob;
|
2013-12-20 16:01:39 +01:00
|
|
|
}
|
2011-03-29 20:31:45 +08:00
|
|
|
}
|
2011-04-18 11:16:33 +02:00
|
|
|
|
2016-01-29 10:20:44 +01:00
|
|
|
virBitmapFree(vcpuinfo->cpumask);
|
2021-03-24 10:32:58 +01:00
|
|
|
vcpuinfo->cpumask = g_steal_pointer(&pcpumap);
|
2011-04-18 11:16:33 +02:00
|
|
|
|
2011-03-29 20:31:45 +08:00
|
|
|
ret = 0;
|
|
|
|
|
2013-12-20 16:01:39 +01:00
|
|
|
if (flags & VIR_DOMAIN_AFFECT_LIVE) {
|
2019-11-27 12:53:10 +00:00
|
|
|
ret = virDomainObjSave(vm, driver->xmlopt, cfg->stateDir);
|
2013-12-20 16:01:39 +01:00
|
|
|
} else if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
|
2019-11-27 12:53:10 +00:00
|
|
|
ret = virDomainDefSave(targetDef, driver->xmlopt, cfg->configDir);
|
2013-12-20 16:01:39 +01:00
|
|
|
}
|
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
endjob:
|
2016-06-12 18:30:00 +08:00
|
|
|
libxlDomainObjEndJob(driver, vm);
|
2014-02-06 17:16:14 -07:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2016-06-12 18:30:00 +08:00
|
|
|
virDomainObjEndAPI(&vm);
|
2013-12-20 16:01:46 +01:00
|
|
|
virBitmapFree(pcpumap);
|
2013-08-30 14:52:14 -06:00
|
|
|
virObjectUnref(cfg);
|
2011-03-29 20:31:45 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-12-20 16:01:39 +01:00
|
|
|
static int
|
|
|
|
libxlDomainPinVcpu(virDomainPtr dom, unsigned int vcpu, unsigned char *cpumap,
|
|
|
|
int maplen)
|
|
|
|
{
|
|
|
|
return libxlDomainPinVcpuFlags(dom, vcpu, cpumap, maplen,
|
|
|
|
VIR_DOMAIN_AFFECT_LIVE);
|
|
|
|
}
|
|
|
|
|
2013-12-20 16:01:31 +01:00
|
|
|
static int
|
|
|
|
libxlDomainGetVcpuPinInfo(virDomainPtr dom, int ncpumaps,
|
|
|
|
unsigned char *cpumaps, int maplen,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
|
|
|
virDomainObj *vm = NULL;
|
|
|
|
virDomainDef *targetDef = NULL;
|
2020-08-07 15:48:27 +02:00
|
|
|
g_autoptr(virBitmap) hostcpus = NULL;
|
2016-02-22 15:29:25 +01:00
|
|
|
int ret = -1;
|
2013-12-20 16:01:31 +01:00
|
|
|
|
|
|
|
virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
|
|
|
|
VIR_DOMAIN_AFFECT_CONFIG, -1);
|
|
|
|
|
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virDomainGetVcpuPinInfoEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virDomainLiveConfigHelperMethod(cfg->caps, driver->xmlopt, vm,
|
|
|
|
&flags, &targetDef) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2014-11-13 15:27:11 +01:00
|
|
|
if (flags & VIR_DOMAIN_AFFECT_LIVE)
|
2013-12-20 16:01:31 +01:00
|
|
|
targetDef = vm->def;
|
|
|
|
|
|
|
|
/* Make sure coverity knows targetDef is valid at this point. */
|
|
|
|
sa_assert(targetDef);
|
|
|
|
|
2020-10-01 17:42:11 +02:00
|
|
|
hostcpus = virBitmapNew(libxl_get_max_cpus(cfg->ctx));
|
2020-08-07 15:48:27 +02:00
|
|
|
virBitmapSetAll(hostcpus);
|
|
|
|
|
2016-02-22 15:29:25 +01:00
|
|
|
ret = virDomainDefGetVcpuPinInfoHelper(targetDef, maplen, ncpumaps, cpumaps,
|
2020-08-07 15:48:27 +02:00
|
|
|
hostcpus, NULL);
|
2013-12-20 16:01:31 +01:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2018-03-09 11:47:59 -05:00
|
|
|
virDomainObjEndAPI(&vm);
|
2013-12-20 16:01:31 +01:00
|
|
|
virObjectUnref(cfg);
|
|
|
|
return ret;
|
|
|
|
}
|
2011-03-29 20:31:45 +08:00
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainGetVcpus(virDomainPtr dom, virVcpuInfoPtr info, int maxinfo,
|
|
|
|
unsigned char *cpumaps, int maplen)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
|
|
|
virDomainObj *vm;
|
2011-03-29 20:31:45 +08:00
|
|
|
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 15:09:33 +01:00
|
|
|
size_t i;
|
2011-03-29 20:31:45 +08:00
|
|
|
unsigned char *cpumap;
|
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-03-29 20:31:45 +08:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virDomainGetVcpusEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2018-04-17 22:13:29 +00:00
|
|
|
if (virDomainObjCheckActive(vm) < 0)
|
2011-03-29 20:31:45 +08:00
|
|
|
goto cleanup;
|
|
|
|
|
2015-02-11 16:40:07 -07:00
|
|
|
if ((vcpuinfo = libxl_list_vcpu(cfg->ctx, vm->def->id, &maxcpu,
|
2011-03-29 20:31:45 +08:00
|
|
|
&hostcpus)) == NULL) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to list vcpus for domain '%d' with libxenlight"),
|
2014-03-27 17:55:02 +01:00
|
|
|
vm->def->id);
|
2011-03-29 20:31:45 +08: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 09:28:56 -07:00
|
|
|
libxl_vcpuinfo_dispose(&vcpuinfo[i]);
|
2011-03-29 20:31:45 +08:00
|
|
|
}
|
|
|
|
VIR_FREE(vcpuinfo);
|
|
|
|
|
|
|
|
ret = maxinfo;
|
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2018-03-09 11:47:59 -05:00
|
|
|
virDomainObjEndAPI(&vm);
|
2015-02-11 16:40:07 -07:00
|
|
|
virObjectUnref(cfg);
|
2011-03-29 20:31:45 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-02-10 15:42:34 -07:00
|
|
|
static char *
|
2011-07-06 14:40:19 -06:00
|
|
|
libxlDomainGetXMLDesc(virDomainPtr dom, unsigned int flags)
|
2011-02-10 15:42:34 -07:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
|
|
|
virDomainObj *vm;
|
|
|
|
virDomainDef *def;
|
2011-02-10 15:42:34 -07:00
|
|
|
char *ret = NULL;
|
|
|
|
|
2019-02-14 14:25:01 -06:00
|
|
|
virCheckFlags(VIR_DOMAIN_XML_COMMON_FLAGS, NULL);
|
2011-07-13 16:24:38 -06:00
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-02-10 15:42:34 -07:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virDomainGetXMLDescEnsureACL(dom->conn, vm->def, flags) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2015-06-24 16:15:22 -06:00
|
|
|
if ((flags & VIR_DOMAIN_XML_INACTIVE) && vm->newDef)
|
|
|
|
def = vm->newDef;
|
|
|
|
else
|
|
|
|
def = vm->def;
|
|
|
|
|
2019-11-27 11:57:34 +00:00
|
|
|
ret = virDomainDefFormat(def, driver->xmlopt,
|
2015-06-24 16:15:22 -06:00
|
|
|
virDomainDefFormatConvertXMLFlags(flags));
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2018-03-09 11:47:59 -05:00
|
|
|
virDomainObjEndAPI(&vm);
|
2016-02-03 21:40:35 +00:00
|
|
|
virObjectUnref(cfg);
|
2011-02-10 15:42:34 -07:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-03-29 20:39:18 +08:00
|
|
|
static char *
|
2014-03-07 10:31:45 -07:00
|
|
|
libxlConnectDomainXMLFromNative(virConnectPtr conn,
|
|
|
|
const char *nativeFormat,
|
|
|
|
const char *nativeConfig,
|
2013-04-23 13:50:18 +01:00
|
|
|
unsigned int flags)
|
2011-03-29 20:39:18 +08:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = conn->privateData;
|
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
|
|
|
virDomainDef *def = NULL;
|
2019-10-15 14:47:50 +02:00
|
|
|
g_autoptr(virConf) conf = NULL;
|
2011-03-29 20:39:18 +08:00
|
|
|
char *xml = NULL;
|
|
|
|
|
2011-07-06 16:17:10 -06:00
|
|
|
virCheckFlags(0, NULL);
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virConnectDomainXMLFromNativeEnsureACL(conn) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2016-05-17 17:34:44 +08:00
|
|
|
if (STREQ(nativeFormat, XEN_CONFIG_FORMAT_XL)) {
|
2017-08-07 17:12:02 +02:00
|
|
|
if (!(conf = virConfReadString(nativeConfig, 0)))
|
2014-12-15 21:30:06 -07:00
|
|
|
goto cleanup;
|
|
|
|
if (!(def = xenParseXL(conf,
|
|
|
|
cfg->caps,
|
2015-12-04 19:11:39 -07:00
|
|
|
driver->xmlopt)))
|
2014-12-15 21:30:06 -07:00
|
|
|
goto cleanup;
|
2016-05-17 17:34:44 +08:00
|
|
|
} else if (STREQ(nativeFormat, XEN_CONFIG_FORMAT_XM)) {
|
2017-08-07 17:12:02 +02:00
|
|
|
if (!(conf = virConfReadString(nativeConfig, 0)))
|
2014-03-07 10:31:45 -07:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(def = xenParseXM(conf,
|
2015-11-28 05:33:55 +01:00
|
|
|
cfg->caps,
|
|
|
|
driver->xmlopt)))
|
2014-03-07 10:31:45 -07:00
|
|
|
goto cleanup;
|
2016-05-17 17:34:44 +08:00
|
|
|
} else if (STREQ(nativeFormat, XEN_CONFIG_FORMAT_SEXPR)) {
|
2019-07-03 08:16:47 +02:00
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
|
|
|
_("conversion from 'xen-sxpr' format is no longer supported"));
|
|
|
|
goto cleanup;
|
2014-03-07 10:31:45 -07:00
|
|
|
} else {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("unsupported config type %s"), nativeFormat);
|
2011-03-29 20:39:18 +08:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2019-11-27 11:57:34 +00:00
|
|
|
xml = virDomainDefFormat(def, driver->xmlopt, VIR_DOMAIN_DEF_FORMAT_INACTIVE);
|
2011-03-29 20:39:18 +08:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2011-03-29 20:39:18 +08:00
|
|
|
virDomainDefFree(def);
|
2013-08-30 14:52:14 -06:00
|
|
|
virObjectUnref(cfg);
|
2011-03-29 20:39:18 +08:00
|
|
|
return xml;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define MAX_CONFIG_SIZE (1024 * 65)
|
|
|
|
static char *
|
2013-04-23 13:50:18 +01:00
|
|
|
libxlConnectDomainXMLToNative(virConnectPtr conn, const char * nativeFormat,
|
|
|
|
const char * domainXml,
|
|
|
|
unsigned int flags)
|
2011-03-29 20:39:18 +08:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = conn->privateData;
|
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
|
|
|
virDomainDef *def = NULL;
|
2019-10-15 14:47:50 +02:00
|
|
|
g_autoptr(virConf) conf = NULL;
|
2011-03-29 20:39:18 +08:00
|
|
|
int len = MAX_CONFIG_SIZE;
|
|
|
|
char *ret = NULL;
|
|
|
|
|
2011-07-06 16:17:10 -06:00
|
|
|
virCheckFlags(0, NULL);
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virConnectDomainXMLToNativeEnsureACL(conn) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2013-03-28 14:55:55 +01:00
|
|
|
if (!(def = virDomainDefParseString(domainXml,
|
2019-11-27 12:29:21 +00:00
|
|
|
driver->xmlopt, NULL,
|
2014-11-18 16:44:00 +00:00
|
|
|
VIR_DOMAIN_DEF_PARSE_INACTIVE)))
|
2011-03-29 20:39:18 +08:00
|
|
|
goto cleanup;
|
|
|
|
|
2016-05-17 17:34:44 +08:00
|
|
|
if (STREQ(nativeFormat, XEN_CONFIG_FORMAT_XL)) {
|
2015-12-04 19:11:39 -07:00
|
|
|
if (!(conf = xenFormatXL(def, conn)))
|
2014-12-15 21:30:06 -07:00
|
|
|
goto cleanup;
|
2016-05-17 17:34:44 +08:00
|
|
|
} else if (STREQ(nativeFormat, XEN_CONFIG_FORMAT_XM)) {
|
2015-12-04 19:11:39 -07:00
|
|
|
if (!(conf = xenFormatXM(conn, def)))
|
2014-12-15 21:30:06 -07:00
|
|
|
goto cleanup;
|
|
|
|
} else {
|
|
|
|
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("unsupported config type %s"), nativeFormat);
|
2011-03-29 20:39:18 +08:00
|
|
|
goto cleanup;
|
2014-12-15 21:30:06 -07:00
|
|
|
}
|
2011-03-29 20:39:18 +08:00
|
|
|
|
2020-09-23 20:43:09 +02:00
|
|
|
ret = g_new0(char, len);
|
2011-03-29 20:39:18 +08:00
|
|
|
|
|
|
|
if (virConfWriteMem(ret, &len, conf) < 0) {
|
|
|
|
VIR_FREE(ret);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2011-03-29 20:39:18 +08:00
|
|
|
virDomainDefFree(def);
|
2013-08-30 14:52:14 -06:00
|
|
|
virObjectUnref(cfg);
|
2011-03-29 20:39:18 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-02-10 15:42:34 -07:00
|
|
|
static int
|
2013-04-23 13:50:18 +01:00
|
|
|
libxlConnectListDefinedDomains(virConnectPtr conn,
|
|
|
|
char **const names, int nnames)
|
2011-02-10 15:42:34 -07:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = conn->privateData;
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virConnectListDefinedDomainsEnsureACL(conn) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2019-10-17 10:10:10 +02:00
|
|
|
return virDomainObjListGetInactiveNames(driver->domains, names, nnames,
|
|
|
|
virConnectListDefinedDomainsCheckACL,
|
|
|
|
conn);
|
2011-02-10 15:42:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-04-23 13:50:18 +01:00
|
|
|
libxlConnectNumOfDefinedDomains(virConnectPtr conn)
|
2011-02-10 15:42:34 -07:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = conn->privateData;
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virConnectNumOfDefinedDomainsEnsureACL(conn) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2019-10-17 10:10:10 +02:00
|
|
|
return virDomainObjListNumOfDomains(driver->domains, false,
|
|
|
|
virConnectNumOfDefinedDomainsCheckACL,
|
|
|
|
conn);
|
2011-02-10 15:42:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainCreateWithFlags(virDomainPtr dom,
|
2011-07-06 16:17:10 -06:00
|
|
|
unsigned int flags)
|
2011-02-10 15:42:34 -07:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
virDomainObj *vm;
|
2011-02-10 15:42:34 -07:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(VIR_DOMAIN_START_PAUSED, -1);
|
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-02-10 15:42:34 -07:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virDomainCreateWithFlagsEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2015-03-01 18:24:26 -07:00
|
|
|
if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-02-10 15:42:34 -07:00
|
|
|
if (virDomainObjIsActive(vm)) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("Domain is already running"));
|
2015-03-01 18:24:26 -07:00
|
|
|
goto endjob;
|
2011-02-10 15:42:34 -07:00
|
|
|
}
|
|
|
|
|
libxl: support Xen migration stream V2 in save/restore
Xen 4.6 introduced a new migration stream commonly referred to as
"migration V2". Xen 4.6 and newer always produce this new stream,
whereas Xen 4.5 and older always produce the legacy stream.
Support for migration stream V2 can be detected at build time with
LIBXL_HAVE_SRM_V2 from libxl.h. The legacy and V2 streams are not
compatible, but a V2 host can accept and convert a legacy stream.
Commit e7440656 changed the libxl driver to use the lowest libxl
API version possible (version 0x040200) to ensure the driver
builds against older Xen releases. The old 4.2 restore API does
not support specifying a stream version and assumes a legacy
stream, even if the incoming stream is migration V2. Thinking it
has been given a legacy stream, libxl will fail to convert an
incoming stream that is already V2, which causes the entire
restore operation to fail. Xen's libvirt-related OSSTest has been
failing since commit e7440656 landed in libvirt.git master. One
of the more recent failures can be seen here
http://lists.xenproject.org/archives/html/xen-devel/2016-05/msg00071.html
This patch changes the call to libxl_domain_create_restore() to
include the stream version if LIBXL_HAVE_SRM_V2 is defined. The
version field of the libxlSavefileHeader struct is also updated
to '2' when LIBXL_HAVE_SRM_V2 is defined, ensuring the stream
version in the header matches the actual stream version produced
by Xen. Along with bumping the libxl API requirement to 0x040400,
this patch fixes save/restore on a migration V2 Xen host.
Oddly, migration has never used the libxlSavefileHeader. It
handles passing configuration in the Begin and Prepare phases,
and then calls libxl directly to transfer domain state/memory
in the Perform phase. A subsequent patch will add stream
version handling in the Begin and Prepare phase handshaking,
which will fix the migration related OSSTest failures.
Signed-off-by: Jim Fehlig <jfehlig@suse.com>
2016-05-02 12:00:39 -06:00
|
|
|
ret = libxlDomainStartNew(driver, vm,
|
|
|
|
(flags & VIR_DOMAIN_START_PAUSED) != 0);
|
2015-02-05 06:17:07 +01:00
|
|
|
if (ret < 0)
|
2015-03-01 18:24:26 -07:00
|
|
|
goto endjob;
|
2015-02-05 06:17:07 +01:00
|
|
|
dom->id = vm->def->id;
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2015-03-01 18:24:26 -07:00
|
|
|
endjob:
|
2016-06-12 18:30:00 +08:00
|
|
|
libxlDomainObjEndJob(driver, vm);
|
2015-03-01 18:24:26 -07:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2016-06-12 18:30:00 +08:00
|
|
|
virDomainObjEndAPI(&vm);
|
2011-02-10 15:42:34 -07:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainCreate(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
return libxlDomainCreateWithFlags(dom, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static virDomainPtr
|
2014-11-18 14:19:38 +00:00
|
|
|
libxlDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flags)
|
2011-02-10 15:42:34 -07:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = conn->privateData;
|
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
|
|
|
virDomainDef *def = NULL;
|
|
|
|
virDomainObj *vm = NULL;
|
2011-02-10 15:42:34 -07:00
|
|
|
virDomainPtr dom = NULL;
|
2021-03-11 08:16:13 +01:00
|
|
|
virObjectEvent *event = NULL;
|
|
|
|
virDomainDef *oldDef = NULL;
|
2014-11-18 17:34:42 +00:00
|
|
|
unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2014-11-18 17:34:42 +00:00
|
|
|
virCheckFlags(VIR_DOMAIN_DEFINE_VALIDATE, NULL);
|
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_DEFINE_VALIDATE)
|
2016-05-24 17:20:20 +02:00
|
|
|
parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
|
2014-11-18 14:19:38 +00:00
|
|
|
|
2019-11-27 12:29:21 +00:00
|
|
|
if (!(def = virDomainDefParseString(xml, driver->xmlopt,
|
2016-09-22 17:14:17 +02:00
|
|
|
NULL, parse_flags)))
|
2014-09-18 15:05:34 -06:00
|
|
|
goto cleanup;
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2016-11-11 10:17:37 +01:00
|
|
|
if (virXMLCheckIllegalChars("name", def->name, "\n") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2014-11-18 14:19:38 +00:00
|
|
|
if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0)
|
2014-09-18 15:05:34 -06:00
|
|
|
goto cleanup;
|
2013-04-23 11:56:22 +01:00
|
|
|
|
2013-03-28 14:55:55 +01:00
|
|
|
if (!(vm = virDomainObjListAdd(driver->domains, def,
|
2013-03-31 20:03:42 +02: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 14:46:58 +00:00
|
|
|
0,
|
|
|
|
&oldDef)))
|
2014-09-18 15:05:34 -06:00
|
|
|
goto cleanup;
|
2011-02-10 15:42:34 -07:00
|
|
|
def = NULL;
|
2018-04-23 10:40:48 -04:00
|
|
|
|
2011-02-10 15:42:34 -07:00
|
|
|
vm->persistent = 1;
|
|
|
|
|
2019-11-26 19:40:46 +00:00
|
|
|
if (virDomainDefSave(vm->newDef ? vm->newDef : vm->def,
|
2019-11-27 12:53:10 +00:00
|
|
|
driver->xmlopt, cfg->configDir) < 0) {
|
2013-01-11 16:04:47 +00:00
|
|
|
virDomainObjListRemove(driver->domains, vm);
|
2011-02-10 15:42:34 -07:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2017-03-28 17:08:03 +02:00
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid, vm->def->id);
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2013-11-21 18:03:26 +01:00
|
|
|
event = virDomainEventLifecycleNewFromObj(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 14:46:58 +00:00
|
|
|
!oldDef ?
|
2011-03-29 20:18:24 +08:00
|
|
|
VIR_DOMAIN_EVENT_DEFINED_ADDED :
|
|
|
|
VIR_DOMAIN_EVENT_DEFINED_UPDATED);
|
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2011-02-10 15:42:34 -07:00
|
|
|
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 14:46:58 +00:00
|
|
|
virDomainDefFree(oldDef);
|
2018-03-16 15:29:48 -06:00
|
|
|
virDomainObjEndAPI(&vm);
|
2018-06-12 13:33:01 -04:00
|
|
|
virObjectEventStateQueue(driver->domainEventState, event);
|
2013-08-30 14:52:14 -06:00
|
|
|
virObjectUnref(cfg);
|
2011-02-10 15:42:34 -07:00
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
2014-11-18 14:19:38 +00:00
|
|
|
static virDomainPtr
|
|
|
|
libxlDomainDefineXML(virConnectPtr conn, const char *xml)
|
|
|
|
{
|
|
|
|
return libxlDomainDefineXMLFlags(conn, xml, 0);
|
|
|
|
}
|
|
|
|
|
2011-02-10 15:42:34 -07:00
|
|
|
static int
|
2011-07-20 11:05:20 +08:00
|
|
|
libxlDomainUndefineFlags(virDomainPtr dom,
|
|
|
|
unsigned int flags)
|
2011-02-10 15:42:34 -07:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
|
|
|
virDomainObj *vm;
|
|
|
|
virObjectEvent *event = NULL;
|
2021-02-16 18:37:09 -07:00
|
|
|
g_autofree char *name = NULL;
|
2011-02-10 15:42:34 -07:00
|
|
|
int ret = -1;
|
|
|
|
|
2011-07-20 11:05:20 +08:00
|
|
|
virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE, -1);
|
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-02-10 15:42:34 -07:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virDomainUndefineFlagsEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-02-10 15:42:34 -07:00
|
|
|
if (!vm->persistent) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("cannot undefine transient domain"));
|
2011-02-10 15:42:34 -07:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-07-20 11:05:20 +08: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 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Failed to remove domain managed save image"));
|
2011-07-20 11:05:20 +08:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
} else {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("Refusing to undefine while domain managed "
|
|
|
|
"save image exists"));
|
2011-07-20 11:05:20 +08:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-30 14:52:14 -06:00
|
|
|
if (virDomainDeleteConfig(cfg->configDir, cfg->autostartDir, vm) < 0)
|
2011-02-10 15:42:34 -07:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-11-21 18:03:26 +01:00
|
|
|
event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_UNDEFINED,
|
2011-03-29 20:18:24 +08:00
|
|
|
VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
|
|
|
|
|
2018-04-23 10:40:48 -04:00
|
|
|
if (virDomainObjIsActive(vm))
|
2011-08-19 21:46:22 +08:00
|
|
|
vm->persistent = 0;
|
2018-04-23 10:40:48 -04:00
|
|
|
else
|
2013-01-11 16:04:47 +00:00
|
|
|
virDomainObjListRemove(driver->domains, vm);
|
2011-08-19 21:46:22 +08:00
|
|
|
|
2011-02-10 15:42:34 -07:00
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2018-03-09 11:47:59 -05:00
|
|
|
virDomainObjEndAPI(&vm);
|
2018-06-12 13:33:01 -04:00
|
|
|
virObjectEventStateQueue(driver->domainEventState, event);
|
2013-08-30 14:52:14 -06:00
|
|
|
virObjectUnref(cfg);
|
2011-02-10 15:42:34 -07:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-07-20 11:05:20 +08:00
|
|
|
static int
|
|
|
|
libxlDomainUndefine(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
return libxlDomainUndefineFlags(dom, 0);
|
|
|
|
}
|
|
|
|
|
2011-05-26 23:27:06 +08:00
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDomainChangeEjectableMedia(virDomainObj *vm, virDomainDiskDef *disk)
|
2011-05-26 23:27:06 +08:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(libxl_driver);
|
|
|
|
virDomainDiskDef *origdisk = NULL;
|
2011-05-26 23:27:06 +08:00
|
|
|
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 15:09:33 +01:00
|
|
|
size_t i;
|
2011-05-26 23:27:06 +08:00
|
|
|
int ret = -1;
|
|
|
|
|
2013-05-21 15:21:16 +08:00
|
|
|
for (i = 0; i < vm->def->ndisks; i++) {
|
2011-05-26 23:27:06 +08: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 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("No device with bus '%s' and target '%s'"),
|
|
|
|
virDomainDiskBusTypeToString(disk->bus), disk->dst);
|
2011-05-26 23:27:06 +08:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (origdisk->device != VIR_DOMAIN_DISK_DEVICE_CDROM) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Removable media not supported for %s device"),
|
|
|
|
virDomainDiskDeviceTypeToString(disk->device));
|
2021-05-18 21:26:31 +02:00
|
|
|
goto cleanup;
|
2011-05-26 23:27:06 +08:00
|
|
|
}
|
|
|
|
|
2012-11-26 09:28:56 -07:00
|
|
|
if (libxlMakeDisk(disk, &x_disk) < 0)
|
2011-05-26 23:27:06 +08:00
|
|
|
goto cleanup;
|
|
|
|
|
2015-02-11 16:40:07 -07:00
|
|
|
if ((ret = libxl_cdrom_insert(cfg->ctx, vm->def->id, &x_disk, NULL)) < 0) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("libxenlight failed to change media for disk '%s'"),
|
|
|
|
disk->dst);
|
2011-05-26 23:27:06 +08:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2020-11-05 01:23:41 -05:00
|
|
|
virDomainDiskSetSource(origdisk, virDomainDiskGetSource(disk));
|
2014-03-17 14:14:11 -06:00
|
|
|
virDomainDiskSetType(origdisk, virDomainDiskGetType(disk));
|
2011-05-26 23:27:06 +08:00
|
|
|
|
|
|
|
virDomainDiskDefFree(disk);
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2015-02-11 16:40:07 -07:00
|
|
|
virObjectUnref(cfg);
|
2011-05-26 23:27:06 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDomainAttachDeviceDiskLive(virDomainObj *vm, virDomainDeviceDef *dev)
|
2011-05-26 23:27:06 +08:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(libxl_driver);
|
|
|
|
virDomainDiskDef *l_disk = dev->data.disk;
|
2011-05-26 23:27:06 +08:00
|
|
|
libxl_device_disk x_disk;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
switch (l_disk->device) {
|
|
|
|
case VIR_DOMAIN_DISK_DEVICE_CDROM:
|
2015-02-11 16:40:07 -07:00
|
|
|
ret = libxlDomainChangeEjectableMedia(vm, l_disk);
|
2011-05-26 23:27:06 +08:00
|
|
|
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 20:38:36 -06:00
|
|
|
if (virDomainDiskIndexByName(vm->def, l_disk->dst, true) >= 0) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("target %s already exists"), l_disk->dst);
|
2011-05-26 23:27:06 +08:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2014-03-17 14:14:11 -06:00
|
|
|
if (!virDomainDiskGetSource(l_disk)) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("disk source path is missing"));
|
2011-05-26 23:27:06 +08:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2021-03-20 00:37:05 +01:00
|
|
|
VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1);
|
2011-05-26 23:27:06 +08:00
|
|
|
|
2012-11-26 09:28:56 -07:00
|
|
|
if (libxlMakeDisk(l_disk, &x_disk) < 0)
|
2011-05-26 23:27:06 +08:00
|
|
|
goto cleanup;
|
|
|
|
|
2019-01-23 13:58:46 +01:00
|
|
|
if (virDomainLockImageAttach(libxl_driver->lockManager,
|
|
|
|
"xen:///system",
|
|
|
|
vm, l_disk->src) < 0)
|
2015-04-14 14:38:46 -06:00
|
|
|
goto cleanup;
|
|
|
|
|
2015-02-11 16:40:07 -07:00
|
|
|
if ((ret = libxl_device_disk_add(cfg->ctx, vm->def->id,
|
2012-11-26 09:28:56 -07:00
|
|
|
&x_disk, NULL)) < 0) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("libxenlight failed to attach disk '%s'"),
|
|
|
|
l_disk->dst);
|
2019-01-23 13:58:46 +01:00
|
|
|
if (virDomainLockImageDetach(libxl_driver->lockManager,
|
|
|
|
vm, l_disk->src) < 0) {
|
2015-04-14 14:38:46 -06:00
|
|
|
VIR_WARN("Unable to release lock on %s",
|
|
|
|
virDomainDiskGetSource(l_disk));
|
|
|
|
}
|
2011-05-26 23:27:06 +08:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2017-02-07 12:05:15 -07:00
|
|
|
libxlUpdateDiskDef(l_disk, &x_disk);
|
2011-05-26 23:27:06 +08:00
|
|
|
virDomainDiskInsertPreAlloced(vm->def, l_disk);
|
|
|
|
|
|
|
|
} else {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("disk bus '%s' cannot be hotplugged."),
|
|
|
|
virDomainDiskBusTypeToString(l_disk->bus));
|
2011-05-26 23:27:06 +08:00
|
|
|
}
|
|
|
|
break;
|
2021-04-16 10:46:00 +02:00
|
|
|
case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
|
|
|
|
case VIR_DOMAIN_DISK_DEVICE_LUN:
|
|
|
|
case VIR_DOMAIN_DISK_DEVICE_LAST:
|
2011-05-26 23:27:06 +08:00
|
|
|
default:
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("disk device type '%s' cannot be hotplugged"),
|
|
|
|
virDomainDiskDeviceTypeToString(l_disk->device));
|
2011-05-26 23:27:06 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2015-02-11 16:40:07 -07:00
|
|
|
virObjectUnref(cfg);
|
2011-05-26 23:27:06 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-03-06 17:46:11 +08:00
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDomainAttachHostPCIDevice(libxlDriverPrivate *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainHostdevDef *hostdev)
|
2014-03-06 17:46:11 +08:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
2015-04-24 15:56:23 +00:00
|
|
|
libxl_device_pci pcidev;
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainHostdevDef *found;
|
|
|
|
virHostdevManager *hostdev_mgr = driver->hostdevMgr;
|
|
|
|
virDomainHostdevSubsysPCI *pcisrc = &hostdev->source.subsys.u.pci;
|
2015-02-11 16:40:07 -07:00
|
|
|
int ret = -1;
|
2014-03-06 17:46:11 +08:00
|
|
|
|
2015-04-24 15:56:23 +00:00
|
|
|
libxl_device_pci_init(&pcidev);
|
|
|
|
|
2014-03-06 17:46:11 +08:00
|
|
|
if (virDomainHostdevFind(vm->def, hostdev, &found) >= 0) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
2019-07-30 14:43:44 +02:00
|
|
|
_("target pci device " VIR_PCI_DEVICE_ADDRESS_FMT
|
|
|
|
" already exists"),
|
2014-07-03 16:31:39 -04:00
|
|
|
pcisrc->addr.domain, pcisrc->addr.bus,
|
|
|
|
pcisrc->addr.slot, pcisrc->addr.function);
|
2015-02-11 16:40:07 -07:00
|
|
|
goto cleanup;
|
2014-03-06 17:46:11 +08:00
|
|
|
}
|
|
|
|
|
2021-03-20 00:37:05 +01:00
|
|
|
VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs + 1);
|
2014-03-06 17:46:11 +08:00
|
|
|
|
2020-05-04 15:20:37 -06:00
|
|
|
if (virHostdevPreparePCIDevices(hostdev_mgr, LIBXL_DRIVER_INTERNAL_NAME,
|
2014-03-06 17:46:11 +08:00
|
|
|
vm->def->name, vm->def->uuid,
|
|
|
|
&hostdev, 1, 0) < 0)
|
2015-02-11 16:40:07 -07:00
|
|
|
goto cleanup;
|
2014-03-06 17:46:11 +08:00
|
|
|
|
2014-03-13 11:59:32 +00:00
|
|
|
if (libxlMakePCI(hostdev, &pcidev) < 0)
|
2014-03-19 11:15:25 +08:00
|
|
|
goto error;
|
2014-03-06 17:46:11 +08:00
|
|
|
|
2015-02-11 16:40:07 -07:00
|
|
|
if (libxl_device_pci_add(cfg->ctx, vm->def->id, &pcidev, 0) < 0) {
|
2014-03-06 17:46:11 +08:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2019-07-30 14:43:44 +02:00
|
|
|
_("libxenlight failed to attach pci device "
|
|
|
|
VIR_PCI_DEVICE_ADDRESS_FMT),
|
2014-07-03 16:31:39 -04:00
|
|
|
pcisrc->addr.domain, pcisrc->addr.bus,
|
|
|
|
pcisrc->addr.slot, pcisrc->addr.function);
|
2014-03-19 11:15:25 +08:00
|
|
|
goto error;
|
2014-03-06 17:46:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;
|
2015-02-11 16:40:07 -07:00
|
|
|
ret = 0;
|
|
|
|
goto cleanup;
|
2014-03-06 17:46:11 +08:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
error:
|
2020-05-04 15:20:37 -06:00
|
|
|
virHostdevReAttachPCIDevices(hostdev_mgr, LIBXL_DRIVER_INTERNAL_NAME,
|
2021-01-26 00:31:16 -05:00
|
|
|
vm->def->name, &hostdev, 1);
|
2015-02-11 16:40:07 -07:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virObjectUnref(cfg);
|
2015-04-24 15:56:23 +00:00
|
|
|
libxl_device_pci_dispose(&pcidev);
|
2015-02-11 16:40:07 -07:00
|
|
|
return ret;
|
2014-03-06 17:46:11 +08:00
|
|
|
}
|
|
|
|
|
2016-05-19 16:14:34 +08:00
|
|
|
#ifdef LIBXL_HAVE_PVUSB
|
2016-06-15 14:00:10 +08:00
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDomainAttachControllerDevice(libxlDriverPrivate *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainControllerDef *controller)
|
2016-06-15 14:00:10 +08:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
2016-06-15 14:00:10 +08:00
|
|
|
const char *type = virDomainControllerTypeToString(controller->type);
|
|
|
|
libxl_device_usbctrl usbctrl;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
libxl_device_usbctrl_init(&usbctrl);
|
|
|
|
|
|
|
|
if (controller->type != VIR_DOMAIN_CONTROLLER_TYPE_USB) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
|
|
|
_("'%s' controller cannot be hot plugged."),
|
|
|
|
type);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (controller->idx == -1)
|
|
|
|
controller->idx = virDomainControllerFindUnusedIndex(vm->def,
|
|
|
|
controller->type);
|
|
|
|
|
|
|
|
if (controller->opts.usbopts.ports == -1)
|
|
|
|
controller->opts.usbopts.ports = 8;
|
|
|
|
|
|
|
|
if (virDomainControllerFind(vm->def, controller->type, controller->idx) >= 0) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("target %s:%d already exists"),
|
|
|
|
type, controller->idx);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2021-03-20 00:37:05 +01:00
|
|
|
VIR_REALLOC_N(vm->def->controllers, vm->def->ncontrollers + 1);
|
2016-06-15 14:00:10 +08:00
|
|
|
|
|
|
|
if (libxlMakeUSBController(controller, &usbctrl) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (libxl_device_usbctrl_add(cfg->ctx, vm->def->id, &usbctrl, 0) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("libxenlight failed to attach USB controller"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainControllerInsertPreAlloced(vm->def, controller);
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virObjectUnref(cfg);
|
|
|
|
libxl_device_usbctrl_dispose(&usbctrl);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-05-19 16:14:34 +08:00
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDomainAttachHostUSBDevice(libxlDriverPrivate *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainHostdevDef *hostdev)
|
2016-05-19 16:14:34 +08:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
2016-05-19 16:14:34 +08:00
|
|
|
libxl_device_usbdev usbdev;
|
2021-03-11 08:16:13 +01:00
|
|
|
virHostdevManager *hostdev_mgr = driver->hostdevMgr;
|
2016-05-19 16:14:34 +08:00
|
|
|
int ret = -1;
|
2016-06-15 14:00:11 +08:00
|
|
|
size_t i;
|
|
|
|
int ports = 0, usbdevs = 0;
|
2016-05-19 16:14:34 +08:00
|
|
|
|
|
|
|
libxl_device_usbdev_init(&usbdev);
|
|
|
|
|
|
|
|
if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
|
|
|
|
hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
|
|
|
|
goto cleanup;
|
|
|
|
|
2016-06-15 14:00:11 +08:00
|
|
|
/* search for available controller:port */
|
|
|
|
for (i = 0; i < vm->def->ncontrollers; i++)
|
|
|
|
ports += vm->def->controllers[i]->opts.usbopts.ports;
|
|
|
|
|
|
|
|
for (i = 0; i < vm->def->nhostdevs; i++) {
|
|
|
|
if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
|
|
|
|
hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
|
|
|
|
usbdevs++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ports <= usbdevs) {
|
|
|
|
/* no free ports, we will create a new usb controller */
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainControllerDef *controller;
|
2016-06-15 14:00:11 +08:00
|
|
|
|
|
|
|
if (!(controller = virDomainControllerDefNew(VIR_DOMAIN_CONTROLLER_TYPE_USB)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
controller->model = VIR_DOMAIN_CONTROLLER_MODEL_USB_QUSB2;
|
|
|
|
controller->idx = -1;
|
|
|
|
controller->opts.usbopts.ports = 8;
|
|
|
|
|
|
|
|
if (libxlDomainAttachControllerDevice(driver, vm, controller) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("No available USB controller and port, and "
|
|
|
|
"failed to attach a new one"));
|
|
|
|
virDomainControllerDefFree(controller);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-20 00:37:05 +01:00
|
|
|
VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs + 1);
|
2016-05-19 16:14:34 +08:00
|
|
|
|
2020-05-04 15:20:37 -06:00
|
|
|
if (virHostdevPrepareUSBDevices(hostdev_mgr, LIBXL_DRIVER_INTERNAL_NAME,
|
2016-05-19 16:14:34 +08:00
|
|
|
vm->def->name, &hostdev, 1, 0) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (libxlMakeUSB(hostdev, &usbdev) < 0)
|
|
|
|
goto reattach;
|
|
|
|
|
|
|
|
if (libxl_device_usbdev_add(cfg->ctx, vm->def->id, &usbdev, 0) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("libxenlight failed to attach usb device Busnum:%3x, Devnum:%3x"),
|
|
|
|
hostdev->source.subsys.u.usb.bus,
|
|
|
|
hostdev->source.subsys.u.usb.device);
|
|
|
|
goto reattach;
|
|
|
|
}
|
|
|
|
|
|
|
|
vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;
|
|
|
|
ret = 0;
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
reattach:
|
2020-05-04 15:20:37 -06:00
|
|
|
virHostdevReAttachUSBDevices(hostdev_mgr, LIBXL_DRIVER_INTERNAL_NAME,
|
2016-05-19 16:14:34 +08:00
|
|
|
vm->def->name, &hostdev, 1);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virObjectUnref(cfg);
|
|
|
|
libxl_device_usbdev_dispose(&usbdev);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-03-06 17:46:11 +08:00
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDomainAttachHostDevice(libxlDriverPrivate *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainHostdevDef *hostdev)
|
2014-03-06 17:46:11 +08:00
|
|
|
{
|
|
|
|
if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("hostdev mode '%s' not supported"),
|
|
|
|
virDomainHostdevModeTypeToString(hostdev->mode));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (hostdev->source.subsys.type) {
|
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
|
2015-02-11 16:40:07 -07:00
|
|
|
if (libxlDomainAttachHostPCIDevice(driver, vm, hostdev) < 0)
|
2014-03-19 11:15:25 +08:00
|
|
|
return -1;
|
2014-03-06 17:46:11 +08:00
|
|
|
break;
|
|
|
|
|
2016-05-19 16:14:34 +08:00
|
|
|
#ifdef LIBXL_HAVE_PVUSB
|
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
|
|
|
|
if (libxlDomainAttachHostUSBDevice(driver, vm, hostdev) < 0)
|
|
|
|
return -1;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
|
2014-03-06 17:46:11 +08:00
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("hostdev subsys type '%s' not supported"),
|
|
|
|
virDomainHostdevSubsysTypeToString(hostdev->source.subsys.type));
|
2014-03-19 11:15:25 +08:00
|
|
|
return -1;
|
2014-03-06 17:46:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-05-26 23:27:06 +08:00
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDomainDetachDeviceDiskLive(virDomainObj *vm, virDomainDeviceDef *dev)
|
2011-05-26 23:27:06 +08:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(libxl_driver);
|
|
|
|
virDomainDiskDef *l_disk = NULL;
|
2011-05-26 23:27:06 +08:00
|
|
|
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 15:09:33 +01:00
|
|
|
int idx;
|
2011-05-26 23:27:06 +08: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 15:09:33 +01:00
|
|
|
if ((idx = virDomainDiskIndexByName(vm->def,
|
|
|
|
dev->data.disk->dst,
|
|
|
|
false)) < 0) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("disk %s not found"), dev->data.disk->dst);
|
2011-05-26 23:27:06 +08: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 15:09:33 +01:00
|
|
|
l_disk = vm->def->disks[idx];
|
2011-05-26 23:27:06 +08:00
|
|
|
|
2012-11-26 09:28:56 -07:00
|
|
|
if (libxlMakeDisk(l_disk, &x_disk) < 0)
|
2011-05-26 23:27:06 +08:00
|
|
|
goto cleanup;
|
|
|
|
|
2015-02-11 16:40:07 -07:00
|
|
|
if ((ret = libxl_device_disk_remove(cfg->ctx, vm->def->id,
|
2012-11-26 09:28:56 -07:00
|
|
|
&x_disk, NULL)) < 0) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("libxenlight failed to detach disk '%s'"),
|
|
|
|
l_disk->dst);
|
2011-05-26 23:27:06 +08:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2019-01-23 13:58:46 +01:00
|
|
|
if (virDomainLockImageDetach(libxl_driver->lockManager,
|
|
|
|
vm, l_disk->src) < 0)
|
2015-04-14 14:38:46 -06:00
|
|
|
VIR_WARN("Unable to release lock on %s",
|
|
|
|
virDomainDiskGetSource(l_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 15:09:33 +01:00
|
|
|
virDomainDiskRemove(vm->def, idx);
|
2011-05-26 23:27:06 +08:00
|
|
|
virDomainDiskDefFree(l_disk);
|
|
|
|
|
|
|
|
} else {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("disk bus '%s' cannot be hot unplugged."),
|
|
|
|
virDomainDiskBusTypeToString(dev->data.disk->bus));
|
2011-05-26 23:27:06 +08:00
|
|
|
}
|
|
|
|
break;
|
2021-04-16 10:46:00 +02:00
|
|
|
case VIR_DOMAIN_DISK_DEVICE_CDROM:
|
|
|
|
case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
|
|
|
|
case VIR_DOMAIN_DISK_DEVICE_LUN:
|
|
|
|
case VIR_DOMAIN_DISK_DEVICE_LAST:
|
2011-05-26 23:27:06 +08:00
|
|
|
default:
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("device type '%s' cannot hot unplugged"),
|
|
|
|
virDomainDiskDeviceTypeToString(dev->data.disk->device));
|
2011-05-26 23:27:06 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2015-02-11 16:40:07 -07:00
|
|
|
virObjectUnref(cfg);
|
2011-05-26 23:27:06 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-07-15 13:03:15 +08:00
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDomainAttachNetDevice(libxlDriverPrivate *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainNetDef *net)
|
2014-07-15 13:03:15 +08:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
2016-09-23 17:04:53 +02:00
|
|
|
virDomainNetType actualType;
|
2014-07-15 13:03:15 +08:00
|
|
|
libxl_device_nic nic;
|
|
|
|
int ret = -1;
|
2015-03-06 15:36:16 +01:00
|
|
|
char mac[VIR_MAC_STRING_BUFLEN];
|
2021-01-08 00:31:05 -05:00
|
|
|
g_autoptr(virConnect) conn = NULL;
|
2019-04-30 16:17:14 +02:00
|
|
|
virErrorPtr save_err = NULL;
|
2014-07-15 13:03:15 +08:00
|
|
|
|
2016-03-21 16:11:36 +08:00
|
|
|
libxl_device_nic_init(&nic);
|
|
|
|
|
2014-07-15 13:03:15 +08:00
|
|
|
/* preallocate new slot for device */
|
2021-03-20 00:37:05 +01:00
|
|
|
VIR_REALLOC_N(vm->def->nets, vm->def->nnets + 1);
|
2014-07-15 13:03:15 +08:00
|
|
|
|
|
|
|
/* If appropriate, grab a physical device from the configured
|
|
|
|
* network's pool of devices, or resolve bridge device name
|
|
|
|
* to the one defined in the network definition.
|
|
|
|
*/
|
2018-07-26 15:32:04 +01:00
|
|
|
if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
|
|
|
|
if (!(conn = virGetConnectNetwork()))
|
|
|
|
goto cleanup;
|
|
|
|
if (virDomainNetAllocateActualDevice(conn, vm->def, net) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2014-07-15 13:03:15 +08:00
|
|
|
|
conf: add hypervisor agnostic, domain start-time, validation function for NetDef
<interface> devices (virDomainNetDef) are a bit different from other
types of devices in that their actual type may come from a network (in
the form of a port connection), and that doesn't happen until the
domain is started. This means that any validation of an <interface> at
parse time needs to be a bit liberal in what it accepts - when
type='network', you could think that something is/isn't allowed, but
once the domain is started and a port is created by the configured
network, the opposite might be true.
To solve this problem hypervisor drivers need to do an extra
validation step when the domain is being started. I recently (commit
3cff23f7, libvirt 5.7.0) added a function to peform such validation
for all interfaces to the QEMU driver -
qemuDomainValidateActualNetDef() - but while that function is a good
single point to call for the multiple places that need to "start" an
interface (domain startup, device hotplug, device update), it can't be
called by the other hypervisor drivers, since 1) it's in the QEMU
driver, and 2) it contains some checks specific to QEMU. For
validation that applies to network devices on *all* hypervisors, we
need yet another interface validation function that can be called by
any hypervisor driver (not just QEMU) right after its network port has
been created during domain startup or hotplug. This patch adds that
function - virDomainActualNetDefValidate(), in the conf directory,
and calls it in appropriate places in the QEMU, lxc, and libxl
drivers.
This new function is the place to put all network device validation
that 1) is hypervisor agnostic, and 2) can't be done until we know the
"actual type" of an interface.
There is no framework for validation at domain startup as there is for
post-parse validation, but I don't want to create a whole elaborate
system that will only be used by one type of device. For that reason,
I just made a single function that should be called directly from the
hypervisors, when they are initializing interfaces to start a domain,
right after conditionally allocating the network port (and regardless
of whether or not that was actually needed). In the case of the QEMU
driver, qemuDomainValidateActualNetDef() is already called in all the
appropriate places, so we can just call the new function from
there. In the case of the other hypervisors, we search for
virDomainNetAllocateActualDevice() (which is the hypervisor-agnostic
function that calls virNetworkPortCreateXML()), and add the call to our
new function right after that.
The new function itself could be plunked down into many places in the
code, but we already have 3 validation functions for network devices
in 2 different places (not counting any basic validation done in
virDomainNetDefParseXML() itself):
1) post-parse hypervisor-agnostic
(virDomainNetDefValidate() - domain_conf.c:6145)
2) post-parse hypervisor-specific
(qemuDomainDeviceDefValidateNetwork() - qemu_domain.c:5498)
3) domain-start hypervisor-specific
(qemuDomainValidateActualNetDef() - qemu_domain.c:5390)
I placed (3) right next to (2) when I added it, specifically to avoid
spreading validation all over the code. For the same reason, I decided
to put this new function right next to (1) - this way if someone needs
to add validation specific to qemu, they go to one location, and if
they need to add validation applying to everyone, they go to the
other. It looks a bit strange to have a public function in between a
bunch of statics, but I think it's better than the alternative of
further fragmentation. (I'm open to other ideas though, of course.)
Signed-off-by: Laine Stump <laine@redhat.com>
Reviewed-by: Cole Robinson <crobinso@redhat.com>
2019-10-18 15:48:13 -04:00
|
|
|
/* final validation now that actual type is known */
|
|
|
|
if (virDomainActualNetDefValidate(net) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2014-07-15 13:03:15 +08:00
|
|
|
actualType = virDomainNetGetActualType(net);
|
|
|
|
|
2015-03-06 15:36:16 +01:00
|
|
|
if (virDomainHasNet(vm->def, net)) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("network device with mac %s already exists"),
|
|
|
|
virMacAddrFormat(&net->mac, mac));
|
2016-03-21 16:11:36 +08:00
|
|
|
goto cleanup;
|
2015-03-06 15:36:16 +01:00
|
|
|
}
|
|
|
|
|
2014-07-15 13:03:15 +08:00
|
|
|
if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainHostdevDef *hostdev = virDomainNetGetActualHostdev(net);
|
|
|
|
virDomainHostdevSubsysPCI *pcisrc = &hostdev->source.subsys.u.pci;
|
2016-03-21 16:11:40 +08:00
|
|
|
|
|
|
|
/* For those just allocated from a network pool whose backend is
|
|
|
|
* still VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT, we need to set
|
|
|
|
* backend correctly.
|
|
|
|
*/
|
|
|
|
if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
|
|
|
|
hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
|
|
|
|
pcisrc->backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN;
|
|
|
|
|
2014-07-15 13:03:15 +08:00
|
|
|
/* This is really a "smart hostdev", so it should be attached
|
|
|
|
* as a hostdev (the hostdev code will reach over into the
|
|
|
|
* netdev-specific code as appropriate), then also added to
|
2016-03-28 12:59:36 -06:00
|
|
|
* the nets list if successful.
|
2014-07-15 13:03:15 +08:00
|
|
|
*/
|
2016-03-21 16:11:40 +08:00
|
|
|
ret = libxlDomainAttachHostDevice(driver, vm, hostdev);
|
2016-03-21 16:11:36 +08:00
|
|
|
goto cleanup;
|
2014-07-15 13:03:15 +08:00
|
|
|
}
|
|
|
|
|
2016-12-14 10:53:32 +00:00
|
|
|
if (libxlMakeNic(vm->def, net, &nic, true) < 0)
|
2014-07-15 13:03:15 +08:00
|
|
|
goto cleanup;
|
|
|
|
|
2015-02-11 16:40:07 -07:00
|
|
|
if (libxl_device_nic_add(cfg->ctx, vm->def->id, &nic, 0)) {
|
2014-07-15 13:03:15 +08:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("libxenlight failed to attach network device"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
2019-04-30 16:17:14 +02:00
|
|
|
virErrorPreserveLast(&save_err);
|
2014-07-15 13:03:15 +08:00
|
|
|
libxl_device_nic_dispose(&nic);
|
2016-03-30 14:57:29 -06:00
|
|
|
if (!ret) {
|
|
|
|
vm->def->nets[vm->def->nnets++] = net;
|
|
|
|
} else {
|
2016-03-21 16:11:36 +08:00
|
|
|
virDomainNetRemoveHostdev(vm->def, net);
|
2018-07-26 15:32:04 +01:00
|
|
|
if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK && conn)
|
|
|
|
virDomainNetReleaseActualDevice(conn, vm->def, net);
|
2016-03-21 16:11:36 +08:00
|
|
|
}
|
2015-02-11 16:40:07 -07:00
|
|
|
virObjectUnref(cfg);
|
2019-04-30 16:17:14 +02:00
|
|
|
virErrorRestore(&save_err);
|
2014-07-15 13:03:15 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-05-26 23:27:06 +08:00
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDomainAttachDeviceLive(libxlDriverPrivate *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainDeviceDef *dev)
|
2011-05-26 23:27:06 +08:00
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
switch (dev->type) {
|
|
|
|
case VIR_DOMAIN_DEVICE_DISK:
|
2015-02-11 16:40:07 -07:00
|
|
|
ret = libxlDomainAttachDeviceDiskLive(vm, dev);
|
2011-05-26 23:27:06 +08:00
|
|
|
if (!ret)
|
|
|
|
dev->data.disk = NULL;
|
|
|
|
break;
|
|
|
|
|
2016-08-02 09:20:32 -04:00
|
|
|
#ifdef LIBXL_HAVE_PVUSB
|
2016-06-15 14:00:10 +08:00
|
|
|
case VIR_DOMAIN_DEVICE_CONTROLLER:
|
|
|
|
ret = libxlDomainAttachControllerDevice(driver, vm, dev->data.controller);
|
|
|
|
if (!ret)
|
|
|
|
dev->data.controller = NULL;
|
|
|
|
break;
|
2016-08-02 09:20:32 -04:00
|
|
|
#endif
|
2016-06-15 14:00:10 +08:00
|
|
|
|
2014-07-15 13:03:15 +08:00
|
|
|
case VIR_DOMAIN_DEVICE_NET:
|
2015-02-11 16:40:07 -07:00
|
|
|
ret = libxlDomainAttachNetDevice(driver, vm,
|
2014-07-15 13:03:15 +08:00
|
|
|
dev->data.net);
|
|
|
|
if (!ret)
|
|
|
|
dev->data.net = NULL;
|
|
|
|
break;
|
|
|
|
|
2014-03-06 17:46:11 +08:00
|
|
|
case VIR_DOMAIN_DEVICE_HOSTDEV:
|
2015-02-11 16:40:07 -07:00
|
|
|
ret = libxlDomainAttachHostDevice(driver, vm,
|
2014-07-15 13:03:15 +08:00
|
|
|
dev->data.hostdev);
|
2014-03-06 17:46:11 +08:00
|
|
|
if (!ret)
|
|
|
|
dev->data.hostdev = NULL;
|
|
|
|
break;
|
|
|
|
|
2011-05-26 23:27:06 +08:00
|
|
|
default:
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("device type '%s' cannot be attached"),
|
|
|
|
virDomainDeviceTypeToString(dev->type));
|
2011-05-26 23:27:06 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDomainAttachDeviceConfig(virDomainDef *vmdef, virDomainDeviceDef *dev)
|
2011-05-26 23:27:06 +08:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainDiskDef *disk;
|
|
|
|
virDomainNetDef *net;
|
|
|
|
virDomainHostdevDef *hostdev;
|
|
|
|
virDomainControllerDef *controller;
|
|
|
|
virDomainHostdevDef *found;
|
2015-03-06 15:36:16 +01:00
|
|
|
char mac[VIR_MAC_STRING_BUFLEN];
|
2011-05-26 23:27:06 +08:00
|
|
|
|
|
|
|
switch (dev->type) {
|
|
|
|
case VIR_DOMAIN_DEVICE_DISK:
|
2021-03-24 17:33:14 +01:00
|
|
|
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 20:38:36 -06:00
|
|
|
if (virDomainDiskIndexByName(vmdef, disk->dst, true) >= 0) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("target %s already exists."), disk->dst);
|
2011-05-26 23:27:06 +08:00
|
|
|
return -1;
|
|
|
|
}
|
2020-11-05 22:32:57 -05:00
|
|
|
virDomainDiskInsert(vmdef, disk);
|
2011-05-26 23:27:06 +08:00
|
|
|
/* vmdef has the pointer. Generic codes for vmdef will do all jobs */
|
2021-03-24 17:33:14 +01:00
|
|
|
dev->data.disk = NULL;
|
2011-05-26 23:27:06 +08:00
|
|
|
break;
|
2014-07-15 13:03:15 +08:00
|
|
|
|
2016-06-15 14:00:10 +08:00
|
|
|
case VIR_DOMAIN_DEVICE_CONTROLLER:
|
2021-03-24 17:33:14 +01:00
|
|
|
controller = dev->data.controller;
|
2016-06-15 14:00:10 +08:00
|
|
|
if (controller->idx != -1 &&
|
|
|
|
virDomainControllerFind(vmdef, controller->type,
|
|
|
|
controller->idx) >= 0) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("Target already exists"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-11-05 22:32:58 -05:00
|
|
|
virDomainControllerInsert(vmdef, controller);
|
2021-03-24 17:33:14 +01:00
|
|
|
dev->data.controller = NULL;
|
2016-06-15 14:00:10 +08:00
|
|
|
break;
|
|
|
|
|
2014-07-15 13:03:15 +08:00
|
|
|
case VIR_DOMAIN_DEVICE_NET:
|
2021-03-24 17:33:14 +01:00
|
|
|
net = dev->data.net;
|
2015-03-06 15:36:16 +01:00
|
|
|
if (virDomainHasNet(vmdef, net)) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("network device with mac %s already exists"),
|
|
|
|
virMacAddrFormat(&net->mac, mac));
|
|
|
|
return -1;
|
|
|
|
}
|
2014-07-15 13:03:15 +08:00
|
|
|
if (virDomainNetInsert(vmdef, net))
|
|
|
|
return -1;
|
2021-03-24 17:33:14 +01:00
|
|
|
dev->data.net = NULL;
|
2014-07-15 13:03:15 +08:00
|
|
|
break;
|
|
|
|
|
2014-03-06 17:46:11 +08:00
|
|
|
case VIR_DOMAIN_DEVICE_HOSTDEV:
|
|
|
|
hostdev = dev->data.hostdev;
|
|
|
|
|
2016-05-19 16:14:34 +08:00
|
|
|
switch (hostdev->source.subsys.type) {
|
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
|
|
|
|
#ifndef LIBXL_HAVE_PVUSB
|
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
|
|
|
|
#endif
|
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
|
2014-03-06 17:46:11 +08:00
|
|
|
return -1;
|
2016-05-19 16:14:34 +08:00
|
|
|
}
|
2014-03-06 17:46:11 +08:00
|
|
|
|
|
|
|
if (virDomainHostdevFind(vmdef, hostdev, &found) >= 0) {
|
2016-05-19 16:14:34 +08:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("device is already in the domain configuration"));
|
2014-03-06 17:46:11 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-09-11 17:52:58 -04:00
|
|
|
if (virDomainHostdevInsert(vmdef, hostdev) < 0)
|
|
|
|
return -1;
|
2015-09-17 01:15:22 -04:00
|
|
|
dev->data.hostdev = NULL;
|
2014-03-06 17:46:11 +08:00
|
|
|
break;
|
2011-05-26 23:27:06 +08:00
|
|
|
|
|
|
|
default:
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("persistent attach of device is not supported"));
|
2011-05-26 23:27:06 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlComparePCIDevice(virDomainDef *def G_GNUC_UNUSED,
|
|
|
|
virDomainDeviceDef *device G_GNUC_UNUSED,
|
|
|
|
virDomainDeviceInfo *info1,
|
2014-03-06 17:46:11 +08:00
|
|
|
void *opaque)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainDeviceInfo *info2 = opaque;
|
2014-03-06 17:46:11 +08:00
|
|
|
|
|
|
|
if (info1->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI ||
|
|
|
|
info2->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (info1->addr.pci.domain == info2->addr.pci.domain &&
|
|
|
|
info1->addr.pci.bus == info2->addr.pci.bus &&
|
|
|
|
info1->addr.pci.slot == info2->addr.pci.slot &&
|
|
|
|
info1->addr.pci.function != info2->addr.pci.function)
|
|
|
|
return -1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlIsMultiFunctionDevice(virDomainDef *def,
|
|
|
|
virDomainDeviceInfo *dev)
|
2014-03-06 17:46:11 +08:00
|
|
|
{
|
|
|
|
if (virDomainDeviceInfoIterate(def, libxlComparePCIDevice, dev) < 0)
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDomainDetachHostPCIDevice(libxlDriverPrivate *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainHostdevDef *hostdev)
|
2014-03-06 17:46:11 +08:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
|
|
|
virDomainHostdevSubsys *subsys = &hostdev->source.subsys;
|
|
|
|
virDomainHostdevSubsysPCI *pcisrc = &subsys->u.pci;
|
2014-03-06 17:46:11 +08:00
|
|
|
libxl_device_pci pcidev;
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainHostdevDef *detach;
|
2014-03-06 17:46:11 +08:00
|
|
|
int idx;
|
2021-03-11 08:16:13 +01:00
|
|
|
virHostdevManager *hostdev_mgr = driver->hostdevMgr;
|
2015-02-11 16:40:07 -07:00
|
|
|
int ret = -1;
|
2014-03-06 17:46:11 +08:00
|
|
|
|
2015-04-24 15:56:23 +00:00
|
|
|
libxl_device_pci_init(&pcidev);
|
|
|
|
|
2014-03-06 17:46:11 +08:00
|
|
|
idx = virDomainHostdevFind(vm->def, hostdev, &detach);
|
|
|
|
if (idx < 0) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
2019-07-30 14:43:44 +02:00
|
|
|
_("host pci device " VIR_PCI_DEVICE_ADDRESS_FMT
|
|
|
|
" not found"),
|
2014-07-03 16:31:39 -04:00
|
|
|
pcisrc->addr.domain, pcisrc->addr.bus,
|
|
|
|
pcisrc->addr.slot, pcisrc->addr.function);
|
2015-02-11 16:40:07 -07:00
|
|
|
goto cleanup;
|
2014-03-06 17:46:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (libxlIsMultiFunctionDevice(vm->def, detach->info)) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
2019-07-30 14:43:44 +02:00
|
|
|
_("cannot hot unplug multifunction PCI device: "
|
|
|
|
VIR_PCI_DEVICE_ADDRESS_FMT),
|
2014-07-03 16:31:39 -04:00
|
|
|
pcisrc->addr.domain, pcisrc->addr.bus,
|
|
|
|
pcisrc->addr.slot, pcisrc->addr.function);
|
2014-03-19 11:15:25 +08:00
|
|
|
goto error;
|
2014-03-06 17:46:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-13 11:59:32 +00:00
|
|
|
if (libxlMakePCI(detach, &pcidev) < 0)
|
2014-03-19 11:15:25 +08:00
|
|
|
goto error;
|
2014-03-06 17:46:11 +08:00
|
|
|
|
2015-02-11 16:40:07 -07:00
|
|
|
if (libxl_device_pci_remove(cfg->ctx, vm->def->id, &pcidev, 0) < 0) {
|
2014-03-06 17:46:11 +08:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2019-01-08 15:24:07 +01:00
|
|
|
_("libxenlight failed to detach pci device "
|
2019-07-30 14:43:44 +02:00
|
|
|
VIR_PCI_DEVICE_ADDRESS_FMT),
|
2014-07-03 16:31:39 -04:00
|
|
|
pcisrc->addr.domain, pcisrc->addr.bus,
|
|
|
|
pcisrc->addr.slot, pcisrc->addr.function);
|
2014-03-19 11:15:25 +08:00
|
|
|
goto error;
|
2014-03-06 17:46:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
virDomainHostdevRemove(vm->def, idx);
|
|
|
|
|
2020-05-04 15:20:37 -06:00
|
|
|
virHostdevReAttachPCIDevices(hostdev_mgr, LIBXL_DRIVER_INTERNAL_NAME,
|
2021-01-26 00:31:16 -05:00
|
|
|
vm->def->name, &hostdev, 1);
|
2014-03-06 17:46:11 +08:00
|
|
|
|
2015-02-11 16:40:07 -07:00
|
|
|
ret = 0;
|
2014-03-06 17:46:11 +08:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
error:
|
2014-03-06 17:46:11 +08:00
|
|
|
virDomainHostdevDefFree(detach);
|
2015-02-11 16:40:07 -07:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virObjectUnref(cfg);
|
2015-04-24 15:56:23 +00:00
|
|
|
libxl_device_pci_dispose(&pcidev);
|
2015-02-11 16:40:07 -07:00
|
|
|
return ret;
|
2014-03-06 17:46:11 +08:00
|
|
|
}
|
|
|
|
|
2016-05-19 16:14:34 +08:00
|
|
|
#ifdef LIBXL_HAVE_PVUSB
|
2016-06-15 14:00:10 +08:00
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDomainDetachControllerDevice(libxlDriverPrivate *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainDeviceDef *dev)
|
2016-06-15 14:00:10 +08:00
|
|
|
{
|
|
|
|
int idx, ret = -1;
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainControllerDef *detach = NULL;
|
|
|
|
virDomainControllerDef *controller = dev->data.controller;
|
2016-06-15 14:00:10 +08:00
|
|
|
const char *type = virDomainControllerTypeToString(controller->type);
|
|
|
|
libxl_device_usbctrl usbctrl;
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
2016-06-15 14:00:10 +08:00
|
|
|
|
|
|
|
libxl_device_usbctrl_init(&usbctrl);
|
|
|
|
|
|
|
|
if (controller->type != VIR_DOMAIN_CONTROLLER_TYPE_USB) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
|
|
|
_("'%s' controller cannot be hot plugged."),
|
|
|
|
type);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((idx = virDomainControllerFind(vm->def,
|
|
|
|
controller->type,
|
|
|
|
controller->idx)) < 0) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("controller %s:%d not found"),
|
|
|
|
type, controller->idx);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
detach = vm->def->controllers[idx];
|
|
|
|
|
|
|
|
if (libxlMakeUSBController(controller, &usbctrl) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (libxl_device_usbctrl_remove(cfg->ctx, vm->def->id, &usbctrl, 0) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("libxenlight failed to detach USB controller"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainControllerRemove(vm->def, idx);
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virDomainControllerDefFree(detach);
|
|
|
|
virObjectUnref(cfg);
|
|
|
|
libxl_device_usbctrl_dispose(&usbctrl);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-05-19 16:14:34 +08:00
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDomainDetachHostUSBDevice(libxlDriverPrivate *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainHostdevDef *hostdev)
|
2016-05-19 16:14:34 +08:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
|
|
|
virDomainHostdevSubsys *subsys = &hostdev->source.subsys;
|
|
|
|
virDomainHostdevSubsysUSB *usbsrc = &subsys->u.usb;
|
|
|
|
virHostdevManager *hostdev_mgr = driver->hostdevMgr;
|
2016-05-19 16:14:34 +08:00
|
|
|
libxl_device_usbdev usbdev;
|
|
|
|
libxl_device_usbdev *usbdevs = NULL;
|
|
|
|
int num = 0;
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainHostdevDef *detach;
|
2016-05-19 16:14:34 +08:00
|
|
|
int idx;
|
|
|
|
size_t i;
|
|
|
|
bool found = false;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
libxl_device_usbdev_init(&usbdev);
|
|
|
|
|
|
|
|
idx = virDomainHostdevFind(vm->def, hostdev, &detach);
|
|
|
|
if (idx < 0) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("host USB device Busnum: %3x, Devnum: %3x not found"),
|
|
|
|
usbsrc->bus, usbsrc->device);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
usbdevs = libxl_device_usbdev_list(cfg->ctx, vm->def->id, &num);
|
|
|
|
for (i = 0; i < num; i++) {
|
|
|
|
if (usbdevs[i].u.hostdev.hostbus == usbsrc->bus &&
|
|
|
|
usbdevs[i].u.hostdev.hostaddr == usbsrc->device) {
|
|
|
|
libxl_device_usbdev_copy(cfg->ctx, &usbdev, &usbdevs[i]);
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
libxl_device_usbdev_list_free(usbdevs, num);
|
|
|
|
|
|
|
|
if (!found) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("host USB device Busnum: %3x, Devnum: %3x not found"),
|
|
|
|
usbsrc->bus, usbsrc->device);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (libxl_device_usbdev_remove(cfg->ctx, vm->def->id, &usbdev, 0) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2019-01-08 15:24:07 +01:00
|
|
|
_("libxenlight failed to detach USB device "
|
|
|
|
"Busnum: %3x, Devnum: %3x"),
|
2016-05-19 16:14:34 +08:00
|
|
|
usbsrc->bus, usbsrc->device);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainHostdevRemove(vm->def, idx);
|
|
|
|
|
2020-05-04 15:20:37 -06:00
|
|
|
virHostdevReAttachUSBDevices(hostdev_mgr, LIBXL_DRIVER_INTERNAL_NAME,
|
2016-05-19 16:14:34 +08:00
|
|
|
vm->def->name, &hostdev, 1);
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virDomainHostdevDefFree(detach);
|
|
|
|
virObjectUnref(cfg);
|
|
|
|
libxl_device_usbdev_dispose(&usbdev);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-03-06 17:46:11 +08:00
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDomainDetachHostDevice(libxlDriverPrivate *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainHostdevDef *hostdev)
|
2014-03-06 17:46:11 +08:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainHostdevSubsys *subsys = &hostdev->source.subsys;
|
2014-03-06 17:46:11 +08:00
|
|
|
|
|
|
|
if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("hostdev mode '%s' not supported"),
|
|
|
|
virDomainHostdevModeTypeToString(hostdev->mode));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (subsys->type) {
|
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
|
2015-02-11 16:40:07 -07:00
|
|
|
return libxlDomainDetachHostPCIDevice(driver, vm, hostdev);
|
2014-03-06 17:46:11 +08:00
|
|
|
|
2016-05-19 16:14:34 +08:00
|
|
|
#ifdef LIBXL_HAVE_PVUSB
|
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
|
|
|
|
return libxlDomainDetachHostUSBDevice(driver, vm, hostdev);
|
|
|
|
#endif
|
|
|
|
|
2014-03-06 17:46:11 +08:00
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unexpected hostdev type %d"), subsys->type);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-07-15 13:03:15 +08:00
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDomainDetachNetDevice(libxlDriverPrivate *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainNetDef *net)
|
2014-07-15 13:03:15 +08:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
2014-07-15 13:03:15 +08:00
|
|
|
int detachidx;
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainNetDef *detach = NULL;
|
2014-07-15 13:03:15 +08:00
|
|
|
libxl_device_nic nic;
|
|
|
|
char mac[VIR_MAC_STRING_BUFLEN];
|
|
|
|
int ret = -1;
|
2019-04-30 16:17:14 +02:00
|
|
|
virErrorPtr save_err = NULL;
|
2014-07-15 13:03:15 +08:00
|
|
|
|
2016-03-21 16:11:37 +08:00
|
|
|
libxl_device_nic_init(&nic);
|
|
|
|
|
2014-07-15 13:03:15 +08:00
|
|
|
if ((detachidx = virDomainNetFindIdx(vm->def, net)) < 0)
|
2016-03-21 16:11:37 +08:00
|
|
|
goto cleanup;
|
2014-07-15 13:03:15 +08:00
|
|
|
|
|
|
|
detach = vm->def->nets[detachidx];
|
|
|
|
|
|
|
|
if (virDomainNetGetActualType(detach) == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
|
|
|
|
/* This is really a "smart hostdev", so it should be attached as a
|
|
|
|
* hostdev, then also removed from nets list (see out:) if successful.
|
|
|
|
*/
|
2015-02-11 16:40:07 -07:00
|
|
|
ret = libxlDomainDetachHostDevice(driver, vm,
|
2014-07-15 13:03:15 +08:00
|
|
|
virDomainNetGetActualHostdev(detach));
|
2016-03-21 16:11:37 +08:00
|
|
|
goto cleanup;
|
2014-07-15 13:03:15 +08:00
|
|
|
}
|
|
|
|
|
2015-02-11 16:40:07 -07:00
|
|
|
if (libxl_mac_to_device_nic(cfg->ctx, vm->def->id,
|
2014-07-15 13:03:15 +08:00
|
|
|
virMacAddrFormat(&detach->mac, mac), &nic))
|
|
|
|
goto cleanup;
|
|
|
|
|
2015-02-11 16:40:07 -07:00
|
|
|
if (libxl_device_nic_remove(cfg->ctx, vm->def->id, &nic, 0)) {
|
2014-07-15 13:03:15 +08:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("libxenlight failed to detach network device"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
2019-04-30 16:17:14 +02:00
|
|
|
virErrorPreserveLast(&save_err);
|
2014-07-15 13:03:15 +08:00
|
|
|
libxl_device_nic_dispose(&nic);
|
2016-03-30 15:12:35 -06:00
|
|
|
if (!ret) {
|
2018-07-26 15:32:04 +01:00
|
|
|
if (detach->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
|
2021-01-08 00:31:05 -05:00
|
|
|
g_autoptr(virConnect) conn = virGetConnectNetwork();
|
|
|
|
if (conn)
|
2018-07-26 15:32:04 +01:00
|
|
|
virDomainNetReleaseActualDevice(conn, vm->def, detach);
|
2021-01-08 00:31:05 -05:00
|
|
|
else
|
2018-07-26 15:32:04 +01:00
|
|
|
VIR_WARN("Unable to release network device '%s'", NULLSTR(detach->ifname));
|
|
|
|
}
|
2016-03-30 15:12:35 -06:00
|
|
|
virDomainNetRemove(vm->def, detachidx);
|
|
|
|
}
|
2015-02-11 16:40:07 -07:00
|
|
|
virObjectUnref(cfg);
|
2019-04-30 16:17:14 +02:00
|
|
|
virErrorRestore(&save_err);
|
2014-07-15 13:03:15 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-03-06 17:46:11 +08:00
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDomainDetachDeviceLive(libxlDriverPrivate *driver,
|
|
|
|
virDomainObj *vm,
|
|
|
|
virDomainDeviceDef *dev)
|
2011-05-26 23:27:06 +08:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainHostdevDef *hostdev;
|
2011-05-26 23:27:06 +08:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
switch (dev->type) {
|
|
|
|
case VIR_DOMAIN_DEVICE_DISK:
|
2015-02-11 16:40:07 -07:00
|
|
|
ret = libxlDomainDetachDeviceDiskLive(vm, dev);
|
2011-05-26 23:27:06 +08:00
|
|
|
break;
|
|
|
|
|
2016-08-02 09:20:32 -04:00
|
|
|
#ifdef LIBXL_HAVE_PVUSB
|
2016-06-15 14:00:10 +08:00
|
|
|
case VIR_DOMAIN_DEVICE_CONTROLLER:
|
|
|
|
ret = libxlDomainDetachControllerDevice(driver, vm, dev);
|
|
|
|
break;
|
2016-08-02 09:20:32 -04:00
|
|
|
#endif
|
2016-06-15 14:00:10 +08:00
|
|
|
|
2014-07-15 13:03:15 +08:00
|
|
|
case VIR_DOMAIN_DEVICE_NET:
|
2015-02-11 16:40:07 -07:00
|
|
|
ret = libxlDomainDetachNetDevice(driver, vm,
|
2014-07-15 13:03:15 +08:00
|
|
|
dev->data.net);
|
|
|
|
break;
|
|
|
|
|
2014-03-06 17:46:11 +08:00
|
|
|
case VIR_DOMAIN_DEVICE_HOSTDEV:
|
2016-03-21 16:11:38 +08:00
|
|
|
hostdev = dev->data.hostdev;
|
|
|
|
|
|
|
|
/* If this is a network hostdev, we need to use the higher-level
|
|
|
|
* detach function so that mac address / virtualport are reset
|
|
|
|
*/
|
2018-07-26 17:24:30 +01:00
|
|
|
if (hostdev->parentnet)
|
2016-03-21 16:11:38 +08:00
|
|
|
ret = libxlDomainDetachNetDevice(driver, vm,
|
2018-07-26 17:24:30 +01:00
|
|
|
hostdev->parentnet);
|
2016-03-21 16:11:38 +08:00
|
|
|
else
|
|
|
|
ret = libxlDomainDetachHostDevice(driver, vm, hostdev);
|
2014-03-06 17:46:11 +08:00
|
|
|
break;
|
|
|
|
|
2011-05-26 23:27:06 +08:00
|
|
|
default:
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("device type '%s' cannot be detached"),
|
|
|
|
virDomainDeviceTypeToString(dev->type));
|
2011-05-26 23:27:06 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-03-06 17:46:11 +08:00
|
|
|
|
2011-05-26 23:27:06 +08:00
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDomainDetachDeviceConfig(virDomainDef *vmdef, virDomainDeviceDef *dev)
|
2011-05-26 23:27:06 +08:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainDiskDef *disk;
|
|
|
|
virDomainDiskDef *detach;
|
|
|
|
virDomainHostdevDef *hostdev;
|
|
|
|
virDomainHostdevDef *det_hostdev;
|
|
|
|
virDomainControllerDef *cont;
|
|
|
|
virDomainControllerDef *det_cont;
|
|
|
|
virDomainNetDef *net;
|
2014-07-15 13:03:14 +08:00
|
|
|
int idx;
|
2011-05-26 23:27:06 +08:00
|
|
|
|
|
|
|
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 18:06:14 -05:00
|
|
|
if (!(detach = virDomainDiskRemoveByName(vmdef, disk->dst))) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("no target device %s"), disk->dst);
|
2014-07-15 13:03:14 +08:00
|
|
|
return -1;
|
2011-05-26 23:27:06 +08:00
|
|
|
}
|
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 18:06:14 -05:00
|
|
|
virDomainDiskDefFree(detach);
|
2011-05-26 23:27:06 +08:00
|
|
|
break;
|
2014-07-15 13:03:14 +08:00
|
|
|
|
2016-06-15 14:00:10 +08:00
|
|
|
case VIR_DOMAIN_DEVICE_CONTROLLER:
|
|
|
|
cont = dev->data.controller;
|
|
|
|
if ((idx = virDomainControllerFind(vmdef, cont->type,
|
|
|
|
cont->idx)) < 0) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("device not present in domain configuration"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
det_cont = virDomainControllerRemove(vmdef, idx);
|
|
|
|
virDomainControllerDefFree(det_cont);
|
|
|
|
break;
|
|
|
|
|
2014-07-15 13:03:15 +08:00
|
|
|
case VIR_DOMAIN_DEVICE_NET:
|
|
|
|
net = dev->data.net;
|
|
|
|
if ((idx = virDomainNetFindIdx(vmdef, net)) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* this is guaranteed to succeed */
|
|
|
|
virDomainNetDefFree(virDomainNetRemove(vmdef, idx));
|
|
|
|
break;
|
|
|
|
|
2014-07-15 13:03:14 +08:00
|
|
|
case VIR_DOMAIN_DEVICE_HOSTDEV: {
|
|
|
|
hostdev = dev->data.hostdev;
|
|
|
|
if ((idx = virDomainHostdevFind(vmdef, hostdev, &det_hostdev)) < 0) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("device not present in domain configuration"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
virDomainHostdevRemove(vmdef, idx);
|
|
|
|
virDomainHostdevDefFree(det_hostdev);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-05-26 23:27:06 +08:00
|
|
|
default:
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("persistent detach of device is not supported"));
|
2014-07-15 13:03:14 +08:00
|
|
|
return -1;
|
2011-05-26 23:27:06 +08:00
|
|
|
}
|
|
|
|
|
2014-07-15 13:03:14 +08:00
|
|
|
return 0;
|
2011-05-26 23:27:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDomainUpdateDeviceLive(virDomainObj *vm, virDomainDeviceDef *dev)
|
2011-05-26 23:27:06 +08:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainDiskDef *disk;
|
2011-05-26 23:27:06 +08:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
switch (dev->type) {
|
|
|
|
case VIR_DOMAIN_DEVICE_DISK:
|
|
|
|
disk = dev->data.disk;
|
|
|
|
switch (disk->device) {
|
|
|
|
case VIR_DOMAIN_DISK_DEVICE_CDROM:
|
2015-02-11 16:40:07 -07:00
|
|
|
ret = libxlDomainChangeEjectableMedia(vm, disk);
|
2011-05-26 23:27:06 +08:00
|
|
|
if (ret == 0)
|
|
|
|
dev->data.disk = NULL;
|
|
|
|
break;
|
2021-04-16 10:46:00 +02:00
|
|
|
case VIR_DOMAIN_DISK_DEVICE_DISK:
|
|
|
|
case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
|
|
|
|
case VIR_DOMAIN_DISK_DEVICE_LUN:
|
|
|
|
case VIR_DOMAIN_DISK_DEVICE_LAST:
|
2011-05-26 23:27:06 +08:00
|
|
|
default:
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("disk bus '%s' cannot be updated."),
|
|
|
|
virDomainDiskBusTypeToString(disk->bus));
|
2011-05-26 23:27:06 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("device type '%s' cannot be updated"),
|
|
|
|
virDomainDeviceTypeToString(dev->type));
|
2011-05-26 23:27:06 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDomainUpdateDeviceConfig(virDomainDef *vmdef, virDomainDeviceDef *dev)
|
2011-05-26 23:27:06 +08:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainDiskDef *orig;
|
|
|
|
virDomainDiskDef *disk;
|
2011-05-26 23:27:06 +08:00
|
|
|
|
|
|
|
switch (dev->type) {
|
|
|
|
case VIR_DOMAIN_DEVICE_DISK:
|
|
|
|
disk = dev->data.disk;
|
2019-10-14 17:24:20 +02:00
|
|
|
if (!(orig = virDomainDiskByTarget(vmdef, disk->dst))) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("target %s doesn't exist."), disk->dst);
|
2019-10-21 15:19:06 -03:00
|
|
|
return -1;
|
2011-05-26 23:27:06 +08:00
|
|
|
}
|
|
|
|
if (!(orig->device == VIR_DOMAIN_DISK_DEVICE_CDROM)) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("this disk doesn't support update"));
|
2019-10-21 15:19:06 -03:00
|
|
|
return -1;
|
2011-05-26 23:27:06 +08:00
|
|
|
}
|
|
|
|
|
2020-11-05 01:23:41 -05:00
|
|
|
virDomainDiskSetSource(orig, virDomainDiskGetSource(disk));
|
2014-03-17 14:14:11 -06:00
|
|
|
virDomainDiskSetType(orig, virDomainDiskGetType(disk));
|
|
|
|
virDomainDiskSetFormat(orig, virDomainDiskGetFormat(disk));
|
2020-11-05 22:32:37 -05:00
|
|
|
virDomainDiskSetDriver(orig, virDomainDiskGetDriver(disk));
|
2011-05-26 23:27:06 +08:00
|
|
|
break;
|
|
|
|
default:
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("persistent update of device is not supported"));
|
2019-10-21 15:19:06 -03:00
|
|
|
return -1;
|
2011-05-26 23:27:06 +08:00
|
|
|
}
|
|
|
|
|
2019-10-21 15:19:06 -03:00
|
|
|
return 0;
|
2011-05-26 23:27:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-05-27 17:29:33 -06:00
|
|
|
static void
|
|
|
|
libxlDomainAttachDeviceNormalize(const virDomainDeviceDef *devConf,
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainDeviceDef *devLive)
|
2020-05-27 17:29:33 -06:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Fixup anything that needs to be identical in the live and
|
|
|
|
* config versions of DeviceDef, but might not be. Do this by
|
|
|
|
* changing the contents of devLive. This is done after all
|
|
|
|
* post-parse tweaks and validation, so be very careful about what
|
|
|
|
* changes are made.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* MAC address should be identical in both DeviceDefs, but if it
|
|
|
|
* wasn't specified in the XML, and was instead autogenerated, it
|
|
|
|
* will be different for the two since they are each the result of
|
|
|
|
* a separate parser call. If it *was* specified, it will already
|
|
|
|
* be the same, so copying does no harm.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (devConf->type == VIR_DOMAIN_DEVICE_NET)
|
|
|
|
virMacAddrSet(&devLive->data.net->mac, &devConf->data.net->mac);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-05-26 23:27:06 +08:00
|
|
|
static int
|
2013-04-29 16:59:42 +01:00
|
|
|
libxlDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
|
|
|
|
unsigned int flags)
|
2011-05-26 23:27:06 +08:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
|
|
|
virDomainObj *vm = NULL;
|
|
|
|
virDomainDef *vmdef = NULL;
|
|
|
|
virDomainDeviceDef *devConf = NULL;
|
2020-05-27 17:29:33 -06:00
|
|
|
virDomainDeviceDef devConfSave = { 0 };
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainDeviceDef *devLive = NULL;
|
2011-05-26 23:27:06 +08:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE |
|
|
|
|
VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1);
|
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-05-26 23:27:06 +08:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virDomainAttachDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2014-02-06 17:21:41 -07:00
|
|
|
if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2016-03-02 17:30:04 +03:00
|
|
|
if (virDomainObjUpdateModificationImpact(vm, &flags) < 0)
|
|
|
|
goto endjob;
|
2011-05-26 23:27:06 +08:00
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
|
2020-05-27 17:29:33 -06:00
|
|
|
if (!(devConf = virDomainDeviceDefParse(xml, vm->def,
|
|
|
|
driver->xmlopt, NULL,
|
|
|
|
VIR_DOMAIN_DEF_PARSE_INACTIVE)))
|
2014-02-06 17:21:41 -07:00
|
|
|
goto endjob;
|
2011-05-26 23:27:06 +08:00
|
|
|
|
|
|
|
/* Make a copy for updated domain. */
|
2019-11-27 12:41:59 +00:00
|
|
|
if (!(vmdef = virDomainObjCopyPersistentDef(vm, driver->xmlopt, NULL)))
|
2014-02-06 17:21:41 -07:00
|
|
|
goto endjob;
|
2011-05-26 23:27:06 +08:00
|
|
|
|
2020-05-27 17:29:33 -06:00
|
|
|
/*
|
|
|
|
* devConf will be NULLed out by
|
|
|
|
* libxlDomainAttachDeviceConfig(), so save it for later use by
|
|
|
|
* libxlDomainAttachDeviceNormalize()
|
|
|
|
*/
|
|
|
|
devConfSave = *devConf;
|
|
|
|
|
|
|
|
if (libxlDomainAttachDeviceConfig(vmdef, devConf) < 0)
|
2014-02-06 17:21:41 -07:00
|
|
|
goto endjob;
|
2013-04-29 16:59:42 +01:00
|
|
|
}
|
2011-05-26 23:27:06 +08:00
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) {
|
2020-05-27 17:29:33 -06:00
|
|
|
if (!(devLive = virDomainDeviceDefParse(xml, vm->def,
|
2019-11-27 12:29:21 +00:00
|
|
|
driver->xmlopt, NULL,
|
2014-11-18 16:44:00 +00:00
|
|
|
VIR_DOMAIN_DEF_PARSE_INACTIVE)))
|
2014-02-06 17:21:41 -07:00
|
|
|
goto endjob;
|
2011-05-26 23:27:06 +08:00
|
|
|
|
2020-05-27 17:29:33 -06:00
|
|
|
if (flags & VIR_DOMAIN_AFFECT_CONFIG)
|
|
|
|
libxlDomainAttachDeviceNormalize(&devConfSave, devLive);
|
|
|
|
|
|
|
|
if (libxlDomainAttachDeviceLive(driver, vm, devLive) < 0)
|
2014-02-06 17:21:41 -07:00
|
|
|
goto endjob;
|
2013-04-29 16:59:42 +01:00
|
|
|
|
2011-05-26 23:27:06 +08:00
|
|
|
/*
|
|
|
|
* update domain status forcibly because the domain status may be
|
|
|
|
* changed even if we attach the device failed.
|
|
|
|
*/
|
2019-11-27 12:53:10 +00:00
|
|
|
if (virDomainObjSave(vm, driver->xmlopt, cfg->stateDir) < 0)
|
2014-07-15 13:03:16 +08:00
|
|
|
goto endjob;
|
2011-05-26 23:27:06 +08:00
|
|
|
}
|
|
|
|
|
2014-07-15 13:03:16 +08:00
|
|
|
ret = 0;
|
|
|
|
|
2011-05-26 23:27:06 +08:00
|
|
|
/* Finally, if no error until here, we can save config. */
|
2014-07-15 13:03:16 +08:00
|
|
|
if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
|
2019-11-27 12:53:10 +00:00
|
|
|
ret = virDomainDefSave(vmdef, driver->xmlopt, cfg->configDir);
|
2011-05-26 23:27:06 +08: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 14:46:58 +00:00
|
|
|
virDomainObjAssignDef(vm, vmdef, false, NULL);
|
2011-05-26 23:27:06 +08:00
|
|
|
vmdef = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
endjob:
|
2016-06-12 18:30:00 +08:00
|
|
|
libxlDomainObjEndJob(driver, vm);
|
2014-02-06 17:21:41 -07:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2011-05-26 23:27:06 +08:00
|
|
|
virDomainDefFree(vmdef);
|
2020-05-27 17:29:33 -06:00
|
|
|
virDomainDeviceDefFree(devConf);
|
|
|
|
virDomainDeviceDefFree(devLive);
|
2016-06-12 18:30:00 +08:00
|
|
|
virDomainObjEndAPI(&vm);
|
2013-08-30 14:52:14 -06:00
|
|
|
virObjectUnref(cfg);
|
2011-05-26 23:27:06 +08: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)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
|
|
|
virDomainObj *vm = NULL;
|
|
|
|
virDomainDef *vmdef = NULL;
|
|
|
|
virDomainDeviceDef *dev = NULL;
|
2013-04-29 16:59:42 +01:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE |
|
|
|
|
VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1);
|
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2013-04-29 16:59:42 +01:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virDomainDetachDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2014-02-06 17:21:41 -07:00
|
|
|
if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2016-03-02 17:30:04 +03:00
|
|
|
if (virDomainObjUpdateModificationImpact(vm, &flags) < 0)
|
|
|
|
goto endjob;
|
2013-04-29 16:59:42 +01:00
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
|
|
|
|
if (!(dev = virDomainDeviceDefParse(xml, vm->def,
|
2019-11-27 12:29:21 +00:00
|
|
|
driver->xmlopt, NULL,
|
2016-05-27 10:56:56 +02:00
|
|
|
VIR_DOMAIN_DEF_PARSE_INACTIVE |
|
|
|
|
VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE)))
|
2014-02-06 17:21:41 -07:00
|
|
|
goto endjob;
|
2013-04-29 16:59:42 +01:00
|
|
|
|
|
|
|
/* Make a copy for updated domain. */
|
2019-11-27 12:41:59 +00:00
|
|
|
if (!(vmdef = virDomainObjCopyPersistentDef(vm, driver->xmlopt, NULL)))
|
2014-02-06 17:21:41 -07:00
|
|
|
goto endjob;
|
2013-04-29 16:59:42 +01:00
|
|
|
|
2014-07-15 13:03:16 +08:00
|
|
|
if (libxlDomainDetachDeviceConfig(vmdef, dev) < 0)
|
2014-02-06 17:21:41 -07:00
|
|
|
goto endjob;
|
2013-04-29 16:59:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
2019-11-27 12:29:21 +00:00
|
|
|
driver->xmlopt, NULL,
|
2016-05-27 10:56:56 +02:00
|
|
|
VIR_DOMAIN_DEF_PARSE_INACTIVE |
|
|
|
|
VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE)))
|
2014-02-06 17:21:41 -07:00
|
|
|
goto endjob;
|
2013-04-29 16:59:42 +01:00
|
|
|
|
2015-02-11 16:40:07 -07:00
|
|
|
if (libxlDomainDetachDeviceLive(driver, vm, dev) < 0)
|
2014-02-06 17:21:41 -07:00
|
|
|
goto endjob;
|
2013-04-29 16:59:42 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* update domain status forcibly because the domain status may be
|
|
|
|
* changed even if we attach the device failed.
|
|
|
|
*/
|
2019-11-27 12:53:10 +00:00
|
|
|
if (virDomainObjSave(vm, driver->xmlopt, cfg->stateDir) < 0)
|
2014-07-15 13:03:16 +08:00
|
|
|
goto endjob;
|
2013-04-29 16:59:42 +01:00
|
|
|
}
|
|
|
|
|
2014-07-15 13:03:16 +08:00
|
|
|
ret = 0;
|
|
|
|
|
2013-04-29 16:59:42 +01:00
|
|
|
/* Finally, if no error until here, we can save config. */
|
2014-07-15 13:03:16 +08:00
|
|
|
if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
|
2019-11-27 12:53:10 +00:00
|
|
|
ret = virDomainDefSave(vmdef, driver->xmlopt, cfg->configDir);
|
2013-04-29 16:59:42 +01:00
|
|
|
if (!ret) {
|
|
|
|
virDomainObjAssignDef(vm, vmdef, false, NULL);
|
|
|
|
vmdef = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
endjob:
|
2016-06-12 18:30:00 +08:00
|
|
|
libxlDomainObjEndJob(driver, vm);
|
2014-02-06 17:21:41 -07:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2013-04-29 16:59:42 +01:00
|
|
|
virDomainDefFree(vmdef);
|
|
|
|
virDomainDeviceDefFree(dev);
|
2016-06-12 18:30:00 +08:00
|
|
|
virDomainObjEndAPI(&vm);
|
2013-08-30 14:52:14 -06:00
|
|
|
virObjectUnref(cfg);
|
2013-04-29 16:59:42 +01:00
|
|
|
return ret;
|
2011-05-26 23:27:06 +08: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)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
|
|
|
virDomainObj *vm = NULL;
|
|
|
|
virDomainDef *vmdef = NULL;
|
|
|
|
virDomainDeviceDef *dev = NULL;
|
2013-04-29 16:59:42 +01:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE |
|
|
|
|
VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1);
|
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2013-04-29 16:59:42 +01:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virDomainUpdateDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2016-03-02 17:30:04 +03:00
|
|
|
if (virDomainObjUpdateModificationImpact(vm, &flags) < 0)
|
|
|
|
goto cleanup;
|
2013-04-29 16:59:42 +01:00
|
|
|
|
|
|
|
if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
|
|
|
|
if (!(dev = virDomainDeviceDefParse(xml, vm->def,
|
2019-11-27 12:29:21 +00:00
|
|
|
driver->xmlopt, NULL,
|
2014-11-18 16:44:00 +00:00
|
|
|
VIR_DOMAIN_DEF_PARSE_INACTIVE)))
|
2013-04-29 16:59:42 +01:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* Make a copy for updated domain. */
|
2019-11-27 12:41:59 +00:00
|
|
|
if (!(vmdef = virDomainObjCopyPersistentDef(vm, driver->xmlopt, NULL)))
|
2013-04-29 16:59:42 +01:00
|
|
|
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,
|
2019-11-27 12:29:21 +00:00
|
|
|
driver->xmlopt, NULL,
|
2014-11-18 16:44:00 +00:00
|
|
|
VIR_DOMAIN_DEF_PARSE_INACTIVE)))
|
2013-04-29 16:59:42 +01:00
|
|
|
goto cleanup;
|
|
|
|
|
2015-02-11 16:40:07 -07:00
|
|
|
if ((ret = libxlDomainUpdateDeviceLive(vm, dev)) < 0)
|
2013-04-29 16:59:42 +01:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* update domain status forcibly because the domain status may be
|
|
|
|
* changed even if we attach the device failed.
|
|
|
|
*/
|
2019-11-27 12:53:10 +00:00
|
|
|
if (virDomainObjSave(vm, driver->xmlopt, cfg->stateDir) < 0)
|
2013-04-29 16:59:42 +01:00
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Finally, if no error until here, we can save config. */
|
|
|
|
if (!ret && (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG)) {
|
2019-11-27 12:53:10 +00:00
|
|
|
ret = virDomainDefSave(vmdef, driver->xmlopt, cfg->configDir);
|
2013-04-29 16:59:42 +01:00
|
|
|
if (!ret) {
|
|
|
|
virDomainObjAssignDef(vm, vmdef, false, NULL);
|
|
|
|
vmdef = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2013-04-29 16:59:42 +01:00
|
|
|
virDomainDefFree(vmdef);
|
|
|
|
virDomainDeviceDefFree(dev);
|
2018-03-09 11:47:59 -05:00
|
|
|
virDomainObjEndAPI(&vm);
|
2013-08-30 14:52:14 -06:00
|
|
|
virObjectUnref(cfg);
|
2013-04-29 16:59:42 +01:00
|
|
|
return ret;
|
2011-05-26 23:27:06 +08:00
|
|
|
}
|
|
|
|
|
2011-03-21 10:35:53 +01:00
|
|
|
static unsigned long long
|
|
|
|
libxlNodeGetFreeMemory(virConnectPtr conn)
|
|
|
|
{
|
|
|
|
libxl_physinfo phy_info;
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = conn->privateData;
|
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
2013-08-30 14:52:14 -06:00
|
|
|
unsigned long long ret = 0;
|
2011-03-21 10:35:53 +01:00
|
|
|
|
2017-01-31 20:07:30 -07:00
|
|
|
libxl_physinfo_init(&phy_info);
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virNodeGetFreeMemoryEnsureACL(conn) < 0)
|
2013-08-30 14:52:14 -06:00
|
|
|
goto cleanup;
|
2013-04-23 11:56:22 +01:00
|
|
|
|
2013-08-30 14:52:14 -06:00
|
|
|
if (libxl_get_physinfo(cfg->ctx, &phy_info)) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("libxl_get_physinfo_info failed"));
|
2013-08-30 14:52:14 -06:00
|
|
|
goto cleanup;
|
2011-03-21 10:35:53 +01:00
|
|
|
}
|
|
|
|
|
2013-08-30 14:52:14 -06:00
|
|
|
ret = phy_info.free_pages * cfg->verInfo->pagesize;
|
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2017-01-31 20:07:30 -07:00
|
|
|
libxl_physinfo_dispose(&phy_info);
|
2013-08-30 14:52:14 -06:00
|
|
|
virObjectUnref(cfg);
|
|
|
|
return ret;
|
2011-03-21 10:35:53 +01:00
|
|
|
}
|
|
|
|
|
2013-06-28 16:32:52 +02: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;
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = conn->privateData;
|
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
2013-06-28 16:32:52 +02:00
|
|
|
|
|
|
|
if (virNodeGetCellsFreeMemoryEnsureACL(conn) < 0)
|
2013-08-30 14:52:14 -06:00
|
|
|
goto cleanup;
|
2013-06-28 16:32:52 +02:00
|
|
|
|
2013-08-30 14:52:14 -06:00
|
|
|
numa_info = libxl_get_numainfo(cfg->ctx, &nr_nodes);
|
2013-06-28 16:32:52 +02:00
|
|
|
if (numa_info == NULL || nr_nodes == 0) {
|
2013-08-09 11:05:58 +02:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("libxl_get_numainfo failed"));
|
|
|
|
goto cleanup;
|
2013-06-28 16:32:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Check/sanitize the cell range */
|
2013-08-09 11:05:58 +02:00
|
|
|
if (startCell >= nr_nodes) {
|
2013-06-28 16:32:52 +02:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("start cell %d out of range (0-%d)"),
|
2013-08-09 11:05:58 +02:00
|
|
|
startCell, nr_nodes - 1);
|
2013-06-28 16:32:52 +02:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
lastCell = startCell + maxCells - 1;
|
2013-08-09 11:05:58 +02:00
|
|
|
if (lastCell >= nr_nodes)
|
|
|
|
lastCell = nr_nodes - 1;
|
2013-06-28 16:32:52 +02: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 15:33:48 -06:00
|
|
|
|
2013-06-28 16:32:52 +02:00
|
|
|
ret = numCells;
|
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2013-06-28 16:32:52 +02:00
|
|
|
libxl_numainfo_list_free(numa_info, nr_nodes);
|
2013-08-30 14:52:14 -06:00
|
|
|
virObjectUnref(cfg);
|
2013-06-28 16:32:52 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-03-29 20:18:24 +08:00
|
|
|
static int
|
2013-04-23 13:50:18 +01:00
|
|
|
libxlConnectDomainEventRegister(virConnectPtr conn,
|
event: make deregister return value match docs
Ever since their introduction (commit 1509b80 in v0.5.0 for
virConnectDomainEventRegister, commit 4445723 in v0.8.0 for
virConnectDomainEventDeregisterAny), the event deregistration
functions have been documented as returning 0 on success;
likewise for older registration (only the newer RegisterAny
must return a non-zero callbackID). And now that we are
adding virConnectNetworkEventDeregisterAny for v1.2.1, it
should have the same semantics.
Fortunately, all of the stateful drivers have been obeying
the docs and returning 0, thanks to the way the remote_driver
tracks things (in fact, the RPC wire protocol is unable to
send a return value for DomainEventRegisterAny, at least not
without adding a new RPC number). Well, except for vbox,
which was always failing deregistration, due to failure to
set the return value to anything besides its initial -1.
But for local drivers, such as test:///default, we've been
returning non-zero numbers; worse, the non-zero numbers have
differed over time. For example, in Fedora 12 (libvirt 0.8.2),
calling Register twice would return 0 and 1 [the callbackID
generated under the hood]; while in Fedora 20 (libvirt 1.1.3),
it returns 1 and 2 [the number of callbacks registered for
that event type]. Since we have changed the behavior over
time, and since it differs by local vs. remote, we can safely
argue that no one could have been reasonably relying on any
particular behavior, so we might as well obey the docs, as well
as prepare callers that might deal with older clients to not be
surprised if the docs are not strictly followed.
For consistency, this patch fixes the code for all drivers,
even though it only makes an impact for vbox and for local
drivers. By fixing all drivers, future copy and paste from
a remote driver to a local driver is less likely to
reintroduce the bug.
Finally, update the testsuite to gain some coverage of the
issue for local drivers, including the first test of old-style
domain event registration via function pointer instead of
event id.
* src/libvirt.c (virConnectDomainEventRegister)
(virConnectDomainEventDeregister)
(virConnectDomainEventDeregisterAny): Clarify docs.
* src/libxl/libxl_driver.c (libxlConnectDomainEventRegister)
(libxlConnectDomainEventDeregister)
(libxlConnectDomainEventDeregisterAny): Match documentation.
* src/lxc/lxc_driver.c (lxcConnectDomainEventRegister)
(lxcConnectDomainEventDeregister)
(lxcConnectDomainEventDeregisterAny): Likewise.
* src/test/test_driver.c (testConnectDomainEventRegister)
(testConnectDomainEventDeregister)
(testConnectDomainEventDeregisterAny)
(testConnectNetworkEventDeregisterAny): Likewise.
* src/uml/uml_driver.c (umlConnectDomainEventRegister)
(umlConnectDomainEventDeregister)
(umlConnectDomainEventDeregisterAny): Likewise.
* src/vbox/vbox_tmpl.c (vboxConnectDomainEventRegister)
(vboxConnectDomainEventDeregister)
(vboxConnectDomainEventDeregisterAny): Likewise.
* src/xen/xen_driver.c (xenUnifiedConnectDomainEventRegister)
(xenUnifiedConnectDomainEventDeregister)
(xenUnifiedConnectDomainEventDeregisterAny): Likewise.
* src/network/bridge_driver.c
(networkConnectNetworkEventDeregisterAny): Likewise.
* tests/objecteventtest.c (testDomainCreateXMLOld): New test.
(mymain): Run it.
(testDomainCreateXML): Check return values.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-03 14:21:17 -07:00
|
|
|
virConnectDomainEventCallback callback,
|
|
|
|
void *opaque,
|
2013-04-23 13:50:18 +01:00
|
|
|
virFreeCallback freecb)
|
2011-03-29 20:18:24 +08:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = conn->privateData;
|
2011-03-29 20:18:24 +08:00
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virConnectDomainEventRegisterEnsureACL(conn) < 0)
|
|
|
|
return -1;
|
|
|
|
|
event: make deregister return value match docs
Ever since their introduction (commit 1509b80 in v0.5.0 for
virConnectDomainEventRegister, commit 4445723 in v0.8.0 for
virConnectDomainEventDeregisterAny), the event deregistration
functions have been documented as returning 0 on success;
likewise for older registration (only the newer RegisterAny
must return a non-zero callbackID). And now that we are
adding virConnectNetworkEventDeregisterAny for v1.2.1, it
should have the same semantics.
Fortunately, all of the stateful drivers have been obeying
the docs and returning 0, thanks to the way the remote_driver
tracks things (in fact, the RPC wire protocol is unable to
send a return value for DomainEventRegisterAny, at least not
without adding a new RPC number). Well, except for vbox,
which was always failing deregistration, due to failure to
set the return value to anything besides its initial -1.
But for local drivers, such as test:///default, we've been
returning non-zero numbers; worse, the non-zero numbers have
differed over time. For example, in Fedora 12 (libvirt 0.8.2),
calling Register twice would return 0 and 1 [the callbackID
generated under the hood]; while in Fedora 20 (libvirt 1.1.3),
it returns 1 and 2 [the number of callbacks registered for
that event type]. Since we have changed the behavior over
time, and since it differs by local vs. remote, we can safely
argue that no one could have been reasonably relying on any
particular behavior, so we might as well obey the docs, as well
as prepare callers that might deal with older clients to not be
surprised if the docs are not strictly followed.
For consistency, this patch fixes the code for all drivers,
even though it only makes an impact for vbox and for local
drivers. By fixing all drivers, future copy and paste from
a remote driver to a local driver is less likely to
reintroduce the bug.
Finally, update the testsuite to gain some coverage of the
issue for local drivers, including the first test of old-style
domain event registration via function pointer instead of
event id.
* src/libvirt.c (virConnectDomainEventRegister)
(virConnectDomainEventDeregister)
(virConnectDomainEventDeregisterAny): Clarify docs.
* src/libxl/libxl_driver.c (libxlConnectDomainEventRegister)
(libxlConnectDomainEventDeregister)
(libxlConnectDomainEventDeregisterAny): Match documentation.
* src/lxc/lxc_driver.c (lxcConnectDomainEventRegister)
(lxcConnectDomainEventDeregister)
(lxcConnectDomainEventDeregisterAny): Likewise.
* src/test/test_driver.c (testConnectDomainEventRegister)
(testConnectDomainEventDeregister)
(testConnectDomainEventDeregisterAny)
(testConnectNetworkEventDeregisterAny): Likewise.
* src/uml/uml_driver.c (umlConnectDomainEventRegister)
(umlConnectDomainEventDeregister)
(umlConnectDomainEventDeregisterAny): Likewise.
* src/vbox/vbox_tmpl.c (vboxConnectDomainEventRegister)
(vboxConnectDomainEventDeregister)
(vboxConnectDomainEventDeregisterAny): Likewise.
* src/xen/xen_driver.c (xenUnifiedConnectDomainEventRegister)
(xenUnifiedConnectDomainEventDeregister)
(xenUnifiedConnectDomainEventDeregisterAny): Likewise.
* src/network/bridge_driver.c
(networkConnectNetworkEventDeregisterAny): Likewise.
* tests/objecteventtest.c (testDomainCreateXMLOld): New test.
(mymain): Run it.
(testDomainCreateXML): Check return values.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-03 14:21:17 -07:00
|
|
|
if (virDomainEventStateRegister(conn,
|
|
|
|
driver->domainEventState,
|
|
|
|
callback, opaque, freecb) < 0)
|
|
|
|
return -1;
|
2011-03-29 20:18:24 +08:00
|
|
|
|
event: make deregister return value match docs
Ever since their introduction (commit 1509b80 in v0.5.0 for
virConnectDomainEventRegister, commit 4445723 in v0.8.0 for
virConnectDomainEventDeregisterAny), the event deregistration
functions have been documented as returning 0 on success;
likewise for older registration (only the newer RegisterAny
must return a non-zero callbackID). And now that we are
adding virConnectNetworkEventDeregisterAny for v1.2.1, it
should have the same semantics.
Fortunately, all of the stateful drivers have been obeying
the docs and returning 0, thanks to the way the remote_driver
tracks things (in fact, the RPC wire protocol is unable to
send a return value for DomainEventRegisterAny, at least not
without adding a new RPC number). Well, except for vbox,
which was always failing deregistration, due to failure to
set the return value to anything besides its initial -1.
But for local drivers, such as test:///default, we've been
returning non-zero numbers; worse, the non-zero numbers have
differed over time. For example, in Fedora 12 (libvirt 0.8.2),
calling Register twice would return 0 and 1 [the callbackID
generated under the hood]; while in Fedora 20 (libvirt 1.1.3),
it returns 1 and 2 [the number of callbacks registered for
that event type]. Since we have changed the behavior over
time, and since it differs by local vs. remote, we can safely
argue that no one could have been reasonably relying on any
particular behavior, so we might as well obey the docs, as well
as prepare callers that might deal with older clients to not be
surprised if the docs are not strictly followed.
For consistency, this patch fixes the code for all drivers,
even though it only makes an impact for vbox and for local
drivers. By fixing all drivers, future copy and paste from
a remote driver to a local driver is less likely to
reintroduce the bug.
Finally, update the testsuite to gain some coverage of the
issue for local drivers, including the first test of old-style
domain event registration via function pointer instead of
event id.
* src/libvirt.c (virConnectDomainEventRegister)
(virConnectDomainEventDeregister)
(virConnectDomainEventDeregisterAny): Clarify docs.
* src/libxl/libxl_driver.c (libxlConnectDomainEventRegister)
(libxlConnectDomainEventDeregister)
(libxlConnectDomainEventDeregisterAny): Match documentation.
* src/lxc/lxc_driver.c (lxcConnectDomainEventRegister)
(lxcConnectDomainEventDeregister)
(lxcConnectDomainEventDeregisterAny): Likewise.
* src/test/test_driver.c (testConnectDomainEventRegister)
(testConnectDomainEventDeregister)
(testConnectDomainEventDeregisterAny)
(testConnectNetworkEventDeregisterAny): Likewise.
* src/uml/uml_driver.c (umlConnectDomainEventRegister)
(umlConnectDomainEventDeregister)
(umlConnectDomainEventDeregisterAny): Likewise.
* src/vbox/vbox_tmpl.c (vboxConnectDomainEventRegister)
(vboxConnectDomainEventDeregister)
(vboxConnectDomainEventDeregisterAny): Likewise.
* src/xen/xen_driver.c (xenUnifiedConnectDomainEventRegister)
(xenUnifiedConnectDomainEventDeregister)
(xenUnifiedConnectDomainEventDeregisterAny): Likewise.
* src/network/bridge_driver.c
(networkConnectNetworkEventDeregisterAny): Likewise.
* tests/objecteventtest.c (testDomainCreateXMLOld): New test.
(mymain): Run it.
(testDomainCreateXML): Check return values.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-03 14:21:17 -07:00
|
|
|
return 0;
|
2011-03-29 20:18:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2013-04-23 13:50:18 +01:00
|
|
|
libxlConnectDomainEventDeregister(virConnectPtr conn,
|
|
|
|
virConnectDomainEventCallback callback)
|
2011-03-29 20:18:24 +08:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = conn->privateData;
|
2011-03-29 20:18:24 +08:00
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virConnectDomainEventDeregisterEnsureACL(conn) < 0)
|
|
|
|
return -1;
|
|
|
|
|
event: make deregister return value match docs
Ever since their introduction (commit 1509b80 in v0.5.0 for
virConnectDomainEventRegister, commit 4445723 in v0.8.0 for
virConnectDomainEventDeregisterAny), the event deregistration
functions have been documented as returning 0 on success;
likewise for older registration (only the newer RegisterAny
must return a non-zero callbackID). And now that we are
adding virConnectNetworkEventDeregisterAny for v1.2.1, it
should have the same semantics.
Fortunately, all of the stateful drivers have been obeying
the docs and returning 0, thanks to the way the remote_driver
tracks things (in fact, the RPC wire protocol is unable to
send a return value for DomainEventRegisterAny, at least not
without adding a new RPC number). Well, except for vbox,
which was always failing deregistration, due to failure to
set the return value to anything besides its initial -1.
But for local drivers, such as test:///default, we've been
returning non-zero numbers; worse, the non-zero numbers have
differed over time. For example, in Fedora 12 (libvirt 0.8.2),
calling Register twice would return 0 and 1 [the callbackID
generated under the hood]; while in Fedora 20 (libvirt 1.1.3),
it returns 1 and 2 [the number of callbacks registered for
that event type]. Since we have changed the behavior over
time, and since it differs by local vs. remote, we can safely
argue that no one could have been reasonably relying on any
particular behavior, so we might as well obey the docs, as well
as prepare callers that might deal with older clients to not be
surprised if the docs are not strictly followed.
For consistency, this patch fixes the code for all drivers,
even though it only makes an impact for vbox and for local
drivers. By fixing all drivers, future copy and paste from
a remote driver to a local driver is less likely to
reintroduce the bug.
Finally, update the testsuite to gain some coverage of the
issue for local drivers, including the first test of old-style
domain event registration via function pointer instead of
event id.
* src/libvirt.c (virConnectDomainEventRegister)
(virConnectDomainEventDeregister)
(virConnectDomainEventDeregisterAny): Clarify docs.
* src/libxl/libxl_driver.c (libxlConnectDomainEventRegister)
(libxlConnectDomainEventDeregister)
(libxlConnectDomainEventDeregisterAny): Match documentation.
* src/lxc/lxc_driver.c (lxcConnectDomainEventRegister)
(lxcConnectDomainEventDeregister)
(lxcConnectDomainEventDeregisterAny): Likewise.
* src/test/test_driver.c (testConnectDomainEventRegister)
(testConnectDomainEventDeregister)
(testConnectDomainEventDeregisterAny)
(testConnectNetworkEventDeregisterAny): Likewise.
* src/uml/uml_driver.c (umlConnectDomainEventRegister)
(umlConnectDomainEventDeregister)
(umlConnectDomainEventDeregisterAny): Likewise.
* src/vbox/vbox_tmpl.c (vboxConnectDomainEventRegister)
(vboxConnectDomainEventDeregister)
(vboxConnectDomainEventDeregisterAny): Likewise.
* src/xen/xen_driver.c (xenUnifiedConnectDomainEventRegister)
(xenUnifiedConnectDomainEventDeregister)
(xenUnifiedConnectDomainEventDeregisterAny): Likewise.
* src/network/bridge_driver.c
(networkConnectNetworkEventDeregisterAny): Likewise.
* tests/objecteventtest.c (testDomainCreateXMLOld): New test.
(mymain): Run it.
(testDomainCreateXML): Check return values.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-03 14:21:17 -07:00
|
|
|
if (virDomainEventStateDeregister(conn,
|
|
|
|
driver->domainEventState,
|
|
|
|
callback) < 0)
|
|
|
|
return -1;
|
2011-03-29 20:18:24 +08:00
|
|
|
|
event: make deregister return value match docs
Ever since their introduction (commit 1509b80 in v0.5.0 for
virConnectDomainEventRegister, commit 4445723 in v0.8.0 for
virConnectDomainEventDeregisterAny), the event deregistration
functions have been documented as returning 0 on success;
likewise for older registration (only the newer RegisterAny
must return a non-zero callbackID). And now that we are
adding virConnectNetworkEventDeregisterAny for v1.2.1, it
should have the same semantics.
Fortunately, all of the stateful drivers have been obeying
the docs and returning 0, thanks to the way the remote_driver
tracks things (in fact, the RPC wire protocol is unable to
send a return value for DomainEventRegisterAny, at least not
without adding a new RPC number). Well, except for vbox,
which was always failing deregistration, due to failure to
set the return value to anything besides its initial -1.
But for local drivers, such as test:///default, we've been
returning non-zero numbers; worse, the non-zero numbers have
differed over time. For example, in Fedora 12 (libvirt 0.8.2),
calling Register twice would return 0 and 1 [the callbackID
generated under the hood]; while in Fedora 20 (libvirt 1.1.3),
it returns 1 and 2 [the number of callbacks registered for
that event type]. Since we have changed the behavior over
time, and since it differs by local vs. remote, we can safely
argue that no one could have been reasonably relying on any
particular behavior, so we might as well obey the docs, as well
as prepare callers that might deal with older clients to not be
surprised if the docs are not strictly followed.
For consistency, this patch fixes the code for all drivers,
even though it only makes an impact for vbox and for local
drivers. By fixing all drivers, future copy and paste from
a remote driver to a local driver is less likely to
reintroduce the bug.
Finally, update the testsuite to gain some coverage of the
issue for local drivers, including the first test of old-style
domain event registration via function pointer instead of
event id.
* src/libvirt.c (virConnectDomainEventRegister)
(virConnectDomainEventDeregister)
(virConnectDomainEventDeregisterAny): Clarify docs.
* src/libxl/libxl_driver.c (libxlConnectDomainEventRegister)
(libxlConnectDomainEventDeregister)
(libxlConnectDomainEventDeregisterAny): Match documentation.
* src/lxc/lxc_driver.c (lxcConnectDomainEventRegister)
(lxcConnectDomainEventDeregister)
(lxcConnectDomainEventDeregisterAny): Likewise.
* src/test/test_driver.c (testConnectDomainEventRegister)
(testConnectDomainEventDeregister)
(testConnectDomainEventDeregisterAny)
(testConnectNetworkEventDeregisterAny): Likewise.
* src/uml/uml_driver.c (umlConnectDomainEventRegister)
(umlConnectDomainEventDeregister)
(umlConnectDomainEventDeregisterAny): Likewise.
* src/vbox/vbox_tmpl.c (vboxConnectDomainEventRegister)
(vboxConnectDomainEventDeregister)
(vboxConnectDomainEventDeregisterAny): Likewise.
* src/xen/xen_driver.c (xenUnifiedConnectDomainEventRegister)
(xenUnifiedConnectDomainEventDeregister)
(xenUnifiedConnectDomainEventDeregisterAny): Likewise.
* src/network/bridge_driver.c
(networkConnectNetworkEventDeregisterAny): Likewise.
* tests/objecteventtest.c (testDomainCreateXMLOld): New test.
(mymain): Run it.
(testDomainCreateXML): Check return values.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-03 14:21:17 -07:00
|
|
|
return 0;
|
2011-03-29 20:18:24 +08:00
|
|
|
}
|
|
|
|
|
2011-03-28 12:49:22 +02:00
|
|
|
static int
|
|
|
|
libxlDomainGetAutostart(virDomainPtr dom, int *autostart)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainObj *vm;
|
2011-03-28 12:49:22 +02:00
|
|
|
int ret = -1;
|
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-03-28 12:49:22 +02:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virDomainGetAutostartEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-03-28 12:49:22 +02:00
|
|
|
*autostart = vm->autostart;
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2018-03-09 11:47:59 -05:00
|
|
|
virDomainObjEndAPI(&vm);
|
2011-03-28 12:49:22 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainSetAutostart(virDomainPtr dom, int autostart)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
|
|
|
virDomainObj *vm;
|
2021-02-16 18:37:09 -07:00
|
|
|
g_autofree char *configFile = NULL;
|
|
|
|
g_autofree char *autostartLink = NULL;
|
2011-03-28 12:49:22 +02:00
|
|
|
int ret = -1;
|
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-03-28 12:49:22 +02:00
|
|
|
goto cleanup;
|
|
|
|
|
2015-06-22 11:36:59 -06:00
|
|
|
LIBXL_CHECK_DOM0_GOTO(vm->def->name, cleanup);
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virDomainSetAutostartEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2014-02-06 17:24:48 -07:00
|
|
|
if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-03-28 12:49:22 +02:00
|
|
|
if (!vm->persistent) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("cannot set autostart for transient domain"));
|
2014-02-06 17:24:48 -07:00
|
|
|
goto endjob;
|
2011-03-28 12:49:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
autostart = (autostart != 0);
|
|
|
|
|
|
|
|
if (vm->autostart != autostart) {
|
2013-08-30 14:52:14 -06:00
|
|
|
if (!(configFile = virDomainConfigFile(cfg->configDir, vm->def->name)))
|
2014-02-06 17:24:48 -07:00
|
|
|
goto endjob;
|
2013-08-30 14:52:14 -06:00
|
|
|
if (!(autostartLink = virDomainConfigFile(cfg->autostartDir, vm->def->name)))
|
2014-02-06 17:24:48 -07:00
|
|
|
goto endjob;
|
2011-03-28 12:49:22 +02:00
|
|
|
|
|
|
|
if (autostart) {
|
2021-02-26 09:37:10 +01:00
|
|
|
if (g_mkdir_with_parents(cfg->autostartDir, 0777) < 0) {
|
2011-07-05 23:02:53 +02:00
|
|
|
virReportSystemError(errno,
|
2011-03-28 12:49:22 +02:00
|
|
|
_("cannot create autostart directory %s"),
|
2013-08-30 14:52:14 -06:00
|
|
|
cfg->autostartDir);
|
2014-02-06 17:24:48 -07:00
|
|
|
goto endjob;
|
2011-03-28 12:49:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (symlink(configFile, autostartLink) < 0) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("Failed to create symlink '%s to '%s'"),
|
|
|
|
autostartLink, configFile);
|
2014-02-06 17:24:48 -07:00
|
|
|
goto endjob;
|
2011-03-28 12:49:22 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("Failed to delete symlink '%s'"),
|
|
|
|
autostartLink);
|
2014-02-06 17:24:48 -07:00
|
|
|
goto endjob;
|
2011-03-28 12:49:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
vm->autostart = autostart;
|
|
|
|
}
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
endjob:
|
2016-06-12 18:30:00 +08:00
|
|
|
libxlDomainObjEndJob(driver, vm);
|
2014-02-06 17:24:48 -07:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2016-06-12 18:30:00 +08:00
|
|
|
virDomainObjEndAPI(&vm);
|
2013-08-30 14:52:14 -06:00
|
|
|
virObjectUnref(cfg);
|
2011-03-28 12:49:22 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-03-29 20:46:55 +08:00
|
|
|
static char *
|
|
|
|
libxlDomainGetSchedulerType(virDomainPtr dom, int *nparams)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
|
|
|
virDomainObj *vm;
|
2011-03-29 20:46:55 +08:00
|
|
|
char * ret = NULL;
|
2013-05-03 14:42:47 +02:00
|
|
|
const char *name = NULL;
|
2012-11-26 09:28:56 -07:00
|
|
|
libxl_scheduler sched_id;
|
2011-03-29 20:46:55 +08:00
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-03-29 20:46:55 +08:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virDomainGetSchedulerTypeEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2018-04-17 22:13:29 +00:00
|
|
|
if (virDomainObjCheckActive(vm) < 0)
|
2011-03-29 20:46:55 +08:00
|
|
|
goto cleanup;
|
|
|
|
|
2015-02-11 16:40:07 -07:00
|
|
|
sched_id = libxl_get_scheduler(cfg->ctx);
|
2011-03-29 20:46:55 +08:00
|
|
|
|
2011-05-18 09:55:32 +02:00
|
|
|
if (nparams)
|
|
|
|
*nparams = 0;
|
2018-02-14 09:43:59 +00:00
|
|
|
switch ((int)sched_id) {
|
2012-11-26 09:28:56 -07:00
|
|
|
case LIBXL_SCHEDULER_SEDF:
|
2013-05-03 14:42:47 +02:00
|
|
|
name = "sedf";
|
2011-03-29 20:46:55 +08:00
|
|
|
break;
|
2012-11-26 09:28:56 -07:00
|
|
|
case LIBXL_SCHEDULER_CREDIT:
|
2013-05-03 14:42:47 +02:00
|
|
|
name = "credit";
|
2011-05-18 09:55:32 +02:00
|
|
|
if (nparams)
|
|
|
|
*nparams = XEN_SCHED_CREDIT_NPARAM;
|
2011-03-29 20:46:55 +08:00
|
|
|
break;
|
2012-11-26 09:28:56 -07:00
|
|
|
case LIBXL_SCHEDULER_CREDIT2:
|
2013-05-03 14:42:47 +02:00
|
|
|
name = "credit2";
|
2020-01-29 12:05:15 +01:00
|
|
|
if (nparams)
|
|
|
|
*nparams = XEN_SCHED_CREDIT_NPARAM;
|
2011-03-29 20:46:55 +08:00
|
|
|
break;
|
2012-11-26 09:28:56 -07:00
|
|
|
case LIBXL_SCHEDULER_ARINC653:
|
2013-05-03 14:42:47 +02:00
|
|
|
name = "arinc653";
|
2011-03-29 20:46:55 +08:00
|
|
|
break;
|
|
|
|
default:
|
2012-11-26 09:28:56 -07:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to get scheduler id for domain '%d'"
|
2014-03-27 17:55:02 +01:00
|
|
|
" with libxenlight"), vm->def->id);
|
2011-03-29 20:46:55 +08:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2019-10-18 13:27:03 +02:00
|
|
|
ret = g_strdup(name);
|
2011-03-29 20:46:55 +08:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2018-03-09 11:47:59 -05:00
|
|
|
virDomainObjEndAPI(&vm);
|
2015-02-11 16:40:07 -07:00
|
|
|
virObjectUnref(cfg);
|
2011-03-29 20:46:55 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-04-06 10:58:40 +02:00
|
|
|
static int
|
2011-05-17 16:33:53 -06:00
|
|
|
libxlDomainGetSchedulerParametersFlags(virDomainPtr dom,
|
|
|
|
virTypedParameterPtr params,
|
|
|
|
int *nparams,
|
|
|
|
unsigned int flags)
|
2011-04-06 10:58:40 +02:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
|
|
|
virDomainObj *vm;
|
2012-11-26 09:28:56 -07:00
|
|
|
libxl_domain_sched_params sc_info;
|
|
|
|
libxl_scheduler sched_id;
|
2011-04-06 10:58:40 +02:00
|
|
|
int ret = -1;
|
|
|
|
|
2013-07-13 02:27:10 +02: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 16:33:53 -06:00
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-04-06 10:58:40 +02:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virDomainGetSchedulerParametersFlagsEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2018-04-17 22:13:29 +00:00
|
|
|
if (virDomainObjCheckActive(vm) < 0)
|
2011-04-06 10:58:40 +02:00
|
|
|
goto cleanup;
|
|
|
|
|
2020-01-29 12:05:15 +01:00
|
|
|
/* Only credit and credit2 are supported for now. */
|
2015-02-11 16:40:07 -07:00
|
|
|
sched_id = libxl_get_scheduler(cfg->ctx);
|
2020-01-29 12:05:15 +01:00
|
|
|
if (sched_id != LIBXL_SCHEDULER_CREDIT && sched_id != LIBXL_SCHEDULER_CREDIT2) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
2020-01-29 12:05:15 +01:00
|
|
|
_("Only 'credit' and 'credit2' schedulers are supported"));
|
2011-04-06 10:58:40 +02:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2015-02-11 16:40:07 -07:00
|
|
|
if (libxl_domain_sched_params_get(cfg->ctx, vm->def->id, &sc_info) != 0) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to get scheduler parameters for domain '%d'"
|
2014-03-27 17:55:02 +01:00
|
|
|
" with libxenlight"), vm->def->id);
|
2011-04-06 10:58:40 +02:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2012-01-07 05:47:43 -07:00
|
|
|
if (virTypedParameterAssign(¶ms[0], VIR_DOMAIN_SCHEDULER_WEIGHT,
|
|
|
|
VIR_TYPED_PARAM_UINT, sc_info.weight) < 0)
|
2011-04-06 10:58:40 +02:00
|
|
|
goto cleanup;
|
|
|
|
|
2011-11-02 11:42:38 -06:00
|
|
|
if (*nparams > 1) {
|
2016-09-27 22:18:50 -06:00
|
|
|
if (virTypedParameterAssign(¶ms[1], VIR_DOMAIN_SCHEDULER_CAP,
|
2012-01-07 05:47:43 -07:00
|
|
|
VIR_TYPED_PARAM_UINT, sc_info.cap) < 0)
|
2011-11-02 11:42:38 -06:00
|
|
|
goto cleanup;
|
2011-04-06 10:58:40 +02:00
|
|
|
}
|
|
|
|
|
2011-11-02 11:42:38 -06:00
|
|
|
if (*nparams > XEN_SCHED_CREDIT_NPARAM)
|
|
|
|
*nparams = XEN_SCHED_CREDIT_NPARAM;
|
2011-04-06 10:58:40 +02:00
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2018-03-09 11:47:59 -05:00
|
|
|
virDomainObjEndAPI(&vm);
|
2015-02-11 16:40:07 -07:00
|
|
|
virObjectUnref(cfg);
|
2011-04-06 10:58:40 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2011-05-17 16:33:53 -06: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 10:58:40 +02:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
|
|
|
virDomainObj *vm;
|
2012-11-26 09:28:56 -07:00
|
|
|
libxl_domain_sched_params sc_info;
|
2011-04-06 10:58:40 +02: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 15:09:33 +01:00
|
|
|
size_t i;
|
2011-04-06 10:58:40 +02:00
|
|
|
int ret = -1;
|
|
|
|
|
2011-05-17 16:33:53 -06:00
|
|
|
virCheckFlags(0, -1);
|
2013-05-03 15:34:10 +02: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 05:47:43 -07:00
|
|
|
return -1;
|
2011-05-17 16:33:53 -06:00
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-04-06 10:58:40 +02:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virDomainSetSchedulerParametersFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2014-02-06 17:29:09 -07:00
|
|
|
if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2018-04-17 22:13:29 +00:00
|
|
|
if (virDomainObjCheckActive(vm) < 0)
|
2014-02-06 17:29:09 -07:00
|
|
|
goto endjob;
|
2011-04-06 10:58:40 +02:00
|
|
|
|
2020-01-29 12:05:15 +01:00
|
|
|
/* Only credit and credit2 are supported for now. */
|
2015-02-11 16:40:07 -07:00
|
|
|
sched_id = libxl_get_scheduler(cfg->ctx);
|
2020-01-29 12:05:15 +01:00
|
|
|
if (sched_id != LIBXL_SCHEDULER_CREDIT && sched_id != LIBXL_SCHEDULER_CREDIT2) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
2020-01-29 12:05:15 +01:00
|
|
|
_("Only 'credit' and 'credit2' schedulers are supported"));
|
2014-02-06 17:29:09 -07:00
|
|
|
goto endjob;
|
2011-04-06 10:58:40 +02:00
|
|
|
}
|
|
|
|
|
2015-02-11 16:40:07 -07:00
|
|
|
if (libxl_domain_sched_params_get(cfg->ctx, vm->def->id, &sc_info) != 0) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to get scheduler parameters for domain '%d'"
|
2014-03-27 17:55:02 +01:00
|
|
|
" with libxenlight"), vm->def->id);
|
2014-02-06 17:29:09 -07:00
|
|
|
goto endjob;
|
2011-04-06 10:58:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < nparams; ++i) {
|
2011-05-26 11:39:04 -06:00
|
|
|
virTypedParameterPtr param = ¶ms[i];
|
2011-04-06 10:58:40 +02:00
|
|
|
|
2013-08-14 15:33:48 -06:00
|
|
|
if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_WEIGHT))
|
2011-04-06 10:58:40 +02:00
|
|
|
sc_info.weight = params[i].value.ui;
|
2013-08-14 15:33:48 -06:00
|
|
|
else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_CAP))
|
2011-04-06 10:58:40 +02:00
|
|
|
sc_info.cap = params[i].value.ui;
|
|
|
|
}
|
|
|
|
|
2015-02-11 16:40:07 -07:00
|
|
|
if (libxl_domain_sched_params_set(cfg->ctx, vm->def->id, &sc_info) != 0) {
|
2012-07-18 14:32:10 +01:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to set scheduler parameters for domain '%d'"
|
2014-03-27 17:55:02 +01:00
|
|
|
" with libxenlight"), vm->def->id);
|
2014-02-06 17:29:09 -07:00
|
|
|
goto endjob;
|
2011-04-06 10:58:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
endjob:
|
2016-06-12 18:30:00 +08:00
|
|
|
libxlDomainObjEndJob(driver, vm);
|
2014-02-06 17:29:09 -07:00
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2016-06-12 18:30:00 +08:00
|
|
|
virDomainObjEndAPI(&vm);
|
2015-02-11 16:40:07 -07:00
|
|
|
virObjectUnref(cfg);
|
2011-04-06 10:58:40 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-07-26 11:30:50 +08:00
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainOpenConsole(virDomainPtr dom,
|
|
|
|
const char *dev_name,
|
|
|
|
virStreamPtr st,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainObj *vm = NULL;
|
2013-07-26 11:30:50 +08:00
|
|
|
int ret = -1;
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainChrDef *chr = NULL;
|
|
|
|
libxlDomainObjPrivate *priv;
|
2013-07-26 11:30:50 +08:00
|
|
|
|
|
|
|
virCheckFlags(VIR_DOMAIN_CONSOLE_FORCE, -1);
|
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2013-07-26 11:30:50 +08:00
|
|
|
goto cleanup;
|
|
|
|
|
2015-06-22 11:36:59 -06:00
|
|
|
LIBXL_CHECK_DOM0_GOTO(vm->def->name, cleanup);
|
|
|
|
|
2013-07-26 11:30:50 +08:00
|
|
|
if (virDomainOpenConsoleEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2018-04-17 22:13:29 +00:00
|
|
|
if (virDomainObjCheckActive(vm) < 0)
|
2013-07-26 11:30:50 +08:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
priv = vm->privateData;
|
2016-08-18 10:20:48 +08:00
|
|
|
if (dev_name) {
|
|
|
|
size_t i;
|
2013-07-26 11:30:50 +08:00
|
|
|
|
2016-08-18 10:20:48 +08:00
|
|
|
for (i = 0; !chr && i < vm->def->nserials; i++) {
|
|
|
|
if (STREQ(dev_name, vm->def->serials[i]->info.alias)) {
|
|
|
|
chr = vm->def->serials[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (vm->def->nconsoles) {
|
2014-04-25 16:54:20 +01:00
|
|
|
chr = vm->def->consoles[0];
|
2016-06-21 20:25:23 -06:00
|
|
|
if (chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL)
|
|
|
|
chr = vm->def->serials[0];
|
|
|
|
}
|
2013-07-26 11:30:50 +08:00
|
|
|
|
|
|
|
if (!chr) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("cannot find character device %s"),
|
|
|
|
NULLSTR(dev_name));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2016-10-21 07:45:54 -04:00
|
|
|
if (chr->source->type != VIR_DOMAIN_CHR_TYPE_PTY) {
|
2013-07-26 11:30:50 +08:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("character device %s is not using a PTY"),
|
2015-06-15 21:58:36 +08:00
|
|
|
dev_name ? dev_name : NULLSTR(chr->info.alias));
|
2013-07-26 11:30:50 +08:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* handle mutually exclusive access to console devices */
|
|
|
|
ret = virChrdevOpen(priv->devs,
|
2016-10-21 07:45:54 -04:00
|
|
|
chr->source,
|
2013-07-26 11:30:50 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2018-03-09 11:47:59 -05:00
|
|
|
virDomainObjEndAPI(&vm);
|
2013-07-26 11:30:50 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-05-17 16:33:53 -06:00
|
|
|
static int
|
|
|
|
libxlDomainSetSchedulerParameters(virDomainPtr dom, virTypedParameterPtr params,
|
|
|
|
int nparams)
|
|
|
|
{
|
|
|
|
return libxlDomainSetSchedulerParametersFlags(dom, params, nparams, 0);
|
|
|
|
}
|
|
|
|
|
2013-07-13 02:27:18 +02: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)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
libxlDriverConfig *cfg = libxlDriverConfigGet(driver);
|
|
|
|
virDomainObj *vm;
|
2013-07-13 02:27:18 +02:00
|
|
|
libxl_bitmap nodemap;
|
2021-03-11 08:16:13 +01:00
|
|
|
virBitmap *nodes = NULL;
|
2013-07-13 02:27:18 +02:00
|
|
|
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-12-20 16:29:47 +01:00
|
|
|
libxl_bitmap_init(&nodemap);
|
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2013-07-13 02:27:18 +02:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virDomainGetNumaParametersEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2018-04-17 22:13:29 +00:00
|
|
|
if (virDomainObjCheckActive(vm) < 0)
|
2013-07-13 02:27:18 +02:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
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];
|
2013-12-18 15:39:12 +01:00
|
|
|
int numnodes;
|
2021-02-16 18:37:09 -07:00
|
|
|
g_autofree char *nodeset = NULL;
|
2013-07-13 02:27:18 +02:00
|
|
|
|
|
|
|
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 */
|
2015-02-11 16:40:07 -07:00
|
|
|
numnodes = libxl_get_max_nodes(cfg->ctx);
|
2013-12-18 15:39:12 +01:00
|
|
|
if (numnodes <= 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2021-02-24 11:32:10 +01:00
|
|
|
if (libxl_node_bitmap_alloc(cfg->ctx, &nodemap, 0))
|
|
|
|
abort();
|
|
|
|
|
2020-10-01 17:42:11 +02:00
|
|
|
nodes = virBitmapNew(numnodes);
|
2013-07-13 02:27:18 +02:00
|
|
|
|
2015-02-11 16:40:07 -07:00
|
|
|
rc = libxl_domain_get_nodeaffinity(cfg->ctx,
|
2013-07-13 02:27:18 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-05 12:42:40 +02:00
|
|
|
if (!(nodeset = virBitmapFormat(nodes)))
|
2013-07-13 02:27:18 +02:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virTypedParameterAssign(param, VIR_DOMAIN_NUMA_NODESET,
|
|
|
|
VIR_TYPED_PARAM_STRING, nodeset) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
nodeset = NULL;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*nparams > LIBXL_NUMA_NPARAM)
|
|
|
|
*nparams = LIBXL_NUMA_NPARAM;
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2013-07-13 02:27:18 +02:00
|
|
|
virBitmapFree(nodes);
|
|
|
|
libxl_bitmap_dispose(&nodemap);
|
2018-03-09 11:47:59 -05:00
|
|
|
virDomainObjEndAPI(&vm);
|
2015-02-11 16:40:07 -07:00
|
|
|
virObjectUnref(cfg);
|
2013-07-13 02:27:18 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2011-02-10 15:42:34 -07:00
|
|
|
static int
|
|
|
|
libxlDomainIsActive(virDomainPtr dom)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainObj *obj;
|
2011-02-10 15:42:34 -07:00
|
|
|
int ret = -1;
|
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(obj = libxlDomObjFromDomain(dom)))
|
2011-02-10 15:42:34 -07:00
|
|
|
goto cleanup;
|
2013-04-23 11:56:22 +01:00
|
|
|
|
|
|
|
if (virDomainIsActiveEnsureACL(dom->conn, obj->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-02-10 15:42:34 -07:00
|
|
|
ret = virDomainObjIsActive(obj);
|
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2018-03-09 11:47:59 -05:00
|
|
|
virDomainObjEndAPI(&obj);
|
2011-02-10 15:42:34 -07:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainIsPersistent(virDomainPtr dom)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainObj *obj;
|
2011-02-10 15:42:34 -07:00
|
|
|
int ret = -1;
|
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(obj = libxlDomObjFromDomain(dom)))
|
2011-02-10 15:42:34 -07:00
|
|
|
goto cleanup;
|
2013-04-23 11:56:22 +01:00
|
|
|
|
|
|
|
if (virDomainIsPersistentEnsureACL(dom->conn, obj->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-02-10 15:42:34 -07:00
|
|
|
ret = obj->persistent;
|
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2018-03-09 11:47:59 -05:00
|
|
|
virDomainObjEndAPI(&obj);
|
2011-02-10 15:42:34 -07:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-04-06 10:58:39 +02:00
|
|
|
static int
|
|
|
|
libxlDomainIsUpdated(virDomainPtr dom)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainObj *vm;
|
2011-04-06 10:58:39 +02:00
|
|
|
int ret = -1;
|
|
|
|
|
2013-08-30 14:58:31 -06:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
2011-04-06 10:58:39 +02:00
|
|
|
goto cleanup;
|
2013-04-23 11:56:22 +01:00
|
|
|
|
|
|
|
if (virDomainIsUpdatedEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-04-06 10:58:39 +02:00
|
|
|
ret = vm->updated;
|
|
|
|
|
2014-03-25 07:51:17 +01:00
|
|
|
cleanup:
|
2018-03-09 11:47:59 -05:00
|
|
|
virDomainObjEndAPI(&vm);
|
2011-04-06 10:58:39 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-02-24 13:25:46 +00:00
|
|
|
static int
|
|
|
|
libxlDomainInterfaceStats(virDomainPtr dom,
|
2017-10-13 13:25:42 -07:00
|
|
|
const char *device,
|
2016-02-24 13:25:46 +00:00
|
|
|
virDomainInterfaceStatsPtr stats)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
virDomainObj *vm;
|
|
|
|
virDomainNetDef *net = NULL;
|
2016-02-24 13:25:46 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virDomainInterfaceStatsEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_QUERY) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2018-04-17 22:13:29 +00:00
|
|
|
if (virDomainObjCheckActive(vm) < 0)
|
2016-02-24 13:25:46 +00:00
|
|
|
goto endjob;
|
|
|
|
|
2017-10-13 13:25:42 -07:00
|
|
|
if (!(net = virDomainNetFind(vm->def, device)))
|
2017-10-02 15:24:39 +02:00
|
|
|
goto endjob;
|
|
|
|
|
2017-10-13 16:29:36 -07:00
|
|
|
if (virNetDevTapInterfaceStats(net->ifname, stats,
|
2017-10-02 13:36:56 +02:00
|
|
|
!virDomainNetTypeSharesHostView(net)) < 0)
|
2017-10-02 15:24:39 +02:00
|
|
|
goto endjob;
|
|
|
|
|
|
|
|
ret = 0;
|
2016-02-24 13:25:46 +00:00
|
|
|
|
|
|
|
endjob:
|
2016-06-12 18:30:00 +08:00
|
|
|
libxlDomainObjEndJob(driver, vm);
|
2016-02-24 13:25:46 +00:00
|
|
|
|
|
|
|
cleanup:
|
2016-06-12 18:30:00 +08:00
|
|
|
virDomainObjEndAPI(&vm);
|
2016-02-24 13:25:46 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-11-13 13:14:41 +00:00
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDomainGetTotalCPUStats(libxlDriverPrivate *driver,
|
|
|
|
virDomainObj *vm,
|
2015-11-13 13:14:41 +00:00
|
|
|
virTypedParameterPtr params,
|
|
|
|
unsigned int nparams)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverConfig *cfg;
|
2015-11-13 13:14:41 +00:00
|
|
|
libxl_dominfo d_info;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (nparams == 0)
|
|
|
|
return LIBXL_NB_TOTAL_CPU_STAT_PARAM;
|
|
|
|
|
2015-11-18 15:47:24 -07:00
|
|
|
libxl_dominfo_init(&d_info);
|
|
|
|
cfg = libxlDriverConfigGet(driver);
|
|
|
|
|
2015-11-13 13:14:41 +00:00
|
|
|
if (libxl_domain_info(cfg->ctx, &d_info, vm->def->id) != 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("libxl_domain_info failed for domain '%d'"),
|
|
|
|
vm->def->id);
|
2015-11-18 15:47:24 -07:00
|
|
|
goto cleanup;
|
2015-11-13 13:14:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (virTypedParameterAssign(¶ms[0], VIR_DOMAIN_CPU_STATS_CPUTIME,
|
|
|
|
VIR_TYPED_PARAM_ULLONG, d_info.cpu_time) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = nparams;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
libxl_dominfo_dispose(&d_info);
|
2015-11-18 15:47:24 -07:00
|
|
|
virObjectUnref(cfg);
|
2015-11-13 13:14:41 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDomainGetPerCPUStats(libxlDriverPrivate *driver,
|
|
|
|
virDomainObj *vm,
|
2015-11-13 13:14:41 +00:00
|
|
|
virTypedParameterPtr params,
|
|
|
|
unsigned int nparams,
|
|
|
|
int start_cpu,
|
|
|
|
unsigned int ncpus)
|
|
|
|
{
|
|
|
|
libxl_vcpuinfo *vcpuinfo;
|
|
|
|
int maxcpu, hostcpus;
|
|
|
|
size_t i;
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverConfig *cfg;
|
2015-11-13 13:14:41 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (nparams == 0 && ncpus != 0)
|
|
|
|
return LIBXL_NB_TOTAL_CPU_STAT_PARAM;
|
|
|
|
else if (nparams == 0)
|
2015-10-19 19:21:24 +02:00
|
|
|
return virDomainDefGetVcpusMax(vm->def);
|
2015-11-13 13:14:41 +00:00
|
|
|
|
2015-11-18 15:47:24 -07:00
|
|
|
cfg = libxlDriverConfigGet(driver);
|
2015-11-13 13:14:41 +00:00
|
|
|
if ((vcpuinfo = libxl_list_vcpu(cfg->ctx, vm->def->id, &maxcpu,
|
|
|
|
&hostcpus)) == NULL) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to list vcpus for domain '%d' with libxenlight"),
|
|
|
|
vm->def->id);
|
2015-11-18 15:47:24 -07:00
|
|
|
goto cleanup;
|
2015-11-13 13:14:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = start_cpu; i < maxcpu && i < ncpus; ++i) {
|
|
|
|
if (virTypedParameterAssign(¶ms[(i-start_cpu)],
|
|
|
|
VIR_DOMAIN_CPU_STATS_CPUTIME,
|
|
|
|
VIR_TYPED_PARAM_ULLONG,
|
|
|
|
vcpuinfo[i].vcpu_time) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
ret = nparams;
|
|
|
|
|
|
|
|
cleanup:
|
2015-11-18 15:47:24 -07:00
|
|
|
if (vcpuinfo)
|
|
|
|
libxl_vcpuinfo_list_free(vcpuinfo, maxcpu);
|
|
|
|
virObjectUnref(cfg);
|
2015-11-13 13:14:41 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainGetCPUStats(virDomainPtr dom,
|
|
|
|
virTypedParameterPtr params,
|
|
|
|
unsigned int nparams,
|
|
|
|
int start_cpu,
|
|
|
|
unsigned int ncpus,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
virDomainObj *vm = NULL;
|
2015-11-13 13:14:41 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
|
|
|
|
|
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virDomainGetCPUStatsEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2018-04-17 22:13:29 +00:00
|
|
|
if (virDomainObjCheckActive(vm) < 0)
|
2015-11-13 13:14:41 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (start_cpu == -1)
|
|
|
|
ret = libxlDomainGetTotalCPUStats(driver, vm, params, nparams);
|
|
|
|
else
|
|
|
|
ret = libxlDomainGetPerCPUStats(driver, vm, params, nparams,
|
|
|
|
start_cpu, ncpus);
|
|
|
|
|
|
|
|
cleanup:
|
2018-03-09 11:47:59 -05:00
|
|
|
virDomainObjEndAPI(&vm);
|
2015-11-13 13:14:41 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-11-13 13:14:42 +00:00
|
|
|
#define LIBXL_SET_MEMSTAT(TAG, VAL) \
|
|
|
|
if (i < nr_stats) { \
|
|
|
|
stats[i].tag = TAG; \
|
|
|
|
stats[i].val = VAL; \
|
|
|
|
i++; \
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainMemoryStats(virDomainPtr dom,
|
|
|
|
virDomainMemoryStatPtr stats,
|
|
|
|
unsigned int nr_stats,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
libxlDriverConfig *cfg;
|
|
|
|
virDomainObj *vm;
|
2015-11-13 13:14:42 +00:00
|
|
|
libxl_dominfo d_info;
|
|
|
|
unsigned mem, maxmem;
|
|
|
|
size_t i = 0;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2016-01-21 10:21:10 +00:00
|
|
|
libxl_dominfo_init(&d_info);
|
2015-11-18 15:47:24 -07:00
|
|
|
cfg = libxlDriverConfigGet(driver);
|
|
|
|
|
2015-11-13 13:14:42 +00:00
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virDomainMemoryStatsEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_QUERY) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2018-04-17 22:13:29 +00:00
|
|
|
if (virDomainObjCheckActive(vm) < 0)
|
2015-11-13 13:14:42 +00:00
|
|
|
goto endjob;
|
|
|
|
|
|
|
|
if (libxl_domain_info(cfg->ctx, &d_info, vm->def->id) != 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("libxl_domain_info failed for domain '%d'"),
|
|
|
|
vm->def->id);
|
|
|
|
goto endjob;
|
|
|
|
}
|
|
|
|
mem = d_info.current_memkb;
|
2017-01-16 10:51:40 -07:00
|
|
|
maxmem = virDomainDefGetMemoryTotal(vm->def);
|
2015-11-13 13:14:42 +00:00
|
|
|
|
|
|
|
LIBXL_SET_MEMSTAT(VIR_DOMAIN_MEMORY_STAT_ACTUAL_BALLOON, mem);
|
|
|
|
LIBXL_SET_MEMSTAT(VIR_DOMAIN_MEMORY_STAT_AVAILABLE, maxmem);
|
|
|
|
|
|
|
|
ret = i;
|
|
|
|
|
|
|
|
endjob:
|
2016-06-12 18:30:00 +08:00
|
|
|
libxlDomainObjEndJob(driver, vm);
|
2015-11-13 13:14:42 +00:00
|
|
|
|
|
|
|
cleanup:
|
2016-01-21 10:21:10 +00:00
|
|
|
libxl_dominfo_dispose(&d_info);
|
2016-06-12 18:30:00 +08:00
|
|
|
virDomainObjEndAPI(&vm);
|
2015-11-18 15:47:24 -07:00
|
|
|
virObjectUnref(cfg);
|
2015-11-13 13:14:42 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef LIBXL_SET_MEMSTAT
|
|
|
|
|
2015-11-13 13:14:47 +00:00
|
|
|
static int
|
|
|
|
libxlDomainGetJobInfo(virDomainPtr dom,
|
|
|
|
virDomainJobInfoPtr info)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDomainObjPrivate *priv;
|
|
|
|
virDomainObj *vm;
|
2015-11-13 13:14:47 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virDomainGetJobInfoEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
priv = vm->privateData;
|
|
|
|
if (!priv->job.active) {
|
|
|
|
memset(info, 0, sizeof(*info));
|
|
|
|
info->type = VIR_DOMAIN_JOB_NONE;
|
|
|
|
ret = 0;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* In libxl we don't have an estimated completion time
|
|
|
|
* thus we always set to unbounded and update time
|
|
|
|
* for the active job. */
|
|
|
|
if (libxlDomainJobUpdateTime(&priv->job) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
memcpy(info, priv->job.current, sizeof(virDomainJobInfo));
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
2018-03-09 11:47:59 -05:00
|
|
|
virDomainObjEndAPI(&vm);
|
2015-11-13 13:14:47 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-11-13 13:14:48 +00:00
|
|
|
static int
|
|
|
|
libxlDomainGetJobStats(virDomainPtr dom,
|
|
|
|
int *type,
|
|
|
|
virTypedParameterPtr *params,
|
|
|
|
int *nparams,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDomainObjPrivate *priv;
|
|
|
|
virDomainObj *vm;
|
2015-11-13 13:14:48 +00:00
|
|
|
virDomainJobInfoPtr jobInfo;
|
|
|
|
int ret = -1;
|
|
|
|
int maxparams = 0;
|
|
|
|
|
|
|
|
/* VIR_DOMAIN_JOB_STATS_COMPLETED not supported yet */
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virDomainGetJobStatsEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
priv = vm->privateData;
|
|
|
|
jobInfo = priv->job.current;
|
|
|
|
if (!priv->job.active) {
|
|
|
|
*type = VIR_DOMAIN_JOB_NONE;
|
|
|
|
*params = NULL;
|
|
|
|
*nparams = 0;
|
|
|
|
ret = 0;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* In libxl we don't have an estimated completion time
|
|
|
|
* thus we always set to unbounded and update time
|
|
|
|
* for the active job. */
|
|
|
|
if (libxlDomainJobUpdateTime(&priv->job) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virTypedParamsAddULLong(params, nparams, &maxparams,
|
|
|
|
VIR_DOMAIN_JOB_TIME_ELAPSED,
|
|
|
|
jobInfo->timeElapsed) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
*type = jobInfo->type;
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
2018-03-09 11:47:59 -05:00
|
|
|
virDomainObjEndAPI(&vm);
|
2015-11-13 13:14:48 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2015-11-13 13:14:47 +00:00
|
|
|
|
2016-08-14 04:24:37 +03:00
|
|
|
#ifdef __linux__
|
2016-07-26 00:45:14 +01:00
|
|
|
static int
|
|
|
|
libxlDiskPathToID(const char *virtpath)
|
|
|
|
{
|
|
|
|
static char const* drive_prefix[] = {"xvd", "hd", "sd"};
|
|
|
|
int disk, partition, chrused;
|
|
|
|
int fmt, id;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
fmt = id = -1;
|
|
|
|
|
|
|
|
/* Find any disk prefixes we know about */
|
2019-10-15 13:55:26 +02:00
|
|
|
for (i = 0; i < G_N_ELEMENTS(drive_prefix); i++) {
|
2016-07-26 00:45:14 +01:00
|
|
|
if (STRPREFIX(virtpath, drive_prefix[i]) &&
|
|
|
|
!virDiskNameParse(virtpath, &disk, &partition)) {
|
|
|
|
fmt = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Handle it same way as xvd */
|
|
|
|
if (fmt < 0 &&
|
|
|
|
(sscanf(virtpath, "d%ip%i%n", &disk, &partition, &chrused) >= 2
|
|
|
|
&& chrused == strlen(virtpath)))
|
|
|
|
fmt = 0;
|
|
|
|
|
|
|
|
/* Test indexes ranges and calculate the device id */
|
|
|
|
switch (fmt) {
|
|
|
|
case 0: /* xvd */
|
|
|
|
if (disk <= 15 && partition <= 15)
|
|
|
|
id = (202 << 8) | (disk << 4) | partition;
|
|
|
|
else if ((disk <= ((1<<20)-1)) || partition <= 255)
|
|
|
|
id = (1 << 28) | (disk << 8) | partition;
|
|
|
|
break;
|
|
|
|
case 1: /* hd */
|
|
|
|
if (disk <= 3 && partition <= 63)
|
|
|
|
id = ((disk < 2 ? 3 : 22) << 8) | ((disk & 1) << 6) | partition;
|
|
|
|
break;
|
|
|
|
case 2: /* sd */
|
|
|
|
if (disk <= 15 && (partition <= 15))
|
|
|
|
id = (8 << 8) | (disk << 4) | partition;
|
|
|
|
break;
|
|
|
|
default: /* invalid */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
2016-08-16 09:04:47 +02:00
|
|
|
# define LIBXL_VBD_SECTOR_SIZE 512
|
2016-07-26 00:45:14 +01:00
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDiskSectorSize(int domid, int devno)
|
|
|
|
{
|
|
|
|
char *path, *val;
|
|
|
|
struct xs_handle *handle;
|
|
|
|
int ret = LIBXL_VBD_SECTOR_SIZE;
|
|
|
|
unsigned int len;
|
|
|
|
|
|
|
|
handle = xs_daemon_open_readonly();
|
|
|
|
if (!handle) {
|
|
|
|
VIR_WARN("cannot read sector size");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
path = val = NULL;
|
2019-10-22 15:26:14 +02:00
|
|
|
path = g_strdup_printf("/local/domain/%d/device/vbd/%d/backend", domid, devno);
|
2016-07-26 00:45:14 +01:00
|
|
|
|
|
|
|
if ((val = xs_read(handle, XBT_NULL, path, &len)) == NULL)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
VIR_FREE(path);
|
2019-10-22 15:26:14 +02:00
|
|
|
path = g_strdup_printf("%s/physical-sector-size", val);
|
2016-07-26 00:45:14 +01:00
|
|
|
|
|
|
|
VIR_FREE(val);
|
|
|
|
if ((val = xs_read(handle, XBT_NULL, path, &len)) == NULL)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (sscanf(val, "%d", &ret) != 1)
|
|
|
|
ret = LIBXL_VBD_SECTOR_SIZE;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(val);
|
|
|
|
VIR_FREE(path);
|
|
|
|
xs_daemon_close(handle);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDomainBlockStatsVBD(virDomainObj *vm,
|
2016-07-26 00:45:14 +01:00
|
|
|
const char *dev,
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlBlockStats *stats)
|
2016-07-26 00:45:14 +01:00
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
int devno = libxlDiskPathToID(dev);
|
|
|
|
int size;
|
|
|
|
char *path, *name, *val;
|
2017-08-24 12:34:13 +01:00
|
|
|
unsigned long long status;
|
2016-07-26 00:45:14 +01:00
|
|
|
|
|
|
|
path = name = val = NULL;
|
|
|
|
if (devno < 0) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
"%s", _("cannot find device number"));
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
size = libxlDiskSectorSize(vm->def->id, devno);
|
|
|
|
|
2019-10-20 13:49:46 +02:00
|
|
|
stats->backend = g_strdup("vbd");
|
2016-07-26 00:45:14 +01:00
|
|
|
|
2019-10-22 15:26:14 +02:00
|
|
|
path = g_strdup_printf("/sys/bus/xen-backend/devices/vbd-%d-%d/statistics",
|
|
|
|
vm->def->id, devno);
|
2016-07-26 00:45:14 +01:00
|
|
|
|
|
|
|
if (!virFileExists(path)) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
"%s", _("cannot open bus path"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2017-11-03 13:09:47 +01:00
|
|
|
# define LIBXL_SET_VBDSTAT(FIELD, VAR, MUL) \
|
2019-10-22 15:26:14 +02:00
|
|
|
name = g_strdup_printf("%s/"FIELD, path); \
|
|
|
|
if ((virFileReadAll(name, 256, &val) < 0) || \
|
2017-11-03 13:09:47 +01:00
|
|
|
(sscanf(val, "%llu", &status) != 1)) { \
|
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED, \
|
|
|
|
_("cannot read %s"), name); \
|
|
|
|
goto cleanup; \
|
|
|
|
} \
|
|
|
|
VAR += (status * MUL); \
|
|
|
|
VIR_FREE(name); \
|
2016-07-26 00:45:14 +01:00
|
|
|
VIR_FREE(val);
|
|
|
|
|
|
|
|
LIBXL_SET_VBDSTAT("f_req", stats->f_req, 1)
|
|
|
|
LIBXL_SET_VBDSTAT("wr_req", stats->wr_req, 1)
|
|
|
|
LIBXL_SET_VBDSTAT("rd_req", stats->rd_req, 1)
|
|
|
|
LIBXL_SET_VBDSTAT("wr_sect", stats->wr_bytes, size)
|
|
|
|
LIBXL_SET_VBDSTAT("rd_sect", stats->rd_bytes, size)
|
|
|
|
|
|
|
|
LIBXL_SET_VBDSTAT("ds_req", stats->u.vbd.ds_req, size)
|
|
|
|
LIBXL_SET_VBDSTAT("oo_req", stats->u.vbd.oo_req, 1)
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(name);
|
|
|
|
VIR_FREE(path);
|
|
|
|
VIR_FREE(val);
|
|
|
|
|
|
|
|
# undef LIBXL_SET_VBDSTAT
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDomainBlockStatsVBD(virDomainObj *vm G_GNUC_UNUSED,
|
2019-10-14 14:45:33 +02:00
|
|
|
const char *dev G_GNUC_UNUSED,
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlBlockStats *stats G_GNUC_UNUSED)
|
2016-07-26 00:45:14 +01:00
|
|
|
{
|
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
|
|
|
"%s", _("platform unsupported"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDomainBlockStatsGatherSingle(virDomainObj *vm,
|
2016-07-26 00:45:14 +01:00
|
|
|
const char *path,
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlBlockStats *stats)
|
2016-07-26 00:45:14 +01:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainDiskDef *disk;
|
2016-07-26 00:45:14 +01:00
|
|
|
const char *disk_drv;
|
|
|
|
int ret = -1, disk_fmt;
|
|
|
|
|
|
|
|
if (!(disk = virDomainDiskByName(vm->def, path, false))) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("invalid path: %s"), path);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
disk_fmt = virDomainDiskGetFormat(disk);
|
|
|
|
if (!(disk_drv = virDomainDiskGetDriver(disk)))
|
|
|
|
disk_drv = "qemu";
|
|
|
|
|
|
|
|
if (STREQ(disk_drv, "phy")) {
|
2017-02-07 11:00:33 -07:00
|
|
|
if (disk_fmt != VIR_STORAGE_FILE_RAW) {
|
2016-07-26 00:45:14 +01:00
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
|
|
|
_("unsupported format %s"),
|
|
|
|
virStorageFileFormatTypeToString(disk_fmt));
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = libxlDomainBlockStatsVBD(vm, disk->dst, stats);
|
|
|
|
} else {
|
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
|
|
|
_("unsupported disk driver %s"),
|
|
|
|
disk_drv);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDomainBlockStatsGather(virDomainObj *vm,
|
2016-07-26 00:45:14 +01:00
|
|
|
const char *path,
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlBlockStats *stats)
|
2016-07-26 00:45:14 +01:00
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (*path) {
|
|
|
|
if (libxlDomainBlockStatsGatherSingle(vm, path, stats) < 0)
|
|
|
|
return ret;
|
|
|
|
} else {
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < vm->def->ndisks; ++i) {
|
|
|
|
if (libxlDomainBlockStatsGatherSingle(vm, vm->def->disks[i]->dst,
|
|
|
|
stats) < 0)
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainBlockStats(virDomainPtr dom,
|
|
|
|
const char *path,
|
|
|
|
virDomainBlockStatsPtr stats)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
virDomainObj *vm;
|
2016-07-26 00:45:14 +01:00
|
|
|
libxlBlockStats blkstats;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virDomainBlockStatsEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_QUERY) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2018-04-17 22:13:29 +00:00
|
|
|
if (virDomainObjCheckActive(vm) < 0)
|
2016-07-26 00:45:14 +01:00
|
|
|
goto endjob;
|
|
|
|
|
|
|
|
memset(&blkstats, 0, sizeof(libxlBlockStats));
|
|
|
|
if ((ret = libxlDomainBlockStatsGather(vm, path, &blkstats)) < 0)
|
|
|
|
goto endjob;
|
|
|
|
|
|
|
|
stats->rd_req = blkstats.rd_req;
|
|
|
|
stats->rd_bytes = blkstats.rd_bytes;
|
|
|
|
stats->wr_req = blkstats.wr_req;
|
|
|
|
stats->wr_bytes = blkstats.wr_bytes;
|
|
|
|
if (STREQ_NULLABLE(blkstats.backend, "vbd"))
|
|
|
|
stats->errs = blkstats.u.vbd.oo_req;
|
|
|
|
else
|
|
|
|
stats->errs = -1;
|
|
|
|
|
|
|
|
endjob:
|
|
|
|
libxlDomainObjEndJob(driver, vm);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virDomainObjEndAPI(&vm);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainBlockStatsFlags(virDomainPtr dom,
|
|
|
|
const char *path,
|
|
|
|
virTypedParameterPtr params,
|
|
|
|
int *nparams,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
virDomainObj *vm;
|
2016-07-26 00:45:14 +01:00
|
|
|
libxlBlockStats blkstats;
|
|
|
|
int nstats;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
|
|
|
|
|
|
|
|
flags &= ~VIR_TYPED_PARAM_STRING_OKAY;
|
|
|
|
|
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virDomainBlockStatsFlagsEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_QUERY) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2018-04-17 22:13:29 +00:00
|
|
|
if (virDomainObjCheckActive(vm) < 0)
|
2016-07-26 00:45:14 +01:00
|
|
|
goto endjob;
|
|
|
|
|
|
|
|
/* return count of supported stats */
|
|
|
|
if (*nparams == 0) {
|
|
|
|
*nparams = LIBXL_NB_TOTAL_BLK_STAT_PARAM;
|
|
|
|
ret = 0;
|
|
|
|
goto endjob;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(&blkstats, 0, sizeof(libxlBlockStats));
|
|
|
|
if ((ret = libxlDomainBlockStatsGather(vm, path, &blkstats)) < 0)
|
|
|
|
goto endjob;
|
|
|
|
|
|
|
|
nstats = 0;
|
|
|
|
|
2017-11-03 13:09:47 +01:00
|
|
|
#define LIBXL_BLKSTAT_ASSIGN_PARAM(VAR, NAME) \
|
|
|
|
if (nstats < *nparams && (blkstats.VAR) != -1) { \
|
|
|
|
if (virTypedParameterAssign(params + nstats, NAME, \
|
2016-07-26 00:45:14 +01:00
|
|
|
VIR_TYPED_PARAM_LLONG, (blkstats.VAR)) < 0) \
|
2017-11-03 13:09:47 +01:00
|
|
|
goto endjob; \
|
|
|
|
nstats++; \
|
2016-07-26 00:45:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
LIBXL_BLKSTAT_ASSIGN_PARAM(wr_bytes, VIR_DOMAIN_BLOCK_STATS_WRITE_BYTES);
|
|
|
|
LIBXL_BLKSTAT_ASSIGN_PARAM(wr_req, VIR_DOMAIN_BLOCK_STATS_WRITE_REQ);
|
|
|
|
|
|
|
|
LIBXL_BLKSTAT_ASSIGN_PARAM(rd_bytes, VIR_DOMAIN_BLOCK_STATS_READ_BYTES);
|
|
|
|
LIBXL_BLKSTAT_ASSIGN_PARAM(rd_req, VIR_DOMAIN_BLOCK_STATS_READ_REQ);
|
|
|
|
|
|
|
|
LIBXL_BLKSTAT_ASSIGN_PARAM(f_req, VIR_DOMAIN_BLOCK_STATS_FLUSH_REQ);
|
|
|
|
|
|
|
|
if (STREQ_NULLABLE(blkstats.backend, "vbd"))
|
|
|
|
LIBXL_BLKSTAT_ASSIGN_PARAM(u.vbd.oo_req, VIR_DOMAIN_BLOCK_STATS_ERRS);
|
|
|
|
|
|
|
|
*nparams = nstats;
|
|
|
|
|
|
|
|
#undef LIBXL_BLKSTAT_ASSIGN_PARAM
|
|
|
|
|
|
|
|
endjob:
|
|
|
|
libxlDomainObjEndJob(driver, vm);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virDomainObjEndAPI(&vm);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-03-29 20:18:24 +08:00
|
|
|
static int
|
2013-04-23 13:50:18 +01:00
|
|
|
libxlConnectDomainEventRegisterAny(virConnectPtr conn, virDomainPtr dom, int eventID,
|
|
|
|
virConnectDomainEventGenericCallback callback,
|
|
|
|
void *opaque, virFreeCallback freecb)
|
2011-03-29 20:18:24 +08:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = conn->privateData;
|
2011-03-29 20:18:24 +08:00
|
|
|
int ret;
|
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virConnectDomainEventRegisterAnyEnsureACL(conn) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2011-12-13 11:14:46 +00:00
|
|
|
if (virDomainEventStateRegisterID(conn,
|
|
|
|
driver->domainEventState,
|
|
|
|
dom, eventID, callback, opaque,
|
|
|
|
freecb, &ret) < 0)
|
Return count of callbacks when registering callbacks
When registering a callback for a particular event some callers
need to know how many callbacks already exist for that event.
While it is possible to ask for a count, this is not free from
race conditions when threaded. Thus the API for registering
callbacks should return the count of callbacks. Also rename
virDomainEventStateDeregisterAny to virDomainEventStateDeregisterID
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Return count of callbacks when
registering callbacks
* src/libxl/libxl_driver.c, src/libxl/libxl_driver.c,
src/qemu/qemu_driver.c, src/remote/remote_driver.c,
src/remote/remote_driver.c, src/uml/uml_driver.c,
src/vbox/vbox_tmpl.c, src/xen/xen_driver.c: Update
for change in APIs
2011-12-13 23:38:54 +00:00
|
|
|
ret = -1;
|
2011-03-29 20:18:24 +08:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2013-04-23 13:50:18 +01:00
|
|
|
libxlConnectDomainEventDeregisterAny(virConnectPtr conn, int callbackID)
|
2011-03-29 20:18:24 +08:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = conn->privateData;
|
2011-03-29 20:18:24 +08:00
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virConnectDomainEventDeregisterAnyEnsureACL(conn) < 0)
|
|
|
|
return -1;
|
|
|
|
|
event: make deregister return value match docs
Ever since their introduction (commit 1509b80 in v0.5.0 for
virConnectDomainEventRegister, commit 4445723 in v0.8.0 for
virConnectDomainEventDeregisterAny), the event deregistration
functions have been documented as returning 0 on success;
likewise for older registration (only the newer RegisterAny
must return a non-zero callbackID). And now that we are
adding virConnectNetworkEventDeregisterAny for v1.2.1, it
should have the same semantics.
Fortunately, all of the stateful drivers have been obeying
the docs and returning 0, thanks to the way the remote_driver
tracks things (in fact, the RPC wire protocol is unable to
send a return value for DomainEventRegisterAny, at least not
without adding a new RPC number). Well, except for vbox,
which was always failing deregistration, due to failure to
set the return value to anything besides its initial -1.
But for local drivers, such as test:///default, we've been
returning non-zero numbers; worse, the non-zero numbers have
differed over time. For example, in Fedora 12 (libvirt 0.8.2),
calling Register twice would return 0 and 1 [the callbackID
generated under the hood]; while in Fedora 20 (libvirt 1.1.3),
it returns 1 and 2 [the number of callbacks registered for
that event type]. Since we have changed the behavior over
time, and since it differs by local vs. remote, we can safely
argue that no one could have been reasonably relying on any
particular behavior, so we might as well obey the docs, as well
as prepare callers that might deal with older clients to not be
surprised if the docs are not strictly followed.
For consistency, this patch fixes the code for all drivers,
even though it only makes an impact for vbox and for local
drivers. By fixing all drivers, future copy and paste from
a remote driver to a local driver is less likely to
reintroduce the bug.
Finally, update the testsuite to gain some coverage of the
issue for local drivers, including the first test of old-style
domain event registration via function pointer instead of
event id.
* src/libvirt.c (virConnectDomainEventRegister)
(virConnectDomainEventDeregister)
(virConnectDomainEventDeregisterAny): Clarify docs.
* src/libxl/libxl_driver.c (libxlConnectDomainEventRegister)
(libxlConnectDomainEventDeregister)
(libxlConnectDomainEventDeregisterAny): Match documentation.
* src/lxc/lxc_driver.c (lxcConnectDomainEventRegister)
(lxcConnectDomainEventDeregister)
(lxcConnectDomainEventDeregisterAny): Likewise.
* src/test/test_driver.c (testConnectDomainEventRegister)
(testConnectDomainEventDeregister)
(testConnectDomainEventDeregisterAny)
(testConnectNetworkEventDeregisterAny): Likewise.
* src/uml/uml_driver.c (umlConnectDomainEventRegister)
(umlConnectDomainEventDeregister)
(umlConnectDomainEventDeregisterAny): Likewise.
* src/vbox/vbox_tmpl.c (vboxConnectDomainEventRegister)
(vboxConnectDomainEventDeregister)
(vboxConnectDomainEventDeregisterAny): Likewise.
* src/xen/xen_driver.c (xenUnifiedConnectDomainEventRegister)
(xenUnifiedConnectDomainEventDeregister)
(xenUnifiedConnectDomainEventDeregisterAny): Likewise.
* src/network/bridge_driver.c
(networkConnectNetworkEventDeregisterAny): Likewise.
* tests/objecteventtest.c (testDomainCreateXMLOld): New test.
(mymain): Run it.
(testDomainCreateXML): Check return values.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-03 14:21:17 -07:00
|
|
|
if (virObjectEventStateDeregisterID(conn,
|
|
|
|
driver->domainEventState,
|
2017-06-14 07:32:15 -04:00
|
|
|
callbackID, true) < 0)
|
event: make deregister return value match docs
Ever since their introduction (commit 1509b80 in v0.5.0 for
virConnectDomainEventRegister, commit 4445723 in v0.8.0 for
virConnectDomainEventDeregisterAny), the event deregistration
functions have been documented as returning 0 on success;
likewise for older registration (only the newer RegisterAny
must return a non-zero callbackID). And now that we are
adding virConnectNetworkEventDeregisterAny for v1.2.1, it
should have the same semantics.
Fortunately, all of the stateful drivers have been obeying
the docs and returning 0, thanks to the way the remote_driver
tracks things (in fact, the RPC wire protocol is unable to
send a return value for DomainEventRegisterAny, at least not
without adding a new RPC number). Well, except for vbox,
which was always failing deregistration, due to failure to
set the return value to anything besides its initial -1.
But for local drivers, such as test:///default, we've been
returning non-zero numbers; worse, the non-zero numbers have
differed over time. For example, in Fedora 12 (libvirt 0.8.2),
calling Register twice would return 0 and 1 [the callbackID
generated under the hood]; while in Fedora 20 (libvirt 1.1.3),
it returns 1 and 2 [the number of callbacks registered for
that event type]. Since we have changed the behavior over
time, and since it differs by local vs. remote, we can safely
argue that no one could have been reasonably relying on any
particular behavior, so we might as well obey the docs, as well
as prepare callers that might deal with older clients to not be
surprised if the docs are not strictly followed.
For consistency, this patch fixes the code for all drivers,
even though it only makes an impact for vbox and for local
drivers. By fixing all drivers, future copy and paste from
a remote driver to a local driver is less likely to
reintroduce the bug.
Finally, update the testsuite to gain some coverage of the
issue for local drivers, including the first test of old-style
domain event registration via function pointer instead of
event id.
* src/libvirt.c (virConnectDomainEventRegister)
(virConnectDomainEventDeregister)
(virConnectDomainEventDeregisterAny): Clarify docs.
* src/libxl/libxl_driver.c (libxlConnectDomainEventRegister)
(libxlConnectDomainEventDeregister)
(libxlConnectDomainEventDeregisterAny): Match documentation.
* src/lxc/lxc_driver.c (lxcConnectDomainEventRegister)
(lxcConnectDomainEventDeregister)
(lxcConnectDomainEventDeregisterAny): Likewise.
* src/test/test_driver.c (testConnectDomainEventRegister)
(testConnectDomainEventDeregister)
(testConnectDomainEventDeregisterAny)
(testConnectNetworkEventDeregisterAny): Likewise.
* src/uml/uml_driver.c (umlConnectDomainEventRegister)
(umlConnectDomainEventDeregister)
(umlConnectDomainEventDeregisterAny): Likewise.
* src/vbox/vbox_tmpl.c (vboxConnectDomainEventRegister)
(vboxConnectDomainEventDeregister)
(vboxConnectDomainEventDeregisterAny): Likewise.
* src/xen/xen_driver.c (xenUnifiedConnectDomainEventRegister)
(xenUnifiedConnectDomainEventDeregister)
(xenUnifiedConnectDomainEventDeregisterAny): Likewise.
* src/network/bridge_driver.c
(networkConnectNetworkEventDeregisterAny): Likewise.
* tests/objecteventtest.c (testDomainCreateXMLOld): New test.
(mymain): Run it.
(testDomainCreateXML): Check return values.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-03 14:21:17 -07:00
|
|
|
return -1;
|
2011-03-29 20:18:24 +08:00
|
|
|
|
event: make deregister return value match docs
Ever since their introduction (commit 1509b80 in v0.5.0 for
virConnectDomainEventRegister, commit 4445723 in v0.8.0 for
virConnectDomainEventDeregisterAny), the event deregistration
functions have been documented as returning 0 on success;
likewise for older registration (only the newer RegisterAny
must return a non-zero callbackID). And now that we are
adding virConnectNetworkEventDeregisterAny for v1.2.1, it
should have the same semantics.
Fortunately, all of the stateful drivers have been obeying
the docs and returning 0, thanks to the way the remote_driver
tracks things (in fact, the RPC wire protocol is unable to
send a return value for DomainEventRegisterAny, at least not
without adding a new RPC number). Well, except for vbox,
which was always failing deregistration, due to failure to
set the return value to anything besides its initial -1.
But for local drivers, such as test:///default, we've been
returning non-zero numbers; worse, the non-zero numbers have
differed over time. For example, in Fedora 12 (libvirt 0.8.2),
calling Register twice would return 0 and 1 [the callbackID
generated under the hood]; while in Fedora 20 (libvirt 1.1.3),
it returns 1 and 2 [the number of callbacks registered for
that event type]. Since we have changed the behavior over
time, and since it differs by local vs. remote, we can safely
argue that no one could have been reasonably relying on any
particular behavior, so we might as well obey the docs, as well
as prepare callers that might deal with older clients to not be
surprised if the docs are not strictly followed.
For consistency, this patch fixes the code for all drivers,
even though it only makes an impact for vbox and for local
drivers. By fixing all drivers, future copy and paste from
a remote driver to a local driver is less likely to
reintroduce the bug.
Finally, update the testsuite to gain some coverage of the
issue for local drivers, including the first test of old-style
domain event registration via function pointer instead of
event id.
* src/libvirt.c (virConnectDomainEventRegister)
(virConnectDomainEventDeregister)
(virConnectDomainEventDeregisterAny): Clarify docs.
* src/libxl/libxl_driver.c (libxlConnectDomainEventRegister)
(libxlConnectDomainEventDeregister)
(libxlConnectDomainEventDeregisterAny): Match documentation.
* src/lxc/lxc_driver.c (lxcConnectDomainEventRegister)
(lxcConnectDomainEventDeregister)
(lxcConnectDomainEventDeregisterAny): Likewise.
* src/test/test_driver.c (testConnectDomainEventRegister)
(testConnectDomainEventDeregister)
(testConnectDomainEventDeregisterAny)
(testConnectNetworkEventDeregisterAny): Likewise.
* src/uml/uml_driver.c (umlConnectDomainEventRegister)
(umlConnectDomainEventDeregister)
(umlConnectDomainEventDeregisterAny): Likewise.
* src/vbox/vbox_tmpl.c (vboxConnectDomainEventRegister)
(vboxConnectDomainEventDeregister)
(vboxConnectDomainEventDeregisterAny): Likewise.
* src/xen/xen_driver.c (xenUnifiedConnectDomainEventRegister)
(xenUnifiedConnectDomainEventDeregister)
(xenUnifiedConnectDomainEventDeregisterAny): Likewise.
* src/network/bridge_driver.c
(networkConnectNetworkEventDeregisterAny): Likewise.
* tests/objecteventtest.c (testDomainCreateXMLOld): New test.
(mymain): Run it.
(testDomainCreateXML): Check return values.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-01-03 14:21:17 -07:00
|
|
|
return 0;
|
2011-03-29 20:18:24 +08:00
|
|
|
}
|
|
|
|
|
2011-02-10 15:42:34 -07:00
|
|
|
|
2011-09-23 08:56:13 +02:00
|
|
|
static int
|
2019-10-14 14:45:33 +02:00
|
|
|
libxlConnectIsAlive(virConnectPtr conn G_GNUC_UNUSED)
|
2011-09-23 08:56:13 +02:00
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2012-06-11 11:04:57 +02:00
|
|
|
static int
|
2013-04-23 13:50:18 +01:00
|
|
|
libxlConnectListAllDomains(virConnectPtr conn,
|
|
|
|
virDomainPtr **domains,
|
|
|
|
unsigned int flags)
|
2012-06-11 11:04:57 +02:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = conn->privateData;
|
2012-06-11 11:04:57 +02:00
|
|
|
|
2012-08-03 23:48:05 +08:00
|
|
|
virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
|
2012-06-11 11:04:57 +02:00
|
|
|
|
2013-04-23 11:56:22 +01:00
|
|
|
if (virConnectListAllDomainsEnsureACL(conn) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2019-10-17 10:10:10 +02:00
|
|
|
return virDomainObjListExport(driver->domains, conn, domains,
|
|
|
|
virConnectListAllDomainsCheckACL, flags);
|
2012-06-11 11:04:57 +02:00
|
|
|
}
|
|
|
|
|
2013-07-13 02:27:10 +02:00
|
|
|
/* Which features are supported by this driver? */
|
|
|
|
static int
|
|
|
|
libxlConnectSupportsFeature(virConnectPtr conn, int feature)
|
|
|
|
{
|
|
|
|
if (virConnectSupportsFeatureEnsureACL(conn) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2018-03-08 13:20:24 +01:00
|
|
|
switch ((virDrvFeature) feature) {
|
2016-08-29 10:08:01 -06:00
|
|
|
case VIR_DRV_FEATURE_MIGRATION_V3:
|
2013-07-13 02:27:10 +02:00
|
|
|
case VIR_DRV_FEATURE_TYPED_PARAM_STRING:
|
2014-05-08 15:56:51 -06:00
|
|
|
case VIR_DRV_FEATURE_MIGRATION_PARAMS:
|
2016-02-05 20:45:02 +00:00
|
|
|
case VIR_DRV_FEATURE_MIGRATION_P2P:
|
lib: Fix calling of virNetworkUpdate() driver callback
The order in which virNetworkUpdate() accepts @section and
@command arguments is not the same as in which it passes them
onto networkUpdate() callback. Until recently, it did not really
matter, because calling the API on client side meant arguments
were encoded in reversed order (compared to the public API), but
then on the server it was fixed again - because the server
decoded RPC (still swapped), called public API (still swapped)
and in turn called the network driver callback (with reversing
the order - so magically fixing the order).
Long story short, if the public API is called even number of
times those swaps cancel each other out. The problem is when the
API is called an odd numbed of times - which happens with split
daemons and the right URI. There's one call in the client (e.g.
virsh net-update), the other in a hypervisor daemon (say
virtqemud) which ends up calling the API in the virnetworkd.
The fix is obvious - fix the order in which arguments are passed
to the callback.
But, to maintain compatibility with older, yet unfixed, daemons
new connection feature is introduced. The feature is detected
just before calling the callback and allows client to pass
arguments in correct order (talking to fixed daemon) or in
reversed order (talking to older daemon).
Unfortunately, older client talking to newer daemon can't be
fixed. Let's hope that it's less frequent scenario.
Fixes: 574b9bc66b6b10cc4cf50f299c3f0ff55f2cbefb
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1870552
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Martin Kletzander <mkletzan@redhat.com>
2021-03-16 10:33:26 +01:00
|
|
|
case VIR_DRV_FEATURE_NETWORK_UPDATE_HAS_CORRECT_ORDER:
|
2013-07-13 02:27:10 +02:00
|
|
|
return 1;
|
2018-03-08 13:20:24 +01:00
|
|
|
case VIR_DRV_FEATURE_FD_PASSING:
|
|
|
|
case VIR_DRV_FEATURE_MIGRATE_CHANGE_PROTECTION:
|
|
|
|
case VIR_DRV_FEATURE_MIGRATION_DIRECT:
|
|
|
|
case VIR_DRV_FEATURE_MIGRATION_OFFLINE:
|
|
|
|
case VIR_DRV_FEATURE_MIGRATION_V1:
|
|
|
|
case VIR_DRV_FEATURE_MIGRATION_V2:
|
|
|
|
case VIR_DRV_FEATURE_PROGRAM_KEEPALIVE:
|
|
|
|
case VIR_DRV_FEATURE_REMOTE:
|
|
|
|
case VIR_DRV_FEATURE_REMOTE_CLOSE_CALLBACK:
|
|
|
|
case VIR_DRV_FEATURE_REMOTE_EVENT_CALLBACK:
|
|
|
|
case VIR_DRV_FEATURE_XML_MIGRATABLE:
|
2013-07-13 02:27:10 +02:00
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2012-06-11 11:04:57 +02:00
|
|
|
|
2014-03-06 17:46:11 +08:00
|
|
|
static int
|
|
|
|
libxlNodeDeviceDetachFlags(virNodeDevicePtr dev,
|
|
|
|
const char *driverName,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dev->conn->privateData;
|
|
|
|
virHostdevManager *hostdev_mgr = driver->hostdevMgr;
|
2014-03-06 17:46:11 +08:00
|
|
|
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2021-03-01 15:41:44 -07:00
|
|
|
if (!driverName)
|
|
|
|
driverName = "xen";
|
|
|
|
|
|
|
|
if (STRNEQ(driverName, "xen")) {
|
2021-01-30 13:59:06 -03:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("unsupported driver name '%s'"), driverName);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2021-01-30 14:23:41 -03:00
|
|
|
/* virNodeDeviceDetachFlagsEnsureACL() is being called by
|
|
|
|
* virDomainDriverNodeDeviceDetachFlags() */
|
|
|
|
return virDomainDriverNodeDeviceDetachFlags(dev, hostdev_mgr, driverName);
|
2014-03-06 17:46:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlNodeDeviceDettach(virNodeDevicePtr dev)
|
|
|
|
{
|
|
|
|
return libxlNodeDeviceDetachFlags(dev, NULL, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlNodeDeviceReAttach(virNodeDevicePtr dev)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dev->conn->privateData;
|
|
|
|
virHostdevManager *hostdev_mgr = driver->hostdevMgr;
|
2014-03-06 17:46:11 +08:00
|
|
|
|
2021-01-30 13:40:35 -03:00
|
|
|
/* virNodeDeviceReAttachEnsureACL() is being called by
|
|
|
|
* virDomainDriverNodeDeviceReAttach() */
|
|
|
|
return virDomainDriverNodeDeviceReAttach(dev, hostdev_mgr);
|
2014-03-06 17:46:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlNodeDeviceReset(virNodeDevicePtr dev)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dev->conn->privateData;
|
|
|
|
virHostdevManager *hostdev_mgr = driver->hostdevMgr;
|
2014-03-06 17:46:11 +08:00
|
|
|
|
2021-01-29 22:19:29 -03:00
|
|
|
/* virNodeDeviceResetEnsureACL() is being called by
|
|
|
|
* virDomainDriverNodeDeviceReset() */
|
|
|
|
return virDomainDriverNodeDeviceReset(dev, hostdev_mgr);
|
2014-03-06 17:46:11 +08:00
|
|
|
}
|
|
|
|
|
2014-05-08 15:56:51 -06:00
|
|
|
static char *
|
|
|
|
libxlDomainMigrateBegin3Params(virDomainPtr domain,
|
|
|
|
virTypedParameterPtr params,
|
|
|
|
int nparams,
|
2016-04-29 15:08:05 -06:00
|
|
|
char **cookieout,
|
|
|
|
int *cookieoutlen,
|
2014-05-08 15:56:51 -06:00
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
const char *xmlin = NULL;
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainObj *vm = NULL;
|
2018-03-12 11:51:43 -06:00
|
|
|
char *xmlout = NULL;
|
2014-05-08 15:56:51 -06:00
|
|
|
|
2014-06-24 11:10:49 -06:00
|
|
|
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
|
|
|
|
virReportUnsupportedError();
|
|
|
|
return NULL;
|
|
|
|
#endif
|
|
|
|
|
2014-05-08 15:56:51 -06:00
|
|
|
virCheckFlags(LIBXL_MIGRATION_FLAGS, NULL);
|
|
|
|
if (virTypedParamsValidate(params, nparams, LIBXL_MIGRATION_PARAMETERS) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (virTypedParamsGetString(params, nparams,
|
|
|
|
VIR_MIGRATE_PARAM_DEST_XML,
|
|
|
|
&xmlin) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!(vm = libxlDomObjFromDomain(domain)))
|
|
|
|
return NULL;
|
|
|
|
|
2015-06-22 11:36:59 -06:00
|
|
|
if (STREQ_NULLABLE(vm->def->name, "Domain-0")) {
|
2018-03-12 11:51:43 -06:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("Domain-0 cannot be migrated"));
|
|
|
|
goto cleanup;
|
2015-06-22 11:36:59 -06:00
|
|
|
}
|
|
|
|
|
2018-03-12 11:51:43 -06:00
|
|
|
if (virDomainMigrateBegin3ParamsEnsureACL(domain->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
2014-05-08 15:56:51 -06:00
|
|
|
|
2018-04-17 22:13:29 +00:00
|
|
|
if (virDomainObjCheckActive(vm) < 0)
|
2018-03-12 11:51:43 -06:00
|
|
|
goto cleanup;
|
2014-05-08 15:56:51 -06:00
|
|
|
|
2018-03-20 11:42:56 -06:00
|
|
|
xmlout = libxlDomainMigrationSrcBegin(domain->conn, vm, xmlin,
|
|
|
|
cookieout, cookieoutlen);
|
2018-03-12 11:51:43 -06:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virDomainObjEndAPI(&vm);
|
|
|
|
return xmlout;
|
2014-05-08 15:56:51 -06:00
|
|
|
}
|
|
|
|
|
2017-02-15 11:17:38 +00:00
|
|
|
static int
|
|
|
|
libxlDomainMigratePrepareTunnel3Params(virConnectPtr dconn,
|
|
|
|
virStreamPtr st,
|
|
|
|
virTypedParameterPtr params,
|
|
|
|
int nparams,
|
|
|
|
const char *cookiein,
|
|
|
|
int cookieinlen,
|
2019-10-14 14:45:33 +02:00
|
|
|
char **cookieout G_GNUC_UNUSED,
|
|
|
|
int *cookieoutlen G_GNUC_UNUSED,
|
2017-02-15 11:17:38 +00:00
|
|
|
unsigned int flags)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dconn->privateData;
|
|
|
|
virDomainDef *def = NULL;
|
2017-02-15 11:17:38 +00:00
|
|
|
const char *dom_xml = NULL;
|
|
|
|
const char *dname = NULL;
|
|
|
|
const char *uri_in = NULL;
|
|
|
|
|
|
|
|
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
|
|
|
|
virReportUnsupportedError();
|
|
|
|
return -1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
virCheckFlags(LIBXL_MIGRATION_FLAGS, -1);
|
|
|
|
if (virTypedParamsValidate(params, nparams, LIBXL_MIGRATION_PARAMETERS) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (virTypedParamsGetString(params, nparams,
|
|
|
|
VIR_MIGRATE_PARAM_DEST_XML,
|
|
|
|
&dom_xml) < 0 ||
|
|
|
|
virTypedParamsGetString(params, nparams,
|
|
|
|
VIR_MIGRATE_PARAM_DEST_NAME,
|
|
|
|
&dname) < 0 ||
|
|
|
|
virTypedParamsGetString(params, nparams,
|
|
|
|
VIR_MIGRATE_PARAM_URI,
|
|
|
|
&uri_in) < 0)
|
|
|
|
|
|
|
|
goto error;
|
|
|
|
|
2018-03-20 11:42:56 -06:00
|
|
|
if (!(def = libxlDomainMigrationDstPrepareDef(driver, dom_xml, dname)))
|
2017-02-15 11:17:38 +00:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (virDomainMigratePrepareTunnel3ParamsEnsureACL(dconn, def) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2018-03-20 11:42:56 -06:00
|
|
|
if (libxlDomainMigrationDstPrepareTunnel3(dconn, st, &def, cookiein,
|
|
|
|
cookieinlen, flags) < 0)
|
2017-02-15 11:17:38 +00:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
virDomainDefFree(def);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-05-08 15:56:51 -06:00
|
|
|
static int
|
|
|
|
libxlDomainMigratePrepare3Params(virConnectPtr dconn,
|
|
|
|
virTypedParameterPtr params,
|
|
|
|
int nparams,
|
2016-04-29 15:08:05 -06:00
|
|
|
const char *cookiein,
|
|
|
|
int cookieinlen,
|
2019-10-14 14:45:33 +02:00
|
|
|
char **cookieout G_GNUC_UNUSED,
|
|
|
|
int *cookieoutlen G_GNUC_UNUSED,
|
2014-05-08 15:56:51 -06:00
|
|
|
char **uri_out,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dconn->privateData;
|
|
|
|
virDomainDef *def = NULL;
|
2014-05-08 15:56:51 -06:00
|
|
|
const char *dom_xml = NULL;
|
|
|
|
const char *dname = NULL;
|
|
|
|
const char *uri_in = NULL;
|
|
|
|
|
2014-06-24 11:10:49 -06:00
|
|
|
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
|
|
|
|
virReportUnsupportedError();
|
|
|
|
return -1;
|
|
|
|
#endif
|
|
|
|
|
2014-05-08 15:56:51 -06:00
|
|
|
virCheckFlags(LIBXL_MIGRATION_FLAGS, -1);
|
|
|
|
if (virTypedParamsValidate(params, nparams, LIBXL_MIGRATION_PARAMETERS) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (virTypedParamsGetString(params, nparams,
|
|
|
|
VIR_MIGRATE_PARAM_DEST_XML,
|
|
|
|
&dom_xml) < 0 ||
|
|
|
|
virTypedParamsGetString(params, nparams,
|
|
|
|
VIR_MIGRATE_PARAM_DEST_NAME,
|
|
|
|
&dname) < 0 ||
|
|
|
|
virTypedParamsGetString(params, nparams,
|
|
|
|
VIR_MIGRATE_PARAM_URI,
|
|
|
|
&uri_in) < 0)
|
|
|
|
|
|
|
|
goto error;
|
|
|
|
|
2018-03-20 11:42:56 -06:00
|
|
|
if (!(def = libxlDomainMigrationDstPrepareDef(driver, dom_xml, dname)))
|
2014-05-08 15:56:51 -06:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (virDomainMigratePrepare3ParamsEnsureACL(dconn, def) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2018-03-20 11:42:56 -06:00
|
|
|
if (libxlDomainMigrationDstPrepare(dconn, &def, uri_in, uri_out,
|
|
|
|
cookiein, cookieinlen, flags) < 0)
|
2014-05-08 15:56:51 -06:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
virDomainDefFree(def);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainMigratePerform3Params(virDomainPtr dom,
|
|
|
|
const char *dconnuri,
|
|
|
|
virTypedParameterPtr params,
|
|
|
|
int nparams,
|
2019-10-14 14:45:33 +02:00
|
|
|
const char *cookiein G_GNUC_UNUSED,
|
|
|
|
int cookieinlen G_GNUC_UNUSED,
|
|
|
|
char **cookieout G_GNUC_UNUSED,
|
|
|
|
int *cookieoutlen G_GNUC_UNUSED,
|
2014-05-08 15:56:51 -06:00
|
|
|
unsigned int flags)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
|
|
|
virDomainObj *vm = NULL;
|
2014-05-08 15:56:51 -06:00
|
|
|
const char *dom_xml = NULL;
|
|
|
|
const char *dname = NULL;
|
|
|
|
const char *uri = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
2014-06-24 11:10:49 -06:00
|
|
|
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
|
|
|
|
virReportUnsupportedError();
|
|
|
|
return -1;
|
|
|
|
#endif
|
|
|
|
|
2014-05-08 15:56:51 -06:00
|
|
|
virCheckFlags(LIBXL_MIGRATION_FLAGS, -1);
|
|
|
|
if (virTypedParamsValidate(params, nparams, LIBXL_MIGRATION_PARAMETERS) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virTypedParamsGetString(params, nparams,
|
|
|
|
VIR_MIGRATE_PARAM_DEST_XML,
|
|
|
|
&dom_xml) < 0 ||
|
|
|
|
virTypedParamsGetString(params, nparams,
|
|
|
|
VIR_MIGRATE_PARAM_DEST_NAME,
|
|
|
|
&dname) < 0 ||
|
|
|
|
virTypedParamsGetString(params, nparams,
|
|
|
|
VIR_MIGRATE_PARAM_URI,
|
|
|
|
&uri) < 0)
|
|
|
|
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virDomainMigratePerform3ParamsEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2017-02-15 11:17:38 +00:00
|
|
|
if ((flags & (VIR_MIGRATE_TUNNELLED | VIR_MIGRATE_PEER2PEER))) {
|
2018-03-20 11:42:56 -06:00
|
|
|
if (libxlDomainMigrationSrcPerformP2P(driver, vm, dom->conn, dom_xml,
|
|
|
|
dconnuri, uri, dname, flags) < 0)
|
2016-02-05 20:45:02 +00:00
|
|
|
goto cleanup;
|
|
|
|
} else {
|
2018-03-20 11:42:56 -06:00
|
|
|
if (libxlDomainMigrationSrcPerform(driver, vm, dom_xml, dconnuri,
|
|
|
|
uri, dname, flags) < 0)
|
2016-02-05 20:45:02 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2014-05-08 15:56:51 -06:00
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
2018-03-13 11:05:36 -06:00
|
|
|
virDomainObjEndAPI(&vm);
|
2014-05-08 15:56:51 -06:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static virDomainPtr
|
|
|
|
libxlDomainMigrateFinish3Params(virConnectPtr dconn,
|
|
|
|
virTypedParameterPtr params,
|
|
|
|
int nparams,
|
2019-10-14 14:45:33 +02:00
|
|
|
const char *cookiein G_GNUC_UNUSED,
|
|
|
|
int cookieinlen G_GNUC_UNUSED,
|
|
|
|
char **cookieout G_GNUC_UNUSED,
|
|
|
|
int *cookieoutlen G_GNUC_UNUSED,
|
2014-05-08 15:56:51 -06:00
|
|
|
unsigned int flags,
|
|
|
|
int cancelled)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dconn->privateData;
|
|
|
|
virDomainObj *vm = NULL;
|
2014-05-08 15:56:51 -06:00
|
|
|
const char *dname = NULL;
|
2014-11-13 14:41:56 -07:00
|
|
|
virDomainPtr ret = NULL;
|
2014-05-08 15:56:51 -06:00
|
|
|
|
2014-06-24 11:10:49 -06:00
|
|
|
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
|
|
|
|
virReportUnsupportedError();
|
|
|
|
return NULL;
|
|
|
|
#endif
|
|
|
|
|
2014-05-08 15:56:51 -06:00
|
|
|
virCheckFlags(LIBXL_MIGRATION_FLAGS, NULL);
|
|
|
|
if (virTypedParamsValidate(params, nparams, LIBXL_MIGRATION_PARAMETERS) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (virTypedParamsGetString(params, nparams,
|
|
|
|
VIR_MIGRATE_PARAM_DEST_NAME,
|
|
|
|
&dname) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!dname ||
|
|
|
|
!(vm = virDomainObjListFindByName(driver->domains, dname))) {
|
|
|
|
/* Migration obviously failed if the domain doesn't exist */
|
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("Migration failed. No domain on destination host "
|
|
|
|
"with matching name '%s'"),
|
|
|
|
NULLSTR(dname));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virDomainMigrateFinish3ParamsEnsureACL(dconn, vm->def) < 0) {
|
2015-04-23 18:00:01 +02:00
|
|
|
virDomainObjEndAPI(&vm);
|
2014-05-08 15:56:51 -06:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-03-20 11:42:56 -06:00
|
|
|
ret = libxlDomainMigrationDstFinish(dconn, vm, flags, cancelled);
|
2014-11-13 14:41:56 -07:00
|
|
|
|
2015-04-23 18:00:01 +02:00
|
|
|
virDomainObjEndAPI(&vm);
|
2014-11-13 14:41:56 -07:00
|
|
|
|
|
|
|
return ret;
|
2014-05-08 15:56:51 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainMigrateConfirm3Params(virDomainPtr domain,
|
|
|
|
virTypedParameterPtr params,
|
|
|
|
int nparams,
|
2019-10-14 14:45:33 +02:00
|
|
|
const char *cookiein G_GNUC_UNUSED,
|
|
|
|
int cookieinlen G_GNUC_UNUSED,
|
2014-05-08 15:56:51 -06:00
|
|
|
unsigned int flags,
|
|
|
|
int cancelled)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = domain->conn->privateData;
|
|
|
|
virDomainObj *vm = NULL;
|
2018-03-12 12:22:34 -06:00
|
|
|
int ret = -1;
|
2014-05-08 15:56:51 -06:00
|
|
|
|
2014-06-24 11:10:49 -06:00
|
|
|
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
|
|
|
|
virReportUnsupportedError();
|
|
|
|
return -1;
|
|
|
|
#endif
|
|
|
|
|
2014-05-08 15:56:51 -06:00
|
|
|
virCheckFlags(LIBXL_MIGRATION_FLAGS, -1);
|
|
|
|
if (virTypedParamsValidate(params, nparams, LIBXL_MIGRATION_PARAMETERS) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (!(vm = libxlDomObjFromDomain(domain)))
|
|
|
|
return -1;
|
|
|
|
|
2018-03-12 12:22:34 -06:00
|
|
|
if (virDomainMigrateConfirm3ParamsEnsureACL(domain->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
2014-05-08 15:56:51 -06:00
|
|
|
|
2018-03-20 11:42:56 -06:00
|
|
|
ret = libxlDomainMigrationSrcConfirm(driver, vm, flags, cancelled);
|
2018-03-12 12:22:34 -06:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virDomainObjEndAPI(&vm);
|
|
|
|
return ret;
|
2014-05-08 15:56:51 -06:00
|
|
|
}
|
|
|
|
|
2015-05-15 12:26:30 -06:00
|
|
|
static int libxlNodeGetSecurityModel(virConnectPtr conn,
|
|
|
|
virSecurityModelPtr secmodel)
|
|
|
|
{
|
|
|
|
memset(secmodel, 0, sizeof(*secmodel));
|
|
|
|
|
|
|
|
if (virNodeGetSecurityModelEnsureACL(conn) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Currently the libxl driver does not support security model.
|
|
|
|
* Similar to the qemu driver, treat this as success and simply
|
|
|
|
* return no data in secmodel. Avoids spamming the libvirt log
|
|
|
|
* with "this function is not supported by the connection driver:
|
|
|
|
* virNodeGetSecurityModel"
|
|
|
|
*/
|
|
|
|
return 0;
|
|
|
|
}
|
2011-09-23 08:56:13 +02:00
|
|
|
|
2016-05-13 14:21:23 +08:00
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlGetDHCPInterfaces(virDomainObj *vm,
|
2016-05-13 14:21:23 +08:00
|
|
|
virDomainInterfacePtr **ifaces)
|
|
|
|
{
|
2019-12-04 10:18:22 +01:00
|
|
|
g_autoptr(virConnect) conn = NULL;
|
2019-12-04 10:22:13 +01:00
|
|
|
virDomainInterfacePtr *ifaces_ret = NULL;
|
|
|
|
size_t ifaces_count = 0;
|
|
|
|
size_t i;
|
2016-05-13 14:21:23 +08:00
|
|
|
|
2019-12-04 10:18:22 +01:00
|
|
|
if (!(conn = virGetConnectNetwork()))
|
2016-05-13 14:21:23 +08:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
for (i = 0; i < vm->def->nnets; i++) {
|
2019-12-04 10:22:13 +01:00
|
|
|
g_autoptr(virNetwork) network = NULL;
|
|
|
|
char macaddr[VIR_MAC_STRING_BUFLEN];
|
2019-12-04 10:26:58 +01:00
|
|
|
virNetworkDHCPLeasePtr *leases = NULL;
|
|
|
|
int n_leases = 0;
|
2019-12-04 10:22:13 +01:00
|
|
|
virDomainInterfacePtr iface = NULL;
|
|
|
|
size_t j;
|
|
|
|
|
2016-05-13 14:21:23 +08:00
|
|
|
if (vm->def->nets[i]->type != VIR_DOMAIN_NET_TYPE_NETWORK)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
virMacAddrFormat(&(vm->def->nets[i]->mac), macaddr);
|
2019-12-04 10:22:13 +01:00
|
|
|
|
2019-12-04 10:18:22 +01:00
|
|
|
network = virNetworkLookupByName(conn,
|
2016-05-13 14:21:23 +08:00
|
|
|
vm->def->nets[i]->data.network.name);
|
2019-12-04 10:18:22 +01:00
|
|
|
if (!network)
|
|
|
|
goto error;
|
2016-05-13 14:21:23 +08:00
|
|
|
|
|
|
|
if ((n_leases = virNetworkGetDHCPLeases(network, macaddr,
|
|
|
|
&leases, 0)) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (n_leases) {
|
2020-09-23 20:43:09 +02:00
|
|
|
ifaces_ret = g_renew(virDomainInterfacePtr, ifaces_ret, ifaces_count + 1);
|
|
|
|
ifaces_ret[ifaces_count] = g_new0(virDomainInterface, 1);
|
2019-12-04 10:26:58 +01:00
|
|
|
iface = ifaces_ret[ifaces_count];
|
|
|
|
ifaces_count++;
|
2016-05-13 14:21:23 +08:00
|
|
|
|
|
|
|
/* Assuming each lease corresponds to a separate IP */
|
|
|
|
iface->naddrs = n_leases;
|
|
|
|
|
2020-09-23 20:43:09 +02:00
|
|
|
iface->addrs = g_new0(virDomainIPAddress, iface->naddrs);
|
2019-10-20 13:49:46 +02:00
|
|
|
iface->name = g_strdup(vm->def->nets[i]->ifname);
|
|
|
|
iface->hwaddr = g_strdup(macaddr);
|
2016-05-13 14:21:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
for (j = 0; j < n_leases; j++) {
|
|
|
|
virNetworkDHCPLeasePtr lease = leases[j];
|
|
|
|
virDomainIPAddressPtr ip_addr = &iface->addrs[j];
|
|
|
|
|
2019-10-20 13:49:46 +02:00
|
|
|
ip_addr->addr = g_strdup(lease->ipaddr);
|
2016-05-13 14:21:23 +08:00
|
|
|
ip_addr->type = lease->type;
|
|
|
|
ip_addr->prefix = lease->prefix;
|
|
|
|
|
|
|
|
virNetworkDHCPLeaseFree(leases[j]);
|
2019-12-04 10:26:58 +01:00
|
|
|
}
|
2016-05-13 14:21:23 +08:00
|
|
|
|
|
|
|
VIR_FREE(leases);
|
|
|
|
}
|
|
|
|
|
2019-12-04 10:26:58 +01:00
|
|
|
*ifaces = g_steal_pointer(&ifaces_ret);
|
|
|
|
return ifaces_count;
|
2016-05-13 14:21:23 +08:00
|
|
|
|
|
|
|
error:
|
|
|
|
if (ifaces_ret) {
|
|
|
|
for (i = 0; i < ifaces_count; i++)
|
|
|
|
virDomainInterfaceFree(ifaces_ret[i]);
|
|
|
|
}
|
|
|
|
VIR_FREE(ifaces_ret);
|
|
|
|
|
2019-12-04 10:26:58 +01:00
|
|
|
return -1;
|
2016-05-13 14:21:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlDomainInterfaceAddresses(virDomainPtr dom,
|
|
|
|
virDomainInterfacePtr **ifaces,
|
|
|
|
unsigned int source,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainObj *vm = NULL;
|
2016-05-13 14:21:23 +08:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
|
|
|
goto cleanup;
|
|
|
|
|
2020-09-18 17:54:14 +02:00
|
|
|
if (virDomainInterfaceAddressesEnsureACL(dom->conn, vm->def, source) < 0)
|
2016-05-13 14:21:23 +08:00
|
|
|
goto cleanup;
|
|
|
|
|
2018-04-17 22:13:29 +00:00
|
|
|
if (virDomainObjCheckActive(vm) < 0)
|
2016-05-13 14:21:23 +08:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
switch (source) {
|
|
|
|
case VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE:
|
2019-12-04 10:18:22 +01:00
|
|
|
ret = libxlGetDHCPInterfaces(vm, ifaces);
|
2016-05-13 14:21:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
|
|
|
|
_("Unsupported IP address data source %d"),
|
|
|
|
source);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virDomainObjEndAPI(&vm);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-16 15:21:59 -06:00
|
|
|
static char *
|
|
|
|
libxlConnectGetDomainCapabilities(virConnectPtr conn,
|
|
|
|
const char *emulatorbin,
|
|
|
|
const char *arch_str,
|
|
|
|
const char *machine,
|
|
|
|
const char *virttype_str,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = conn->privateData;
|
|
|
|
libxlDriverConfig *cfg;
|
2016-05-16 15:21:59 -06:00
|
|
|
char *ret = NULL;
|
|
|
|
int virttype = VIR_DOMAIN_VIRT_XEN;
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainCaps *domCaps = NULL;
|
2016-05-16 15:21:59 -06:00
|
|
|
int arch = virArchFromHost(); /* virArch */
|
|
|
|
|
|
|
|
virCheckFlags(0, ret);
|
|
|
|
|
|
|
|
if (virConnectGetDomainCapabilitiesEnsureACL(conn) < 0)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
cfg = libxlDriverConfigGet(driver);
|
|
|
|
|
|
|
|
if (virttype_str &&
|
|
|
|
(virttype = virDomainVirtTypeFromString(virttype_str)) < 0) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("unknown virttype: %s"),
|
|
|
|
virttype_str);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virttype != VIR_DOMAIN_VIRT_XEN) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("unknown virttype: %s"),
|
|
|
|
virttype_str);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (arch_str && (arch = virArchFromString(arch_str)) == VIR_ARCH_NONE) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("unknown architecture: %s"),
|
|
|
|
arch_str);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (emulatorbin == NULL)
|
|
|
|
emulatorbin = "/usr/bin/qemu-system-x86_64";
|
|
|
|
|
|
|
|
if (machine) {
|
2018-11-26 20:34:37 +01:00
|
|
|
if (STRNEQ(machine, "xenpv") &&
|
|
|
|
STRNEQ(machine, "xenpvh") &&
|
|
|
|
STRNEQ(machine, "xenfv")) {
|
2016-05-16 15:21:59 -06:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
2018-11-26 20:34:37 +01:00
|
|
|
_("Xen only supports 'xenpv', 'xenpvh' and 'xenfv' machines"));
|
2016-05-16 15:21:59 -06:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
machine = "xenpv";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(domCaps = virDomainCapsNew(emulatorbin, machine, arch, virttype)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (libxlMakeDomainCapabilities(domCaps, cfg->firmwares,
|
|
|
|
cfg->nfirmwares) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = virDomainCapsFormat(domCaps);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virObjectUnref(domCaps);
|
|
|
|
virObjectUnref(cfg);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-20 20:08:48 +01:00
|
|
|
static int
|
|
|
|
libxlConnectCompareCPU(virConnectPtr conn,
|
|
|
|
const char *xmlDesc,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = conn->privateData;
|
|
|
|
libxlDriverConfig *cfg;
|
2016-07-20 20:08:48 +01:00
|
|
|
int ret = VIR_CPU_COMPARE_ERROR;
|
|
|
|
bool failIncompatible;
|
2020-10-07 10:54:55 +02:00
|
|
|
bool validateXML;
|
2016-07-20 20:08:48 +01:00
|
|
|
|
2020-10-07 10:54:55 +02:00
|
|
|
virCheckFlags(VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE |
|
|
|
|
VIR_CONNECT_COMPARE_CPU_VALIDATE_XML,
|
2016-07-20 20:08:48 +01:00
|
|
|
VIR_CPU_COMPARE_ERROR);
|
|
|
|
|
|
|
|
if (virConnectCompareCPUEnsureACL(conn) < 0)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
failIncompatible = !!(flags & VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE);
|
2020-10-07 10:54:55 +02:00
|
|
|
validateXML = !!(flags & VIR_CONNECT_COMPARE_CPU_VALIDATE_XML);
|
2016-07-20 20:08:48 +01:00
|
|
|
|
|
|
|
cfg = libxlDriverConfigGet(driver);
|
|
|
|
|
2016-08-09 13:26:53 +02:00
|
|
|
ret = virCPUCompareXML(cfg->caps->host.arch, cfg->caps->host.cpu,
|
2020-10-07 10:54:55 +02:00
|
|
|
xmlDesc, failIncompatible, validateXML);
|
2016-07-20 20:08:48 +01:00
|
|
|
|
|
|
|
virObjectUnref(cfg);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-07-20 20:08:49 +01:00
|
|
|
static char *
|
|
|
|
libxlConnectBaselineCPU(virConnectPtr conn,
|
|
|
|
const char **xmlCPUs,
|
|
|
|
unsigned int ncpus,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virCPUDef **cpus = NULL;
|
|
|
|
virCPUDef *cpu = NULL;
|
2017-09-13 16:27:15 +02:00
|
|
|
char *cpustr = NULL;
|
2016-07-20 20:08:49 +01:00
|
|
|
|
|
|
|
virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES |
|
|
|
|
VIR_CONNECT_BASELINE_CPU_MIGRATABLE, NULL);
|
|
|
|
|
|
|
|
if (virConnectBaselineCPUEnsureACL(conn) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2017-09-13 16:27:15 +02:00
|
|
|
if (!(cpus = virCPUDefListParse(xmlCPUs, ncpus, VIR_CPU_TYPE_HOST)))
|
|
|
|
goto cleanup;
|
|
|
|
|
2018-05-15 11:57:35 +02:00
|
|
|
if (!(cpu = virCPUBaseline(VIR_ARCH_NONE, cpus, ncpus, NULL, NULL,
|
2018-05-15 10:50:32 +02:00
|
|
|
!!(flags & VIR_CONNECT_BASELINE_CPU_MIGRATABLE))))
|
2017-09-13 16:27:15 +02:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if ((flags & VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES) &&
|
|
|
|
virCPUExpandFeatures(cpus[0]->arch, cpu) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2017-06-30 15:47:23 +02:00
|
|
|
cpustr = virCPUDefFormat(cpu, NULL);
|
2016-07-20 20:08:49 +01:00
|
|
|
|
|
|
|
cleanup:
|
2017-09-13 16:27:15 +02:00
|
|
|
virCPUDefListFree(cpus);
|
|
|
|
virCPUDefFree(cpu);
|
|
|
|
|
|
|
|
return cpustr;
|
2016-07-20 20:08:49 +01:00
|
|
|
}
|
|
|
|
|
2019-08-05 10:42:49 +02:00
|
|
|
static int
|
|
|
|
libxlDomainSetMetadata(virDomainPtr dom,
|
|
|
|
int type,
|
|
|
|
const char *metadata,
|
|
|
|
const char *key,
|
|
|
|
const char *uri,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
libxlDriverPrivate *driver = dom->conn->privateData;
|
2019-10-15 14:47:50 +02:00
|
|
|
g_autoptr(libxlDriverConfig) cfg = libxlDriverConfigGet(driver);
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainObj *vm = NULL;
|
2019-08-05 10:42:49 +02:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
|
|
|
|
VIR_DOMAIN_AFFECT_CONFIG, -1);
|
|
|
|
|
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (virDomainSetMetadataEnsureACL(dom->conn, vm->def, flags) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2019-11-27 12:53:10 +00:00
|
|
|
ret = virDomainObjSetMetadata(vm, type, metadata, key, uri,
|
2019-08-05 10:42:49 +02:00
|
|
|
driver->xmlopt, cfg->stateDir,
|
|
|
|
cfg->configDir, flags);
|
|
|
|
|
|
|
|
if (ret == 0) {
|
2021-03-11 08:16:13 +01:00
|
|
|
virObjectEvent *ev = NULL;
|
2019-08-05 10:42:49 +02:00
|
|
|
ev = virDomainEventMetadataChangeNewFromObj(vm, type, uri);
|
|
|
|
virObjectEventStateQueue(driver->domainEventState, ev);
|
|
|
|
}
|
|
|
|
|
|
|
|
libxlDomainObjEndJob(driver, vm);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virDomainObjEndAPI(&vm);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
|
|
|
libxlDomainGetMetadata(virDomainPtr dom,
|
|
|
|
int type,
|
|
|
|
const char *uri,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virDomainObj *vm;
|
2019-08-05 10:42:49 +02:00
|
|
|
char *ret = NULL;
|
|
|
|
|
|
|
|
if (!(vm = libxlDomObjFromDomain(dom)))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (virDomainGetMetadataEnsureACL(dom->conn, vm->def) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = virDomainObjGetMetadata(vm, type, uri, flags);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virDomainObjEndAPI(&vm);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-01-20 16:16:26 +00:00
|
|
|
static virHypervisorDriver libxlHypervisorDriver = {
|
2020-05-04 14:51:32 -06:00
|
|
|
.name = LIBXL_DRIVER_EXTERNAL_NAME,
|
2018-03-27 17:24:44 +01:00
|
|
|
.connectURIProbe = libxlConnectURIProbe,
|
2013-04-23 13:50:18 +01:00
|
|
|
.connectOpen = libxlConnectOpen, /* 0.9.0 */
|
|
|
|
.connectClose = libxlConnectClose, /* 0.9.0 */
|
|
|
|
.connectGetType = libxlConnectGetType, /* 0.9.0 */
|
|
|
|
.connectGetVersion = libxlConnectGetVersion, /* 0.9.0 */
|
2013-04-26 17:39:11 +01:00
|
|
|
.connectGetHostname = libxlConnectGetHostname, /* 0.9.0 */
|
2013-06-25 15:25:29 +02:00
|
|
|
.connectGetSysinfo = libxlConnectGetSysinfo, /* 1.1.0 */
|
2013-04-23 13:50:18 +01:00
|
|
|
.connectGetMaxVcpus = libxlConnectGetMaxVcpus, /* 0.9.0 */
|
2011-05-13 14:35:01 +01:00
|
|
|
.nodeGetInfo = libxlNodeGetInfo, /* 0.9.0 */
|
2013-04-23 13:50:18 +01:00
|
|
|
.connectGetCapabilities = libxlConnectGetCapabilities, /* 0.9.0 */
|
|
|
|
.connectListDomains = libxlConnectListDomains, /* 0.9.0 */
|
|
|
|
.connectNumOfDomains = libxlConnectNumOfDomains, /* 0.9.0 */
|
|
|
|
.connectListAllDomains = libxlConnectListAllDomains, /* 0.9.13 */
|
2011-05-13 14:35:01 +01: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 18:31:55 +01:00
|
|
|
.domainShutdownFlags = libxlDomainShutdownFlags, /* 0.9.10 */
|
2011-05-13 14:35:01 +01:00
|
|
|
.domainReboot = libxlDomainReboot, /* 0.9.0 */
|
|
|
|
.domainDestroy = libxlDomainDestroy, /* 0.9.0 */
|
2011-07-20 18:47:46 +02:00
|
|
|
.domainDestroyFlags = libxlDomainDestroyFlags, /* 0.9.4 */
|
2018-09-07 21:29:55 +02:00
|
|
|
#ifdef LIBXL_HAVE_DOMAIN_SUSPEND_ONLY
|
|
|
|
.domainPMSuspendForDuration = libxlDomainPMSuspendForDuration, /* 4.8.0 */
|
|
|
|
#endif
|
|
|
|
.domainPMWakeup = libxlDomainPMWakeup, /* 4.8.0 */
|
2011-05-13 14:35:01 +01:00
|
|
|
.domainGetOSType = libxlDomainGetOSType, /* 0.9.0 */
|
|
|
|
.domainGetMaxMemory = libxlDomainGetMaxMemory, /* 0.9.0 */
|
2011-05-30 11:53:03 +02:00
|
|
|
.domainSetMaxMemory = libxlDomainSetMaxMemory, /* 0.9.2 */
|
2011-05-13 14:35:01 +01:00
|
|
|
.domainSetMemory = libxlDomainSetMemory, /* 0.9.0 */
|
|
|
|
.domainSetMemoryFlags = libxlDomainSetMemoryFlags, /* 0.9.0 */
|
|
|
|
.domainGetInfo = libxlDomainGetInfo, /* 0.9.0 */
|
|
|
|
.domainGetState = libxlDomainGetState, /* 0.9.2 */
|
2011-05-30 11:53:02 +02: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 20:55:29 -06:00
|
|
|
.domainSaveFlags = libxlDomainSaveFlags, /* 0.9.4 */
|
2011-05-30 11:53:02 +02: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 20:55:29 -06:00
|
|
|
.domainRestoreFlags = libxlDomainRestoreFlags, /* 0.9.4 */
|
2011-05-30 11:53:01 +02:00
|
|
|
.domainCoreDump = libxlDomainCoreDump, /* 0.9.2 */
|
2011-05-13 14:35:01 +01:00
|
|
|
.domainSetVcpus = libxlDomainSetVcpus, /* 0.9.0 */
|
|
|
|
.domainSetVcpusFlags = libxlDomainSetVcpusFlags, /* 0.9.0 */
|
|
|
|
.domainGetVcpusFlags = libxlDomainGetVcpusFlags, /* 0.9.0 */
|
2017-01-06 12:19:31 -07:00
|
|
|
.domainGetMaxVcpus = libxlDomainGetMaxVcpus, /* 3.0.0 */
|
2011-05-13 14:35:01 +01:00
|
|
|
.domainPinVcpu = libxlDomainPinVcpu, /* 0.9.0 */
|
2013-12-20 16:01:39 +01:00
|
|
|
.domainPinVcpuFlags = libxlDomainPinVcpuFlags, /* 1.2.1 */
|
2011-05-13 14:35:01 +01:00
|
|
|
.domainGetVcpus = libxlDomainGetVcpus, /* 0.9.0 */
|
2013-12-20 16:01:31 +01:00
|
|
|
.domainGetVcpuPinInfo = libxlDomainGetVcpuPinInfo, /* 1.2.1 */
|
2011-05-13 14:35:01 +01:00
|
|
|
.domainGetXMLDesc = libxlDomainGetXMLDesc, /* 0.9.0 */
|
2013-04-23 13:50:18 +01:00
|
|
|
.connectDomainXMLFromNative = libxlConnectDomainXMLFromNative, /* 0.9.0 */
|
|
|
|
.connectDomainXMLToNative = libxlConnectDomainXMLToNative, /* 0.9.0 */
|
|
|
|
.connectListDefinedDomains = libxlConnectListDefinedDomains, /* 0.9.0 */
|
|
|
|
.connectNumOfDefinedDomains = libxlConnectNumOfDefinedDomains, /* 0.9.0 */
|
2011-05-13 14:35:01 +01:00
|
|
|
.domainCreate = libxlDomainCreate, /* 0.9.0 */
|
|
|
|
.domainCreateWithFlags = libxlDomainCreateWithFlags, /* 0.9.0 */
|
|
|
|
.domainDefineXML = libxlDomainDefineXML, /* 0.9.0 */
|
2014-11-18 14:19:38 +00:00
|
|
|
.domainDefineXMLFlags = libxlDomainDefineXMLFlags, /* 1.2.12 */
|
2011-05-13 14:35:01 +01:00
|
|
|
.domainUndefine = libxlDomainUndefine, /* 0.9.0 */
|
2011-07-20 11:05:20 +08:00
|
|
|
.domainUndefineFlags = libxlDomainUndefineFlags, /* 0.9.4 */
|
2011-05-26 23:27:06 +08: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 14:35:01 +01:00
|
|
|
.domainGetAutostart = libxlDomainGetAutostart, /* 0.9.0 */
|
|
|
|
.domainSetAutostart = libxlDomainSetAutostart, /* 0.9.0 */
|
|
|
|
.domainGetSchedulerType = libxlDomainGetSchedulerType, /* 0.9.0 */
|
|
|
|
.domainGetSchedulerParameters = libxlDomainGetSchedulerParameters, /* 0.9.0 */
|
2011-05-17 16:33:53 -06:00
|
|
|
.domainGetSchedulerParametersFlags = libxlDomainGetSchedulerParametersFlags, /* 0.9.2 */
|
2011-05-13 14:35:01 +01:00
|
|
|
.domainSetSchedulerParameters = libxlDomainSetSchedulerParameters, /* 0.9.0 */
|
2011-05-17 16:33:53 -06:00
|
|
|
.domainSetSchedulerParametersFlags = libxlDomainSetSchedulerParametersFlags, /* 0.9.2 */
|
2013-07-13 02:27:18 +02:00
|
|
|
#ifdef LIBXL_HAVE_DOMAIN_NODEAFFINITY
|
|
|
|
.domainGetNumaParameters = libxlDomainGetNumaParameters, /* 1.1.1 */
|
|
|
|
#endif
|
2011-05-13 14:35:01 +01:00
|
|
|
.nodeGetFreeMemory = libxlNodeGetFreeMemory, /* 0.9.0 */
|
2013-06-28 16:32:52 +02:00
|
|
|
.nodeGetCellsFreeMemory = libxlNodeGetCellsFreeMemory, /* 1.1.1 */
|
2015-11-13 13:14:47 +00:00
|
|
|
.domainGetJobInfo = libxlDomainGetJobInfo, /* 1.3.1 */
|
2015-11-13 13:14:48 +00:00
|
|
|
.domainGetJobStats = libxlDomainGetJobStats, /* 1.3.1 */
|
2015-11-24 12:48:50 +01:00
|
|
|
.domainMemoryStats = libxlDomainMemoryStats, /* 1.3.0 */
|
|
|
|
.domainGetCPUStats = libxlDomainGetCPUStats, /* 1.3.0 */
|
2016-02-24 13:25:46 +00:00
|
|
|
.domainInterfaceStats = libxlDomainInterfaceStats, /* 1.3.2 */
|
2016-07-26 00:45:14 +01:00
|
|
|
.domainBlockStats = libxlDomainBlockStats, /* 2.1.0 */
|
|
|
|
.domainBlockStatsFlags = libxlDomainBlockStatsFlags, /* 2.1.0 */
|
2013-04-23 13:50:18 +01:00
|
|
|
.connectDomainEventRegister = libxlConnectDomainEventRegister, /* 0.9.0 */
|
|
|
|
.connectDomainEventDeregister = libxlConnectDomainEventDeregister, /* 0.9.0 */
|
2011-06-02 20:39:40 +08:00
|
|
|
.domainManagedSave = libxlDomainManagedSave, /* 0.9.2 */
|
|
|
|
.domainHasManagedSaveImage = libxlDomainHasManagedSaveImage, /* 0.9.2 */
|
|
|
|
.domainManagedSaveRemove = libxlDomainManagedSaveRemove, /* 0.9.2 */
|
2013-07-26 11:30:50 +08:00
|
|
|
.domainOpenConsole = libxlDomainOpenConsole, /* 1.1.2 */
|
2011-05-13 14:35:01 +01:00
|
|
|
.domainIsActive = libxlDomainIsActive, /* 0.9.0 */
|
|
|
|
.domainIsPersistent = libxlDomainIsPersistent, /* 0.9.0 */
|
|
|
|
.domainIsUpdated = libxlDomainIsUpdated, /* 0.9.0 */
|
2013-04-23 13:50:18 +01:00
|
|
|
.connectDomainEventRegisterAny = libxlConnectDomainEventRegisterAny, /* 0.9.0 */
|
|
|
|
.connectDomainEventDeregisterAny = libxlConnectDomainEventDeregisterAny, /* 0.9.0 */
|
|
|
|
.connectIsAlive = libxlConnectIsAlive, /* 0.9.8 */
|
2013-07-13 02:27:10 +02:00
|
|
|
.connectSupportsFeature = libxlConnectSupportsFeature, /* 1.1.1 */
|
2014-03-06 17:46:11 +08:00
|
|
|
.nodeDeviceDettach = libxlNodeDeviceDettach, /* 1.2.3 */
|
|
|
|
.nodeDeviceDetachFlags = libxlNodeDeviceDetachFlags, /* 1.2.3 */
|
|
|
|
.nodeDeviceReAttach = libxlNodeDeviceReAttach, /* 1.2.3 */
|
|
|
|
.nodeDeviceReset = libxlNodeDeviceReset, /* 1.2.3 */
|
2014-06-24 11:12:21 -06:00
|
|
|
.domainMigrateBegin3Params = libxlDomainMigrateBegin3Params, /* 1.2.6 */
|
|
|
|
.domainMigratePrepare3Params = libxlDomainMigratePrepare3Params, /* 1.2.6 */
|
2017-02-15 11:17:38 +00:00
|
|
|
.domainMigratePrepareTunnel3Params = libxlDomainMigratePrepareTunnel3Params, /* 3.1.0 */
|
2014-06-24 11:12:21 -06:00
|
|
|
.domainMigratePerform3Params = libxlDomainMigratePerform3Params, /* 1.2.6 */
|
|
|
|
.domainMigrateFinish3Params = libxlDomainMigrateFinish3Params, /* 1.2.6 */
|
|
|
|
.domainMigrateConfirm3Params = libxlDomainMigrateConfirm3Params, /* 1.2.6 */
|
2015-05-15 12:26:30 -06:00
|
|
|
.nodeGetSecurityModel = libxlNodeGetSecurityModel, /* 1.2.16 */
|
2016-05-13 14:21:23 +08:00
|
|
|
.domainInterfaceAddresses = libxlDomainInterfaceAddresses, /* 1.3.5 */
|
2016-06-14 11:15:18 +02:00
|
|
|
.connectGetDomainCapabilities = libxlConnectGetDomainCapabilities, /* 2.0.0 */
|
2016-07-20 20:08:48 +01:00
|
|
|
.connectCompareCPU = libxlConnectCompareCPU, /* 2.3.0 */
|
2016-07-20 20:08:49 +01:00
|
|
|
.connectBaselineCPU = libxlConnectBaselineCPU, /* 2.3.0 */
|
2019-08-05 10:42:49 +02:00
|
|
|
.domainSetMetadata = libxlDomainSetMetadata, /* 5.7.0 */
|
|
|
|
.domainGetMetadata = libxlDomainGetMetadata, /* 5.7.0 */
|
|
|
|
|
2011-02-10 15:42:34 -07:00
|
|
|
};
|
|
|
|
|
2015-01-20 16:16:26 +00:00
|
|
|
static virConnectDriver libxlConnectDriver = {
|
2018-03-28 10:53:31 +01:00
|
|
|
.localOnly = true,
|
2018-03-27 15:51:45 +01:00
|
|
|
.uriSchemes = (const char *[]){ "xen", NULL },
|
2015-01-20 16:16:26 +00:00
|
|
|
.hypervisorDriver = &libxlHypervisorDriver,
|
|
|
|
};
|
|
|
|
|
2011-02-10 15:42:34 -07:00
|
|
|
static virStateDriver libxlStateDriver = {
|
2020-05-04 14:51:32 -06:00
|
|
|
.name = LIBXL_DRIVER_EXTERNAL_NAME,
|
2013-04-23 13:50:18 +01:00
|
|
|
.stateInitialize = libxlStateInitialize,
|
|
|
|
.stateCleanup = libxlStateCleanup,
|
|
|
|
.stateReload = libxlStateReload,
|
2011-02-10 15:42:34 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
libxlRegister(void)
|
|
|
|
{
|
2015-01-20 16:16:26 +00:00
|
|
|
if (virRegisterConnectDriver(&libxlConnectDriver,
|
|
|
|
true) < 0)
|
2011-02-10 15:42:34 -07:00
|
|
|
return -1;
|
|
|
|
if (virRegisterStateDriver(&libxlStateDriver) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|