libvirt/src/xen/xen_driver.c

2961 lines
80 KiB
C
Raw Normal View History

/*
* xen_driver.c: Unified Xen driver.
*
maint: improve VIR_ERR_NO_SUPPORT usage We weren't very consistent in our use of VIR_ERR_NO_SUPPORT; many users just passed __FUNCTION__ on, while others passed "%s" to silence over-eager compilers that warn about __FUNCTION__ not containing any %. It's nicer to route all these uses through a single macro, so that if we ever need to change the reporting, we can do it in one place. I verified that 'virsh -c test:///default qemu-monitor-command test foo' gives the same error message before and after this patch: error: this function is not supported by the connection driver: virDomainQemuMonitorCommand Note that in libvirt.c, we were inconsistent on whether virDomain* API used virLibConnError() (with VIR_FROM_NONE) or virLibDomainError() (with VIR_FROM_DOMAIN); this patch unifies these errors to all use VIR_FROM_NONE, on the grounds that it is unlikely that a caller learning that a call is unimplemented can do anything in particular with extra knowledge of which error domain it belongs to. One particular change to note is virDomainOpenGraphics which was trying to fail with VIR_ERR_NO_SUPPORT after a failed VIR_DRV_SUPPORTS_FEATURE check; all other places that fail a feature check report VIR_ERR_ARGUMENT_UNSUPPORTED. * src/util/virerror.h (virReportUnsupportedError): New macro. * src/libvirt-qemu.c: Use new macro. * src/libvirt-lxc.c: Likewise. * src/lxc/lxc_driver.c: Likewise. * src/security/security_manager.c: Likewise. * src/util/virinitctl.c: Likewise. * src/libvirt.c: Likewise. (virDomainOpenGraphics): Use correct error for unsupported feature. Signed-off-by: Eric Blake <eblake@redhat.com>
2013-12-20 01:38:59 +00:00
* Copyright (C) 2007-2014 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*
* Richard W.M. Jones <rjones@redhat.com>
*/
#include <config.h>
/* Note:
*
* This driver provides a unified interface to the five
* separate underlying Xen drivers (xen_internal,
* xend_internal, xs_internal and xm_internal). Historically
* the body of libvirt.c handled the five Xen drivers,
* and contained Xen-specific code.
*/
#include <stdint.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <fcntl.h>
#include <xen/dom0_ops.h>
#include "virerror.h"
2012-12-12 17:59:27 +00:00
#include "virlog.h"
#include "datatypes.h"
#include "xen_driver.h"
2011-02-21 13:40:08 +00:00
#include "xen_sxpr.h"
2011-02-21 13:40:10 +00:00
#include "xen_xm.h"
#include "xen_hypervisor.h"
#include "xend_internal.h"
#include "xs_internal.h"
#include "xm_internal.h"
#if WITH_XEN_INOTIFY
# include "xen_inotify.h"
#endif
2012-12-13 18:13:21 +00:00
#include "virxml.h"
2012-12-12 18:06:53 +00:00
#include "viralloc.h"
2009-04-03 12:38:52 +00:00
#include "node_device_conf.h"
2012-12-13 14:52:25 +00:00
#include "virpci.h"
2012-12-13 18:01:25 +00:00
#include "viruuid.h"
#include "fdstream.h"
#include "virfile.h"
#include "viruri.h"
#include "vircommand.h"
#include "virnodesuspend.h"
#include "nodeinfo.h"
#include "configmake.h"
#include "virstring.h"
#include "viraccessapicheck.h"
#define VIR_FROM_THIS VIR_FROM_XEN
VIR_LOG_INIT("xen.xen_driver");
#define XEN_SAVE_DIR LOCALSTATEDIR "/lib/libvirt/xen/save"
static int
xenUnifiedNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info);
static int
xenUnifiedDomainGetVcpusFlagsInternal(virDomainPtr dom,
virDomainDefPtr def,
unsigned int flags);
static int
xenUnifiedDomainGetVcpusInternal(virDomainPtr dom,
virDomainDefPtr def,
virVcpuInfoPtr info,
int maxinfo,
unsigned char *cpumaps,
int maplen);
static bool is_privileged = false;
static virSysinfoDefPtr hostsysinfo = NULL;
2009-01-22 17:49:41 +00:00
static virDomainDefPtr xenGetDomainDefForID(virConnectPtr conn, int id)
{
virDomainDefPtr ret;
ret = xenHypervisorLookupDomainByID(conn, id);
if (!ret && virGetLastError() == NULL)
virReportError(VIR_ERR_NO_DOMAIN, __FUNCTION__);
return ret;
}
static virDomainDefPtr xenGetDomainDefForName(virConnectPtr conn, const char *name)
{
xenUnifiedPrivatePtr priv = conn->privateData;
virDomainDefPtr ret;
ret = xenDaemonLookupByName(conn, name);
/* Try XM for inactive domains. */
if (!ret &&
priv->xendConfigVersion <= XEND_CONFIG_VERSION_3_0_3)
ret = xenXMDomainLookupByName(conn, name);
if (!ret && virGetLastError() == NULL)
virReportError(VIR_ERR_NO_DOMAIN, __FUNCTION__);
return ret;
}
static virDomainDefPtr xenGetDomainDefForUUID(virConnectPtr conn, const unsigned char *uuid)
{
xenUnifiedPrivatePtr priv = conn->privateData;
virDomainDefPtr ret;
ret = xenHypervisorLookupDomainByUUID(conn, uuid);
/* Try XM for inactive domains. */
if (!ret) {
if (priv->xendConfigVersion <= XEND_CONFIG_VERSION_3_0_3)
ret = xenXMDomainLookupByUUID(conn, uuid);
else
ret = xenDaemonLookupByUUID(conn, uuid);
}
if (!ret && virGetLastError() == NULL)
virReportError(VIR_ERR_NO_DOMAIN, __FUNCTION__);
return ret;
}
static virDomainDefPtr xenGetDomainDefForDom(virDomainPtr dom)
{
/* UUID lookup is more efficient than name lookup */
return xenGetDomainDefForUUID(dom->conn, dom->uuid);
}
/**
* xenNumaInit:
* @conn: pointer to the hypervisor connection
*
* Initializer for previous variables. We currently assume that
2008-02-27 10:37:19 +00:00
* the number of physical CPU and the number of NUMA cell is fixed
* until reboot which might be false in future Xen implementations.
*/
static void
xenNumaInit(virConnectPtr conn)
{
virNodeInfo nodeInfo;
2009-01-21 18:11:14 +00:00
xenUnifiedPrivatePtr priv;
int ret;
ret = xenUnifiedNodeGetInfo(conn, &nodeInfo);
if (ret < 0)
return;
2009-01-21 18:11:14 +00:00
priv = conn->privateData;
2009-01-21 18:11:14 +00:00
priv->nbNodeCells = nodeInfo.nodes;
priv->nbNodeCpus = nodeInfo.cpus;
}
2009-01-21 18:11:14 +00:00
/**
* xenDomainUsedCpus:
* @dom: the domain
* @def: the domain definition
*
* Analyze which set of CPUs are used by the domain and
* return a string providing the ranges.
*
* Returns the string which needs to be freed by the caller or
* NULL if the domain uses all CPU or in case of error.
*/
char *
xenDomainUsedCpus(virDomainPtr dom, virDomainDefPtr def)
{
char *res = NULL;
2009-01-21 18:11:14 +00:00
int ncpus;
int nb_vcpu;
virBitmapPtr cpulist = NULL;
unsigned char *cpumap = NULL;
size_t cpumaplen;
int nb = 0;
int n, m;
virVcpuInfoPtr cpuinfo = NULL;
virNodeInfo nodeinfo;
2009-01-21 18:11:14 +00:00
xenUnifiedPrivatePtr priv;
2009-01-21 18:11:14 +00:00
priv = dom->conn->privateData;
if (priv->nbNodeCpus <= 0)
return NULL;
nb_vcpu = xenUnifiedDomainGetVcpusFlagsInternal(dom, def,
(VIR_DOMAIN_VCPU_LIVE |
VIR_DOMAIN_VCPU_MAXIMUM));
if (nb_vcpu <= 0)
return NULL;
if (xenUnifiedNodeGetInfo(dom->conn, &nodeinfo) < 0)
return NULL;
if (!(cpulist = virBitmapNew(priv->nbNodeCpus)))
goto done;
if (VIR_ALLOC_N(cpuinfo, nb_vcpu) < 0)
goto done;
cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo));
if (xalloc_oversized(nb_vcpu, cpumaplen) ||
VIR_ALLOC_N(cpumap, nb_vcpu * cpumaplen) < 0)
goto done;
if ((ncpus = xenUnifiedDomainGetVcpusInternal(dom, def, cpuinfo, nb_vcpu,
cpumap, cpumaplen)) >= 0) {
for (n = 0; n < ncpus; n++) {
for (m = 0; m < priv->nbNodeCpus; m++) {
bool used;
ignore_value(virBitmapGetBit(cpulist, m, &used));
if ((!used) &&
(VIR_CPU_USABLE(cpumap, cpumaplen, n, m))) {
ignore_value(virBitmapSetBit(cpulist, m));
nb++;
/* if all CPU are used just return NULL */
2009-01-21 18:11:14 +00:00
if (nb == priv->nbNodeCpus)
goto done;
}
}
}
res = virBitmapFormat(cpulist);
}
done:
virBitmapFree(cpulist);
VIR_FREE(cpumap);
VIR_FREE(cpuinfo);
return res;
}
2009-01-22 17:49:41 +00:00
static int
xenUnifiedStateInitialize(bool privileged,
virStateInhibitCallback callback ATTRIBUTE_UNUSED,
void *opaque ATTRIBUTE_UNUSED)
2009-01-22 17:49:41 +00:00
{
/* Don't allow driver to work in non-root libvirtd */
if (privileged) {
is_privileged = true;
hostsysinfo = virSysinfoRead();
}
return 0;
}
static int
xenUnifiedStateCleanup(void)
{
virSysinfoDefFree(hostsysinfo);
2009-01-22 17:49:41 +00:00
return 0;
}
static virStateDriver state_driver = {
.name = "Xen",
.stateInitialize = xenUnifiedStateInitialize,
.stateCleanup = xenUnifiedStateCleanup,
2009-01-22 17:49:41 +00:00
};
/*----- Dispatch functions. -----*/
/* These dispatch functions follow the model used historically
* by libvirt.c -- trying each low-level Xen driver in turn
* until one succeeds. However since we know what low-level
* drivers can perform which functions, it is probably better
* in future to optimise these dispatch functions to just call
* the single function (or small number of appropriate functions)
* in the low level drivers directly.
*/
static int
xenUnifiedProbe(void)
{
#ifdef __linux__
if (virFileExists("/proc/xen"))
return 1;
#endif
2008-12-17 21:31:51 +00:00
#ifdef __sun
int fd;
if ((fd = open("/dev/xen/domcaps", O_RDONLY)) >= 0) {
VIR_FORCE_CLOSE(fd);
return 1;
}
#endif
return 0;
}
#ifdef WITH_LIBXL
util: make it easier to grab only regular command exit Auditing all callers of virCommandRun and virCommandWait that passed a non-NULL pointer for exit status turned up some interesting observations. Many callers were merely passing a pointer to avoid the overall command dying, but without caring what the exit status was - but these callers would be better off treating a child death by signal as an abnormal exit. Other callers were actually acting on the status, but not all of them remembered to filter by WIFEXITED and convert with WEXITSTATUS; depending on the platform, this can result in a status being reported as 256 times too big. And among those that correctly parse the output, it gets rather verbose. Finally, there were the callers that explicitly checked that the status was 0, and gave their own message, but with fewer details than what virCommand gives for free. So the best idea is to move the complexity out of callers and into virCommand - by default, we return the actual exit status already cleaned through WEXITSTATUS and treat signals as a failed command; but the few callers that care can ask for raw status and act on it themselves. * src/util/vircommand.h (virCommandRawStatus): New prototype. * src/libvirt_private.syms (util/command.h): Export it. * docs/internals/command.html.in: Document it. * src/util/vircommand.c (virCommandRawStatus): New function. (virCommandWait): Adjust semantics. * tests/commandtest.c (test1): Test it. * daemon/remote.c (remoteDispatchAuthPolkit): Adjust callers. * src/access/viraccessdriverpolkit.c (virAccessDriverPolkitCheck): Likewise. * src/fdstream.c (virFDStreamCloseInt): Likewise. * src/lxc/lxc_process.c (virLXCProcessStart): Likewise. * src/qemu/qemu_command.c (qemuCreateInBridgePortWithHelper): Likewise. * src/xen/xen_driver.c (xenUnifiedXendProbe): Simplify. * tests/reconnect.c (mymain): Likewise. * tests/statstest.c (mymain): Likewise. * src/bhyve/bhyve_process.c (virBhyveProcessStart) (virBhyveProcessStop): Don't overwrite virCommand error. * src/libvirt.c (virConnectAuthGainPolkit): Likewise. * src/openvz/openvz_driver.c (openvzDomainGetBarrierLimit) (openvzDomainSetBarrierLimit): Likewise. * src/util/virebtables.c (virEbTablesOnceInit): Likewise. * src/util/viriptables.c (virIpTablesOnceInit): Likewise. * src/util/virnetdevveth.c (virNetDevVethCreate): Fix debug message. * src/qemu/qemu_capabilities.c (virQEMUCapsInitQMP): Add comment. * src/storage/storage_backend_iscsi.c (virStorageBackendISCSINodeUpdate): Likewise. Signed-off-by: Eric Blake <eblake@redhat.com>
2014-02-20 00:32:19 +00:00
static bool
xenUnifiedXendProbe(void)
{
util: make it easier to grab only regular command exit Auditing all callers of virCommandRun and virCommandWait that passed a non-NULL pointer for exit status turned up some interesting observations. Many callers were merely passing a pointer to avoid the overall command dying, but without caring what the exit status was - but these callers would be better off treating a child death by signal as an abnormal exit. Other callers were actually acting on the status, but not all of them remembered to filter by WIFEXITED and convert with WEXITSTATUS; depending on the platform, this can result in a status being reported as 256 times too big. And among those that correctly parse the output, it gets rather verbose. Finally, there were the callers that explicitly checked that the status was 0, and gave their own message, but with fewer details than what virCommand gives for free. So the best idea is to move the complexity out of callers and into virCommand - by default, we return the actual exit status already cleaned through WEXITSTATUS and treat signals as a failed command; but the few callers that care can ask for raw status and act on it themselves. * src/util/vircommand.h (virCommandRawStatus): New prototype. * src/libvirt_private.syms (util/command.h): Export it. * docs/internals/command.html.in: Document it. * src/util/vircommand.c (virCommandRawStatus): New function. (virCommandWait): Adjust semantics. * tests/commandtest.c (test1): Test it. * daemon/remote.c (remoteDispatchAuthPolkit): Adjust callers. * src/access/viraccessdriverpolkit.c (virAccessDriverPolkitCheck): Likewise. * src/fdstream.c (virFDStreamCloseInt): Likewise. * src/lxc/lxc_process.c (virLXCProcessStart): Likewise. * src/qemu/qemu_command.c (qemuCreateInBridgePortWithHelper): Likewise. * src/xen/xen_driver.c (xenUnifiedXendProbe): Simplify. * tests/reconnect.c (mymain): Likewise. * tests/statstest.c (mymain): Likewise. * src/bhyve/bhyve_process.c (virBhyveProcessStart) (virBhyveProcessStop): Don't overwrite virCommand error. * src/libvirt.c (virConnectAuthGainPolkit): Likewise. * src/openvz/openvz_driver.c (openvzDomainGetBarrierLimit) (openvzDomainSetBarrierLimit): Likewise. * src/util/virebtables.c (virEbTablesOnceInit): Likewise. * src/util/viriptables.c (virIpTablesOnceInit): Likewise. * src/util/virnetdevveth.c (virNetDevVethCreate): Fix debug message. * src/qemu/qemu_capabilities.c (virQEMUCapsInitQMP): Add comment. * src/storage/storage_backend_iscsi.c (virStorageBackendISCSINodeUpdate): Likewise. Signed-off-by: Eric Blake <eblake@redhat.com>
2014-02-20 00:32:19 +00:00
bool ret = false;
if (virFileExists("/usr/sbin/xend")) {
virCommandPtr cmd;
cmd = virCommandNewArgList("/usr/sbin/xend", "status", NULL);
if (virCommandRun(cmd, NULL) == 0)
ret = true;
virCommandFree(cmd);
}
return ret;
}
#endif
static int
xenDomainDeviceDefPostParse(virDomainDeviceDefPtr dev,
maint: avoid 'const fooPtr' in domain_conf 'const fooPtr' is the same as 'foo * const' (the pointer won't change, but it's contents can). But in general, if an interface is trying to be const-correct, it should be using 'const foo *' (the pointer is to data that can't be changed). Fix up offenders in src/conf/domain_conf, and their fallout. Several things to note: virObjectLock() requires a non-const argument; if this were C++, we could treat the locking field as 'mutable' and allow locking an otherwise 'const' object, but that is a more invasive change, so I instead dropped attempts to be const-correct on domain lookup. virXMLPropString and friends require a non-const xmlNodePtr - this is because libxml2 is not a const-correct library. We could make the src/util/virxml wrappers cast away const, but I figured it was easier to not try to mark xmlNodePtr as const. Finally, virDomainDeviceDefCopy was a rather hard conversion - it calls virDomainDeviceDefPostParse, which in turn in the xen driver was actually modifying the domain outside of the current device being visited. We should not be adding a device on the first per-device callback, but waiting until after all per-device callbacks are complete. * src/conf/domain_conf.h (virDomainObjListFindByID) (virDomainObjListFindByUUID, virDomainObjListFindByName) (virDomainObjAssignDef, virDomainObjListAdd): Drop attempt at const. (virDomainDeviceDefCopy): Use intended type. (virDomainDeviceDefParse, virDomainDeviceDefPostParseCallback) (virDomainVideoDefaultType, virDomainVideoDefaultRAM) (virDomainChrGetDomainPtrs): Make const-correct. * src/conf/domain_conf.c (virDomainObjListFindByID) (virDomainObjListFindByUUID, virDomainObjListFindByName) (virDomainDeviceDefCopy, virDomainObjListAdd) (virDomainObjAssignDef, virDomainHostdevSubsysUsbDefParseXML) (virDomainHostdevSubsysPciOrigStatesDefParseXML) (virDomainHostdevSubsysPciDefParseXML) (virDomainHostdevSubsysScsiDefParseXML) (virDomainControllerModelTypeFromString) (virDomainTPMDefParseXML, virDomainTimerDefParseXML) (virDomainSoundCodecDefParseXML, virDomainSoundDefParseXML) (virDomainWatchdogDefParseXML, virDomainRNGDefParseXML) (virDomainMemballoonDefParseXML, virDomainNVRAMDefParseXML) (virSysinfoParseXML, virDomainVideoAccelDefParseXML) (virDomainVideoDefParseXML, virDomainHostdevDefParseXML) (virDomainRedirdevDefParseXML) (virDomainRedirFilterUsbDevDefParseXML) (virDomainRedirFilterDefParseXML, virDomainIdMapEntrySort) (virDomainIdmapDefParseXML, virDomainVcpuPinDefParseXML) (virDiskNameToBusDeviceIndex, virDomainDeviceDefCopy) (virDomainVideoDefaultType, virDomainHostdevAssignAddress) (virDomainDeviceDefPostParseInternal, virDomainDeviceDefPostParse) (virDomainChrGetDomainPtrs, virDomainControllerSCSINextUnit) (virDomainSCSIDriveAddressIsUsed) (virDomainDriveAddressIsUsedByDisk) (virDomainDriveAddressIsUsedByHostdev): Fix fallout. * src/openvz/openvz_driver.c (openvzDomainDeviceDefPostParse): Likewise. * src/libxl/libxl_domain.c (libxlDomainDeviceDefPostParse): Likewise. * src/qemu/qemu_domain.c (qemuDomainDeviceDefPostParse) (qemuDomainDefaultNetModel): Likewise. * src/lxc/lxc_domain.c (virLXCDomainDeviceDefPostParse): Likewise. * src/uml/uml_driver.c (umlDomainDeviceDefPostParse): Likewise. * src/xen/xen_driver.c (xenDomainDeviceDefPostParse): Split... (xenDomainDefPostParse): ...since per-device callback is not the time to be adding a device. Signed-off-by: Eric Blake <eblake@redhat.com>
2013-10-08 15:08:25 +00:00
const virDomainDef *def,
virCapsPtr caps ATTRIBUTE_UNUSED,
void *opaque ATTRIBUTE_UNUSED)
{
if (dev->type == VIR_DOMAIN_DEVICE_CHR &&
dev->data.chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
dev->data.chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_NONE &&
STRNEQ(def->os.type, "hvm"))
dev->data.chr->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN;
/* forbid capabilities mode hostdev in this kind of hypervisor */
if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV &&
dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("hostdev mode 'capabilities' is not "
"supported in %s"),
virDomainVirtTypeToString(def->virtType));
return -1;
}
maint: avoid 'const fooPtr' in domain_conf 'const fooPtr' is the same as 'foo * const' (the pointer won't change, but it's contents can). But in general, if an interface is trying to be const-correct, it should be using 'const foo *' (the pointer is to data that can't be changed). Fix up offenders in src/conf/domain_conf, and their fallout. Several things to note: virObjectLock() requires a non-const argument; if this were C++, we could treat the locking field as 'mutable' and allow locking an otherwise 'const' object, but that is a more invasive change, so I instead dropped attempts to be const-correct on domain lookup. virXMLPropString and friends require a non-const xmlNodePtr - this is because libxml2 is not a const-correct library. We could make the src/util/virxml wrappers cast away const, but I figured it was easier to not try to mark xmlNodePtr as const. Finally, virDomainDeviceDefCopy was a rather hard conversion - it calls virDomainDeviceDefPostParse, which in turn in the xen driver was actually modifying the domain outside of the current device being visited. We should not be adding a device on the first per-device callback, but waiting until after all per-device callbacks are complete. * src/conf/domain_conf.h (virDomainObjListFindByID) (virDomainObjListFindByUUID, virDomainObjListFindByName) (virDomainObjAssignDef, virDomainObjListAdd): Drop attempt at const. (virDomainDeviceDefCopy): Use intended type. (virDomainDeviceDefParse, virDomainDeviceDefPostParseCallback) (virDomainVideoDefaultType, virDomainVideoDefaultRAM) (virDomainChrGetDomainPtrs): Make const-correct. * src/conf/domain_conf.c (virDomainObjListFindByID) (virDomainObjListFindByUUID, virDomainObjListFindByName) (virDomainDeviceDefCopy, virDomainObjListAdd) (virDomainObjAssignDef, virDomainHostdevSubsysUsbDefParseXML) (virDomainHostdevSubsysPciOrigStatesDefParseXML) (virDomainHostdevSubsysPciDefParseXML) (virDomainHostdevSubsysScsiDefParseXML) (virDomainControllerModelTypeFromString) (virDomainTPMDefParseXML, virDomainTimerDefParseXML) (virDomainSoundCodecDefParseXML, virDomainSoundDefParseXML) (virDomainWatchdogDefParseXML, virDomainRNGDefParseXML) (virDomainMemballoonDefParseXML, virDomainNVRAMDefParseXML) (virSysinfoParseXML, virDomainVideoAccelDefParseXML) (virDomainVideoDefParseXML, virDomainHostdevDefParseXML) (virDomainRedirdevDefParseXML) (virDomainRedirFilterUsbDevDefParseXML) (virDomainRedirFilterDefParseXML, virDomainIdMapEntrySort) (virDomainIdmapDefParseXML, virDomainVcpuPinDefParseXML) (virDiskNameToBusDeviceIndex, virDomainDeviceDefCopy) (virDomainVideoDefaultType, virDomainHostdevAssignAddress) (virDomainDeviceDefPostParseInternal, virDomainDeviceDefPostParse) (virDomainChrGetDomainPtrs, virDomainControllerSCSINextUnit) (virDomainSCSIDriveAddressIsUsed) (virDomainDriveAddressIsUsedByDisk) (virDomainDriveAddressIsUsedByHostdev): Fix fallout. * src/openvz/openvz_driver.c (openvzDomainDeviceDefPostParse): Likewise. * src/libxl/libxl_domain.c (libxlDomainDeviceDefPostParse): Likewise. * src/qemu/qemu_domain.c (qemuDomainDeviceDefPostParse) (qemuDomainDefaultNetModel): Likewise. * src/lxc/lxc_domain.c (virLXCDomainDeviceDefPostParse): Likewise. * src/uml/uml_driver.c (umlDomainDeviceDefPostParse): Likewise. * src/xen/xen_driver.c (xenDomainDeviceDefPostParse): Split... (xenDomainDefPostParse): ...since per-device callback is not the time to be adding a device. Signed-off-by: Eric Blake <eblake@redhat.com>
2013-10-08 15:08:25 +00:00
return 0;
}
static int
xenDomainDefPostParse(virDomainDefPtr def,
virCapsPtr caps ATTRIBUTE_UNUSED,
void *opaque ATTRIBUTE_UNUSED)
{
if (!def->memballoon) {
virDomainMemballoonDefPtr memballoon;
if (VIR_ALLOC(memballoon) < 0)
return -1;
memballoon->model = VIR_DOMAIN_MEMBALLOON_MODEL_XEN;
def->memballoon = memballoon;
}
return 0;
}
virDomainDefParserConfig xenDomainDefParserConfig = {
.macPrefix = { 0x00, 0x16, 0x3e },
.devicesPostParseCallback = xenDomainDeviceDefPostParse,
maint: avoid 'const fooPtr' in domain_conf 'const fooPtr' is the same as 'foo * const' (the pointer won't change, but it's contents can). But in general, if an interface is trying to be const-correct, it should be using 'const foo *' (the pointer is to data that can't be changed). Fix up offenders in src/conf/domain_conf, and their fallout. Several things to note: virObjectLock() requires a non-const argument; if this were C++, we could treat the locking field as 'mutable' and allow locking an otherwise 'const' object, but that is a more invasive change, so I instead dropped attempts to be const-correct on domain lookup. virXMLPropString and friends require a non-const xmlNodePtr - this is because libxml2 is not a const-correct library. We could make the src/util/virxml wrappers cast away const, but I figured it was easier to not try to mark xmlNodePtr as const. Finally, virDomainDeviceDefCopy was a rather hard conversion - it calls virDomainDeviceDefPostParse, which in turn in the xen driver was actually modifying the domain outside of the current device being visited. We should not be adding a device on the first per-device callback, but waiting until after all per-device callbacks are complete. * src/conf/domain_conf.h (virDomainObjListFindByID) (virDomainObjListFindByUUID, virDomainObjListFindByName) (virDomainObjAssignDef, virDomainObjListAdd): Drop attempt at const. (virDomainDeviceDefCopy): Use intended type. (virDomainDeviceDefParse, virDomainDeviceDefPostParseCallback) (virDomainVideoDefaultType, virDomainVideoDefaultRAM) (virDomainChrGetDomainPtrs): Make const-correct. * src/conf/domain_conf.c (virDomainObjListFindByID) (virDomainObjListFindByUUID, virDomainObjListFindByName) (virDomainDeviceDefCopy, virDomainObjListAdd) (virDomainObjAssignDef, virDomainHostdevSubsysUsbDefParseXML) (virDomainHostdevSubsysPciOrigStatesDefParseXML) (virDomainHostdevSubsysPciDefParseXML) (virDomainHostdevSubsysScsiDefParseXML) (virDomainControllerModelTypeFromString) (virDomainTPMDefParseXML, virDomainTimerDefParseXML) (virDomainSoundCodecDefParseXML, virDomainSoundDefParseXML) (virDomainWatchdogDefParseXML, virDomainRNGDefParseXML) (virDomainMemballoonDefParseXML, virDomainNVRAMDefParseXML) (virSysinfoParseXML, virDomainVideoAccelDefParseXML) (virDomainVideoDefParseXML, virDomainHostdevDefParseXML) (virDomainRedirdevDefParseXML) (virDomainRedirFilterUsbDevDefParseXML) (virDomainRedirFilterDefParseXML, virDomainIdMapEntrySort) (virDomainIdmapDefParseXML, virDomainVcpuPinDefParseXML) (virDiskNameToBusDeviceIndex, virDomainDeviceDefCopy) (virDomainVideoDefaultType, virDomainHostdevAssignAddress) (virDomainDeviceDefPostParseInternal, virDomainDeviceDefPostParse) (virDomainChrGetDomainPtrs, virDomainControllerSCSINextUnit) (virDomainSCSIDriveAddressIsUsed) (virDomainDriveAddressIsUsedByDisk) (virDomainDriveAddressIsUsedByHostdev): Fix fallout. * src/openvz/openvz_driver.c (openvzDomainDeviceDefPostParse): Likewise. * src/libxl/libxl_domain.c (libxlDomainDeviceDefPostParse): Likewise. * src/qemu/qemu_domain.c (qemuDomainDeviceDefPostParse) (qemuDomainDefaultNetModel): Likewise. * src/lxc/lxc_domain.c (virLXCDomainDeviceDefPostParse): Likewise. * src/uml/uml_driver.c (umlDomainDeviceDefPostParse): Likewise. * src/xen/xen_driver.c (xenDomainDeviceDefPostParse): Split... (xenDomainDefPostParse): ...since per-device callback is not the time to be adding a device. Signed-off-by: Eric Blake <eblake@redhat.com>
2013-10-08 15:08:25 +00:00
.domainPostParseCallback = xenDomainDefPostParse,
};
virDomainXMLOptionPtr
xenDomainXMLConfInit(void)
{
return virDomainXMLOptionNew(&xenDomainDefParserConfig,
NULL, NULL);
}
static virDrvOpenStatus
xenUnifiedConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags)
{
xenUnifiedPrivatePtr priv;
char ebuf[1024];
2009-01-22 17:49:41 +00:00
/*
* Only the libvirtd instance can open this driver.
* Everything else falls back to the remote driver.
*/
if (!is_privileged)
2009-01-22 17:49:41 +00:00
return VIR_DRV_OPEN_DECLINED;
if (conn->uri == NULL) {
if (!xenUnifiedProbe())
return VIR_DRV_OPEN_DECLINED;
#ifdef WITH_LIBXL
/* Decline xen:// URI if xend is not running and libxenlight
* driver is potentially available. */
if (!xenUnifiedXendProbe())
return VIR_DRV_OPEN_DECLINED;
#endif
if (!(conn->uri = virURIParse("xen:///")))
return VIR_DRV_OPEN_ERROR;
} else {
if (conn->uri->scheme) {
/* Decline any scheme which isn't "xen://" or "http://". */
if (STRCASENEQ(conn->uri->scheme, "xen") &&
STRCASENEQ(conn->uri->scheme, "http"))
return VIR_DRV_OPEN_DECLINED;
#ifdef WITH_LIBXL
/* Decline xen:// URI if xend is not running and libxenlight
* driver is potentially available. */
if (!xenUnifiedXendProbe())
return VIR_DRV_OPEN_DECLINED;
#endif
/* Return an error if the path isn't '' or '/' */
if (conn->uri->path &&
STRNEQ(conn->uri->path, "") &&
STRNEQ(conn->uri->path, "/")) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("unexpected Xen URI path '%s', try xen:///"),
conn->uri->path);
return VIR_DRV_OPEN_ERROR;
}
/* Decline any xen:// URI with a server specified, allowing remote
* driver to handle, but keep any http:/// URIs */
if (STRCASEEQ(conn->uri->scheme, "xen") &&
conn->uri->server)
return VIR_DRV_OPEN_DECLINED;
} else {
return VIR_DRV_OPEN_DECLINED;
}
}
/* We now know the URI is definitely for this driver, so beyond
* here, don't return DECLINED, always use ERROR */
if (virConnectOpenEnsureACL(conn) < 0)
return VIR_DRV_OPEN_ERROR;
/* Allocate per-connection private data. */
if (VIR_ALLOC(priv) < 0)
return VIR_DRV_OPEN_ERROR;
2009-01-21 18:11:14 +00:00
if (virMutexInit(&priv->lock) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("cannot initialize mutex"));
2009-01-21 18:11:14 +00:00
VIR_FREE(priv);
return VIR_DRV_OPEN_ERROR;
}
if (!(priv->domainEvents = virObjectEventStateNew())) {
2009-01-21 18:11:14 +00:00
virMutexDestroy(&priv->lock);
VIR_FREE(priv);
return VIR_DRV_OPEN_ERROR;
}
2009-01-21 18:11:14 +00:00
conn->privateData = priv;
priv->handle = -1;
priv->xendConfigVersion = -1;
priv->xshandle = NULL;
/* Hypervisor required to succeed */
VIR_DEBUG("Trying hypervisor sub-driver");
if (xenHypervisorOpen(conn, auth, flags) < 0)
goto error;
VIR_DEBUG("Activated hypervisor sub-driver");
priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET] = 1;
/* XenD is required to succeed */
VIR_DEBUG("Trying XenD sub-driver");
if (xenDaemonOpen(conn, auth, flags) < 0)
goto error;
VIR_DEBUG("Activated XenD sub-driver");
priv->opened[XEN_UNIFIED_XEND_OFFSET] = 1;
/* For old XenD, the XM driver is required to succeed */
if (priv->xendConfigVersion <= XEND_CONFIG_VERSION_3_0_3) {
VIR_DEBUG("Trying XM sub-driver");
if (xenXMOpen(conn, auth, flags) < 0)
goto error;
VIR_DEBUG("Activated XM sub-driver");
priv->opened[XEN_UNIFIED_XM_OFFSET] = 1;
}
VIR_DEBUG("Trying XS sub-driver");
if (xenStoreOpen(conn, auth, flags) < 0)
goto error;
VIR_DEBUG("Activated XS sub-driver");
priv->opened[XEN_UNIFIED_XS_OFFSET] = 1;
2009-01-21 18:11:14 +00:00
xenNumaInit(conn);
2008-09-05 11:35:43 +00:00
if (!(priv->caps = xenHypervisorMakeCapabilities(conn))) {
VIR_DEBUG("Failed to make capabilities");
goto error;
}
if (!(priv->xmlopt = xenDomainXMLConfInit()))
goto error;
#if WITH_XEN_INOTIFY
VIR_DEBUG("Trying Xen inotify sub-driver");
if (xenInotifyOpen(conn, auth, flags) < 0)
goto error;
VIR_DEBUG("Activated Xen inotify sub-driver");
priv->opened[XEN_UNIFIED_INOTIFY_OFFSET] = 1;
#endif
if (VIR_STRDUP(priv->saveDir, XEN_SAVE_DIR) < 0)
goto error;
if (virFileMakePath(priv->saveDir) < 0) {
VIR_ERROR(_("Errored to create save dir '%s': %s"), priv->saveDir,
virStrerror(errno, ebuf, sizeof(ebuf)));
goto error;
}
return VIR_DRV_OPEN_SUCCESS;
error:
VIR_DEBUG("Failed to activate a mandatory sub-driver");
#if WITH_XEN_INOTIFY
if (priv->opened[XEN_UNIFIED_INOTIFY_OFFSET])
xenInotifyClose(conn);
#endif
if (priv->opened[XEN_UNIFIED_XM_OFFSET])
xenXMClose(conn);
if (priv->opened[XEN_UNIFIED_XS_OFFSET])
xenStoreClose(conn);
if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
xenDaemonClose(conn);
if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET])
xenHypervisorClose(conn);
2009-01-21 18:11:14 +00:00
virMutexDestroy(&priv->lock);
VIR_FREE(priv->saveDir);
VIR_FREE(priv);
2009-01-21 18:11:14 +00:00
conn->privateData = NULL;
return VIR_DRV_OPEN_ERROR;
}
static int
xenUnifiedConnectClose(virConnectPtr conn)
{
xenUnifiedPrivatePtr priv = conn->privateData;
virObjectUnref(priv->caps);
virObjectUnref(priv->xmlopt);
virObjectEventStateFree(priv->domainEvents);
#if WITH_XEN_INOTIFY
if (priv->opened[XEN_UNIFIED_INOTIFY_OFFSET])
xenInotifyClose(conn);
#endif
if (priv->opened[XEN_UNIFIED_XM_OFFSET])
xenXMClose(conn);
if (priv->opened[XEN_UNIFIED_XS_OFFSET])
xenStoreClose(conn);
if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
xenDaemonClose(conn);
if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET])
xenHypervisorClose(conn);
VIR_FREE(priv->saveDir);
2009-01-21 18:11:14 +00:00
virMutexDestroy(&priv->lock);
VIR_FREE(conn->privateData);
return 0;
}
#define HV_VERSION ((DOM0_INTERFACE_VERSION >> 24) * 1000000 + \
((DOM0_INTERFACE_VERSION >> 16) & 0xFF) * 1000 + \
(DOM0_INTERFACE_VERSION & 0xFFFF))
unsigned long xenUnifiedVersion(void)
{
return HV_VERSION;
}
static const char *
xenUnifiedConnectGetType(virConnectPtr conn)
{
if (virConnectGetTypeEnsureACL(conn) < 0)
return NULL;
return "Xen";
}
/* Which features are supported by this driver? */
static int
xenUnifiedConnectSupportsFeature(virConnectPtr conn, int feature)
{
if (virConnectSupportsFeatureEnsureACL(conn) < 0)
return -1;
switch (feature) {
Support a new peer-to-peer migration mode & public API Introduces several new public API options for migration - VIR_MIGRATE_PEER2PEER: With this flag the client only invokes the virDomainMigratePerform method, expecting the source host driver to do whatever is required to complete the entire migration process. - VIR_MIGRATE_TUNNELLED: With this flag the actual data for migration will be tunnelled over the libvirtd RPC channel. This requires that VIR_MIGRATE_PEER2PEER is also set. - virDomainMigrateToURI: This is variant of the existing virDomainMigrate method which does not require any virConnectPtr for the destination host. Given suitable driver support, this allows for all the same modes as virDomainMigrate() The URI for VIR_MIGRATE_PEER2PEER must be a valid libvirt URI. For non-p2p migration a hypervisor specific migration URI is used. virDomainMigrateToURI without a PEER2PEER flag is only support for Xen currently, and it involves XenD talking directly to XenD, no libvirtd involved at all. * include/libvirt/libvirt.h.in: Add VIR_MIGRATE_PEER2PEER flag for migration * src/libvirt_internal.h: Add feature flags for peer to peer migration (VIR_FEATURE_MIGRATE_P2P) and direct migration (VIR_MIGRATE_PEER2PEER mode) * src/libvirt.c: Implement support for VIR_MIGRATE_PEER2PEER and virDomainMigrateToURI APIs. * src/xen/xen_driver.c: Advertise support for DIRECT migration * src/xen/xend_internal.c: Add TODO item for p2p migration * src/libvirt_public.syms: Export virDomainMigrateToURI method * src/qemu/qemu_driver.c: Add support for PEER2PEER and migration, and adapt TUNNELLED migration. * tools/virsh.c: Add --p2p and --direct args and use the new virDomainMigrateToURI method where possible.
2009-09-17 17:10:04 +00:00
case VIR_DRV_FEATURE_MIGRATION_V1:
case VIR_DRV_FEATURE_MIGRATION_DIRECT:
return 1;
default:
return 0;
}
}
static int
xenUnifiedConnectGetVersion(virConnectPtr conn, unsigned long *hvVer)
{
if (virConnectGetVersionEnsureACL(conn) < 0)
return -1;
return xenHypervisorGetVersion(conn, hvVer);
}
static char *xenUnifiedConnectGetHostname(virConnectPtr conn)
{
if (virConnectGetHostnameEnsureACL(conn) < 0)
return NULL;
return virGetHostname();
}
static char *
xenUnifiedConnectGetSysinfo(virConnectPtr conn ATTRIBUTE_UNUSED,
unsigned int flags)
{
virBuffer buf = VIR_BUFFER_INITIALIZER;
virCheckFlags(0, NULL);
if (virConnectGetSysinfoEnsureACL(conn) < 0)
return NULL;
if (!hostsysinfo) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("Host SMBIOS information is not available"));
return NULL;
}
if (virSysinfoFormat(&buf, hostsysinfo) < 0)
return NULL;
if (virBufferCheckError(&buf) < 0)
return NULL;
return virBufferContentAndReset(&buf);
}
static int
xenUnifiedConnectIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
{
return 0;
}
static int
xenUnifiedConnectIsSecure(virConnectPtr conn)
{
xenUnifiedPrivatePtr priv = conn->privateData;
int ret = 1;
/* All drivers are secure, except for XenD over TCP */
if (priv->opened[XEN_UNIFIED_XEND_OFFSET] &&
priv->addrfamily != AF_UNIX)
ret = 0;
return ret;
}
static int
xenUnifiedConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
{
/* XenD reconnects for each request */
return 1;
}
int
xenUnifiedConnectGetMaxVcpus(virConnectPtr conn, const char *type)
{
if (virConnectGetMaxVcpusEnsureACL(conn) < 0)
return -1;
if (type && STRCASENEQ(type, "Xen")) {
virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
return -1;
}
return xenHypervisorGetMaxVcpus(conn, type);
}
static int
xenUnifiedNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info)
{
if (virNodeGetInfoEnsureACL(conn) < 0)
return -1;
return xenDaemonNodeGetInfo(conn, info);
}
static char *
xenUnifiedConnectGetCapabilities(virConnectPtr conn)
{
2009-01-21 18:11:14 +00:00
xenUnifiedPrivatePtr priv = conn->privateData;
if (virConnectGetCapabilitiesEnsureACL(conn) < 0)
return NULL;
return virCapabilitiesFormatXML(priv->caps);
}
static int
xenUnifiedConnectListDomains(virConnectPtr conn, int *ids, int maxids)
{
if (virConnectListDomainsEnsureACL(conn) < 0)
return -1;
return xenStoreListDomains(conn, ids, maxids);
}
static int
xenUnifiedConnectNumOfDomains(virConnectPtr conn)
{
if (virConnectNumOfDomainsEnsureACL(conn) < 0)
return -1;
return xenStoreNumOfDomains(conn);
}
static virDomainPtr
xenUnifiedDomainCreateXML(virConnectPtr conn,
const char *xml,
unsigned int flags)
{
xenUnifiedPrivatePtr priv = conn->privateData;
virDomainDefPtr def = NULL;
virDomainPtr ret = NULL;
virCheckFlags(0, NULL);
if (!(def = virDomainDefParseString(xml, priv->caps, priv->xmlopt,
1 << VIR_DOMAIN_VIRT_XEN,
VIR_DOMAIN_XML_INACTIVE)))
goto cleanup;
if (virDomainCreateXMLEnsureACL(conn, def) < 0)
goto cleanup;
if (xenDaemonCreateXML(conn, def) < 0)
goto cleanup;
ret = virGetDomain(conn, def->name, def->uuid);
if (ret)
ret->id = def->id;
cleanup:
virDomainDefFree(def);
return ret;
}
static virDomainPtr
xenUnifiedDomainLookupByID(virConnectPtr conn, int id)
{
virDomainPtr ret = NULL;
virDomainDefPtr def = NULL;
if (!(def = xenGetDomainDefForID(conn, id)))
goto cleanup;
if (virDomainLookupByIDEnsureACL(conn, def) < 0)
goto cleanup;
if (!(ret = virGetDomain(conn, def->name, def->uuid)))
goto cleanup;
ret->id = def->id;
cleanup:
virDomainDefFree(def);
return ret;
}
static virDomainPtr
xenUnifiedDomainLookupByUUID(virConnectPtr conn,
const unsigned char *uuid)
{
virDomainPtr ret = NULL;
virDomainDefPtr def = NULL;
if (!(def = xenGetDomainDefForUUID(conn, uuid)))
goto cleanup;
if (virDomainLookupByUUIDEnsureACL(conn, def) < 0)
goto cleanup;
if (!(ret = virGetDomain(conn, def->name, def->uuid)))
goto cleanup;
ret->id = def->id;
cleanup:
virDomainDefFree(def);
return ret;
}
static virDomainPtr
xenUnifiedDomainLookupByName(virConnectPtr conn,
const char *name)
{
virDomainPtr ret = NULL;
virDomainDefPtr def = NULL;
if (!(def = xenGetDomainDefForName(conn, name)))
goto cleanup;
if (virDomainLookupByNameEnsureACL(conn, def) < 0)
goto cleanup;
if (!(ret = virGetDomain(conn, def->name, def->uuid)))
goto cleanup;
ret->id = def->id;
cleanup:
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedDomainIsActive(virDomainPtr dom)
{
virDomainDefPtr def;
int ret = -1;
if (!(def = xenGetDomainDefForUUID(dom->conn, dom->uuid)))
goto cleanup;
ret = def->id == -1 ? 0 : 1;
cleanup:
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedDomainIsPersistent(virDomainPtr dom)
{
xenUnifiedPrivatePtr priv = dom->conn->privateData;
virDomainDefPtr def = NULL;
int ret = -1;
if (priv->opened[XEN_UNIFIED_XM_OFFSET]) {
/* Old Xen, pre-inactive domain management.
* If the XM driver can see the guest, it is definitely persistent */
def = xenXMDomainLookupByUUID(dom->conn, dom->uuid);
if (def)
ret = 1;
else
ret = 0;
} else {
/* New Xen with inactive domain management */
def = xenDaemonLookupByUUID(dom->conn, dom->uuid);
if (def) {
if (def->id == -1) {
/* If its inactive, then trivially, it must be persistent */
ret = 1;
} else {
char *path;
char uuidstr[VIR_UUID_STRING_BUFLEN];
/* If its running there's no official way to tell, so we
* go behind xend's back & look at the config dir */
virUUIDFormat(dom->uuid, uuidstr);
if (virAsprintf(&path, "%s/%s", XEND_DOMAINS_DIR, uuidstr) < 0)
goto cleanup;
if (access(path, R_OK) == 0)
ret = 1;
else if (errno == ENOENT)
ret = 0;
}
}
}
cleanup:
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedDomainIsUpdated(virDomainPtr dom ATTRIBUTE_UNUSED)
{
return 0;
}
static int
xenUnifiedDomainSuspend(virDomainPtr dom)
{
int ret = -1;
virDomainDefPtr def;
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainSuspendEnsureACL(dom->conn, def) < 0)
goto cleanup;
ret = xenDaemonDomainSuspend(dom->conn, def);
cleanup:
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedDomainResume(virDomainPtr dom)
{
int ret = -1;
virDomainDefPtr def;
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainResumeEnsureACL(dom->conn, def) < 0)
goto cleanup;
ret = xenDaemonDomainResume(dom->conn, def);
cleanup:
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedDomainShutdownFlags(virDomainPtr dom,
unsigned int flags)
{
int ret = -1;
virDomainDefPtr def;
virCheckFlags(0, -1);
if (!(def = xenGetDomainDefForDom(dom)))
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 17:37:29 +00:00
if (virDomainShutdownFlagsEnsureACL(dom->conn, def, flags) < 0)
goto cleanup;
ret = xenDaemonDomainShutdown(dom->conn, def);
cleanup:
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedDomainShutdown(virDomainPtr dom)
{
return xenUnifiedDomainShutdownFlags(dom, 0);
}
static int
xenUnifiedDomainReboot(virDomainPtr dom, unsigned int flags)
{
int ret = -1;
virDomainDefPtr def;
virCheckFlags(0, -1);
if (!(def = xenGetDomainDefForDom(dom)))
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 17:37:29 +00:00
if (virDomainRebootEnsureACL(dom->conn, def, flags) < 0)
goto cleanup;
ret = xenDaemonDomainReboot(dom->conn, def);
cleanup:
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedDomainDestroyFlags(virDomainPtr dom,
unsigned int flags)
{
int ret = -1;
virDomainDefPtr def;
virCheckFlags(0, -1);
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainDestroyFlagsEnsureACL(dom->conn, def) < 0)
goto cleanup;
ret = xenDaemonDomainDestroy(dom->conn, def);
cleanup:
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedDomainDestroy(virDomainPtr dom)
{
return xenUnifiedDomainDestroyFlags(dom, 0);
}
static char *
xenUnifiedDomainGetOSType(virDomainPtr dom)
{
xenUnifiedPrivatePtr priv = dom->conn->privateData;
char *ret = NULL;
virDomainDefPtr def;
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainGetOSTypeEnsureACL(dom->conn, def) < 0)
goto cleanup;
if (def->id < 0) {
if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Unable to query OS type for inactive domain"));
return NULL;
} else {
ret = xenDaemonDomainGetOSType(dom->conn, def);
}
} else {
ret = xenHypervisorDomainGetOSType(dom->conn, def);
}
cleanup:
virDomainDefFree(def);
return ret;
}
xml: use long long internally, to centralize overflow checks On 64-bit platforms, unsigned long and unsigned long long are identical, so we don't have to worry about overflow checks. On 32-bit platforms, anywhere we narrow unsigned long long back to unsigned long, we have to worry about overflow; it's easier to do this in one place by having most of the code use the same or wider types, and only doing the narrowing at the last minute. Therefore, the memory set commands remain unsigned long, and the memory get command now centralizes the overflow check into libvirt.c, so that drivers don't have to repeat the work. This also fixes a bug where xen returned the wrong value on failure (most APIs return -1 on failure, but getMaxMemory must return 0 on failure). * src/driver.h (virDrvDomainGetMaxMemory): Use long long. * src/libvirt.c (virDomainGetMaxMemory): Raise overflow. * src/test/test_driver.c (testGetMaxMemory): Fix driver. * src/rpc/gendispatch.pl (name_to_ProcName): Likewise. * src/xen/xen_hypervisor.c (xenHypervisorGetMaxMemory): Likewise. * src/xen/xen_driver.c (xenUnifiedDomainGetMaxMemory): Likewise. * src/xen/xend_internal.c (xenDaemonDomainGetMaxMemory): Likewise. * src/xen/xend_internal.h (xenDaemonDomainGetMaxMemory): Likewise. * src/xen/xm_internal.c (xenXMDomainGetMaxMemory): Likewise. * src/xen/xm_internal.h (xenXMDomainGetMaxMemory): Likewise. * src/xen/xs_internal.c (xenStoreDomainGetMaxMemory): Likewise. * src/xen/xs_internal.h (xenStoreDomainGetMaxMemory): Likewise. * src/xenapi/xenapi_driver.c (xenapiDomainGetMaxMemory): Likewise. * src/esx/esx_driver.c (esxDomainGetMaxMemory): Likewise. * src/libxl/libxl_driver.c (libxlDomainGetMaxMemory): Likewise. * src/qemu/qemu_driver.c (qemudDomainGetMaxMemory): Likewise. * src/lxc/lxc_driver.c (lxcDomainGetMaxMemory): Likewise. * src/uml/uml_driver.c (umlDomainGetMaxMemory): Likewise.
2012-03-03 00:47:16 +00:00
static unsigned long long
xenUnifiedDomainGetMaxMemory(virDomainPtr dom)
{
xenUnifiedPrivatePtr priv = dom->conn->privateData;
unsigned long long ret = 0;
virDomainDefPtr def;
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainGetMaxMemoryEnsureACL(dom->conn, def) < 0)
goto cleanup;
if (def->id < 0) {
if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
ret = xenXMDomainGetMaxMemory(dom->conn, def);
else
ret = xenDaemonDomainGetMaxMemory(dom->conn, def);
} else {
ret = xenHypervisorGetMaxMemory(dom->conn, def);
}
cleanup:
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedDomainSetMaxMemory(virDomainPtr dom, unsigned long memory)
{
xenUnifiedPrivatePtr priv = dom->conn->privateData;
int ret = -1;
virDomainDefPtr def;
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainSetMaxMemoryEnsureACL(dom->conn, def) < 0)
goto cleanup;
if (def->id < 0) {
if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
ret = xenXMDomainSetMaxMemory(dom->conn, def, memory);
else
ret = xenDaemonDomainSetMaxMemory(dom->conn, def, memory);
} else {
ret = xenHypervisorSetMaxMemory(dom->conn, def, memory);
}
cleanup:
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedDomainSetMemory(virDomainPtr dom, unsigned long memory)
{
xenUnifiedPrivatePtr priv = dom->conn->privateData;
int ret = -1;
virDomainDefPtr def;
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainSetMemoryEnsureACL(dom->conn, def) < 0)
goto cleanup;
if (def->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
ret = xenXMDomainSetMemory(dom->conn, def, memory);
else
ret = xenDaemonDomainSetMemory(dom->conn, def, memory);
cleanup:
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
{
xenUnifiedPrivatePtr priv = dom->conn->privateData;
int ret = -1;
virDomainDefPtr def;
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainGetInfoEnsureACL(dom->conn, def) < 0)
goto cleanup;
if (def->id < 0) {
if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
ret = xenXMDomainGetInfo(dom->conn, def, info);
else
ret = xenDaemonDomainGetInfo(dom->conn, def, info);
} else {
ret = xenHypervisorGetDomainInfo(dom->conn, def, info);
}
cleanup:
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedDomainGetState(virDomainPtr dom,
int *state,
int *reason,
unsigned int flags)
{
xenUnifiedPrivatePtr priv = dom->conn->privateData;
int ret = -1;
virDomainDefPtr def;
virCheckFlags(0, -1);
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainGetStateEnsureACL(dom->conn, def) < 0)
goto cleanup;
if (def->id < 0) {
if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
ret = xenXMDomainGetState(dom->conn, def, state, reason);
else
ret = xenDaemonDomainGetState(dom->conn, def, state, reason);
} else {
ret = xenHypervisorGetDomainState(dom->conn, def, state, reason);
}
cleanup:
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedDomainSaveFlags(virDomainPtr dom, const char *to, const char *dxml,
unsigned int flags)
{
int ret = -1;
virDomainDefPtr def;
virCheckFlags(0, -1);
if (dxml) {
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
_("xml modification unsupported"));
return -1;
}
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainSaveFlagsEnsureACL(dom->conn, def) < 0)
goto cleanup;
ret = xenDaemonDomainSave(dom->conn, def, to);
cleanup:
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedDomainSave(virDomainPtr dom, const char *to)
{
return xenUnifiedDomainSaveFlags(dom, to, NULL, 0);
}
static char *
xenUnifiedDomainManagedSavePath(xenUnifiedPrivatePtr priv,
virDomainDefPtr def)
{
char *ret;
if (virAsprintf(&ret, "%s/%s.save", priv->saveDir, def->name) < 0)
return NULL;
VIR_DEBUG("managed save image: %s", ret);
return ret;
}
static int
xenUnifiedDomainManagedSave(virDomainPtr dom, unsigned int flags)
{
xenUnifiedPrivatePtr priv = dom->conn->privateData;
char *name = NULL;
virDomainDefPtr def = NULL;
int ret = -1;
virCheckFlags(0, -1);
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainManagedSaveEnsureACL(dom->conn, def) < 0)
goto cleanup;
if (!(name = xenUnifiedDomainManagedSavePath(priv, def)))
goto cleanup;
ret = xenDaemonDomainSave(dom->conn, def, name);
cleanup:
VIR_FREE(name);
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
{
xenUnifiedPrivatePtr priv = dom->conn->privateData;
char *name = NULL;
virDomainDefPtr def = NULL;
int ret = -1;
virCheckFlags(0, -1);
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainHasManagedSaveImageEnsureACL(dom->conn, def) < 0)
goto cleanup;
if (!(name = xenUnifiedDomainManagedSavePath(priv, def)))
goto cleanup;
ret = virFileExists(name);
cleanup:
VIR_FREE(name);
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedDomainManagedSaveRemove(virDomainPtr dom, unsigned int flags)
{
xenUnifiedPrivatePtr priv = dom->conn->privateData;
char *name = NULL;
virDomainDefPtr def = NULL;
int ret = -1;
virCheckFlags(0, -1);
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainManagedSaveRemoveEnsureACL(dom->conn, def) < 0)
goto cleanup;
if (!(name = xenUnifiedDomainManagedSavePath(priv, def)))
goto cleanup;
ret = unlink(name);
cleanup:
VIR_FREE(name);
return ret;
}
static int
xenUnifiedDomainRestoreFlags(virConnectPtr conn, const char *from,
const char *dxml, unsigned int flags)
{
virCheckFlags(0, -1);
if (dxml) {
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
_("xml modification unsupported"));
return -1;
}
return xenDaemonDomainRestore(conn, from);
}
static int
xenUnifiedDomainRestore(virConnectPtr conn, const char *from)
{
return xenUnifiedDomainRestoreFlags(conn, from, NULL, 0);
}
static int
xenUnifiedDomainCoreDump(virDomainPtr dom, const char *to, unsigned int flags)
{
virDomainDefPtr def = NULL;
int ret = -1;
virCheckFlags(0, -1);
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainCoreDumpEnsureACL(dom->conn, def) < 0)
goto cleanup;
ret = xenDaemonDomainCoreDump(dom->conn, def, to, flags);
cleanup:
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
unsigned int flags)
{
xenUnifiedPrivatePtr priv = dom->conn->privateData;
virDomainDefPtr def = NULL;
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)) {
virReportError(VIR_ERR_INVALID_ARG,
_("invalid flag combination: (0x%x)"), flags);
return -1;
}
if (!nvcpus || (unsigned short) nvcpus != nvcpus) {
virReportError(VIR_ERR_INVALID_ARG,
_("argument out of range: %d"), nvcpus);
vcpu: make old API trivially wrap to new API Note - this wrapping is completely mechanical; the old API will function identically, since the new API validates that the exact same flags are provided by the old API. On a per-driver basis, it may make sense to have the old API pass a different set of flags, but that should be done in the per-driver patch that implements the full range of flag support in the new API. * src/esx/esx_driver.c (esxDomainSetVcpus, escDomainGetMaxVpcus): Move guts... (esxDomainSetVcpusFlags, esxDomainGetVcpusFlags): ...to new functions. (esxDriver): Trivially support the new API. * src/openvz/openvz_driver.c (openvzDomainSetVcpus) (openvzDomainSetVcpusFlags, openvzDomainGetMaxVcpus) (openvzDomainGetVcpusFlags, openvzDriver): Likewise. * src/phyp/phyp_driver.c (phypDomainSetCPU) (phypDomainSetVcpusFlags, phypGetLparCPUMAX) (phypDomainGetVcpusFlags, phypDriver): Likewise. * src/qemu/qemu_driver.c (qemudDomainSetVcpus) (qemudDomainSetVcpusFlags, qemudDomainGetMaxVcpus) (qemudDomainGetVcpusFlags, qemuDriver): Likewise. * src/test/test_driver.c (testSetVcpus, testDomainSetVcpusFlags) (testDomainGetMaxVcpus, testDomainGetVcpusFlags, testDriver): Likewise. * src/vbox/vbox_tmpl.c (vboxDomainSetVcpus) (vboxDomainSetVcpusFlags, virDomainGetMaxVcpus) (virDomainGetVcpusFlags, virDriver): Likewise. * src/xen/xen_driver.c (xenUnifiedDomainSetVcpus) (xenUnifiedDomainSetVcpusFlags, xenUnifiedDomainGetMaxVcpus) (xenUnifiedDomainGetVcpusFlags, xenUnifiedDriver): Likewise. * src/xenapi/xenapi_driver.c (xenapiDomainSetVcpus) (xenapiDomainSetVcpusFlags, xenapiDomainGetMaxVcpus) (xenapiDomainGetVcpusFlags, xenapiDriver): Likewise. (xenapiError): New helper macro.
2010-09-27 22:37:53 +00:00
return -1;
}
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainSetVcpusFlagsEnsureACL(dom->conn, def, flags) < 0)
goto cleanup;
/* Try non-hypervisor methods first, then hypervisor direct method
* as a last resort.
*/
if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
ret = xenXMDomainSetVcpusFlags(dom->conn, def, nvcpus, flags);
else
ret = xenDaemonDomainSetVcpusFlags(dom->conn, def, nvcpus, flags);
cleanup:
virDomainDefFree(def);
return ret;
}
vcpu: make old API trivially wrap to new API Note - this wrapping is completely mechanical; the old API will function identically, since the new API validates that the exact same flags are provided by the old API. On a per-driver basis, it may make sense to have the old API pass a different set of flags, but that should be done in the per-driver patch that implements the full range of flag support in the new API. * src/esx/esx_driver.c (esxDomainSetVcpus, escDomainGetMaxVpcus): Move guts... (esxDomainSetVcpusFlags, esxDomainGetVcpusFlags): ...to new functions. (esxDriver): Trivially support the new API. * src/openvz/openvz_driver.c (openvzDomainSetVcpus) (openvzDomainSetVcpusFlags, openvzDomainGetMaxVcpus) (openvzDomainGetVcpusFlags, openvzDriver): Likewise. * src/phyp/phyp_driver.c (phypDomainSetCPU) (phypDomainSetVcpusFlags, phypGetLparCPUMAX) (phypDomainGetVcpusFlags, phypDriver): Likewise. * src/qemu/qemu_driver.c (qemudDomainSetVcpus) (qemudDomainSetVcpusFlags, qemudDomainGetMaxVcpus) (qemudDomainGetVcpusFlags, qemuDriver): Likewise. * src/test/test_driver.c (testSetVcpus, testDomainSetVcpusFlags) (testDomainGetMaxVcpus, testDomainGetVcpusFlags, testDriver): Likewise. * src/vbox/vbox_tmpl.c (vboxDomainSetVcpus) (vboxDomainSetVcpusFlags, virDomainGetMaxVcpus) (virDomainGetVcpusFlags, virDriver): Likewise. * src/xen/xen_driver.c (xenUnifiedDomainSetVcpus) (xenUnifiedDomainSetVcpusFlags, xenUnifiedDomainGetMaxVcpus) (xenUnifiedDomainGetVcpusFlags, xenUnifiedDriver): Likewise. * src/xenapi/xenapi_driver.c (xenapiDomainSetVcpus) (xenapiDomainSetVcpusFlags, xenapiDomainGetMaxVcpus) (xenapiDomainGetVcpusFlags, xenapiDriver): Likewise. (xenapiError): New helper macro.
2010-09-27 22:37:53 +00:00
static int
xenUnifiedDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus)
vcpu: make old API trivially wrap to new API Note - this wrapping is completely mechanical; the old API will function identically, since the new API validates that the exact same flags are provided by the old API. On a per-driver basis, it may make sense to have the old API pass a different set of flags, but that should be done in the per-driver patch that implements the full range of flag support in the new API. * src/esx/esx_driver.c (esxDomainSetVcpus, escDomainGetMaxVpcus): Move guts... (esxDomainSetVcpusFlags, esxDomainGetVcpusFlags): ...to new functions. (esxDriver): Trivially support the new API. * src/openvz/openvz_driver.c (openvzDomainSetVcpus) (openvzDomainSetVcpusFlags, openvzDomainGetMaxVcpus) (openvzDomainGetVcpusFlags, openvzDriver): Likewise. * src/phyp/phyp_driver.c (phypDomainSetCPU) (phypDomainSetVcpusFlags, phypGetLparCPUMAX) (phypDomainGetVcpusFlags, phypDriver): Likewise. * src/qemu/qemu_driver.c (qemudDomainSetVcpus) (qemudDomainSetVcpusFlags, qemudDomainGetMaxVcpus) (qemudDomainGetVcpusFlags, qemuDriver): Likewise. * src/test/test_driver.c (testSetVcpus, testDomainSetVcpusFlags) (testDomainGetMaxVcpus, testDomainGetVcpusFlags, testDriver): Likewise. * src/vbox/vbox_tmpl.c (vboxDomainSetVcpus) (vboxDomainSetVcpusFlags, virDomainGetMaxVcpus) (virDomainGetVcpusFlags, virDriver): Likewise. * src/xen/xen_driver.c (xenUnifiedDomainSetVcpus) (xenUnifiedDomainSetVcpusFlags, xenUnifiedDomainGetMaxVcpus) (xenUnifiedDomainGetVcpusFlags, xenUnifiedDriver): Likewise. * src/xenapi/xenapi_driver.c (xenapiDomainSetVcpus) (xenapiDomainSetVcpusFlags, xenapiDomainGetMaxVcpus) (xenapiDomainGetVcpusFlags, xenapiDriver): Likewise. (xenapiError): New helper macro.
2010-09-27 22:37:53 +00:00
{
xenUnifiedPrivatePtr priv = dom->conn->privateData;
unsigned int flags = VIR_DOMAIN_VCPU_LIVE;
/* Per the documented API, it is hypervisor-dependent whether this
* affects just _LIVE or _LIVE|_CONFIG; in xen's case, that
* depends on xendConfigVersion. */
if (priv->xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4)
flags |= VIR_DOMAIN_VCPU_CONFIG;
return xenUnifiedDomainSetVcpusFlags(dom, nvcpus, flags);
vcpu: make old API trivially wrap to new API Note - this wrapping is completely mechanical; the old API will function identically, since the new API validates that the exact same flags are provided by the old API. On a per-driver basis, it may make sense to have the old API pass a different set of flags, but that should be done in the per-driver patch that implements the full range of flag support in the new API. * src/esx/esx_driver.c (esxDomainSetVcpus, escDomainGetMaxVpcus): Move guts... (esxDomainSetVcpusFlags, esxDomainGetVcpusFlags): ...to new functions. (esxDriver): Trivially support the new API. * src/openvz/openvz_driver.c (openvzDomainSetVcpus) (openvzDomainSetVcpusFlags, openvzDomainGetMaxVcpus) (openvzDomainGetVcpusFlags, openvzDriver): Likewise. * src/phyp/phyp_driver.c (phypDomainSetCPU) (phypDomainSetVcpusFlags, phypGetLparCPUMAX) (phypDomainGetVcpusFlags, phypDriver): Likewise. * src/qemu/qemu_driver.c (qemudDomainSetVcpus) (qemudDomainSetVcpusFlags, qemudDomainGetMaxVcpus) (qemudDomainGetVcpusFlags, qemuDriver): Likewise. * src/test/test_driver.c (testSetVcpus, testDomainSetVcpusFlags) (testDomainGetMaxVcpus, testDomainGetVcpusFlags, testDriver): Likewise. * src/vbox/vbox_tmpl.c (vboxDomainSetVcpus) (vboxDomainSetVcpusFlags, virDomainGetMaxVcpus) (virDomainGetVcpusFlags, virDriver): Likewise. * src/xen/xen_driver.c (xenUnifiedDomainSetVcpus) (xenUnifiedDomainSetVcpusFlags, xenUnifiedDomainGetMaxVcpus) (xenUnifiedDomainGetVcpusFlags, xenUnifiedDriver): Likewise. * src/xenapi/xenapi_driver.c (xenapiDomainSetVcpus) (xenapiDomainSetVcpusFlags, xenapiDomainGetMaxVcpus) (xenapiDomainGetVcpusFlags, xenapiDriver): Likewise. (xenapiError): New helper macro.
2010-09-27 22:37:53 +00:00
}
static int
xenUnifiedDomainPinVcpu(virDomainPtr dom, unsigned int vcpu,
unsigned char *cpumap, int maplen)
{
xenUnifiedPrivatePtr priv = dom->conn->privateData;
virDomainDefPtr def = NULL;
int ret = -1;
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainPinVcpuEnsureACL(dom->conn, def) < 0)
goto cleanup;
if (dom->id < 0) {
if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
ret = xenXMDomainPinVcpu(dom->conn, def, vcpu, cpumap, maplen);
else
ret = xenDaemonDomainPinVcpu(dom->conn, def, vcpu, cpumap, maplen);
} else {
ret = xenHypervisorPinVcpu(dom->conn, def, vcpu, cpumap, maplen);
}
cleanup:
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedDomainGetVcpusInternal(virDomainPtr dom,
virDomainDefPtr def,
virVcpuInfoPtr info,
int maxinfo,
unsigned char *cpumaps,
int maplen)
{
xenUnifiedPrivatePtr priv = dom->conn->privateData;
int ret = -1;
if (dom->id < 0) {
if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Cannot get VCPUs of inactive domain"));
} else {
ret = xenDaemonDomainGetVcpus(dom->conn, def, info, maxinfo,
cpumaps, maplen);
}
} else {
ret = xenHypervisorGetVcpus(dom->conn, def, info, maxinfo, cpumaps,
maplen);
}
return ret;
}
static int
xenUnifiedDomainGetVcpus(virDomainPtr dom,
virVcpuInfoPtr info, int maxinfo,
unsigned char *cpumaps, int maplen)
{
virDomainDefPtr def = NULL;
int ret = -1;
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainGetVcpusEnsureACL(dom->conn, def) < 0)
goto cleanup;
ret = xenUnifiedDomainGetVcpusInternal(dom, def, info, maxinfo, cpumaps,
maplen);
cleanup:
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedDomainGetVcpusFlagsInternal(virDomainPtr dom,
virDomainDefPtr def,
unsigned int flags)
{
xenUnifiedPrivatePtr priv = dom->conn->privateData;
int ret = -1;
if (dom->id < 0) {
if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
ret = xenXMDomainGetVcpusFlags(dom->conn, def, flags);
else
ret = xenDaemonDomainGetVcpusFlags(dom->conn, def, flags);
} else {
if (flags == (VIR_DOMAIN_VCPU_CONFIG | VIR_DOMAIN_VCPU_MAXIMUM))
ret = xenHypervisorGetVcpuMax(dom->conn, def);
else
ret = xenDaemonDomainGetVcpusFlags(dom->conn, def, flags);
}
return ret;
}
static int
xenUnifiedDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
{
virDomainDefPtr def = NULL;
int ret = -1;
virCheckFlags(VIR_DOMAIN_VCPU_LIVE |
VIR_DOMAIN_VCPU_CONFIG |
VIR_DOMAIN_VCPU_MAXIMUM, -1);
if (!(def = xenGetDomainDefForDom(dom)))
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 17:37:29 +00:00
if (virDomainGetVcpusFlagsEnsureACL(dom->conn, def, flags) < 0)
goto cleanup;
ret = xenUnifiedDomainGetVcpusFlagsInternal(dom, def, flags);
cleanup:
virDomainDefFree(def);
return ret;
}
vcpu: make old API trivially wrap to new API Note - this wrapping is completely mechanical; the old API will function identically, since the new API validates that the exact same flags are provided by the old API. On a per-driver basis, it may make sense to have the old API pass a different set of flags, but that should be done in the per-driver patch that implements the full range of flag support in the new API. * src/esx/esx_driver.c (esxDomainSetVcpus, escDomainGetMaxVpcus): Move guts... (esxDomainSetVcpusFlags, esxDomainGetVcpusFlags): ...to new functions. (esxDriver): Trivially support the new API. * src/openvz/openvz_driver.c (openvzDomainSetVcpus) (openvzDomainSetVcpusFlags, openvzDomainGetMaxVcpus) (openvzDomainGetVcpusFlags, openvzDriver): Likewise. * src/phyp/phyp_driver.c (phypDomainSetCPU) (phypDomainSetVcpusFlags, phypGetLparCPUMAX) (phypDomainGetVcpusFlags, phypDriver): Likewise. * src/qemu/qemu_driver.c (qemudDomainSetVcpus) (qemudDomainSetVcpusFlags, qemudDomainGetMaxVcpus) (qemudDomainGetVcpusFlags, qemuDriver): Likewise. * src/test/test_driver.c (testSetVcpus, testDomainSetVcpusFlags) (testDomainGetMaxVcpus, testDomainGetVcpusFlags, testDriver): Likewise. * src/vbox/vbox_tmpl.c (vboxDomainSetVcpus) (vboxDomainSetVcpusFlags, virDomainGetMaxVcpus) (virDomainGetVcpusFlags, virDriver): Likewise. * src/xen/xen_driver.c (xenUnifiedDomainSetVcpus) (xenUnifiedDomainSetVcpusFlags, xenUnifiedDomainGetMaxVcpus) (xenUnifiedDomainGetVcpusFlags, xenUnifiedDriver): Likewise. * src/xenapi/xenapi_driver.c (xenapiDomainSetVcpus) (xenapiDomainSetVcpusFlags, xenapiDomainGetMaxVcpus) (xenapiDomainGetVcpusFlags, xenapiDriver): Likewise. (xenapiError): New helper macro.
2010-09-27 22:37:53 +00:00
static int
xenUnifiedDomainGetMaxVcpus(virDomainPtr dom)
vcpu: make old API trivially wrap to new API Note - this wrapping is completely mechanical; the old API will function identically, since the new API validates that the exact same flags are provided by the old API. On a per-driver basis, it may make sense to have the old API pass a different set of flags, but that should be done in the per-driver patch that implements the full range of flag support in the new API. * src/esx/esx_driver.c (esxDomainSetVcpus, escDomainGetMaxVpcus): Move guts... (esxDomainSetVcpusFlags, esxDomainGetVcpusFlags): ...to new functions. (esxDriver): Trivially support the new API. * src/openvz/openvz_driver.c (openvzDomainSetVcpus) (openvzDomainSetVcpusFlags, openvzDomainGetMaxVcpus) (openvzDomainGetVcpusFlags, openvzDriver): Likewise. * src/phyp/phyp_driver.c (phypDomainSetCPU) (phypDomainSetVcpusFlags, phypGetLparCPUMAX) (phypDomainGetVcpusFlags, phypDriver): Likewise. * src/qemu/qemu_driver.c (qemudDomainSetVcpus) (qemudDomainSetVcpusFlags, qemudDomainGetMaxVcpus) (qemudDomainGetVcpusFlags, qemuDriver): Likewise. * src/test/test_driver.c (testSetVcpus, testDomainSetVcpusFlags) (testDomainGetMaxVcpus, testDomainGetVcpusFlags, testDriver): Likewise. * src/vbox/vbox_tmpl.c (vboxDomainSetVcpus) (vboxDomainSetVcpusFlags, virDomainGetMaxVcpus) (virDomainGetVcpusFlags, virDriver): Likewise. * src/xen/xen_driver.c (xenUnifiedDomainSetVcpus) (xenUnifiedDomainSetVcpusFlags, xenUnifiedDomainGetMaxVcpus) (xenUnifiedDomainGetVcpusFlags, xenUnifiedDriver): Likewise. * src/xenapi/xenapi_driver.c (xenapiDomainSetVcpus) (xenapiDomainSetVcpusFlags, xenapiDomainGetMaxVcpus) (xenapiDomainGetVcpusFlags, xenapiDriver): Likewise. (xenapiError): New helper macro.
2010-09-27 22:37:53 +00:00
{
return xenUnifiedDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_LIVE |
VIR_DOMAIN_VCPU_MAXIMUM));
}
static char *
drivers: prefer unsigned int for flags Now that the public APIs always use unsigned flags, the internal driver callbacks might as well do likewise. * src/driver.h (vrDrvOpen, virDrvDomainCoreDump) (virDrvDomainGetXMLDesc, virDrvNetworkGetXMLDesc) (virDrvNWFilterGetXMLDesc): Update type. * src/remote/remote_protocol.x (remote_open_args) (remote_domain_core_dump_args, remote_domain_get_xml_desc_args) (remote_network_get_xml_desc_args) (remote_nwfilter_get_xml_desc_args): Likewise. * src/test/test_driver.c: Update clients. * src/remote/remote_driver.c: Likewise. * src/xen/xen_hypervisor.c: Likewise. * src/xen/xen_hypervisor.h: Likewise. * src/xen/xen_driver.c: Likewise. * src/xen/xend_internal.c: Likewise. * src/xen/xend_internal.h: Likewise. * src/xen/xm_internal.c: Likewise. * src/xen/xm_internal.h: Likewise. * src/xen/xs_internal.c: Likewise. * src/xen/xs_internal.h: Likewise. * src/xen/xen_inotify.c: Likewise. * src/xen/xen_inotify.h: Likewise. * src/phyp/phyp_driver.c: Likewise. * src/openvz/openvz_driver.c: Likewise. * src/vmware/vmware_driver.c: Likewise. * src/vbox/vbox_driver.c: Likewise. * src/vbox/vbox_tmpl.c: Likewise. * src/xenapi/xenapi_driver.c: Likewise. * src/esx/esx_driver.c: Likewise. * src/esx/esx_interface_driver.c: Likewise. * src/esx/esx_network_driver.c: Likewise. * src/esx/esx_storage_driver.c: Likewise. * src/esx/esx_device_monitor.c: Likewise. * src/esx/esx_secret_driver.c: Likewise. * src/esx/esx_nwfilter_driver.c: Likewise. * src/interface/netcf_driver.c: Likewise. * src/nwfilter/nwfilter_driver.c: Likewise. * src/libxl/libxl_driver.c: Likewise. * src/qemu/qemu_driver.c: Likewise. * src/lxc/lxc_driver.c: Likewise. * src/uml/uml_driver.c: Likewise. * src/network/bridge_driver.c: Likewise. * src/secret/secret_driver.c: Likewise. * src/storage/storage_driver.c: Likewise. * src/node_device/node_device_hal.c: Likewise. * src/node_device/node_device_udev.c: Likewise. * src/remote_protocol-structs: Likewise.
2011-07-06 20:40:19 +00:00
xenUnifiedDomainGetXMLDesc(virDomainPtr dom, unsigned int flags)
{
xenUnifiedPrivatePtr priv = dom->conn->privateData;
virDomainDefPtr minidef = NULL;
virDomainDefPtr def = NULL;
char *ret = NULL;
if (!(minidef = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainGetXMLDescEnsureACL(dom->conn, minidef, flags) < 0)
goto cleanup;
if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
def = xenXMDomainGetXMLDesc(dom->conn, minidef);
} else {
char *cpus;
xenUnifiedLock(priv);
cpus = xenDomainUsedCpus(dom, minidef);
xenUnifiedUnlock(priv);
def = xenDaemonDomainGetXMLDesc(dom->conn, minidef, cpus);
VIR_FREE(cpus);
}
if (def)
ret = virDomainDefFormat(def, flags);
cleanup:
virDomainDefFree(def);
virDomainDefFree(minidef);
return ret;
}
static char *
xenUnifiedConnectDomainXMLFromNative(virConnectPtr conn,
const char *format,
const char *config,
unsigned int flags)
{
virDomainDefPtr def = NULL;
char *ret = NULL;
virConfPtr conf = NULL;
2011-02-21 13:40:08 +00:00
int id;
char * tty;
int vncport;
xenUnifiedPrivatePtr priv = conn->privateData;
virCheckFlags(0, NULL);
if (virConnectDomainXMLFromNativeEnsureACL(conn) < 0)
return NULL;
if (STRNEQ(format, XEN_CONFIG_FORMAT_XM) &&
STRNEQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
virReportError(VIR_ERR_INVALID_ARG,
_("unsupported config type %s"), format);
return NULL;
}
if (STREQ(format, XEN_CONFIG_FORMAT_XM)) {
conf = virConfReadMem(config, strlen(config), 0);
if (!conf)
goto cleanup;
2011-02-21 13:40:12 +00:00
def = xenParseXM(conf, priv->xendConfigVersion, priv->caps);
} else if (STREQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
if (xenGetDomIdFromSxprString(config, priv->xendConfigVersion, &id) < 0)
goto cleanup;
2011-02-21 13:40:08 +00:00
xenUnifiedLock(priv);
tty = xenStoreDomainGetConsolePath(conn, id);
vncport = xenStoreDomainGetVNCPort(conn, id);
xenUnifiedUnlock(priv);
2011-02-21 13:40:12 +00:00
def = xenParseSxprString(config, priv->xendConfigVersion, tty,
2011-02-21 13:40:08 +00:00
vncport);
}
if (!def)
goto cleanup;
ret = virDomainDefFormat(def, 0);
cleanup:
virDomainDefFree(def);
if (conf)
virConfFree(conf);
return ret;
}
#define MAX_CONFIG_SIZE (1024 * 65)
static char *
xenUnifiedConnectDomainXMLToNative(virConnectPtr conn,
const char *format,
const char *xmlData,
unsigned int flags)
{
virDomainDefPtr def = NULL;
char *ret = NULL;
virConfPtr conf = NULL;
xenUnifiedPrivatePtr priv = conn->privateData;
virCheckFlags(0, NULL);
if (virConnectDomainXMLToNativeEnsureACL(conn) < 0)
return NULL;
if (STRNEQ(format, XEN_CONFIG_FORMAT_XM) &&
STRNEQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
virReportError(VIR_ERR_INVALID_ARG,
_("unsupported config type %s"), format);
goto cleanup;
}
if (!(def = virDomainDefParseString(xmlData, priv->caps, priv->xmlopt,
1 << VIR_DOMAIN_VIRT_XEN,
VIR_DOMAIN_XML_INACTIVE)))
goto cleanup;
if (STREQ(format, XEN_CONFIG_FORMAT_XM)) {
int len = MAX_CONFIG_SIZE;
2011-02-21 13:40:12 +00:00
conf = xenFormatXM(conn, def, priv->xendConfigVersion);
if (!conf)
goto cleanup;
if (VIR_ALLOC_N(ret, len) < 0)
goto cleanup;
if (virConfWriteMem(ret, &len, conf) < 0) {
VIR_FREE(ret);
goto cleanup;
}
} else if (STREQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
2011-02-21 13:40:12 +00:00
ret = xenFormatSxpr(conn, def, priv->xendConfigVersion);
}
cleanup:
virDomainDefFree(def);
if (conf)
virConfFree(conf);
return ret;
}
static int
xenUnifiedDomainMigratePrepare(virConnectPtr dconn,
char **cookie,
int *cookielen,
const char *uri_in,
char **uri_out,
unsigned long flags,
const char *dname,
unsigned long resource)
{
virCheckFlags(XEN_MIGRATION_FLAGS, -1);
return xenDaemonDomainMigratePrepare(dconn, cookie, cookielen,
uri_in, uri_out,
flags, dname, resource);
}
static int
xenUnifiedDomainMigratePerform(virDomainPtr dom,
const char *cookie,
int cookielen,
const char *uri,
unsigned long flags,
const char *dname,
unsigned long resource)
{
virDomainDefPtr def = NULL;
int ret = -1;
virCheckFlags(XEN_MIGRATION_FLAGS, -1);
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainMigratePerformEnsureACL(dom->conn, def) < 0)
goto cleanup;
ret = xenDaemonDomainMigratePerform(dom->conn, def,
cookie, cookielen, uri,
flags, dname, resource);
cleanup:
virDomainDefFree(def);
return ret;
}
static virDomainPtr
xenUnifiedDomainMigrateFinish(virConnectPtr dconn,
const char *dname,
const char *cookie ATTRIBUTE_UNUSED,
int cookielen ATTRIBUTE_UNUSED,
const char *uri ATTRIBUTE_UNUSED,
unsigned long flags)
{
xenUnifiedPrivatePtr priv = dconn->privateData;
virDomainPtr ret = NULL;
virDomainDefPtr minidef = NULL;
virDomainDefPtr def = NULL;
virCheckFlags(XEN_MIGRATION_FLAGS, NULL);
if (!(minidef = xenGetDomainDefForName(dconn, dname)))
goto cleanup;
if (virDomainMigrateFinishEnsureACL(dconn, minidef) < 0)
goto cleanup;
if (flags & VIR_MIGRATE_PERSIST_DEST) {
if (!(def = xenDaemonDomainGetXMLDesc(dconn, minidef, NULL)))
goto cleanup;
if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
if (xenXMDomainDefineXML(dconn, def) < 0)
goto cleanup;
} else {
if (xenDaemonDomainDefineXML(dconn, def) < 0)
goto cleanup;
}
}
ret = virGetDomain(dconn, minidef->name, minidef->uuid);
if (ret)
ret->id = minidef->id;
cleanup:
virDomainDefFree(def);
virDomainDefFree(minidef);
return ret;
}
static int
xenUnifiedConnectListDefinedDomains(virConnectPtr conn, char **const names,
int maxnames)
{
xenUnifiedPrivatePtr priv = conn->privateData;
if (virConnectListDefinedDomainsEnsureACL(conn) < 0)
return -1;
if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
return xenXMListDefinedDomains(conn, names, maxnames);
} else {
return xenDaemonListDefinedDomains(conn, names, maxnames);
}
}
static int
xenUnifiedConnectNumOfDefinedDomains(virConnectPtr conn)
{
xenUnifiedPrivatePtr priv = conn->privateData;
if (virConnectNumOfDefinedDomainsEnsureACL(conn) < 0)
return -1;
if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
return xenXMNumOfDefinedDomains(conn);
} else {
return xenDaemonNumOfDefinedDomains(conn);
}
}
static int
xenUnifiedDomainCreateWithFlags(virDomainPtr dom, unsigned int flags)
{
xenUnifiedPrivatePtr priv = dom->conn->privateData;
int ret = -1;
virDomainDefPtr def = NULL;
char *name = NULL;
virCheckFlags(0, -1);
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainCreateWithFlagsEnsureACL(dom->conn, def) < 0)
goto cleanup;
if (!(name = xenUnifiedDomainManagedSavePath(priv, def)))
goto cleanup;
if (virFileExists(name)) {
ret = xenDaemonDomainRestore(dom->conn, name);
if (ret == 0)
unlink(name);
goto cleanup;
}
if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
ret = xenXMDomainCreate(dom->conn, def);
else
ret = xenDaemonDomainCreate(dom->conn, def);
if (ret >= 0)
dom->id = def->id;
cleanup:
virDomainDefFree(def);
VIR_FREE(name);
return ret;
}
static int
xenUnifiedDomainCreate(virDomainPtr dom)
{
return xenUnifiedDomainCreateWithFlags(dom, 0);
}
static virDomainPtr
xenUnifiedDomainDefineXML(virConnectPtr conn, const char *xml)
{
xenUnifiedPrivatePtr priv = conn->privateData;
virDomainDefPtr def = NULL;
virDomainPtr ret = NULL;
if (!(def = virDomainDefParseString(xml, priv->caps, priv->xmlopt,
1 << VIR_DOMAIN_VIRT_XEN,
VIR_DOMAIN_XML_INACTIVE)))
goto cleanup;
if (virDomainDefineXMLEnsureACL(conn, def) < 0)
goto cleanup;
if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
if (xenXMDomainDefineXML(conn, def) < 0)
goto cleanup;
ret = virGetDomain(conn, def->name, def->uuid);
def = NULL; /* XM driver owns it now */
} else {
if (xenDaemonDomainDefineXML(conn, def) < 0)
goto cleanup;
ret = virGetDomain(conn, def->name, def->uuid);
}
if (ret)
ret->id = -1;
cleanup:
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedDomainUndefineFlags(virDomainPtr dom, unsigned int flags)
{
xenUnifiedPrivatePtr priv = dom->conn->privateData;
virDomainDefPtr def = NULL;
int ret = -1;
virCheckFlags(0, -1);
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainUndefineFlagsEnsureACL(dom->conn, def) < 0)
goto cleanup;
if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
ret = xenXMDomainUndefine(dom->conn, def);
else
ret = xenDaemonDomainUndefine(dom->conn, def);
cleanup:
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedDomainUndefine(virDomainPtr dom)
{
return xenUnifiedDomainUndefineFlags(dom, 0);
}
static int
xenUnifiedDomainAttachDevice(virDomainPtr dom, const char *xml)
{
xenUnifiedPrivatePtr priv = dom->conn->privateData;
unsigned int flags = VIR_DOMAIN_DEVICE_MODIFY_LIVE;
virDomainDefPtr def = NULL;
int ret = -1;
/*
* HACK: xend with xendConfigVersion >= 3 does not support changing live
* config without touching persistent config, we add the extra flag here
* to make this API work
*/
if (priv->xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4)
flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainAttachDeviceEnsureACL(dom->conn, def) < 0)
goto cleanup;
if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
ret = xenXMDomainAttachDeviceFlags(dom->conn, def, xml, flags);
else
ret = xenDaemonAttachDeviceFlags(dom->conn, def, xml, flags);
cleanup:
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
unsigned int flags)
{
xenUnifiedPrivatePtr priv = dom->conn->privateData;
virDomainDefPtr def = NULL;
int ret = -1;
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainAttachDeviceFlagsEnsureACL(dom->conn, def, flags) < 0)
goto cleanup;
if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
ret = xenXMDomainAttachDeviceFlags(dom->conn, def, xml, flags);
else
ret = xenDaemonAttachDeviceFlags(dom->conn, def, xml, flags);
cleanup:
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedDomainDetachDevice(virDomainPtr dom, const char *xml)
{
xenUnifiedPrivatePtr priv = dom->conn->privateData;
unsigned int flags = VIR_DOMAIN_DEVICE_MODIFY_LIVE;
virDomainDefPtr def = NULL;
int ret = -1;
/*
* HACK: xend with xendConfigVersion >= 3 does not support changing live
* config without touching persistent config, we add the extra flag here
* to make this API work
*/
if (priv->xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4)
flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainDetachDeviceEnsureACL(dom->conn, def) < 0)
goto cleanup;
if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
ret = xenXMDomainDetachDeviceFlags(dom->conn, def, xml, flags);
else
ret = xenDaemonDetachDeviceFlags(dom->conn, def, xml, flags);
cleanup:
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedDomainDetachDeviceFlags(virDomainPtr dom, const char *xml,
unsigned int flags)
{
xenUnifiedPrivatePtr priv = dom->conn->privateData;
virDomainDefPtr def = NULL;
int ret = -1;
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainDetachDeviceFlagsEnsureACL(dom->conn, def, flags) < 0)
goto cleanup;
if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
ret = xenXMDomainDetachDeviceFlags(dom->conn, def, xml, flags);
else
ret = xenDaemonDetachDeviceFlags(dom->conn, def, xml, flags);
cleanup:
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml,
unsigned int flags)
{
virDomainDefPtr def = NULL;
int ret = -1;
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainUpdateDeviceFlagsEnsureACL(dom->conn, def, flags) < 0)
goto cleanup;
ret = xenDaemonUpdateDeviceFlags(dom->conn, def, xml, flags);
cleanup:
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedDomainGetAutostart(virDomainPtr dom, int *autostart)
{
xenUnifiedPrivatePtr priv = dom->conn->privateData;
virDomainDefPtr def = NULL;
int ret = -1;
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainGetAutostartEnsureACL(dom->conn, def) < 0)
goto cleanup;
if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
ret = xenXMDomainGetAutostart(def, autostart);
else
ret = xenDaemonDomainGetAutostart(dom->conn, def, autostart);
cleanup:
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedDomainSetAutostart(virDomainPtr dom, int autostart)
{
xenUnifiedPrivatePtr priv = dom->conn->privateData;
virDomainDefPtr def = NULL;
int ret = -1;
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainSetAutostartEnsureACL(dom->conn, def) < 0)
goto cleanup;
if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
ret = xenXMDomainSetAutostart(def, autostart);
else
ret = xenDaemonDomainSetAutostart(dom->conn, def, autostart);
cleanup:
virDomainDefFree(def);
return ret;
}
static char *
xenUnifiedDomainGetSchedulerType(virDomainPtr dom, int *nparams)
{
xenUnifiedPrivatePtr priv = dom->conn->privateData;
virDomainDefPtr def = NULL;
char *ret = NULL;
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainGetSchedulerTypeEnsureACL(dom->conn, def) < 0)
goto cleanup;
if (dom->id < 0) {
if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Cannot change scheduler parameters"));
goto cleanup;
}
ret = xenDaemonGetSchedulerType(dom->conn, nparams);
} else {
ret = xenHypervisorGetSchedulerType(dom->conn, nparams);
}
cleanup:
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedDomainGetSchedulerParametersFlags(virDomainPtr dom,
virTypedParameterPtr params,
int *nparams,
unsigned int flags)
{
xenUnifiedPrivatePtr priv = dom->conn->privateData;
virDomainDefPtr def = NULL;
int ret = -1;
virCheckFlags(0, -1);
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainGetSchedulerParametersFlagsEnsureACL(dom->conn, def) < 0)
goto cleanup;
if (dom->id < 0) {
if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Cannot change scheduler parameters"));
goto cleanup;
}
ret = xenDaemonGetSchedulerParameters(dom->conn, def, params, nparams);
} else {
ret = xenHypervisorGetSchedulerParameters(dom->conn, def, params, nparams);
}
cleanup:
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedDomainGetSchedulerParameters(virDomainPtr dom,
virTypedParameterPtr params,
int *nparams)
{
return xenUnifiedDomainGetSchedulerParametersFlags(dom, params,
nparams, 0);
}
static int
xenUnifiedDomainSetSchedulerParametersFlags(virDomainPtr dom,
virTypedParameterPtr params,
int nparams,
unsigned int flags)
{
xenUnifiedPrivatePtr priv = dom->conn->privateData;
virDomainDefPtr def = NULL;
int ret = -1;
virCheckFlags(0, -1);
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainSetSchedulerParametersFlagsEnsureACL(dom->conn, def, flags) < 0)
goto cleanup;
if (dom->id < 0) {
if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Cannot change scheduler parameters"));
goto cleanup;
}
ret = xenDaemonSetSchedulerParameters(dom->conn, def, params, nparams);
} else {
ret = xenHypervisorSetSchedulerParameters(dom->conn, def, params, nparams);
}
cleanup:
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedDomainSetSchedulerParameters(virDomainPtr dom,
virTypedParameterPtr params,
int nparams)
{
return xenUnifiedDomainSetSchedulerParametersFlags(dom, params,
nparams, 0);
}
static int
xenUnifiedDomainBlockStats(virDomainPtr dom, const char *path,
virDomainBlockStatsPtr stats)
{
virDomainDefPtr def = NULL;
int ret = -1;
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainBlockStatsEnsureACL(dom->conn, def) < 0)
goto cleanup;
ret = xenHypervisorDomainBlockStats(dom->conn, def, path, stats);
cleanup:
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedDomainInterfaceStats(virDomainPtr dom, const char *path,
virDomainInterfaceStatsPtr stats)
{
virDomainDefPtr def = NULL;
int ret = -1;
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainInterfaceStatsEnsureACL(dom->conn, def) < 0)
goto cleanup;
ret = xenHypervisorDomainInterfaceStats(def, path, stats);
cleanup:
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedDomainBlockPeek(virDomainPtr dom, const char *path,
unsigned long long offset, size_t size,
void *buffer, unsigned int flags)
{
xenUnifiedPrivatePtr priv = dom->conn->privateData;
virDomainDefPtr def = NULL;
int ret = -1;
virCheckFlags(0, -1);
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
if (virDomainBlockPeekEnsureACL(dom->conn, def) < 0)
goto cleanup;
if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
ret = xenXMDomainBlockPeek(dom->conn, def, path, offset, size, buffer);
else
ret = xenDaemonDomainBlockPeek(dom->conn, def, path, offset, size, buffer);
cleanup:
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedNodeGetCellsFreeMemory(virConnectPtr conn, unsigned long long *freeMems,
int startCell, int maxCells)
{
if (virNodeGetCellsFreeMemoryEnsureACL(conn) < 0)
return 0;
return xenHypervisorNodeGetCellsFreeMemory(conn, freeMems,
startCell, maxCells);
}
static unsigned long long
xenUnifiedNodeGetFreeMemory(virConnectPtr conn)
{
unsigned long long freeMem = 0;
if (virNodeGetFreeMemoryEnsureACL(conn) < 0)
return 0;
if (xenHypervisorNodeGetCellsFreeMemory(conn, &freeMem, -1, 1) < 0)
return 0;
return freeMem;
}
static int
xenUnifiedConnectDomainEventRegister(virConnectPtr conn,
virConnectDomainEventCallback callback,
void *opaque,
virFreeCallback freefunc)
{
xenUnifiedPrivatePtr priv = conn->privateData;
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 21:21:17 +00:00
int ret = 0;
if (virConnectDomainEventRegisterEnsureACL(conn) < 0)
return -1;
2009-01-21 18:11:14 +00:00
xenUnifiedLock(priv);
if (priv->xsWatch == -1) {
maint: improve VIR_ERR_NO_SUPPORT usage We weren't very consistent in our use of VIR_ERR_NO_SUPPORT; many users just passed __FUNCTION__ on, while others passed "%s" to silence over-eager compilers that warn about __FUNCTION__ not containing any %. It's nicer to route all these uses through a single macro, so that if we ever need to change the reporting, we can do it in one place. I verified that 'virsh -c test:///default qemu-monitor-command test foo' gives the same error message before and after this patch: error: this function is not supported by the connection driver: virDomainQemuMonitorCommand Note that in libvirt.c, we were inconsistent on whether virDomain* API used virLibConnError() (with VIR_FROM_NONE) or virLibDomainError() (with VIR_FROM_DOMAIN); this patch unifies these errors to all use VIR_FROM_NONE, on the grounds that it is unlikely that a caller learning that a call is unimplemented can do anything in particular with extra knowledge of which error domain it belongs to. One particular change to note is virDomainOpenGraphics which was trying to fail with VIR_ERR_NO_SUPPORT after a failed VIR_DRV_SUPPORTS_FEATURE check; all other places that fail a feature check report VIR_ERR_ARGUMENT_UNSUPPORTED. * src/util/virerror.h (virReportUnsupportedError): New macro. * src/libvirt-qemu.c: Use new macro. * src/libvirt-lxc.c: Likewise. * src/lxc/lxc_driver.c: Likewise. * src/security/security_manager.c: Likewise. * src/util/virinitctl.c: Likewise. * src/libvirt.c: Likewise. (virDomainOpenGraphics): Use correct error for unsupported feature. Signed-off-by: Eric Blake <eblake@redhat.com>
2013-12-20 01:38:59 +00:00
virReportUnsupportedError();
2009-01-21 18:11:14 +00:00
xenUnifiedUnlock(priv);
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 21:21:17 +00:00
if (virDomainEventStateRegister(conn, priv->domainEvents,
callback, opaque, freefunc) < 0)
ret = -1;
2009-01-21 18:11:14 +00:00
xenUnifiedUnlock(priv);
return ret;
}
static int
xenUnifiedConnectDomainEventDeregister(virConnectPtr conn,
virConnectDomainEventCallback callback)
{
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 21:21:17 +00:00
int ret = 0;
xenUnifiedPrivatePtr priv = conn->privateData;
if (virConnectDomainEventDeregisterEnsureACL(conn) < 0)
return -1;
2009-01-21 18:11:14 +00:00
xenUnifiedLock(priv);
if (priv->xsWatch == -1) {
maint: improve VIR_ERR_NO_SUPPORT usage We weren't very consistent in our use of VIR_ERR_NO_SUPPORT; many users just passed __FUNCTION__ on, while others passed "%s" to silence over-eager compilers that warn about __FUNCTION__ not containing any %. It's nicer to route all these uses through a single macro, so that if we ever need to change the reporting, we can do it in one place. I verified that 'virsh -c test:///default qemu-monitor-command test foo' gives the same error message before and after this patch: error: this function is not supported by the connection driver: virDomainQemuMonitorCommand Note that in libvirt.c, we were inconsistent on whether virDomain* API used virLibConnError() (with VIR_FROM_NONE) or virLibDomainError() (with VIR_FROM_DOMAIN); this patch unifies these errors to all use VIR_FROM_NONE, on the grounds that it is unlikely that a caller learning that a call is unimplemented can do anything in particular with extra knowledge of which error domain it belongs to. One particular change to note is virDomainOpenGraphics which was trying to fail with VIR_ERR_NO_SUPPORT after a failed VIR_DRV_SUPPORTS_FEATURE check; all other places that fail a feature check report VIR_ERR_ARGUMENT_UNSUPPORTED. * src/util/virerror.h (virReportUnsupportedError): New macro. * src/libvirt-qemu.c: Use new macro. * src/libvirt-lxc.c: Likewise. * src/lxc/lxc_driver.c: Likewise. * src/security/security_manager.c: Likewise. * src/util/virinitctl.c: Likewise. * src/libvirt.c: Likewise. (virDomainOpenGraphics): Use correct error for unsupported feature. Signed-off-by: Eric Blake <eblake@redhat.com>
2013-12-20 01:38:59 +00:00
virReportUnsupportedError();
2009-01-21 18:11:14 +00:00
xenUnifiedUnlock(priv);
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 21:21:17 +00:00
if (virDomainEventStateDeregister(conn,
priv->domainEvents,
callback) < 0)
ret = -1;
2009-01-21 18:11:14 +00:00
xenUnifiedUnlock(priv);
return ret;
}
2009-04-03 12:38:52 +00:00
static int
xenUnifiedConnectDomainEventRegisterAny(virConnectPtr conn,
virDomainPtr dom,
int eventID,
virConnectDomainEventGenericCallback callback,
void *opaque,
virFreeCallback freefunc)
{
xenUnifiedPrivatePtr priv = conn->privateData;
int ret;
if (virConnectDomainEventRegisterAnyEnsureACL(conn) < 0)
return -1;
xenUnifiedLock(priv);
if (priv->xsWatch == -1) {
maint: improve VIR_ERR_NO_SUPPORT usage We weren't very consistent in our use of VIR_ERR_NO_SUPPORT; many users just passed __FUNCTION__ on, while others passed "%s" to silence over-eager compilers that warn about __FUNCTION__ not containing any %. It's nicer to route all these uses through a single macro, so that if we ever need to change the reporting, we can do it in one place. I verified that 'virsh -c test:///default qemu-monitor-command test foo' gives the same error message before and after this patch: error: this function is not supported by the connection driver: virDomainQemuMonitorCommand Note that in libvirt.c, we were inconsistent on whether virDomain* API used virLibConnError() (with VIR_FROM_NONE) or virLibDomainError() (with VIR_FROM_DOMAIN); this patch unifies these errors to all use VIR_FROM_NONE, on the grounds that it is unlikely that a caller learning that a call is unimplemented can do anything in particular with extra knowledge of which error domain it belongs to. One particular change to note is virDomainOpenGraphics which was trying to fail with VIR_ERR_NO_SUPPORT after a failed VIR_DRV_SUPPORTS_FEATURE check; all other places that fail a feature check report VIR_ERR_ARGUMENT_UNSUPPORTED. * src/util/virerror.h (virReportUnsupportedError): New macro. * src/libvirt-qemu.c: Use new macro. * src/libvirt-lxc.c: Likewise. * src/lxc/lxc_driver.c: Likewise. * src/security/security_manager.c: Likewise. * src/util/virinitctl.c: Likewise. * src/libvirt.c: Likewise. (virDomainOpenGraphics): Use correct error for unsupported feature. Signed-off-by: Eric Blake <eblake@redhat.com>
2013-12-20 01:38:59 +00:00
virReportUnsupportedError();
xenUnifiedUnlock(priv);
return -1;
}
if (virDomainEventStateRegisterID(conn, priv->domainEvents,
dom, eventID,
callback, opaque, freefunc, &ret) < 0)
ret = -1;
xenUnifiedUnlock(priv);
return ret;
}
static int
xenUnifiedConnectDomainEventDeregisterAny(virConnectPtr conn,
int callbackID)
{
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 21:21:17 +00:00
int ret = 0;
xenUnifiedPrivatePtr priv = conn->privateData;
if (virConnectDomainEventDeregisterAnyEnsureACL(conn) < 0)
return -1;
xenUnifiedLock(priv);
if (priv->xsWatch == -1) {
maint: improve VIR_ERR_NO_SUPPORT usage We weren't very consistent in our use of VIR_ERR_NO_SUPPORT; many users just passed __FUNCTION__ on, while others passed "%s" to silence over-eager compilers that warn about __FUNCTION__ not containing any %. It's nicer to route all these uses through a single macro, so that if we ever need to change the reporting, we can do it in one place. I verified that 'virsh -c test:///default qemu-monitor-command test foo' gives the same error message before and after this patch: error: this function is not supported by the connection driver: virDomainQemuMonitorCommand Note that in libvirt.c, we were inconsistent on whether virDomain* API used virLibConnError() (with VIR_FROM_NONE) or virLibDomainError() (with VIR_FROM_DOMAIN); this patch unifies these errors to all use VIR_FROM_NONE, on the grounds that it is unlikely that a caller learning that a call is unimplemented can do anything in particular with extra knowledge of which error domain it belongs to. One particular change to note is virDomainOpenGraphics which was trying to fail with VIR_ERR_NO_SUPPORT after a failed VIR_DRV_SUPPORTS_FEATURE check; all other places that fail a feature check report VIR_ERR_ARGUMENT_UNSUPPORTED. * src/util/virerror.h (virReportUnsupportedError): New macro. * src/libvirt-qemu.c: Use new macro. * src/libvirt-lxc.c: Likewise. * src/lxc/lxc_driver.c: Likewise. * src/security/security_manager.c: Likewise. * src/util/virinitctl.c: Likewise. * src/libvirt.c: Likewise. (virDomainOpenGraphics): Use correct error for unsupported feature. Signed-off-by: Eric Blake <eblake@redhat.com>
2013-12-20 01:38:59 +00:00
virReportUnsupportedError();
xenUnifiedUnlock(priv);
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 21:21:17 +00:00
if (virObjectEventStateDeregisterID(conn,
priv->domainEvents,
callbackID) < 0)
ret = -1;
xenUnifiedUnlock(priv);
return ret;
}
2009-04-03 12:38:52 +00:00
static int
xenUnifiedNodeDeviceGetPCIInfo(virNodeDevicePtr dev,
unsigned *domain,
unsigned *bus,
unsigned *slot,
unsigned *function)
2009-04-03 12:38:52 +00:00
{
virNodeDeviceDefPtr def = NULL;
virNodeDevCapsDefPtr cap;
char *xml = NULL;
int ret = -1;
xml = virNodeDeviceGetXMLDesc(dev, 0);
if (!xml)
goto out;
def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL);
2009-04-03 12:38:52 +00:00
if (!def)
goto out;
cap = def->caps;
while (cap) {
if (cap->type == VIR_NODE_DEV_CAP_PCI_DEV) {
*domain = cap->data.pci_dev.domain;
*bus = cap->data.pci_dev.bus;
*slot = cap->data.pci_dev.slot;
*function = cap->data.pci_dev.function;
break;
}
cap = cap->next;
}
if (!cap) {
virReportError(VIR_ERR_INVALID_ARG,
_("device %s is not a PCI device"), dev->name);
2009-04-03 12:38:52 +00:00
goto out;
}
ret = 0;
out:
2009-04-03 12:38:52 +00:00
virNodeDeviceDefFree(def);
VIR_FREE(xml);
return ret;
}
static int
xenUnifiedNodeDeviceDetachFlags(virNodeDevicePtr dev,
const char *driverName,
unsigned int flags)
2009-04-03 12:38:52 +00:00
{
virPCIDevicePtr pci;
2009-04-03 12:38:52 +00:00
unsigned domain, bus, slot, function;
int ret = -1;
virCheckFlags(0, -1);
if (xenUnifiedNodeDeviceGetPCIInfo(dev, &domain, &bus, &slot, &function) < 0)
2009-04-03 12:38:52 +00:00
return -1;
pci = virPCIDeviceNew(domain, bus, slot, function);
2009-04-03 12:38:52 +00:00
if (!pci)
return -1;
if (!driverName) {
if (virPCIDeviceSetStubDriver(pci, "pciback") < 0)
goto out;
} else {
virReportError(VIR_ERR_INVALID_ARG,
_("unknown driver name '%s'"), driverName);
goto out;
}
if (virPCIDeviceDetach(pci, NULL, NULL) < 0)
2009-04-03 12:38:52 +00:00
goto out;
ret = 0;
out:
virPCIDeviceFree(pci);
2009-04-03 12:38:52 +00:00
return ret;
}
static int
xenUnifiedNodeDeviceDettach(virNodeDevicePtr dev)
{
return xenUnifiedNodeDeviceDetachFlags(dev, NULL, 0);
}
static int
xenUnifiedNodeDeviceAssignedDomainId(virNodeDevicePtr dev)
{
int numdomains;
int ret = -1;
size_t i;
int *ids = NULL;
char *bdf = NULL;
char *xref = NULL;
unsigned int domain, bus, slot, function;
virConnectPtr conn = dev->conn;
xenUnifiedPrivatePtr priv = conn->privateData;
/* Get active domains */
numdomains = xenUnifiedConnectNumOfDomains(conn);
if (numdomains < 0) {
return ret;
}
if (numdomains > 0) {
if (VIR_ALLOC_N(ids, numdomains) < 0)
goto out;
if ((numdomains = xenUnifiedConnectListDomains(conn, &ids[0], numdomains)) < 0) {
goto out;
}
}
/* Get pci bdf */
if (xenUnifiedNodeDeviceGetPCIInfo(dev, &domain, &bus, &slot, &function) < 0)
goto out;
if (virAsprintf(&bdf, "%04x:%02x:%02x.%0x",
domain, bus, slot, function) < 0)
goto out;
xenUnifiedLock(priv);
/* Check if bdf is assigned to one of active domains */
for (i = 0; i < numdomains; i++) {
xref = xenStoreDomainGetPCIID(conn, ids[i], bdf);
if (xref == NULL) {
continue;
} else {
ret = ids[i];
break;
}
}
xenUnifiedUnlock(priv);
VIR_FREE(xref);
VIR_FREE(bdf);
out:
VIR_FREE(ids);
return ret;
}
2009-04-03 12:38:52 +00:00
static int
xenUnifiedNodeDeviceReAttach(virNodeDevicePtr dev)
2009-04-03 12:38:52 +00:00
{
virPCIDevicePtr pci;
2009-04-03 12:38:52 +00:00
unsigned domain, bus, slot, function;
int ret = -1;
int domid;
2009-04-03 12:38:52 +00:00
if (xenUnifiedNodeDeviceGetPCIInfo(dev, &domain, &bus, &slot, &function) < 0)
2009-04-03 12:38:52 +00:00
return -1;
pci = virPCIDeviceNew(domain, bus, slot, function);
2009-04-03 12:38:52 +00:00
if (!pci)
return -1;
/* Check if device is assigned to an active guest */
if ((domid = xenUnifiedNodeDeviceAssignedDomainId(dev)) >= 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Device %s has been assigned to guest %d"),
dev->name, domid);
goto out;
}
if (virPCIDeviceReattach(pci, NULL, NULL) < 0)
2009-04-03 12:38:52 +00:00
goto out;
ret = 0;
out:
virPCIDeviceFree(pci);
2009-04-03 12:38:52 +00:00
return ret;
}
static int
xenUnifiedNodeDeviceReset(virNodeDevicePtr dev)
2009-04-03 12:38:52 +00:00
{
virPCIDevicePtr pci;
2009-04-03 12:38:52 +00:00
unsigned domain, bus, slot, function;
int ret = -1;
if (xenUnifiedNodeDeviceGetPCIInfo(dev, &domain, &bus, &slot, &function) < 0)
2009-04-03 12:38:52 +00:00
return -1;
pci = virPCIDeviceNew(domain, bus, slot, function);
2009-04-03 12:38:52 +00:00
if (!pci)
return -1;
if (virPCIDeviceReset(pci, NULL, NULL) < 0)
2009-04-03 12:38:52 +00:00
goto out;
ret = 0;
out:
virPCIDeviceFree(pci);
2009-04-03 12:38:52 +00:00
return ret;
}
static int
xenUnifiedDomainOpenConsole(virDomainPtr dom,
const char *dev_name,
virStreamPtr st,
unsigned int flags)
{
virDomainDefPtr def = NULL;
int ret = -1;
virDomainChrDefPtr chr = NULL;
virCheckFlags(0, -1);
if (dom->id == -1) {
virReportError(VIR_ERR_OPERATION_INVALID,
"%s", _("domain is not running"));
goto cleanup;
}
if (dev_name) {
/* XXX support device aliases in future */
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("Named device aliases are not supported"));
goto cleanup;
}
def = xenDaemonDomainFetch(dom->conn, dom->id, dom->name, NULL);
if (!def)
goto cleanup;
if (def->nconsoles)
chr = def->consoles[0];
else if (def->nserials)
chr = def->serials[0];
if (!chr) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("cannot find default console device"));
goto cleanup;
}
domain_conf: split source data out from ChrDef This opens up the possibility of reusing the smaller ChrSourceDef for both qemu monitor and a passthrough smartcard device. * src/conf/domain_conf.h (_virDomainChrDef): Factor host details... (_virDomainChrSourceDef): ...into new struct. (virDomainChrSourceDefFree): New prototype. * src/conf/domain_conf.c (virDomainChrDefFree) (virDomainChrDefParseXML, virDomainChrDefFormat): Split... (virDomainChrSourceDefClear, virDomainChrSourceDefFree) (virDomainChrSourceDefParseXML, virDomainChrSourceDefFormat): ...into new functions. (virDomainChrDefParseTargetXML): Update clients to reflect type split. * src/vmx/vmx.c (virVMXParseSerial, virVMXParseParallel) (virVMXFormatSerial, virVMXFormatParallel): Likewise. * src/xen/xen_driver.c (xenUnifiedDomainOpenConsole): Likewise. * src/xen/xend_internal.c (xenDaemonParseSxprChar) (xenDaemonFormatSxprChr): Likewise. * src/vbox/vbox_tmpl.c (vboxDomainDumpXML, vboxAttachSerial) (vboxAttachParallel): Likewise. * src/security/security_dac.c (virSecurityDACSetChardevLabel) (virSecurityDACSetChardevCallback) (virSecurityDACRestoreChardevLabel) (virSecurityDACRestoreChardevCallback): Likewise. * src/security/security_selinux.c (SELinuxSetSecurityChardevLabel) (SELinuxSetSecurityChardevCallback) (SELinuxRestoreSecurityChardevLabel) (SELinuxSetSecurityChardevCallback): Likewise. * src/security/virt-aa-helper.c (get_files): Likewise. * src/lxc/lxc_driver.c (lxcVmStart, lxcDomainOpenConsole): Likewise. * src/uml/uml_conf.c (umlBuildCommandLineChr): Likewise. * src/uml/uml_driver.c (umlIdentifyOneChrPTY, umlIdentifyChrPTY) (umlDomainOpenConsole): Likewise. * src/qemu/qemu_command.c (qemuBuildChrChardevStr) (qemuBuildChrArgStr, qemuBuildCommandLine) (qemuParseCommandLineChr): Likewise. * src/qemu/qemu_domain.c (qemuDomainObjPrivateXMLFormat) (qemuDomainObjPrivateXMLParse): Likewise. * src/qemu/qemu_cgroup.c (qemuSetupChardevCgroup): Likewise. * src/qemu/qemu_hotplug.c (qemuDomainAttachNetDevice): Likewise. * src/qemu/qemu_driver.c (qemudFindCharDevicePTYsMonitor) (qemudFindCharDevicePTYs, qemuPrepareChardevDevice) (qemuPrepareMonitorChr, qemudShutdownVMDaemon) (qemuDomainOpenConsole): Likewise. * src/qemu/qemu_command.h (qemuBuildChrChardevStr) (qemuBuildChrArgStr): Delete, now that they are static. * src/libvirt_private.syms (domain_conf.h): New exports. * cfg.mk (useless_free_options): Update list. * tests/qemuxml2argvtest.c (testCompareXMLToArgvFiles): Update tests.
2011-01-07 22:45:01 +00:00
if (chr->source.type != VIR_DOMAIN_CHR_TYPE_PTY) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("character device %s is not using a PTY"), dev_name);
goto cleanup;
}
if (virFDStreamOpenFile(st, chr->source.data.file.path,
0, 0, O_RDWR) < 0)
goto cleanup;
ret = 0;
cleanup:
virDomainDefFree(def);
return ret;
}
static int
xenUnifiedNodeGetMemoryParameters(virConnectPtr conn,
virTypedParameterPtr params,
int *nparams,
unsigned int flags)
{
if (virNodeGetMemoryParametersEnsureACL(conn) < 0)
return -1;
return nodeGetMemoryParameters(params, nparams, flags);
}
static int
xenUnifiedNodeSetMemoryParameters(virConnectPtr conn,
virTypedParameterPtr params,
int nparams,
unsigned int flags)
{
if (virNodeSetMemoryParametersEnsureACL(conn) < 0)
return -1;
return nodeSetMemoryParameters(params, nparams, flags);
}
static int
xenUnifiedNodeSuspendForDuration(virConnectPtr conn,
unsigned int target,
unsigned long long duration,
unsigned int flags)
{
if (virNodeSuspendForDurationEnsureACL(conn) < 0)
return -1;
return nodeSuspendForDuration(target, duration, flags);
}
/*----- Register with libvirt.c, and initialize Xen drivers. -----*/
/* The interface which we export upwards to libvirt.c. */
static virDriver xenUnifiedDriver = {
.no = VIR_DRV_XEN_UNIFIED,
.name = "Xen",
.connectOpen = xenUnifiedConnectOpen, /* 0.0.3 */
.connectClose = xenUnifiedConnectClose, /* 0.0.3 */
.connectSupportsFeature = xenUnifiedConnectSupportsFeature, /* 0.3.2 */
.connectGetType = xenUnifiedConnectGetType, /* 0.0.3 */
.connectGetVersion = xenUnifiedConnectGetVersion, /* 0.0.3 */
.connectGetHostname = xenUnifiedConnectGetHostname, /* 0.7.3 */
.connectGetSysinfo = xenUnifiedConnectGetSysinfo, /* 1.1.0 */
.connectGetMaxVcpus = xenUnifiedConnectGetMaxVcpus, /* 0.2.1 */
.nodeGetInfo = xenUnifiedNodeGetInfo, /* 0.1.0 */
.connectGetCapabilities = xenUnifiedConnectGetCapabilities, /* 0.2.1 */
.connectListDomains = xenUnifiedConnectListDomains, /* 0.0.3 */
.connectNumOfDomains = xenUnifiedConnectNumOfDomains, /* 0.0.3 */
.domainCreateXML = xenUnifiedDomainCreateXML, /* 0.0.3 */
.domainLookupByID = xenUnifiedDomainLookupByID, /* 0.0.3 */
.domainLookupByUUID = xenUnifiedDomainLookupByUUID, /* 0.0.5 */
.domainLookupByName = xenUnifiedDomainLookupByName, /* 0.0.3 */
.domainSuspend = xenUnifiedDomainSuspend, /* 0.0.3 */
.domainResume = xenUnifiedDomainResume, /* 0.0.3 */
.domainShutdown = xenUnifiedDomainShutdown, /* 0.0.3 */
.domainShutdownFlags = xenUnifiedDomainShutdownFlags, /* 0.9.10 */
.domainReboot = xenUnifiedDomainReboot, /* 0.1.0 */
.domainDestroy = xenUnifiedDomainDestroy, /* 0.0.3 */
.domainDestroyFlags = xenUnifiedDomainDestroyFlags, /* 0.9.4 */
.domainGetOSType = xenUnifiedDomainGetOSType, /* 0.0.3 */
.domainGetMaxMemory = xenUnifiedDomainGetMaxMemory, /* 0.0.3 */
.domainSetMaxMemory = xenUnifiedDomainSetMaxMemory, /* 0.0.3 */
.domainSetMemory = xenUnifiedDomainSetMemory, /* 0.1.1 */
.domainGetInfo = xenUnifiedDomainGetInfo, /* 0.0.3 */
.domainGetState = xenUnifiedDomainGetState, /* 0.9.2 */
.domainSave = xenUnifiedDomainSave, /* 0.0.3 */
.domainSaveFlags = xenUnifiedDomainSaveFlags, /* 0.9.4 */
.domainManagedSave = xenUnifiedDomainManagedSave, /* 1.0.1 */
.domainHasManagedSaveImage = xenUnifiedDomainHasManagedSaveImage, /* 1.0.1 */
.domainManagedSaveRemove = xenUnifiedDomainManagedSaveRemove, /* 1.0.1 */
.domainRestore = xenUnifiedDomainRestore, /* 0.0.3 */
.domainRestoreFlags = xenUnifiedDomainRestoreFlags, /* 0.9.4 */
.domainCoreDump = xenUnifiedDomainCoreDump, /* 0.1.9 */
.domainSetVcpus = xenUnifiedDomainSetVcpus, /* 0.1.4 */
.domainSetVcpusFlags = xenUnifiedDomainSetVcpusFlags, /* 0.8.5 */
.domainGetVcpusFlags = xenUnifiedDomainGetVcpusFlags, /* 0.8.5 */
.domainPinVcpu = xenUnifiedDomainPinVcpu, /* 0.1.4 */
.domainGetVcpus = xenUnifiedDomainGetVcpus, /* 0.1.4 */
.domainGetMaxVcpus = xenUnifiedDomainGetMaxVcpus, /* 0.2.1 */
.domainGetXMLDesc = xenUnifiedDomainGetXMLDesc, /* 0.0.3 */
.connectDomainXMLFromNative = xenUnifiedConnectDomainXMLFromNative, /* 0.6.4 */
.connectDomainXMLToNative = xenUnifiedConnectDomainXMLToNative, /* 0.6.4 */
.connectListDefinedDomains = xenUnifiedConnectListDefinedDomains, /* 0.1.1 */
.connectNumOfDefinedDomains = xenUnifiedConnectNumOfDefinedDomains, /* 0.1.5 */
.domainCreate = xenUnifiedDomainCreate, /* 0.1.1 */
.domainCreateWithFlags = xenUnifiedDomainCreateWithFlags, /* 0.8.2 */
.domainDefineXML = xenUnifiedDomainDefineXML, /* 0.1.1 */
.domainUndefine = xenUnifiedDomainUndefine, /* 0.1.1 */
.domainUndefineFlags = xenUnifiedDomainUndefineFlags, /* 0.9.4 */
.domainAttachDevice = xenUnifiedDomainAttachDevice, /* 0.1.9 */
.domainAttachDeviceFlags = xenUnifiedDomainAttachDeviceFlags, /* 0.7.7 */
.domainDetachDevice = xenUnifiedDomainDetachDevice, /* 0.1.9 */
.domainDetachDeviceFlags = xenUnifiedDomainDetachDeviceFlags, /* 0.7.7 */
.domainUpdateDeviceFlags = xenUnifiedDomainUpdateDeviceFlags, /* 0.8.0 */
.domainGetAutostart = xenUnifiedDomainGetAutostart, /* 0.4.4 */
.domainSetAutostart = xenUnifiedDomainSetAutostart, /* 0.4.4 */
.domainGetSchedulerType = xenUnifiedDomainGetSchedulerType, /* 0.2.3 */
.domainGetSchedulerParameters = xenUnifiedDomainGetSchedulerParameters, /* 0.2.3 */
.domainGetSchedulerParametersFlags = xenUnifiedDomainGetSchedulerParametersFlags, /* 0.9.2 */
.domainSetSchedulerParameters = xenUnifiedDomainSetSchedulerParameters, /* 0.2.3 */
.domainSetSchedulerParametersFlags = xenUnifiedDomainSetSchedulerParametersFlags, /* 0.9.2 */
.domainMigratePrepare = xenUnifiedDomainMigratePrepare, /* 0.3.2 */
.domainMigratePerform = xenUnifiedDomainMigratePerform, /* 0.3.2 */
.domainMigrateFinish = xenUnifiedDomainMigrateFinish, /* 0.3.2 */
.domainBlockStats = xenUnifiedDomainBlockStats, /* 0.3.2 */
.domainInterfaceStats = xenUnifiedDomainInterfaceStats, /* 0.3.2 */
.domainBlockPeek = xenUnifiedDomainBlockPeek, /* 0.4.4 */
.nodeGetCellsFreeMemory = xenUnifiedNodeGetCellsFreeMemory, /* 0.3.3 */
.nodeGetFreeMemory = xenUnifiedNodeGetFreeMemory, /* 0.3.3 */
.connectDomainEventRegister = xenUnifiedConnectDomainEventRegister, /* 0.5.0 */
.connectDomainEventDeregister = xenUnifiedConnectDomainEventDeregister, /* 0.5.0 */
.nodeDeviceDettach = xenUnifiedNodeDeviceDettach, /* 0.6.1 */
.nodeDeviceDetachFlags = xenUnifiedNodeDeviceDetachFlags, /* 1.0.5 */
.nodeDeviceReAttach = xenUnifiedNodeDeviceReAttach, /* 0.6.1 */
.nodeDeviceReset = xenUnifiedNodeDeviceReset, /* 0.6.1 */
.connectIsEncrypted = xenUnifiedConnectIsEncrypted, /* 0.7.3 */
.connectIsSecure = xenUnifiedConnectIsSecure, /* 0.7.3 */
.domainIsActive = xenUnifiedDomainIsActive, /* 0.7.3 */
.domainIsPersistent = xenUnifiedDomainIsPersistent, /* 0.7.3 */
.domainIsUpdated = xenUnifiedDomainIsUpdated, /* 0.8.6 */
.connectDomainEventRegisterAny = xenUnifiedConnectDomainEventRegisterAny, /* 0.8.0 */
.connectDomainEventDeregisterAny = xenUnifiedConnectDomainEventDeregisterAny, /* 0.8.0 */
.domainOpenConsole = xenUnifiedDomainOpenConsole, /* 0.8.6 */
.connectIsAlive = xenUnifiedConnectIsAlive, /* 0.9.8 */
.nodeSuspendForDuration = xenUnifiedNodeSuspendForDuration, /* 0.9.8 */
.nodeGetMemoryParameters = xenUnifiedNodeGetMemoryParameters, /* 0.10.2 */
.nodeSetMemoryParameters = xenUnifiedNodeSetMemoryParameters, /* 0.10.2 */
};
/**
2008-11-21 12:16:08 +00:00
* xenRegister:
*
* Register xen related drivers
*
* Returns the driver priority or -1 in case of error.
*/
int
xenRegister(void)
{
if (virRegisterStateDriver(&state_driver) == -1) return -1;
2009-01-22 17:49:41 +00:00
return virRegisterDriver(&xenUnifiedDriver);
}
/**
* xenUnifiedDomainInfoListFree:
*
* Free the Domain Info List
*/
void
xenUnifiedDomainInfoListFree(xenUnifiedDomainInfoListPtr list)
{
size_t i;
2009-01-15 01:21:36 +00:00
if (list == NULL)
return;
for (i = 0; i < list->count; i++) {
VIR_FREE(list->doms[i]->name);
VIR_FREE(list->doms[i]);
}
VIR_FREE(list->doms);
VIR_FREE(list);
}
/**
* xenUnifiedAddDomainInfo:
*
* Add name and uuid to the domain info list
*
* Returns: 0 on success, -1 on failure
*/
int
xenUnifiedAddDomainInfo(xenUnifiedDomainInfoListPtr list,
int id, char *name,
unsigned char *uuid)
{
xenUnifiedDomainInfoPtr info;
int n;
/* check if we already have this callback on our list */
for (n = 0; n < list->count; n++) {
if (STREQ(list->doms[n]->name, name) &&
!memcmp(list->doms[n]->uuid, uuid, VIR_UUID_BUFLEN)) {
VIR_DEBUG("WARNING: dom already tracked");
return -1;
}
}
if (VIR_ALLOC(info) < 0)
goto error;
if (VIR_STRDUP(info->name, name) < 0)
goto error;
memcpy(info->uuid, uuid, VIR_UUID_BUFLEN);
info->id = id;
/* Make space on list */
if (VIR_APPEND_ELEMENT(list->doms, list->count, info) < 0)
goto error;
return 0;
error:
if (info)
VIR_FREE(info->name);
VIR_FREE(info);
return -1;
}
/**
* xenUnifiedRemoveDomainInfo:
*
* Removes name and uuid to the domain info list
*
* Returns: 0 on success, -1 on failure
*/
int
xenUnifiedRemoveDomainInfo(xenUnifiedDomainInfoListPtr list,
int id, char *name,
unsigned char *uuid)
{
size_t i;
for (i = 0; i < list->count; i++) {
if (list->doms[i]->id == id &&
STREQ(list->doms[i]->name, name) &&
!memcmp(list->doms[i]->uuid, uuid, VIR_UUID_BUFLEN)) {
VIR_FREE(list->doms[i]->name);
VIR_FREE(list->doms[i]);
VIR_DELETE_ELEMENT(list->doms, i, list->count);
return 0;
}
}
return -1;
}
/**
* xenUnifiedDomainEventDispatch:
2009-01-21 18:11:14 +00:00
* @priv: the connection to dispatch events on
* @event: the event to dispatch
*
* Dispatch domain events to registered callbacks
*
2009-01-21 18:11:14 +00:00
* The caller must hold the lock in 'priv' before invoking
*
*/
void xenUnifiedDomainEventDispatch(xenUnifiedPrivatePtr priv,
virObjectEventPtr event)
{
2009-01-21 18:11:14 +00:00
if (!priv)
2008-12-04 21:09:20 +00:00
return;
virObjectEventStateQueue(priv->domainEvents, event);
2009-01-21 18:11:14 +00:00
}
void xenUnifiedLock(xenUnifiedPrivatePtr priv)
{
virMutexLock(&priv->lock);
}
void xenUnifiedUnlock(xenUnifiedPrivatePtr priv)
{
virMutexUnlock(&priv->lock);
}