# Stateful drivers are useful only when building the daemon.
if test "$with_libvirtd" = "no" ; then
with_qemu=no
- with_xen=no
with_lxc=no
with_libxl=no
with_uml=no
dnl Virtualization drivers check
dnl
-LIBVIRT_DRIVER_ARG_XEN
LIBVIRT_DRIVER_ARG_QEMU
LIBVIRT_DRIVER_ARG_OPENVZ
LIBVIRT_DRIVER_ARG_VMWARE
LIBVIRT_DRIVER_ARG_NETWORK
LIBVIRT_DRIVER_ARG_INTERFACE
-LIBVIRT_DRIVER_CHECK_XEN
LIBVIRT_DRIVER_CHECK_QEMU
LIBVIRT_DRIVER_CHECK_OPENVZ
LIBVIRT_DRIVER_CHECK_VMWARE
LIBVIRT_DRIVER_CHECK_NETWORK
LIBVIRT_DRIVER_CHECK_INTERFACE
-AM_CONDITIONAL([WITH_XENCONFIG], [test "$with_libxl" = "yes" || test "$with_xen" = "yes"])
+AM_CONDITIONAL([WITH_XENCONFIG], [test "$with_libxl" = "yes"])
dnl
AC_MSG_NOTICE([])
AC_MSG_NOTICE([Drivers])
AC_MSG_NOTICE([])
-LIBVIRT_DRIVER_RESULT_XEN
LIBVIRT_DRIVER_RESULT_QEMU
LIBVIRT_DRIVER_RESULT_UML
LIBVIRT_DRIVER_RESULT_OPENVZ
LIBVIRT_RESULT_UDEV
LIBVIRT_RESULT_VIRTUALPORT
LIBVIRT_RESULT_XDR
-LIBVIRT_RESULT_XEN
LIBVIRT_RESULT_XENAPI
LIBVIRT_RESULT_YAJL
AC_MSG_NOTICE([])
+++ /dev/null
-dnl The XEN driver
-dnl
-dnl Copyright (C) 2016 Red Hat, Inc.
-dnl
-dnl This library is free software; you can redistribute it and/or
-dnl modify it under the terms of the GNU Lesser General Public
-dnl License as published by the Free Software Foundation; either
-dnl version 2.1 of the License, or (at your option) any later version.
-dnl
-dnl This library is distributed in the hope that it will be useful,
-dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
-dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-dnl Lesser General Public License for more details.
-dnl
-dnl You should have received a copy of the GNU Lesser General Public
-dnl License along with this library. If not, see
-dnl <http://www.gnu.org/licenses/>.
-dnl
-
-AC_DEFUN([LIBVIRT_DRIVER_ARG_XEN], [
- LIBVIRT_ARG_WITH_FEATURE([XEN], [XEN], [check])
- LIBVIRT_ARG_WITH_FEATURE([XEN_INOTIFY], [XEN inotify], [check])
-])
-
-AC_DEFUN([LIBVIRT_DRIVER_CHECK_XEN], [
- old_LIBS="$LIBS"
- old_CFLAGS="$CFLAGS"
- XEN_LIBS=""
- XEN_CFLAGS=""
- fail=0
-
- dnl search for the Xen store library
- dnl Either use the provided path, or make use of pkgconfig
- dnl Xen versions prior 4.9 had no pkgconfig file
- if test "$with_xen" != "no" ; then
- xen_path_provided="no"
- if test "$with_xen" != "yes" && test "$with_xen" != "check" ; then
- XEN_CFLAGS="-I$with_xen/include"
- XEN_LIBS="-L$with_xen/lib64 -L$with_xen/lib"
- xen_path_provided="yes"
- fi
-
- if test "$xen_path_provided" = "no" ; then
- PKG_CHECK_MODULES([XEN], [xenstore], [
- with_xen=yes
- ], [
- fail=1
- ])
- fi
- dnl manual check if either path was provided or pkgconfig does not exist
- if test "$xen_path_provided" = "yes" || test "$fail" = 1 ; then
- CFLAGS="$CFLAGS $XEN_CFLAGS"
- LIBS="$LIBS $XEN_LIBS"
- fail=0
- AC_CHECK_LIB([xenstore], [xs_read], [
- with_xen=yes
- XEN_LIBS="$XEN_LIBS -lxenstore"
- ],[
- if test "$with_xen" = "yes"; then
- fail=1
- fi
- with_xen=no
- ])
- fi
- fi
-
- if test "$with_xen" != "no" ; then
- dnl In Xen 4.2, xs.h is deprecated in favor of xenstore.h.
- AC_CHECK_HEADERS([xenstore.h])
- AC_CHECK_HEADERS([xen/xen.h xen/version.h xen/dom0_ops.h],,[
- if test "$with_xen" = "yes"; then
- fail=1
- fi
- with_xen=no
- ],
-[#include <stdio.h>
-#include <stdint.h>
-])
- fi
-
- if test "$with_xen" != "no" ; then
- dnl Search for the location of <xen/{linux,sys}/privcmd.h>.
- found=
- AC_CHECK_HEADERS([xen/sys/privcmd.h xen/linux/privcmd.h], [found=yes; break;], [],
- [#include <stdio.h>
- #include <stdint.h>
- #include <xen/xen.h>
- ])
- if test "x$found" != "xyes"; then
- if test "$with_xen" = "yes"; then
- fail=1
- fi
- with_xen=no
- fi
- fi
-
- LIBS="$old_LIBS"
- CFLAGS="$old_CFLAGS"
-
- if test $fail = 1; then
- AC_MSG_ERROR([You must install the Xen development package to compile Xen driver with -lxenstore])
- fi
-
- if test "$with_xen" = "yes"; then
- AC_DEFINE_UNQUOTED([WITH_XEN], 1, [whether Xen driver is enabled])
- fi
-
- AM_CONDITIONAL([WITH_XEN], [test "$with_xen" = "yes"])
- AC_SUBST([XEN_CFLAGS])
- AC_SUBST([XEN_LIBS])
-
- dnl
- dnl check for kernel headers required by xen_inotify
- dnl
- if test "$with_xen" != "yes"; then
- with_xen_inotify=no
- fi
- if test "$with_xen_inotify" != "no"; then
- AC_CHECK_HEADER([sys/inotify.h], [
- with_xen_inotify=yes
- ], [
- if test "$with_xen_inotify" = "check"; then
- with_xen_inotify=no
- AC_MSG_NOTICE([Header file <sys/inotify.h> is required for Xen Inotify support, disabling it])
- else
- AC_MSG_ERROR([Header file <sys/inotify.h> is required for Xen Inotify support!])
- fi
- 0])
- fi
- if test "$with_xen_inotify" = "yes"; then
- AC_DEFINE_UNQUOTED([WITH_XEN_INOTIFY], 1, [whether Xen inotify sub-driver is enabled])
- fi
- AM_CONDITIONAL([WITH_XEN_INOTIFY], [test "$with_xen_inotify" = "yes"])
-])
-
-AC_DEFUN([LIBVIRT_RESULT_XEN], [
- LIBVIRT_RESULT_LIB([XEN])
-])
-
-AC_DEFUN([LIBVIRT_DRIVER_RESULT_XEN], [
- LIBVIRT_RESULT([XEN], [$with_xen])
-])
src/vz/vz_sdk.c
src/vz/vz_utils.c
src/vz/vz_utils.h
-src/xen/block_stats.c
-src/xen/xen_driver.c
-src/xen/xen_hypervisor.c
-src/xen/xen_inotify.c
-src/xen/xend_internal.c
-src/xen/xm_internal.c
-src/xen/xs_internal.c
src/xenapi/xenapi_driver.c
src/xenapi/xenapi_utils.c
src/xenconfig/xen_common.c
include bhyve/Makefile.inc.am
include xenconfig/Makefile.inc.am
include libxl/Makefile.inc.am
-include xen/Makefile.inc.am
include xenapi/Makefile.inc.am
include vz/Makefile.inc.am
include lxc/Makefile.inc.am
+++ /dev/null
-XEN_DRIVER_SOURCES = \
- xen/block_stats.c \
- xen/block_stats.h \
- xen/xen_hypervisor.c \
- xen/xen_hypervisor.h \
- xen/xen_driver.c \
- xen/xen_driver.h \
- xen/xend_internal.c \
- xen/xend_internal.h \
- xen/xm_internal.c \
- xen/xm_internal.h \
- xen/xs_internal.c \
- xen/xs_internal.h \
- $(NULL)
-
-XEN_DRIVER_INOTIFY_SOURCES = \
- xen/xen_inotify.c \
- xen/xen_inotify.h \
- $(NULL)
-
-if WITH_XEN_INOTIFY
-XEN_DRIVER_SOURCES += $(XEN_DRIVER_INOTIFY_SOURCES)
-endif WITH_XEN_INOTIFY
-
-DRIVER_SOURCE_FILES += $(XEN_DRIVER_SOURCES)
-STATEFUL_DRIVER_SOURCE_FILES += $(XEN_DRIVER_SOURCES)
-EXTRA_DIST += $(XEN_DRIVER_SOURCES) $(XEN_DRIVER_INOTIFY_SOURCES)
-
-if WITH_XEN
-noinst_LTLIBRARIES += libvirt_driver_xen_impl.la
-libvirt_driver_xen_la_SOURCES =
-libvirt_driver_xen_la_LIBADD = \
- libvirt_driver_xen_impl.la \
- libvirt.la \
- ../gnulib/lib/libgnu.la \
- $(NULL)
-mod_LTLIBRARIES += libvirt_driver_xen.la
-libvirt_driver_xen_la_LDFLAGS = $(AM_LDFLAGS_MOD_NOUNDEF)
-
-libvirt_driver_xen_impl_la_CFLAGS = \
- $(XEN_CFLAGS) \
- -I$(srcdir)/access \
- -I$(srcdir)/conf \
- -I$(srcdir)/xenconfig \
- $(AM_CFLAGS) \
- $(NULL)
-libvirt_driver_xen_impl_la_LDFLAGS = $(AM_LDFLAGS)
-libvirt_driver_xen_impl_la_LIBADD = \
- $(XEN_LIBS) \
- libvirt_xenconfig.la \
- $(NULL)
-libvirt_driver_xen_impl_la_SOURCES = $(XEN_DRIVER_SOURCES)
-
-INSTALL_DATA_DIRS += xen
-
-install-data-xen:
- $(MKDIR_P) "$(DESTDIR)$(localstatedir)/lib/libvirt/xen"
-
-uninstall-data-xen:
- rmdir "$(DESTDIR)$(localstatedir)/lib/libvirt/xen" ||:
-
-endif WITH_XEN
-
-.PHONY: \
- install-data-xen \
- uninstall-data-xen \
- $(NULL)
+++ /dev/null
-/*
- * Linux block and network stats.
- *
- * Copyright (C) 2007-2009, 2013 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>
-
-/* This file only applies on Linux. */
-#ifdef __linux__
-
-# include <stdio.h>
-# include <stdlib.h>
-# include <fcntl.h>
-# include <string.h>
-# include <unistd.h>
-# include <regex.h>
-
-# if HAVE_XENSTORE_H
-# include <xenstore.h>
-# else
-# include <xs.h>
-# endif
-
-# include "virerror.h"
-# include "datatypes.h"
-# include "block_stats.h"
-# include "viralloc.h"
-# include "virfile.h"
-# include "virstring.h"
-
-# define VIR_FROM_THIS VIR_FROM_STATS_LINUX
-
-
-/*-------------------- Xen: block stats --------------------*/
-
-# include <linux/major.h>
-
-/* This is normally defined in <linux/major.h> but previously we
- * hard-coded it. So if it's not defined, hard-code again.
- */
-# ifndef XENVBD_MAJOR
-# define XENVBD_MAJOR 202
-# endif
-
-static int64_t
-read_stat(const char *path)
-{
- char str[64];
- long long r;
- size_t i;
- FILE *fp;
-
- fp = fopen(path, "r");
- if (!fp)
- return -1;
-
- /* read, but don't bail out before closing */
- i = fread(str, 1, sizeof(str) - 1, fp);
-
- if (VIR_FCLOSE(fp) != 0 /* disk error */
- || i < 1) /* ensure we read at least one byte */
- return -1;
-
- str[i] = '\0'; /* make sure the string is nul-terminated */
- if (virStrToLong_ll(str, NULL, 10, &r) < 0)
- return -1;
-
- return r;
-}
-
-static int64_t
-read_bd_stat(int device, int domid, const char *str)
-{
- static const char *paths[] = {
- "/sys/bus/xen-backend/devices/vbd-%d-%d/statistics/%s",
- "/sys/bus/xen-backend/devices/tap-%d-%d/statistics/%s",
- "/sys/devices/xen-backend/vbd-%d-%d/statistics/%s",
- "/sys/devices/xen-backend/tap-%d-%d/statistics/%s"
- };
-
- size_t i;
- char *path;
- int64_t r;
-
- for (i = 0; i < ARRAY_CARDINALITY(paths); ++i) {
- if (virAsprintf(&path, paths[i], domid, device, str) < 0)
- return -1;
-
- r = read_stat(path);
-
- VIR_FREE(path);
-
- if (r >= 0)
- return r;
- }
-
- return -1;
-}
-
-/* In Xenstore, /local/domain/0/backend/vbd/<domid>/<device>/state,
- * if available, must be XenbusStateConnected (= 4), otherwise there
- * is no connected device.
- */
-static int
-check_bd_connected(xenUnifiedPrivatePtr priv, int device, int domid)
-{
- char s[256], *rs;
- int r;
- unsigned len = 0;
-
- /* This code assumes we're connected if we can't get to
- * xenstore, etc.
- */
- if (!priv->xshandle) return 1;
- snprintf(s, sizeof(s), "/local/domain/0/backend/vbd/%d/%d/state",
- domid, device);
- s[sizeof(s) - 1] = '\0';
-
- rs = xs_read(priv->xshandle, 0, s, &len);
- if (!rs) return 1;
- if (len == 0) {
- /* Hmmm ... we can get to xenstore but it returns an empty
- * string instead of an error. Assume it's not connected
- * in this case.
- */
- VIR_FREE(rs);
- return 0;
- }
-
- r = STREQ(rs, "4");
- VIR_FREE(rs);
- return r;
-}
-
-static int
-read_bd_stats(xenUnifiedPrivatePtr priv,
- int device, int domid, virDomainBlockStatsPtr stats)
-{
- stats->rd_req = read_bd_stat(device, domid, "rd_req");
- stats->rd_bytes = read_bd_stat(device, domid, "rd_sect");
- stats->wr_req = read_bd_stat(device, domid, "wr_req");
- stats->wr_bytes = read_bd_stat(device, domid, "wr_sect");
- stats->errs = read_bd_stat(device, domid, "oo_req");
-
- /* None of the files were found - it's likely that this version
- * of Xen is an old one which just doesn't support stats collection.
- */
- if (stats->rd_req == -1 && stats->rd_bytes == -1 &&
- stats->wr_req == -1 && stats->wr_bytes == -1 &&
- stats->errs == -1) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Failed to read any block statistics for domain %d"),
- domid);
- return -1;
- }
-
- /* If stats are all zero then either there really isn't any block
- * device activity, or there is no connected front end device
- * in which case there are no stats.
- */
- if (stats->rd_req == 0 && stats->rd_bytes == 0 &&
- stats->wr_req == 0 && stats->wr_bytes == 0 &&
- stats->errs == 0 &&
- !check_bd_connected(priv, device, domid)) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Frontend block device not connected for domain %d"),
- domid);
- return -1;
- }
-
- /* 'Bytes' was really sectors when we read it. Scale up by
- * an assumed sector size.
- */
- if (stats->rd_bytes > 0) {
- if (stats->rd_bytes >= ((unsigned long long)1)<<(63-9)) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("stats->rd_bytes would overflow 64 bit counter for domain %d"),
- domid);
- return -1;
- }
- stats->rd_bytes *= 512;
- }
- if (stats->wr_bytes > 0) {
- if (stats->wr_bytes >= ((unsigned long long)1)<<(63-9)) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("stats->wr_bytes would overflow 64 bit counter for domain %d"),
- domid);
- return -1;
- }
- stats->wr_bytes *= 512;
- }
-
- return 0;
-}
-
-static int
-disk_re_match(const char *regex, const char *path, int *part)
-{
- regex_t myreg;
- int err;
- int retval;
- regmatch_t pmatch[3];
-
- retval = 0;
-
- err = regcomp(&myreg, regex, REG_EXTENDED);
- if (err != 0)
- return 0;
-
- err = regexec(&myreg, path, 3, pmatch, 0);
-
- if (err == 0) {
- /* OK, we have a match; see if we have a partition */
- *part = 0;
- retval = 1;
- if (pmatch[1].rm_so != -1) {
- if (virStrToLong_i(path + pmatch[1].rm_so, NULL, 10, part) < 0)
- retval = 0;
- }
- }
-
- regfree(&myreg);
-
- return retval;
-}
-
-int
-xenLinuxDomainDeviceID(int domid, const char *path)
-{
- int major, minor;
- int part;
- int retval;
- char *mod_path;
-
- int const scsi_majors[] = { SCSI_DISK0_MAJOR, SCSI_DISK1_MAJOR,
- SCSI_DISK2_MAJOR, SCSI_DISK3_MAJOR,
- SCSI_DISK4_MAJOR, SCSI_DISK5_MAJOR,
- SCSI_DISK6_MAJOR, SCSI_DISK7_MAJOR,
- SCSI_DISK8_MAJOR, SCSI_DISK9_MAJOR,
- SCSI_DISK10_MAJOR, SCSI_DISK11_MAJOR,
- SCSI_DISK12_MAJOR, SCSI_DISK13_MAJOR,
- SCSI_DISK14_MAJOR, SCSI_DISK15_MAJOR };
- int const ide_majors[] = { IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR,
- IDE4_MAJOR, IDE5_MAJOR, IDE6_MAJOR, IDE7_MAJOR,
- IDE8_MAJOR, IDE9_MAJOR };
-
- /*
- * Possible block device majors & partition ranges. This
- * matches the ranges supported in Xend xen/util/blkif.py
- *
- * hdNM: N=a-t, M=1-63, major={IDE0_MAJOR -> IDE9_MAJOR}
- * sdNM: N=a-z,aa-iv, M=1-15, major={SCSI_DISK0_MAJOR -> SCSI_DISK15_MAJOR}
- * xvdNM: N=a-p M=1-15, major=XENVBD_MAJOR
- * xvdNM: N=q-z,aa-iz M=1-15, major=(1<<28)
- *
- * The path for statistics will be
- *
- * /sys/devices/xen-backend/(vbd|tap)-{domid}-{devid}/statistics/{...}
- */
-
- if (strlen(path) >= 5 && STRPREFIX(path, "/dev/")) {
- if (VIR_STRDUP(mod_path, path) < 0)
- return -1;
- } else {
- if (virAsprintf(&mod_path, "/dev/%s", path) < 0)
- return -1;
- }
-
- retval = -1;
-
- if (disk_re_match("/dev/sd[a-z]([1-9]|1[0-5])?$", mod_path, &part)) {
- major = scsi_majors[(mod_path[7] - 'a') / 16];
- minor = ((mod_path[7] - 'a') % 16) * 16 + part;
- retval = major * 256 + minor;
- }
- else if (disk_re_match("/dev/sd[a-h][a-z]([1-9]|1[0-5])?$",
- mod_path, &part) ||
- disk_re_match("/dev/sdi[a-v]([1-9]|1[0-5])?$",
- mod_path, &part)) {
- major = scsi_majors[((mod_path[7] - 'a' + 1) * 26 + (mod_path[8] - 'a')) / 16];
- minor = (((mod_path[7] - 'a' + 1) * 26 + (mod_path[8] - 'a')) % 16)
- * 16 + part;
- retval = major * 256 + minor;
- }
- else if (disk_re_match("/dev/hd[a-t]([1-9]|[1-5][0-9]|6[0-3])?$",
- mod_path, &part)) {
- major = ide_majors[(mod_path[7] - 'a') / 2];
- minor = ((mod_path[7] - 'a') % 2) * 64 + part;
- retval = major * 256 + minor;
- }
- else if (disk_re_match("/dev/xvd[a-p]([1-9]|1[0-5])?$", mod_path, &part))
- retval = (202 << 8) + ((mod_path[8] - 'a') << 4) + part;
- else if (disk_re_match("/dev/xvd[q-z]([1-9]|1[0-5])?$", mod_path, &part))
- retval = (1 << 28) + ((mod_path[8] - 'a') << 8) + part;
- else if (disk_re_match("/dev/xvd[a-i][a-z]([1-9]|1[0-5])?$",
- mod_path, &part))
- retval = (1 << 28) + (((mod_path[8] - 'a' + 1) * 26 + (mod_path[9] - 'a')) << 8) + part;
- /*
- * OK, we've now checked the common case (things that work); check the
- * beginning of the strings for better error messages
- */
- else if (strlen(mod_path) >= 7 && STRPREFIX(mod_path, "/dev/sd"))
- virReportError(VIR_ERR_INVALID_ARG,
- _("invalid path, device names must be in the range "
- "sda[1-15] - sdiv[1-15] for domain %d"), domid);
- else if (strlen(mod_path) >= 7 && STRPREFIX(mod_path, "/dev/hd"))
- virReportError(VIR_ERR_INVALID_ARG,
- _("invalid path, device names must be in the range "
- "hda[1-63] - hdt[1-63] for domain %d"), domid);
- else if (strlen(mod_path) >= 8 && STRPREFIX(mod_path, "/dev/xvd"))
- virReportError(VIR_ERR_INVALID_ARG,
- _("invalid path, device names must be in the range "
- "xvda[1-15] - xvdiz[1-15] for domain %d"), domid);
- else
- virReportError(VIR_ERR_INVALID_ARG,
- _("unsupported path, use xvdN, hdN, or sdN for domain %d"),
- domid);
-
- VIR_FREE(mod_path);
-
- return retval;
-}
-
-int
-xenLinuxDomainBlockStats(xenUnifiedPrivatePtr priv,
- virDomainDefPtr def,
- const char *path,
- virDomainBlockStatsPtr stats)
-{
- int device = xenLinuxDomainDeviceID(def->id, path);
-
- if (device < 0)
- return -1;
-
- return read_bd_stats(priv, device, def->id, stats);
-}
-
-#endif /* __linux__ */
+++ /dev/null
-/*
- * Linux block and network stats.
- *
- * Copyright (C) 2007 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>
- */
-
-#ifndef __BLOCK_STATS_H__
-# define __BLOCK_STATS_H__
-
-# ifdef __linux__
-
-# include "xen_driver.h"
-
-int xenLinuxDomainBlockStats (xenUnifiedPrivatePtr priv,
- virDomainDefPtr def, const char *path,
- virDomainBlockStatsPtr stats);
-
-int xenLinuxDomainDeviceID(int domid, const char *dev);
-
-# endif /* __linux__ */
-
-#endif /* __STATS_LINUX_H__ */
+++ /dev/null
-/*
- * xen_driver.c: Unified Xen driver.
- *
- * Copyright (C) 2007-2015 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"
-#include "virlog.h"
-#include "datatypes.h"
-#include "xen_driver.h"
-
-#include "xen_sxpr.h"
-#include "xen_xm.h"
-#include "xen_common.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
-#include "virxml.h"
-#include "viralloc.h"
-#include "node_device_conf.h"
-#include "virpci.h"
-#include "viruuid.h"
-#include "virfdstream.h"
-#include "virfile.h"
-#include "viruri.h"
-#include "vircommand.h"
-#include "virnodesuspend.h"
-#include "virhostmem.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;
-static virSysinfoDefPtr hostsysinfo;
-
-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)
-{
- virDomainDefPtr ret;
-
- ret = xenDaemonLookupByName(conn, name);
-
- if (!ret && virGetLastError() == NULL)
- virReportError(VIR_ERR_NO_DOMAIN, __FUNCTION__);
-
- return ret;
-}
-
-
-static virDomainDefPtr xenGetDomainDefForUUID(virConnectPtr conn, const unsigned char *uuid)
-{
- virDomainDefPtr ret;
-
- ret = xenHypervisorLookupDomainByUUID(conn, uuid);
-
- /* Try xend for inactive domains. */
- if (!ret)
- 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
- * 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;
- xenUnifiedPrivatePtr priv;
- int ret;
-
- ret = xenUnifiedNodeGetInfo(conn, &nodeInfo);
- if (ret < 0)
- return;
-
- priv = conn->privateData;
-
- priv->nbNodeCells = nodeInfo.nodes;
- priv->nbNodeCpus = nodeInfo.cpus;
-}
-
-
-/**
- * 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;
- 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;
- xenUnifiedPrivatePtr priv;
-
- 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++) {
- if (!virBitmapIsBitSet(cpulist, m) &&
- (VIR_CPU_USABLE(cpumap, cpumaplen, n, m))) {
- ignore_value(virBitmapSetBit(cpulist, m));
- nb++;
- /* if all CPU are used just return NULL */
- if (nb == priv->nbNodeCpus)
- goto done;
-
- }
- }
- }
- res = virBitmapFormat(cpulist);
- }
-
- done:
- virBitmapFree(cpulist);
- VIR_FREE(cpumap);
- VIR_FREE(cpuinfo);
- return res;
-}
-
-static int
-xenUnifiedStateInitialize(bool privileged,
- virStateInhibitCallback callback ATTRIBUTE_UNUSED,
- void *opaque ATTRIBUTE_UNUSED)
-{
- /* 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);
- return 0;
-}
-
-static virStateDriver state_driver = {
- .name = "Xen",
- .stateInitialize = xenUnifiedStateInitialize,
- .stateCleanup = xenUnifiedStateCleanup,
-};
-
-/*----- 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
-#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
-static bool
-xenUnifiedXendProbe(void)
-{
- 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,
- const virDomainDef *def,
- virCapsPtr caps ATTRIBUTE_UNUSED,
- unsigned int parseFlags ATTRIBUTE_UNUSED,
- void *opaque ATTRIBUTE_UNUSED,
- void *parseOpaque 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 &&
- def->os.type != VIR_DOMAIN_OSTYPE_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;
- }
-
- if (dev->type == VIR_DOMAIN_DEVICE_VIDEO && dev->data.video->vram == 0) {
- switch (dev->data.video->type) {
- case VIR_DOMAIN_VIDEO_TYPE_VGA:
- case VIR_DOMAIN_VIDEO_TYPE_CIRRUS:
- case VIR_DOMAIN_VIDEO_TYPE_VMVGA:
- dev->data.video->vram = 16 * 1024;
- break;
-
- case VIR_DOMAIN_VIDEO_TYPE_XEN:
- /* Original Xen PVFB hardcoded to 4 MB */
- dev->data.video->vram = 4 * 1024;
- break;
-
- case VIR_DOMAIN_VIDEO_TYPE_QXL:
- /* Use 64M as the minimal video video memory for qxl device */
- return 64 * 1024;
- }
- }
-
- return 0;
-}
-
-
-static int
-xenDomainDefPostParse(virDomainDefPtr def,
- virCapsPtr caps ATTRIBUTE_UNUSED,
- unsigned int parseFlags ATTRIBUTE_UNUSED,
- void *opaque ATTRIBUTE_UNUSED,
- void *parseOpaque ATTRIBUTE_UNUSED)
-{
- if (!def->memballoon) {
- virDomainMemballoonDefPtr memballoon;
- if (VIR_ALLOC(memballoon) < 0)
- return -1;
-
- memballoon->model = VIR_DOMAIN_MEMBALLOON_MODEL_XEN;
- def->memballoon = memballoon;
- }
-
- /* add implicit input device */
- if (xenDomainDefAddImplicitInputDevice(def) <0)
- return -1;
-
- return 0;
-}
-
-
-virDomainDefParserConfig xenDomainDefParserConfig = {
- .macPrefix = { 0x00, 0x16, 0x3e },
- .devicesPostParseCallback = xenDomainDeviceDefPostParse,
- .domainPostParseCallback = xenDomainDefPostParse,
-};
-
-
-virDomainXMLOptionPtr
-xenDomainXMLConfInit(void)
-{
- return virDomainXMLOptionNew(&xenDomainDefParserConfig,
- NULL, NULL, NULL, NULL);
-}
-
-
-static virDrvOpenStatus
-xenUnifiedConnectOpen(virConnectPtr conn, virConnectAuthPtr auth,
- virConfPtr conf ATTRIBUTE_UNUSED,
- unsigned int flags)
-{
- xenUnifiedPrivatePtr priv;
-
- /*
- * Only the libvirtd instance can open this driver.
- * Everything else falls back to the remote driver.
- */
- if (!is_privileged)
- 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;
- if (virMutexInit(&priv->lock) < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("cannot initialize mutex"));
- VIR_FREE(priv);
- return VIR_DRV_OPEN_ERROR;
- }
-
- if (!(priv->domainEvents = virObjectEventStateNew())) {
- virMutexDestroy(&priv->lock);
- VIR_FREE(priv);
- return VIR_DRV_OPEN_ERROR;
- }
- conn->privateData = priv;
-
- priv->handle = -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;
-
- 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;
-
- xenNumaInit(conn);
-
- 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) {
- virReportSystemError(errno, _("Errored to create save dir '%s'"),
- priv->saveDir);
- 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);
- virMutexDestroy(&priv->lock);
- VIR_FREE(priv->saveDir);
- VIR_FREE(priv);
- conn->privateData = NULL;
- return VIR_DRV_OPEN_ERROR;
-}
-
-static int
-xenUnifiedConnectClose(virConnectPtr conn)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
-
- virObjectUnref(priv->caps);
- virObjectUnref(priv->xmlopt);
- virObjectUnref(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);
- 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 ((virDrvFeature) feature) {
- case VIR_DRV_FEATURE_MIGRATION_V1:
- case VIR_DRV_FEATURE_MIGRATION_DIRECT:
- return 1;
- case VIR_DRV_FEATURE_MIGRATION_V2:
- case VIR_DRV_FEATURE_MIGRATION_V3:
- case VIR_DRV_FEATURE_MIGRATION_P2P:
- case VIR_DRV_FEATURE_MIGRATE_CHANGE_PROTECTION:
- case VIR_DRV_FEATURE_FD_PASSING:
- case VIR_DRV_FEATURE_TYPED_PARAM_STRING:
- case VIR_DRV_FEATURE_XML_MIGRATABLE:
- case VIR_DRV_FEATURE_MIGRATION_OFFLINE:
- case VIR_DRV_FEATURE_MIGRATION_PARAMS:
- case VIR_DRV_FEATURE_PROGRAM_KEEPALIVE:
- case VIR_DRV_FEATURE_REMOTE:
- case VIR_DRV_FEATURE_REMOTE_CLOSE_CALLBACK:
- case VIR_DRV_FEATURE_REMOTE_EVENT_CALLBACK:
- 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)
-{
- 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;
- unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
-
- virCheckFlags(VIR_DOMAIN_START_VALIDATE, NULL);
-
- if (flags & VIR_DOMAIN_START_VALIDATE)
- parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
-
- if (!(def = virDomainDefParseString(xml, priv->caps, priv->xmlopt,
- NULL, parse_flags)))
- goto cleanup;
-
- if (virDomainCreateXMLEnsureACL(conn, def) < 0)
- goto cleanup;
-
- if (xenDaemonCreateXML(conn, def) < 0)
- goto cleanup;
-
- ret = virGetDomain(conn, def->name, def->uuid, 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;
-
- ret = virGetDomain(conn, def->name, def->uuid, 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;
-
- ret = virGetDomain(conn, def->name, def->uuid, 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;
-
- ret = virGetDomain(conn, def->name, def->uuid, 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;
-
- 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;
-
- 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)
-{
- char *ret = NULL;
- virDomainDefPtr def;
-
- if (!(def = xenGetDomainDefForDom(dom)))
- goto cleanup;
-
- if (virDomainGetOSTypeEnsureACL(dom->conn, def) < 0)
- goto cleanup;
-
- if (def->id < 0)
- ret = xenDaemonDomainGetOSType(dom->conn, def);
- else
- ret = xenHypervisorDomainGetOSType(dom->conn, def);
-
- cleanup:
- virDomainDefFree(def);
- return ret;
-}
-
-
-static unsigned long long
-xenUnifiedDomainGetMaxMemory(virDomainPtr dom)
-{
- 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)
- ret = xenDaemonDomainGetMaxMemory(dom->conn, def);
- else
- ret = xenHypervisorGetMaxMemory(dom->conn, def);
-
- cleanup:
- virDomainDefFree(def);
- return ret;
-}
-
-static int
-xenUnifiedDomainSetMaxMemory(virDomainPtr dom, unsigned long memory)
-{
- int ret = -1;
- virDomainDefPtr def;
-
- if (!(def = xenGetDomainDefForDom(dom)))
- goto cleanup;
-
- if (virDomainSetMaxMemoryEnsureACL(dom->conn, def) < 0)
- goto cleanup;
-
- if (def->id < 0)
- 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)
-{
- int ret = -1;
- virDomainDefPtr def;
-
- if (!(def = xenGetDomainDefForDom(dom)))
- goto cleanup;
-
- if (virDomainSetMemoryEnsureACL(dom->conn, def) < 0)
- goto cleanup;
-
- ret = xenDaemonDomainSetMemory(dom->conn, def, memory);
-
- cleanup:
- virDomainDefFree(def);
- return ret;
-}
-
-static int
-xenUnifiedDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
-{
- int ret = -1;
- virDomainDefPtr def;
-
- if (!(def = xenGetDomainDefForDom(dom)))
- goto cleanup;
-
- if (virDomainGetInfoEnsureACL(dom->conn, def) < 0)
- goto cleanup;
-
- if (def->id < 0)
- 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)
-{
-
- 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)
- 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)
-{
- 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);
- return -1;
- }
-
- if (!(def = xenGetDomainDefForDom(dom)))
- goto cleanup;
-
- if (virDomainSetVcpusFlagsEnsureACL(dom->conn, def, flags) < 0)
- goto cleanup;
-
- ret = xenDaemonDomainSetVcpusFlags(dom->conn, def, nvcpus, flags);
-
- cleanup:
- virDomainDefFree(def);
- return ret;
-}
-
-static int
-xenUnifiedDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus)
-{
- unsigned int flags;
-
- /* Per the documented API, it is hypervisor-dependent whether this
- * affects just _LIVE or _LIVE|_CONFIG; in xen's case, both are
- * affected. */
- flags = VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG;
-
- return xenUnifiedDomainSetVcpusFlags(dom, nvcpus, flags);
-}
-
-static int
-xenUnifiedDomainPinVcpu(virDomainPtr dom, unsigned int vcpu,
- unsigned char *cpumap, int maplen)
-{
- virDomainDefPtr def = NULL;
- int ret = -1;
-
- if (!(def = xenGetDomainDefForDom(dom)))
- goto cleanup;
-
- if (virDomainPinVcpuEnsureACL(dom->conn, def) < 0)
- goto cleanup;
-
- if (dom->id < 0)
- 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)
-{
- int ret = -1;
-
- if (dom->id < 0) {
- 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)
-{
- int ret = -1;
-
- if (dom->id < 0) {
- 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;
-
- if (virDomainGetVcpusFlagsEnsureACL(dom->conn, def, flags) < 0)
- goto cleanup;
-
- ret = xenUnifiedDomainGetVcpusFlagsInternal(dom, def, flags);
-
- cleanup:
- virDomainDefFree(def);
- return ret;
-}
-
-static int
-xenUnifiedDomainGetMaxVcpus(virDomainPtr dom)
-{
- return xenUnifiedDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_LIVE |
- VIR_DOMAIN_VCPU_MAXIMUM));
-}
-
-static char *
-xenUnifiedDomainGetXMLDesc(virDomainPtr dom, unsigned int flags)
-{
- xenUnifiedPrivatePtr priv = dom->conn->privateData;
- virDomainDefPtr minidef = NULL;
- virDomainDefPtr def = NULL;
- char *ret = NULL;
- char *cpus = NULL;
-
- if (!(minidef = xenGetDomainDefForDom(dom)))
- goto cleanup;
-
- if (virDomainGetXMLDescEnsureACL(dom->conn, minidef, flags) < 0)
- goto cleanup;
-
- xenUnifiedLock(priv);
- cpus = xenDomainUsedCpus(dom, minidef);
- xenUnifiedUnlock(priv);
- def = xenDaemonDomainGetXMLDesc(dom->conn, minidef, cpus);
-
- if (def)
- ret = virDomainDefFormat(def, priv->caps,
- virDomainDefFormatConvertXMLFlags(flags));
-
- cleanup:
- VIR_FREE(cpus);
- 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;
- 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 = virConfReadString(config, 0);
- if (!conf)
- goto cleanup;
-
- def = xenParseXM(conf, priv->caps, priv->xmlopt);
- } else if (STREQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
- if (xenGetDomIdFromSxprString(config, &id) < 0)
- goto cleanup;
- xenUnifiedLock(priv);
- tty = xenStoreDomainGetConsolePath(conn, id);
- vncport = xenStoreDomainGetVNCPort(conn, id);
- xenUnifiedUnlock(priv);
- def = xenParseSxprString(config, tty,
- vncport, priv->caps, priv->xmlopt);
- }
- if (!def)
- goto cleanup;
-
- ret = virDomainDefFormat(def, priv->caps, 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,
- NULL,
- VIR_DOMAIN_DEF_PARSE_INACTIVE)))
- goto cleanup;
-
- if (STREQ(format, XEN_CONFIG_FORMAT_XM)) {
- int len = MAX_CONFIG_SIZE;
- conf = xenFormatXM(conn, def);
- 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)) {
- ret = xenFormatSxpr(conn, def);
- }
-
- 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)
-{
- 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 (xenDaemonDomainDefineXML(dconn, def) < 0)
- goto cleanup;
- }
-
- ret = virGetDomain(dconn, minidef->name, minidef->uuid, minidef->id);
-
- cleanup:
- virDomainDefFree(def);
- virDomainDefFree(minidef);
- return ret;
-}
-
-static int
-xenUnifiedConnectListDefinedDomains(virConnectPtr conn, char **const names,
- int maxnames)
-{
- if (virConnectListDefinedDomainsEnsureACL(conn) < 0)
- return -1;
-
- return xenDaemonListDefinedDomains(conn, names, maxnames);
-}
-
-static int
-xenUnifiedConnectNumOfDefinedDomains(virConnectPtr conn)
-{
- if (virConnectNumOfDefinedDomainsEnsureACL(conn) < 0)
- return -1;
-
- 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;
- }
-
- 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
-xenUnifiedDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flags)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- virDomainDefPtr def = NULL;
- virDomainPtr ret = NULL;
- unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
-
- virCheckFlags(VIR_DOMAIN_DEFINE_VALIDATE, NULL);
-
- if (flags & VIR_DOMAIN_DEFINE_VALIDATE)
- parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
-
- if (!(def = virDomainDefParseString(xml, priv->caps, priv->xmlopt,
- NULL, parse_flags)))
- goto cleanup;
-
- if (virXMLCheckIllegalChars("name", def->name, "\n") < 0)
- goto cleanup;
-
- if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0)
- goto cleanup;
-
- if (xenDaemonDomainDefineXML(conn, def) < 0)
- goto cleanup;
- ret = virGetDomain(conn, def->name, def->uuid, -1);
-
- cleanup:
- virDomainDefFree(def);
- return ret;
-}
-
-static virDomainPtr
-xenUnifiedDomainDefineXML(virConnectPtr conn, const char *xml)
-{
- return xenUnifiedDomainDefineXMLFlags(conn, xml, 0);
-}
-
-static int
-xenUnifiedDomainUndefineFlags(virDomainPtr dom, unsigned int flags)
-{
- virDomainDefPtr def = NULL;
- int ret = -1;
-
- virCheckFlags(0, -1);
-
- if (!(def = xenGetDomainDefForDom(dom)))
- goto cleanup;
-
- if (virDomainUndefineFlagsEnsureACL(dom->conn, def) < 0)
- goto cleanup;
-
- 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)
-{
- unsigned int flags = VIR_DOMAIN_DEVICE_MODIFY_LIVE;
- virDomainDefPtr def = NULL;
- int ret = -1;
-
- /*
- * HACK: xend does not support changing live config without also touching
- * persistent config. We add the extra flag here to make this API work
- */
- flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
-
- if (!(def = xenGetDomainDefForDom(dom)))
- goto cleanup;
-
- if (virDomainAttachDeviceEnsureACL(dom->conn, def) < 0)
- goto cleanup;
-
- ret = xenDaemonAttachDeviceFlags(dom->conn, def, xml, flags);
-
- cleanup:
- virDomainDefFree(def);
- return ret;
-}
-
-static int
-xenUnifiedDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
- unsigned int flags)
-{
- virDomainDefPtr def = NULL;
- int ret = -1;
-
- if (!(def = xenGetDomainDefForDom(dom)))
- goto cleanup;
-
- if (virDomainAttachDeviceFlagsEnsureACL(dom->conn, def, flags) < 0)
- goto cleanup;
-
- ret = xenDaemonAttachDeviceFlags(dom->conn, def, xml, flags);
-
- cleanup:
- virDomainDefFree(def);
- return ret;
-}
-
-static int
-xenUnifiedDomainDetachDevice(virDomainPtr dom, const char *xml)
-{
- unsigned int flags = VIR_DOMAIN_DEVICE_MODIFY_LIVE;
- virDomainDefPtr def = NULL;
- int ret = -1;
-
- /*
- * HACK: xend does not support changing live config without also touching
- * persistent config. We add the extra flag here to make this API work
- */
- flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
-
- if (!(def = xenGetDomainDefForDom(dom)))
- goto cleanup;
-
- if (virDomainDetachDeviceEnsureACL(dom->conn, def) < 0)
- goto cleanup;
-
- ret = xenDaemonDetachDeviceFlags(dom->conn, def, xml, flags);
-
- cleanup:
- virDomainDefFree(def);
- return ret;
-}
-
-static int
-xenUnifiedDomainDetachDeviceFlags(virDomainPtr dom, const char *xml,
- unsigned int flags)
-{
- virDomainDefPtr def = NULL;
- int ret = -1;
-
- if (!(def = xenGetDomainDefForDom(dom)))
- goto cleanup;
-
- if (virDomainDetachDeviceFlagsEnsureACL(dom->conn, def, flags) < 0)
- goto cleanup;
-
- 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)
-{
- virDomainDefPtr def = NULL;
- int ret = -1;
-
- if (!(def = xenGetDomainDefForDom(dom)))
- goto cleanup;
-
- if (virDomainGetAutostartEnsureACL(dom->conn, def) < 0)
- goto cleanup;
-
- ret = xenDaemonDomainGetAutostart(dom->conn, def, autostart);
-
- cleanup:
- virDomainDefFree(def);
- return ret;
-}
-
-static int
-xenUnifiedDomainSetAutostart(virDomainPtr dom, int autostart)
-{
- virDomainDefPtr def = NULL;
- int ret = -1;
-
- if (!(def = xenGetDomainDefForDom(dom)))
- goto cleanup;
-
- if (virDomainSetAutostartEnsureACL(dom->conn, def) < 0)
- goto cleanup;
-
- ret = xenDaemonDomainSetAutostart(dom->conn, def, autostart);
-
- cleanup:
- virDomainDefFree(def);
- return ret;
-}
-
-static char *
-xenUnifiedDomainGetSchedulerType(virDomainPtr dom, int *nparams)
-{
- virDomainDefPtr def = NULL;
- char *ret = NULL;
-
- if (!(def = xenGetDomainDefForDom(dom)))
- goto cleanup;
-
- if (virDomainGetSchedulerTypeEnsureACL(dom->conn, def) < 0)
- goto cleanup;
-
- if (dom->id < 0)
- 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)
-{
- 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)
- 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)
-{
- 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)
- 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 *device,
- virDomainInterfaceStatsPtr stats)
-{
- virDomainDefPtr def = NULL;
- virDomainNetDefPtr net = NULL;
- int ret = -1;
-
- if (!(def = xenGetDomainDefForDom(dom)))
- goto cleanup;
-
- if (virDomainInterfaceStatsEnsureACL(dom->conn, def) < 0)
- goto cleanup;
-
- if (!(net = virDomainNetFind(def, device)))
- goto cleanup;
-
- ret = xenHypervisorDomainInterfaceStats(def, net->ifname, 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)
-{
- virDomainDefPtr def = NULL;
- int ret = -1;
-
- virCheckFlags(0, -1);
-
- if (!(def = xenGetDomainDefForDom(dom)))
- goto cleanup;
-
- if (virDomainBlockPeekEnsureACL(dom->conn, def) < 0)
- goto cleanup;
-
- 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;
- int ret = 0;
-
- if (virConnectDomainEventRegisterEnsureACL(conn) < 0)
- return -1;
-
- xenUnifiedLock(priv);
-
- if (priv->xsWatch == -1) {
- virReportUnsupportedError();
- xenUnifiedUnlock(priv);
- return -1;
- }
-
- if (virDomainEventStateRegister(conn, priv->domainEvents,
- callback, opaque, freefunc) < 0)
- ret = -1;
-
- xenUnifiedUnlock(priv);
- return ret;
-}
-
-
-static int
-xenUnifiedConnectDomainEventDeregister(virConnectPtr conn,
- virConnectDomainEventCallback callback)
-{
- int ret = 0;
- xenUnifiedPrivatePtr priv = conn->privateData;
-
- if (virConnectDomainEventDeregisterEnsureACL(conn) < 0)
- return -1;
-
- xenUnifiedLock(priv);
-
- if (priv->xsWatch == -1) {
- virReportUnsupportedError();
- xenUnifiedUnlock(priv);
- return -1;
- }
-
- if (virDomainEventStateDeregister(conn,
- priv->domainEvents,
- callback) < 0)
- ret = -1;
-
- xenUnifiedUnlock(priv);
- return ret;
-}
-
-
-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) {
- 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)
-{
- int ret = 0;
- xenUnifiedPrivatePtr priv = conn->privateData;
-
- if (virConnectDomainEventDeregisterAnyEnsureACL(conn) < 0)
- return -1;
-
- xenUnifiedLock(priv);
-
- if (priv->xsWatch == -1) {
- virReportUnsupportedError();
- xenUnifiedUnlock(priv);
- return -1;
- }
-
- if (virObjectEventStateDeregisterID(conn,
- priv->domainEvents,
- callbackID, true) < 0)
- ret = -1;
-
- xenUnifiedUnlock(priv);
- return ret;
-}
-
-
-static int
-xenUnifiedNodeDeviceGetPCIInfo(virNodeDevicePtr dev,
- unsigned *domain,
- unsigned *bus,
- unsigned *slot,
- unsigned *function)
-{
- 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);
- if (!def)
- goto out;
-
- cap = def->caps;
- while (cap) {
- if (cap->data.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);
- goto out;
- }
-
- ret = 0;
- out:
- virNodeDeviceDefFree(def);
- VIR_FREE(xml);
- return ret;
-}
-
-static int
-xenUnifiedNodeDeviceDetachFlags(virNodeDevicePtr dev,
- const char *driverName,
- unsigned int flags)
-{
- virPCIDevicePtr pci;
- unsigned domain, bus, slot, function;
- int ret = -1;
-
- virCheckFlags(0, -1);
-
- if (xenUnifiedNodeDeviceGetPCIInfo(dev, &domain, &bus, &slot, &function) < 0)
- return -1;
-
- pci = virPCIDeviceNew(domain, bus, slot, function);
- if (!pci)
- return -1;
-
- if (!driverName) {
- virPCIDeviceSetStubDriver(pci, VIR_PCI_STUB_DRIVER_XEN);
- } else {
- virReportError(VIR_ERR_INVALID_ARG,
- _("unknown driver name '%s'"), driverName);
- goto out;
- }
-
- if (virPCIDeviceDetach(pci, NULL, NULL) < 0)
- goto out;
-
- ret = 0;
- out:
- virPCIDeviceFree(pci);
- 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;
-}
-
-static int
-xenUnifiedNodeDeviceReAttach(virNodeDevicePtr dev)
-{
- virPCIDevicePtr pci;
- unsigned domain, bus, slot, function;
- int ret = -1;
- int domid;
-
- if (xenUnifiedNodeDeviceGetPCIInfo(dev, &domain, &bus, &slot, &function) < 0)
- return -1;
-
- pci = virPCIDeviceNew(domain, bus, slot, function);
- 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)
- goto out;
-
- ret = 0;
- out:
- virPCIDeviceFree(pci);
- return ret;
-}
-
-static int
-xenUnifiedNodeDeviceReset(virNodeDevicePtr dev)
-{
- virPCIDevicePtr pci;
- unsigned domain, bus, slot, function;
- int ret = -1;
-
- if (xenUnifiedNodeDeviceGetPCIInfo(dev, &domain, &bus, &slot, &function) < 0)
- return -1;
-
- pci = virPCIDeviceNew(domain, bus, slot, function);
- if (!pci)
- return -1;
-
- if (virPCIDeviceReset(pci, NULL, NULL) < 0)
- goto out;
-
- ret = 0;
- out:
- virPCIDeviceFree(pci);
- 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;
- }
-
- if (chr->source->type != VIR_DOMAIN_CHR_TYPE_PTY) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("character device %s is not using a PTY"),
- dev_name ? dev_name : NULLSTR(chr->info.alias));
- 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 virHostMemGetParameters(params, nparams, flags);
-}
-
-
-static int
-xenUnifiedNodeSetMemoryParameters(virConnectPtr conn,
- virTypedParameterPtr params,
- int nparams,
- unsigned int flags)
-{
- if (virNodeSetMemoryParametersEnsureACL(conn) < 0)
- return -1;
-
- return virHostMemSetParameters(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 virNodeSuspend(target, duration, flags);
-}
-
-
-/*----- Register with libvirt.c, and initialize Xen drivers. -----*/
-
-/* The interface which we export upwards to libvirt.c. */
-static virHypervisorDriver xenUnifiedHypervisorDriver = {
- .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 */
- .domainDefineXMLFlags = xenUnifiedDomainDefineXMLFlags, /* 1.2.12 */
- .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 */
-};
-
-
-static virConnectDriver xenUnifiedConnectDriver = {
- .hypervisorDriver = &xenUnifiedHypervisorDriver,
-};
-
-/**
- * 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;
-
- return virRegisterConnectDriver(&xenUnifiedConnectDriver,
- true);
-}
-
-/**
- * xenUnifiedDomainInfoListFree:
- *
- * Free the Domain Info List
- */
-void
-xenUnifiedDomainInfoListFree(xenUnifiedDomainInfoListPtr list)
-{
- size_t i;
-
- 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:
- * @priv: the connection to dispatch events on
- * @event: the event to dispatch
- *
- * Dispatch domain events to registered callbacks
- *
- * The caller must hold the lock in 'priv' before invoking
- *
- */
-void xenUnifiedDomainEventDispatch(xenUnifiedPrivatePtr priv,
- virObjectEventPtr event)
-{
- if (!priv)
- return;
-
- virObjectEventStateQueue(priv->domainEvents, event);
-}
-
-void xenUnifiedLock(xenUnifiedPrivatePtr priv)
-{
- virMutexLock(&priv->lock);
-}
-
-void xenUnifiedUnlock(xenUnifiedPrivatePtr priv)
-{
- virMutexUnlock(&priv->lock);
-}
+++ /dev/null
-/*
- * xen_driver.h: Unified Xen driver.
- *
- * Copyright (C) 2007, 2010-2011 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>
- */
-
-#ifndef __VIR_XEN_UNIFIED_H__
-# define __VIR_XEN_UNIFIED_H__
-
-# include "internal.h"
-# include "capabilities.h"
-# include "driver.h"
-# include "domain_conf.h"
-# include "xs_internal.h"
-# if WITH_XEN_INOTIFY
-# include "xen_inotify.h"
-# endif
-# include "domain_event.h"
-# include "virhash.h"
-
-# ifndef HAVE_WINSOCK2_H
-# include <sys/un.h>
-# include <netinet/in.h>
-# else
-# include <winsock2.h>
-# endif
-
-# include <xen/xen.h>
-
-/* xen-unstable changeset 19788 removed MAX_VIRT_CPUS from public
- * headers. Its semantic was retained with XEN_LEGACY_MAX_VCPUS.
- * Ensure MAX_VIRT_CPUS is defined accordingly.
- */
-# if !defined(MAX_VIRT_CPUS) && defined(XEN_LEGACY_MAX_VCPUS)
-# define MAX_VIRT_CPUS XEN_LEGACY_MAX_VCPUS
-# endif
-
-int xenRegister (void);
-
-# define XEN_UNIFIED_HYPERVISOR_OFFSET 0
-# define XEN_UNIFIED_XEND_OFFSET 1
-# define XEN_UNIFIED_XS_OFFSET 2
-# define XEN_UNIFIED_XM_OFFSET 3
-
-# if WITH_XEN_INOTIFY
-# define XEN_UNIFIED_INOTIFY_OFFSET 4
-# define XEN_UNIFIED_NR_DRIVERS 5
-# else
-# define XEN_UNIFIED_NR_DRIVERS 4
-# endif
-
-# define MIN_XEN_GUEST_SIZE 64 /* 64 megabytes */
-
-# define XEND_DOMAINS_DIR "/var/lib/xend/domains"
-
-# define XEN_SCHED_SEDF_NPARAM 6
-# define XEN_SCHED_CRED_NPARAM 2
-
-/* The set of migration flags explicitly supported by xen. */
-# define XEN_MIGRATION_FLAGS \
- (VIR_MIGRATE_LIVE | \
- VIR_MIGRATE_UNDEFINE_SOURCE | \
- VIR_MIGRATE_PAUSED | \
- VIR_MIGRATE_PERSIST_DEST)
-
-
-typedef struct xenXMConfCache *xenXMConfCachePtr;
-typedef struct xenXMConfCache {
- time_t refreshedAt;
- char *filename;
- virDomainDefPtr def;
-} xenXMConfCache;
-
-/* xenUnifiedDomainInfoPtr:
- * The minimal state we have about active domains
- * This is the minmal info necessary to still get a
- * virDomainPtr when the domain goes away
- */
-struct _xenUnifiedDomainInfo {
- int id;
- char *name;
- unsigned char uuid[VIR_UUID_BUFLEN];
-};
-typedef struct _xenUnifiedDomainInfo xenUnifiedDomainInfo;
-typedef xenUnifiedDomainInfo *xenUnifiedDomainInfoPtr;
-
-struct _xenUnifiedDomainInfoList {
- size_t count;
- xenUnifiedDomainInfoPtr *doms;
-};
-typedef struct _xenUnifiedDomainInfoList xenUnifiedDomainInfoList;
-typedef xenUnifiedDomainInfoList *xenUnifiedDomainInfoListPtr;
-
-/* xenUnifiedPrivatePtr:
- *
- * Per-connection private data, stored in conn->privateData. All Xen
- * low-level drivers access parts of this structure.
- */
-struct _xenUnifiedPrivate {
- virMutex lock;
-
- /* These initial vars are initialized in Open method
- * and readonly thereafter, so can be used without
- * holding the lock
- */
- virCapsPtr caps;
- virDomainXMLOptionPtr xmlopt;
- int handle; /* Xen hypervisor handle */
-
- /* connection to xend */
- struct sockaddr_storage addr;
- socklen_t addrlen;
- int addrfamily;
- int addrprotocol;
-
- /* Keep track of the drivers which opened. We keep a yes/no flag
- * here for each driver, corresponding to the array drivers in
- * xen_unified.c.
- */
- int opened[XEN_UNIFIED_NR_DRIVERS];
-
-
- /*
- * Everything from this point onwards must be protected
- * by the lock when used
- */
-
- struct xs_handle *xshandle; /* handle to talk to the xenstore */
-
-
- /* A list of xenstore watches */
- xenStoreWatchListPtr xsWatchList;
- int xsWatch;
- /* A list of active domain name/uuids */
- xenUnifiedDomainInfoListPtr activeDomainList;
-
- /* NUMA topology info cache */
- int nbNodeCells;
- int nbNodeCpus;
-
- virObjectEventStatePtr domainEvents;
-
- /* Location of config files, either /etc
- * or /var/lib/xen */
- const char *configDir;
- /* Location of managed save dir, default /var/lib/libvirt/xen/save */
- char *saveDir;
-
-# if WITH_XEN_INOTIFY
- /* The inotify fd */
- int inotifyFD;
- int inotifyWatch;
-
- int useXenConfigCache;
- xenUnifiedDomainInfoListPtr configInfoList;
-# endif
-
- /* For the 'xm' driver */
- /* Primary config file name -> virDomainDef map */
- virHashTablePtr configCache;
- /* Domain name to config file name */
- virHashTablePtr nameConfigMap;
- /* So we don't refresh too often */
- time_t lastRefresh;
-};
-
-typedef struct _xenUnifiedPrivate *xenUnifiedPrivatePtr;
-
-char *xenDomainUsedCpus(virDomainPtr dom, virDomainDefPtr def);
-
-virDomainXMLOptionPtr xenDomainXMLConfInit(void);
-
-void xenUnifiedDomainInfoListFree(xenUnifiedDomainInfoListPtr info);
-int xenUnifiedAddDomainInfo(xenUnifiedDomainInfoListPtr info,
- int id, char *name,
- unsigned char *uuid);
-int xenUnifiedRemoveDomainInfo(xenUnifiedDomainInfoListPtr info,
- int id, char *name,
- unsigned char *uuid);
-void xenUnifiedDomainEventDispatch (xenUnifiedPrivatePtr priv,
- virObjectEventPtr event);
-unsigned long xenUnifiedVersion(void);
-int xenUnifiedConnectGetMaxVcpus(virConnectPtr conn, const char *type);
-
-void xenUnifiedLock(xenUnifiedPrivatePtr priv);
-void xenUnifiedUnlock(xenUnifiedPrivatePtr priv);
-
-#endif /* __VIR_XEN_UNIFIED_H__ */
+++ /dev/null
-/*
- * xen_hypervisor.c: direct access to Xen hypervisor level
- *
- * Copyright (C) 2005-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/>.
- *
- * Daniel Veillard <veillard@redhat.com>
- */
-
-#include <config.h>
-
-#include <stdio.h>
-#include <string.h>
-/* required for uint8_t, uint32_t, etc ... */
-#include <stdint.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <sys/ioctl.h>
-#include <limits.h>
-#include <regex.h>
-#include <errno.h>
-
-#ifdef __sun
-# include <sys/systeminfo.h>
-
-# include <priv.h>
-
-# ifndef PRIV_XVM_CONTROL
-# define PRIV_XVM_CONTROL ((const char *)"xvm_control")
-# endif
-
-#endif /* __sun */
-
-/* required for dom0_getdomaininfo_t */
-#include <xen/dom0_ops.h>
-#include <xen/version.h>
-#ifdef HAVE_XEN_LINUX_PRIVCMD_H
-# include <xen/linux/privcmd.h>
-#else
-# ifdef HAVE_XEN_SYS_PRIVCMD_H
-# include <xen/sys/privcmd.h>
-# endif
-#endif
-
-/* required for shutdown flags */
-#include <xen/sched.h>
-
-#include "virerror.h"
-#include "virlog.h"
-#include "datatypes.h"
-#include "driver.h"
-#include "xen_driver.h"
-#include "xen_hypervisor.h"
-#include "xs_internal.h"
-#include "virnetdevtap.h"
-#include "block_stats.h"
-#include "xend_internal.h"
-#include "virbuffer.h"
-#include "capabilities.h"
-#include "viralloc.h"
-#include "virthread.h"
-#include "virfile.h"
-#include "virnodesuspend.h"
-#include "virtypedparam.h"
-#include "virendian.h"
-#include "virstring.h"
-
-#define VIR_FROM_THIS VIR_FROM_XEN
-
-VIR_LOG_INIT("xen.xen_hypervisor");
-
-/*
- * so far there is 2 versions of the structures usable for doing
- * hypervisor calls.
- */
-/* the old one */
-typedef struct v0_hypercall_struct {
- unsigned long op;
- unsigned long arg[5];
-} v0_hypercall_t;
-
-#ifdef __linux__
-# define XEN_V0_IOCTL_HYPERCALL_CMD \
- _IOC(_IOC_NONE, 'P', 0, sizeof(v0_hypercall_t))
-/* the new one */
-typedef struct v1_hypercall_struct
-{
- uint64_t op;
- uint64_t arg[5];
-} v1_hypercall_t;
-# define XEN_V1_IOCTL_HYPERCALL_CMD \
- _IOC(_IOC_NONE, 'P', 0, sizeof(v1_hypercall_t))
-typedef v1_hypercall_t hypercall_t;
-#elif defined(__sun)
-typedef privcmd_hypercall_t hypercall_t;
-#else
-# error "unsupported platform"
-#endif
-
-#ifndef __HYPERVISOR_sysctl
-# define __HYPERVISOR_sysctl 35
-#endif
-#ifndef __HYPERVISOR_domctl
-# define __HYPERVISOR_domctl 36
-#endif
-
-#define SYS_IFACE_MIN_VERS_NUMA 4
-
-static int xen_ioctl_hypercall_cmd;
-static struct xenHypervisorVersions hv_versions = {
- .hv = 0,
- .hypervisor = 2,
- .sys_interface = -1,
- .dom_interface = -1,
-};
-
-static int kb_per_pages;
-
-/* Regular expressions used by xenHypervisorGetCapabilities, and
- * compiled once by xenHypervisorInit. Note that these are POSIX.2
- * extended regular expressions (regex(7)).
- */
-static const char *flags_hvm_re = "^flags[[:blank:]]+:.* (vmx|svm)[[:space:]]";
-static regex_t flags_hvm_rec;
-static const char *flags_pae_re = "^flags[[:blank:]]+:.* pae[[:space:]]";
-static regex_t flags_pae_rec;
-static const char *xen_cap_re = "(xen|hvm)-[[:digit:]]+\\.[[:digit:]]+-(x86_32|x86_64|ia64|powerpc64)(p|be)?";
-static regex_t xen_cap_rec;
-
-/*
- * The content of the structures for a getdomaininfolist system hypercall
- */
-#ifndef DOMFLAGS_DYING
-# define DOMFLAGS_DYING (1<<0) /* Domain is scheduled to die. */
-# define DOMFLAGS_HVM (1<<1) /* Domain is HVM */
-# define DOMFLAGS_SHUTDOWN (1<<2) /* The guest OS has shut down. */
-# define DOMFLAGS_PAUSED (1<<3) /* Currently paused by control software. */
-# define DOMFLAGS_BLOCKED (1<<4) /* Currently blocked pending an event. */
-# define DOMFLAGS_RUNNING (1<<5) /* Domain is currently running. */
-# define DOMFLAGS_CPUMASK 255 /* CPU to which this domain is bound. */
-# define DOMFLAGS_CPUSHIFT 8
-# define DOMFLAGS_SHUTDOWNMASK 255 /* DOMFLAGS_SHUTDOWN guest-supplied code. */
-# define DOMFLAGS_SHUTDOWNSHIFT 16
-#endif
-
-/*
- * These flags explain why a system is in the state of "shutdown". Normally,
- * They are defined in xen/sched.h
- */
-#ifndef SHUTDOWN_poweroff
-# define SHUTDOWN_poweroff 0 /* Domain exited normally. Clean up and kill. */
-# define SHUTDOWN_reboot 1 /* Clean up, kill, and then restart. */
-# define SHUTDOWN_suspend 2 /* Clean up, save suspend info, kill. */
-# define SHUTDOWN_crash 3 /* Tell controller we've crashed. */
-#endif
-
-#define XEN_V0_OP_GETDOMAININFOLIST 38
-#define XEN_V1_OP_GETDOMAININFOLIST 38
-#define XEN_V2_OP_GETDOMAININFOLIST 6
-
-struct xen_v0_getdomaininfo {
- domid_t domain; /* the domain number */
- uint32_t flags; /* flags, see before */
- uint64_t tot_pages; /* total number of pages used */
- uint64_t max_pages; /* maximum number of pages allowed */
- unsigned long shared_info_frame; /* MFN of shared_info struct */
- uint64_t cpu_time; /* CPU time used */
- uint32_t nr_online_vcpus; /* Number of VCPUs currently online. */
- uint32_t max_vcpu_id; /* Maximum VCPUID in use by this domain. */
- uint32_t ssidref;
- xen_domain_handle_t handle;
-};
-typedef struct xen_v0_getdomaininfo xen_v0_getdomaininfo;
-
-struct xen_v2_getdomaininfo {
- domid_t domain; /* the domain number */
- uint32_t flags; /* flags, see before */
- uint64_t tot_pages; /* total number of pages used */
- uint64_t max_pages; /* maximum number of pages allowed */
- uint64_t shared_info_frame; /* MFN of shared_info struct */
- uint64_t cpu_time; /* CPU time used */
- uint32_t nr_online_vcpus; /* Number of VCPUs currently online. */
- uint32_t max_vcpu_id; /* Maximum VCPUID in use by this domain. */
- uint32_t ssidref;
- xen_domain_handle_t handle;
-};
-typedef struct xen_v2_getdomaininfo xen_v2_getdomaininfo;
-
-
-/* As of Hypervisor Call v2, DomCtl v5 we are now 8-byte aligned
- even on 32-bit archs when dealing with uint64_t */
-#define ALIGN_64 __attribute__((aligned(8)))
-
-struct xen_v2d5_getdomaininfo {
- domid_t domain; /* the domain number */
- uint32_t flags; /* flags, see before */
- uint64_t tot_pages ALIGN_64; /* total number of pages used */
- uint64_t max_pages ALIGN_64; /* maximum number of pages allowed */
- uint64_t shared_info_frame ALIGN_64; /* MFN of shared_info struct */
- uint64_t cpu_time ALIGN_64; /* CPU time used */
- uint32_t nr_online_vcpus; /* Number of VCPUs currently online. */
- uint32_t max_vcpu_id; /* Maximum VCPUID in use by this domain. */
- uint32_t ssidref;
- xen_domain_handle_t handle;
-};
-typedef struct xen_v2d5_getdomaininfo xen_v2d5_getdomaininfo;
-
-struct xen_v2d6_getdomaininfo {
- domid_t domain; /* the domain number */
- uint32_t flags; /* flags, see before */
- uint64_t tot_pages ALIGN_64; /* total number of pages used */
- uint64_t max_pages ALIGN_64; /* maximum number of pages allowed */
- uint64_t shr_pages ALIGN_64; /* number of shared pages */
- uint64_t shared_info_frame ALIGN_64; /* MFN of shared_info struct */
- uint64_t cpu_time ALIGN_64; /* CPU time used */
- uint32_t nr_online_vcpus; /* Number of VCPUs currently online. */
- uint32_t max_vcpu_id; /* Maximum VCPUID in use by this domain. */
- uint32_t ssidref;
- xen_domain_handle_t handle;
-};
-typedef struct xen_v2d6_getdomaininfo xen_v2d6_getdomaininfo;
-
-struct xen_v2d7_getdomaininfo {
- domid_t domain; /* the domain number */
- uint32_t flags; /* flags, see before */
- uint64_t tot_pages ALIGN_64; /* total number of pages used */
- uint64_t max_pages ALIGN_64; /* maximum number of pages allowed */
- uint64_t shr_pages ALIGN_64; /* number of shared pages */
- uint64_t shared_info_frame ALIGN_64; /* MFN of shared_info struct */
- uint64_t cpu_time ALIGN_64; /* CPU time used */
- uint32_t nr_online_vcpus; /* Number of VCPUs currently online. */
- uint32_t max_vcpu_id; /* Maximum VCPUID in use by this domain. */
- uint32_t ssidref;
- xen_domain_handle_t handle;
- uint32_t cpupool;
-};
-typedef struct xen_v2d7_getdomaininfo xen_v2d7_getdomaininfo;
-
-struct xen_v2d8_getdomaininfo {
- domid_t domain; /* the domain number */
- uint32_t flags; /* flags, see before */
- uint64_t tot_pages ALIGN_64; /* total number of pages used */
- uint64_t max_pages ALIGN_64; /* maximum number of pages allowed */
- uint64_t shr_pages ALIGN_64; /* number of shared pages */
- uint64_t paged_pages ALIGN_64; /* number of paged pages */
- uint64_t shared_info_frame ALIGN_64; /* MFN of shared_info struct */
- uint64_t cpu_time ALIGN_64; /* CPU time used */
- uint32_t nr_online_vcpus; /* Number of VCPUs currently online. */
- uint32_t max_vcpu_id; /* Maximum VCPUID in use by this domain. */
- uint32_t ssidref;
- xen_domain_handle_t handle;
- uint32_t cpupool;
-};
-typedef struct xen_v2d8_getdomaininfo xen_v2d8_getdomaininfo;
-
-struct xen_v2d9_getdomaininfo {
- domid_t domain; /* the domain number */
- uint32_t flags; /* flags, see before */
- uint64_t tot_pages ALIGN_64; /* total number of pages used */
- uint64_t max_pages ALIGN_64; /* maximum number of pages allowed */
- uint64_t outstanding_pages ALIGN_64;
- uint64_t shr_pages ALIGN_64; /* number of shared pages */
- uint64_t paged_pages ALIGN_64; /* number of paged pages */
- uint64_t shared_info_frame ALIGN_64; /* MFN of shared_info struct */
- uint64_t cpu_time ALIGN_64; /* CPU time used */
- uint32_t nr_online_vcpus; /* Number of VCPUs currently online. */
- uint32_t max_vcpu_id; /* Maximum VCPUID in use by this domain. */
- uint32_t ssidref;
- xen_domain_handle_t handle;
- uint32_t cpupool;
-};
-typedef struct xen_v2d9_getdomaininfo xen_v2d9_getdomaininfo;
-
-union xen_getdomaininfo {
- struct xen_v0_getdomaininfo v0;
- struct xen_v2_getdomaininfo v2;
- struct xen_v2d5_getdomaininfo v2d5;
- struct xen_v2d6_getdomaininfo v2d6;
- struct xen_v2d7_getdomaininfo v2d7;
- struct xen_v2d8_getdomaininfo v2d8;
- struct xen_v2d9_getdomaininfo v2d9;
-};
-typedef union xen_getdomaininfo xen_getdomaininfo;
-
-union xen_getdomaininfolist {
- struct xen_v0_getdomaininfo *v0;
- struct xen_v2_getdomaininfo *v2;
- struct xen_v2d5_getdomaininfo *v2d5;
- struct xen_v2d6_getdomaininfo *v2d6;
- struct xen_v2d7_getdomaininfo *v2d7;
- struct xen_v2d8_getdomaininfo *v2d8;
- struct xen_v2d9_getdomaininfo *v2d9;
-};
-typedef union xen_getdomaininfolist xen_getdomaininfolist;
-
-
-struct xen_v2_getschedulerid {
- uint32_t sched_id; /* Get Scheduler ID from Xen */
-};
-typedef struct xen_v2_getschedulerid xen_v2_getschedulerid;
-
-
-union xen_getschedulerid {
- struct xen_v2_getschedulerid *v2;
-};
-typedef union xen_getschedulerid xen_getschedulerid;
-
-struct xen_v2s4_availheap {
- uint32_t min_bitwidth; /* Smallest address width (zero if don't care). */
- uint32_t max_bitwidth; /* Largest address width (zero if don't care). */
- int32_t node; /* NUMA node (-1 for sum across all nodes). */
- uint64_t avail_bytes; /* Bytes available in the specified region. */
-};
-
-typedef struct xen_v2s4_availheap xen_v2s4_availheap;
-
-struct xen_v2s5_availheap {
- uint32_t min_bitwidth; /* Smallest address width (zero if don't care). */
- uint32_t max_bitwidth; /* Largest address width (zero if don't care). */
- int32_t node; /* NUMA node (-1 for sum across all nodes). */
- uint64_t avail_bytes ALIGN_64; /* Bytes available in the specified region. */
-};
-
-typedef struct xen_v2s5_availheap xen_v2s5_availheap;
-
-
-#define XEN_GETDOMAININFOLIST_ALLOC(domlist, size) \
- (hv_versions.hypervisor < 2 ? \
- (VIR_ALLOC_N(domlist.v0, (size)) == 0) : \
- (hv_versions.dom_interface >= 9 ? \
- (VIR_ALLOC_N(domlist.v2d9, (size)) == 0) : \
- (hv_versions.dom_interface == 8 ? \
- (VIR_ALLOC_N(domlist.v2d8, (size)) == 0) : \
- (hv_versions.dom_interface == 7 ? \
- (VIR_ALLOC_N(domlist.v2d7, (size)) == 0) : \
- (hv_versions.dom_interface == 6 ? \
- (VIR_ALLOC_N(domlist.v2d6, (size)) == 0) : \
- (hv_versions.dom_interface == 5 ? \
- (VIR_ALLOC_N(domlist.v2d5, (size)) == 0) : \
- (VIR_ALLOC_N(domlist.v2, (size)) == 0)))))))
-
-#define XEN_GETDOMAININFOLIST_FREE(domlist) \
- (hv_versions.hypervisor < 2 ? \
- VIR_FREE(domlist.v0) : \
- (hv_versions.dom_interface >= 9 ? \
- VIR_FREE(domlist.v2d9) : \
- (hv_versions.dom_interface == 8 ? \
- VIR_FREE(domlist.v2d8) : \
- (hv_versions.dom_interface == 7 ? \
- VIR_FREE(domlist.v2d7) : \
- (hv_versions.dom_interface == 6 ? \
- VIR_FREE(domlist.v2d6) : \
- (hv_versions.dom_interface == 5 ? \
- VIR_FREE(domlist.v2d5) : \
- VIR_FREE(domlist.v2)))))))
-
-#define XEN_GETDOMAININFOLIST_CLEAR(domlist, size) \
- (hv_versions.hypervisor < 2 ? \
- memset(domlist.v0, 0, sizeof(*domlist.v0) * size) : \
- (hv_versions.dom_interface >= 9 ? \
- memset(domlist.v2d9, 0, sizeof(*domlist.v2d9) * size) : \
- (hv_versions.dom_interface == 8 ? \
- memset(domlist.v2d8, 0, sizeof(*domlist.v2d8) * size) : \
- (hv_versions.dom_interface == 7 ? \
- memset(domlist.v2d7, 0, sizeof(*domlist.v2d7) * size) : \
- (hv_versions.dom_interface == 6 ? \
- memset(domlist.v2d6, 0, sizeof(*domlist.v2d6) * size) : \
- (hv_versions.dom_interface == 5 ? \
- memset(domlist.v2d5, 0, sizeof(*domlist.v2d5) * size) : \
- memset(domlist.v2, 0, sizeof(*domlist.v2) * size)))))))
-
-#define XEN_GETDOMAININFOLIST_DOMAIN(domlist, n) \
- (hv_versions.hypervisor < 2 ? \
- domlist.v0[n].domain : \
- (hv_versions.dom_interface >= 9 ? \
- domlist.v2d9[n].domain : \
- (hv_versions.dom_interface == 8 ? \
- domlist.v2d8[n].domain : \
- (hv_versions.dom_interface == 7 ? \
- domlist.v2d7[n].domain : \
- (hv_versions.dom_interface == 6 ? \
- domlist.v2d6[n].domain : \
- (hv_versions.dom_interface == 5 ? \
- domlist.v2d5[n].domain : \
- domlist.v2[n].domain))))))
-
-#define XEN_GETDOMAININFOLIST_UUID(domlist, n) \
- (hv_versions.hypervisor < 2 ? \
- domlist.v0[n].handle : \
- (hv_versions.dom_interface >= 9 ? \
- domlist.v2d9[n].handle : \
- (hv_versions.dom_interface == 8 ? \
- domlist.v2d8[n].handle : \
- (hv_versions.dom_interface == 7 ? \
- domlist.v2d7[n].handle : \
- (hv_versions.dom_interface == 6 ? \
- domlist.v2d6[n].handle : \
- (hv_versions.dom_interface == 5 ? \
- domlist.v2d5[n].handle : \
- domlist.v2[n].handle))))))
-
-#define XEN_GETDOMAININFOLIST_DATA(domlist) \
- (hv_versions.hypervisor < 2 ? \
- (void*)(domlist->v0) : \
- (hv_versions.dom_interface >= 9 ? \
- (void*)(domlist->v2d9) : \
- (hv_versions.dom_interface == 8 ? \
- (void*)(domlist->v2d8) : \
- (hv_versions.dom_interface == 7 ? \
- (void*)(domlist->v2d7) : \
- (hv_versions.dom_interface == 6 ? \
- (void*)(domlist->v2d6) : \
- (hv_versions.dom_interface == 5 ? \
- (void*)(domlist->v2d5) : \
- (void*)(domlist->v2)))))))
-
-#define XEN_GETDOMAININFO_SIZE \
- (hv_versions.hypervisor < 2 ? \
- sizeof(xen_v0_getdomaininfo) : \
- (hv_versions.dom_interface >= 9 ? \
- sizeof(xen_v2d9_getdomaininfo) : \
- (hv_versions.dom_interface == 8 ? \
- sizeof(xen_v2d8_getdomaininfo) : \
- (hv_versions.dom_interface == 7 ? \
- sizeof(xen_v2d7_getdomaininfo) : \
- (hv_versions.dom_interface == 6 ? \
- sizeof(xen_v2d6_getdomaininfo) : \
- (hv_versions.dom_interface == 5 ? \
- sizeof(xen_v2d5_getdomaininfo) : \
- sizeof(xen_v2_getdomaininfo)))))))
-
-#define XEN_GETDOMAININFO_CLEAR(dominfo) \
- (hv_versions.hypervisor < 2 ? \
- memset(&(dominfo.v0), 0, sizeof(xen_v0_getdomaininfo)) : \
- (hv_versions.dom_interface >= 9 ? \
- memset(&(dominfo.v2d9), 0, sizeof(xen_v2d9_getdomaininfo)) : \
- (hv_versions.dom_interface == 8 ? \
- memset(&(dominfo.v2d8), 0, sizeof(xen_v2d8_getdomaininfo)) : \
- (hv_versions.dom_interface == 7 ? \
- memset(&(dominfo.v2d7), 0, sizeof(xen_v2d7_getdomaininfo)) : \
- (hv_versions.dom_interface == 6 ? \
- memset(&(dominfo.v2d6), 0, sizeof(xen_v2d6_getdomaininfo)) : \
- (hv_versions.dom_interface == 5 ? \
- memset(&(dominfo.v2d5), 0, sizeof(xen_v2d5_getdomaininfo)) : \
- memset(&(dominfo.v2), 0, sizeof(xen_v2_getdomaininfo))))))))
-
-#define XEN_GETDOMAININFO_DOMAIN(dominfo) \
- (hv_versions.hypervisor < 2 ? \
- dominfo.v0.domain : \
- (hv_versions.dom_interface >= 9 ? \
- dominfo.v2d9.domain : \
- (hv_versions.dom_interface == 8 ? \
- dominfo.v2d8.domain : \
- (hv_versions.dom_interface == 7 ? \
- dominfo.v2d7.domain : \
- (hv_versions.dom_interface == 6 ? \
- dominfo.v2d6.domain : \
- (hv_versions.dom_interface == 5 ? \
- dominfo.v2d5.domain : \
- dominfo.v2.domain))))))
-
-#define XEN_GETDOMAININFO_CPUTIME(dominfo) \
- (hv_versions.hypervisor < 2 ? \
- dominfo.v0.cpu_time : \
- (hv_versions.dom_interface >= 9 ? \
- dominfo.v2d9.cpu_time : \
- (hv_versions.dom_interface == 8 ? \
- dominfo.v2d8.cpu_time : \
- (hv_versions.dom_interface == 7 ? \
- dominfo.v2d7.cpu_time : \
- (hv_versions.dom_interface == 6 ? \
- dominfo.v2d6.cpu_time : \
- (hv_versions.dom_interface == 5 ? \
- dominfo.v2d5.cpu_time : \
- dominfo.v2.cpu_time))))))
-
-
-#define XEN_GETDOMAININFO_CPUCOUNT(dominfo) \
- (hv_versions.hypervisor < 2 ? \
- dominfo.v0.nr_online_vcpus : \
- (hv_versions.dom_interface >= 9 ? \
- dominfo.v2d9.nr_online_vcpus : \
- (hv_versions.dom_interface == 8 ? \
- dominfo.v2d8.nr_online_vcpus : \
- (hv_versions.dom_interface == 7 ? \
- dominfo.v2d7.nr_online_vcpus : \
- (hv_versions.dom_interface == 6 ? \
- dominfo.v2d6.nr_online_vcpus : \
- (hv_versions.dom_interface == 5 ? \
- dominfo.v2d5.nr_online_vcpus : \
- dominfo.v2.nr_online_vcpus))))))
-
-#define XEN_GETDOMAININFO_MAXCPUID(dominfo) \
- (hv_versions.hypervisor < 2 ? \
- dominfo.v0.max_vcpu_id : \
- (hv_versions.dom_interface >= 9 ? \
- dominfo.v2d9.max_vcpu_id : \
- (hv_versions.dom_interface == 8 ? \
- dominfo.v2d8.max_vcpu_id : \
- (hv_versions.dom_interface == 7 ? \
- dominfo.v2d7.max_vcpu_id : \
- (hv_versions.dom_interface == 6 ? \
- dominfo.v2d6.max_vcpu_id : \
- (hv_versions.dom_interface == 5 ? \
- dominfo.v2d5.max_vcpu_id : \
- dominfo.v2.max_vcpu_id))))))
-
-#define XEN_GETDOMAININFO_FLAGS(dominfo) \
- (hv_versions.hypervisor < 2 ? \
- dominfo.v0.flags : \
- (hv_versions.dom_interface >= 9 ? \
- dominfo.v2d9.flags : \
- (hv_versions.dom_interface == 8 ? \
- dominfo.v2d8.flags : \
- (hv_versions.dom_interface == 7 ? \
- dominfo.v2d7.flags : \
- (hv_versions.dom_interface == 6 ? \
- dominfo.v2d6.flags : \
- (hv_versions.dom_interface == 5 ? \
- dominfo.v2d5.flags : \
- dominfo.v2.flags))))))
-
-#define XEN_GETDOMAININFO_TOT_PAGES(dominfo) \
- (hv_versions.hypervisor < 2 ? \
- dominfo.v0.tot_pages : \
- (hv_versions.dom_interface >= 9 ? \
- dominfo.v2d9.tot_pages : \
- (hv_versions.dom_interface == 8 ? \
- dominfo.v2d8.tot_pages : \
- (hv_versions.dom_interface == 7 ? \
- dominfo.v2d7.tot_pages : \
- (hv_versions.dom_interface == 6 ? \
- dominfo.v2d6.tot_pages : \
- (hv_versions.dom_interface == 5 ? \
- dominfo.v2d5.tot_pages : \
- dominfo.v2.tot_pages))))))
-
-#define XEN_GETDOMAININFO_MAX_PAGES(dominfo) \
- (hv_versions.hypervisor < 2 ? \
- dominfo.v0.max_pages : \
- (hv_versions.dom_interface >= 9 ? \
- dominfo.v2d9.max_pages : \
- (hv_versions.dom_interface == 8 ? \
- dominfo.v2d8.max_pages : \
- (hv_versions.dom_interface == 7 ? \
- dominfo.v2d7.max_pages : \
- (hv_versions.dom_interface == 6 ? \
- dominfo.v2d6.max_pages : \
- (hv_versions.dom_interface == 5 ? \
- dominfo.v2d5.max_pages : \
- dominfo.v2.max_pages))))))
-
-#define XEN_GETDOMAININFO_UUID(dominfo) \
- (hv_versions.hypervisor < 2 ? \
- dominfo.v0.handle : \
- (hv_versions.dom_interface >= 9 ? \
- dominfo.v2d9.handle : \
- (hv_versions.dom_interface == 8 ? \
- dominfo.v2d8.handle : \
- (hv_versions.dom_interface == 7 ? \
- dominfo.v2d7.handle : \
- (hv_versions.dom_interface == 6 ? \
- dominfo.v2d6.handle : \
- (hv_versions.dom_interface == 5 ? \
- dominfo.v2d5.handle : \
- dominfo.v2.handle))))))
-
-
-static int
-lock_pages(void *addr, size_t len)
-{
-#ifdef __linux__
- if (mlock(addr, len) < 0) {
- virReportSystemError(errno,
- _("Unable to lock %zu bytes of memory"),
- len);
- return -1;
- }
- return 0;
-#elif defined(__sun)
- return 0;
-#endif
-}
-
-static int
-unlock_pages(void *addr, size_t len)
-{
-#ifdef __linux__
- if (munlock(addr, len) < 0) {
- virReportSystemError(errno,
- _("Unable to unlock %zu bytes of memory"),
- len);
- return -1;
- }
- return 0;
-#elif defined(__sun)
- return 0;
-#endif
-}
-
-
-struct xen_v0_getdomaininfolistop {
- domid_t first_domain;
- uint32_t max_domains;
- struct xen_v0_getdomaininfo *buffer;
- uint32_t num_domains;
-};
-typedef struct xen_v0_getdomaininfolistop xen_v0_getdomaininfolistop;
-
-
-struct xen_v2_getdomaininfolistop {
- domid_t first_domain;
- uint32_t max_domains;
- struct xen_v2_getdomaininfo *buffer;
- uint32_t num_domains;
-};
-typedef struct xen_v2_getdomaininfolistop xen_v2_getdomaininfolistop;
-
-/* As of HV version 2, sysctl version 3 the *buffer pointer is 64-bit aligned */
-struct xen_v2s3_getdomaininfolistop {
- domid_t first_domain;
- uint32_t max_domains;
-#ifdef __BIG_ENDIAN__
- struct {
- int __pad[(sizeof(long long) - sizeof(struct xen_v2d5_getdomaininfo *)) / sizeof(int)];
- struct xen_v2d5_getdomaininfo *v;
- } buffer;
-#else
- union {
- struct xen_v2d5_getdomaininfo *v;
- uint64_t pad ALIGN_64;
- } buffer;
-#endif
- uint32_t num_domains;
-};
-typedef struct xen_v2s3_getdomaininfolistop xen_v2s3_getdomaininfolistop;
-
-
-
-struct xen_v0_domainop {
- domid_t domain;
-};
-typedef struct xen_v0_domainop xen_v0_domainop;
-
-/*
- * The information for a pausedomain system hypercall
- */
-#define XEN_V0_OP_PAUSEDOMAIN 10
-#define XEN_V1_OP_PAUSEDOMAIN 10
-#define XEN_V2_OP_PAUSEDOMAIN 3
-
-/*
- * The information for an unpausedomain system hypercall
- */
-#define XEN_V0_OP_UNPAUSEDOMAIN 11
-#define XEN_V1_OP_UNPAUSEDOMAIN 11
-#define XEN_V2_OP_UNPAUSEDOMAIN 4
-
-/*
- * The information for a setmaxmem system hypercall
- */
-#define XEN_V0_OP_SETMAXMEM 28
-#define XEN_V1_OP_SETMAXMEM 28
-#define XEN_V2_OP_SETMAXMEM 11
-
-struct xen_v0_setmaxmem {
- domid_t domain;
- uint64_t maxmem;
-};
-typedef struct xen_v0_setmaxmem xen_v0_setmaxmem;
-typedef struct xen_v0_setmaxmem xen_v1_setmaxmem;
-
-struct xen_v2_setmaxmem {
- uint64_t maxmem;
-};
-typedef struct xen_v2_setmaxmem xen_v2_setmaxmem;
-
-struct xen_v2d5_setmaxmem {
- uint64_t maxmem ALIGN_64;
-};
-typedef struct xen_v2d5_setmaxmem xen_v2d5_setmaxmem;
-
-/*
- * The information for a setvcpumap system hypercall
- * Note that between 1 and 2 the limitation to 64 physical CPU was lifted
- * hence the difference in structures
- */
-#define XEN_V0_OP_SETVCPUMAP 20
-#define XEN_V1_OP_SETVCPUMAP 20
-#define XEN_V2_OP_SETVCPUMAP 9
-
-struct xen_v0_setvcpumap {
- domid_t domain;
- uint32_t vcpu;
- cpumap_t cpumap;
-};
-typedef struct xen_v0_setvcpumap xen_v0_setvcpumap;
-typedef struct xen_v0_setvcpumap xen_v1_setvcpumap;
-
-struct xen_v2_cpumap {
- uint8_t *bitmap;
- uint32_t nr_cpus;
-};
-struct xen_v2_setvcpumap {
- uint32_t vcpu;
- struct xen_v2_cpumap cpumap;
-};
-typedef struct xen_v2_setvcpumap xen_v2_setvcpumap;
-
-/* HV version 2, Dom version 5 requires 64-bit alignment */
-struct xen_v2d5_cpumap {
-#ifdef __BIG_ENDIAN__
- struct {
- int __pad[(sizeof(long long) - sizeof(uint8_t *)) / sizeof(int)];
- uint8_t *v;
- } bitmap;
-#else
- union {
- uint8_t *v;
- uint64_t pad ALIGN_64;
- } bitmap;
-#endif
- uint32_t nr_cpus;
-};
-struct xen_v2d5_setvcpumap {
- uint32_t vcpu;
- struct xen_v2d5_cpumap cpumap;
-};
-typedef struct xen_v2d5_setvcpumap xen_v2d5_setvcpumap;
-
-/*
- * The information for a vcpuinfo system hypercall
- */
-#define XEN_V0_OP_GETVCPUINFO 43
-#define XEN_V1_OP_GETVCPUINFO 43
-#define XEN_V2_OP_GETVCPUINFO 14
-
-struct xen_v0_vcpuinfo {
- domid_t domain; /* owner's domain */
- uint32_t vcpu; /* the vcpu number */
- uint8_t online; /* seen as on line */
- uint8_t blocked; /* blocked on event */
- uint8_t running; /* scheduled on CPU */
- uint64_t cpu_time; /* nanosecond of CPU used */
- uint32_t cpu; /* current mapping */
- cpumap_t cpumap; /* deprecated in V2 */
-};
-typedef struct xen_v0_vcpuinfo xen_v0_vcpuinfo;
-typedef struct xen_v0_vcpuinfo xen_v1_vcpuinfo;
-
-struct xen_v2_vcpuinfo {
- uint32_t vcpu; /* the vcpu number */
- uint8_t online; /* seen as on line */
- uint8_t blocked; /* blocked on event */
- uint8_t running; /* scheduled on CPU */
- uint64_t cpu_time; /* nanosecond of CPU used */
- uint32_t cpu; /* current mapping */
-};
-typedef struct xen_v2_vcpuinfo xen_v2_vcpuinfo;
-
-struct xen_v2d5_vcpuinfo {
- uint32_t vcpu; /* the vcpu number */
- uint8_t online; /* seen as on line */
- uint8_t blocked; /* blocked on event */
- uint8_t running; /* scheduled on CPU */
- uint64_t cpu_time ALIGN_64; /* nanosecond of CPU used */
- uint32_t cpu; /* current mapping */
-};
-typedef struct xen_v2d5_vcpuinfo xen_v2d5_vcpuinfo;
-
-/*
- * from V2 the pinning of a vcpu is read with a separate call
- */
-#define XEN_V2_OP_GETVCPUMAP 25
-typedef struct xen_v2_setvcpumap xen_v2_getvcpumap;
-typedef struct xen_v2d5_setvcpumap xen_v2d5_getvcpumap;
-
-/*
- * from V2 we get the scheduler information
- */
-#define XEN_V2_OP_GETSCHEDULERID 4
-
-/*
- * from V2 we get the available heap information
- */
-#define XEN_V2_OP_GETAVAILHEAP 9
-
-/*
- * from V2 we get the scheduler parameter
- */
-#define XEN_V2_OP_SCHEDULER 16
-/* Scheduler types. */
-#define XEN_SCHEDULER_SEDF 4
-#define XEN_SCHEDULER_CREDIT 5
-/* get/set scheduler parameters */
-#define XEN_DOMCTL_SCHEDOP_putinfo 0
-#define XEN_DOMCTL_SCHEDOP_getinfo 1
-
-struct xen_v2_setschedinfo {
- uint32_t sched_id;
- uint32_t cmd;
- union {
- struct xen_domctl_sched_sedf {
- uint64_t period ALIGN_64;
- uint64_t slice ALIGN_64;
- uint64_t latency ALIGN_64;
- uint32_t extratime;
- uint32_t weight;
- } sedf;
- struct xen_domctl_sched_credit {
- uint16_t weight;
- uint16_t cap;
- } credit;
- } u;
-};
-typedef struct xen_v2_setschedinfo xen_v2_setschedinfo;
-typedef struct xen_v2_setschedinfo xen_v2_getschedinfo;
-
-
-/*
- * The hypercall operation structures also have changed on
- * changeset 86d26e6ec89b
- */
-/* the old structure */
-struct xen_op_v0 {
- uint32_t cmd;
- uint32_t interface_version;
- union {
- xen_v0_getdomaininfolistop getdomaininfolist;
- xen_v0_domainop domain;
- xen_v0_setmaxmem setmaxmem;
- xen_v0_setvcpumap setvcpumap;
- xen_v0_vcpuinfo getvcpuinfo;
- uint8_t padding[128];
- } u;
-};
-typedef struct xen_op_v0 xen_op_v0;
-typedef struct xen_op_v0 xen_op_v1;
-
-/* the new structure for systems operations */
-struct xen_op_v2_sys {
- uint32_t cmd;
- uint32_t interface_version;
- union {
- xen_v2_getdomaininfolistop getdomaininfolist;
- xen_v2s3_getdomaininfolistop getdomaininfolists3;
- xen_v2_getschedulerid getschedulerid;
- xen_v2s4_availheap availheap;
- xen_v2s5_availheap availheap5;
- uint8_t padding[128];
- } u;
-};
-typedef struct xen_op_v2_sys xen_op_v2_sys;
-
-/* the new structure for domains operation */
-struct xen_op_v2_dom {
- uint32_t cmd;
- uint32_t interface_version;
- domid_t domain;
- union {
- xen_v2_setmaxmem setmaxmem;
- xen_v2d5_setmaxmem setmaxmemd5;
- xen_v2_setvcpumap setvcpumap;
- xen_v2d5_setvcpumap setvcpumapd5;
- xen_v2_vcpuinfo getvcpuinfo;
- xen_v2d5_vcpuinfo getvcpuinfod5;
- xen_v2_getvcpumap getvcpumap;
- xen_v2d5_getvcpumap getvcpumapd5;
- xen_v2_setschedinfo setschedinfo;
- xen_v2_getschedinfo getschedinfo;
- uint8_t padding[128];
- } u;
-};
-typedef struct xen_op_v2_dom xen_op_v2_dom;
-
-
-#ifdef __linux__
-# define XEN_HYPERVISOR_SOCKET "/proc/xen/privcmd"
-# define HYPERVISOR_CAPABILITIES "/sys/hypervisor/properties/capabilities"
-#elif defined(__sun)
-# define XEN_HYPERVISOR_SOCKET "/dev/xen/privcmd"
-#else
-# error "unsupported platform"
-#endif
-
-/**
- * xenHypervisorDoV0Op:
- * @handle: the handle to the Xen hypervisor
- * @op: pointer to the hypervisor operation structure
- *
- * Do a hypervisor operation though the old interface,
- * this leads to a hypervisor call through ioctl.
- *
- * Returns 0 in case of success and -1 in case of error.
- */
-static int
-xenHypervisorDoV0Op(int handle, xen_op_v0 * op)
-{
- int ret;
- v0_hypercall_t hc;
-
- memset(&hc, 0, sizeof(hc));
- op->interface_version = hv_versions.hv << 8;
- hc.op = __HYPERVISOR_dom0_op;
- hc.arg[0] = (unsigned long) op;
-
- if (lock_pages(op, sizeof(dom0_op_t)) < 0)
- return -1;
-
- ret = ioctl(handle, xen_ioctl_hypercall_cmd, (unsigned long) &hc);
- if (ret < 0) {
- virReportSystemError(errno,
- _("Unable to issue hypervisor ioctl %d"),
- xen_ioctl_hypercall_cmd);
- }
-
- if (unlock_pages(op, sizeof(dom0_op_t)) < 0)
- ret = -1;
-
- if (ret < 0)
- return -1;
-
- return 0;
-}
-/**
- * xenHypervisorDoV1Op:
- * @handle: the handle to the Xen hypervisor
- * @op: pointer to the hypervisor operation structure
- *
- * Do a hypervisor v1 operation, this leads to a hypervisor call through
- * ioctl.
- *
- * Returns 0 in case of success and -1 in case of error.
- */
-static int
-xenHypervisorDoV1Op(int handle, xen_op_v1* op)
-{
- int ret;
- hypercall_t hc;
-
- memset(&hc, 0, sizeof(hc));
- op->interface_version = DOM0_INTERFACE_VERSION;
- hc.op = __HYPERVISOR_dom0_op;
- hc.arg[0] = (unsigned long) op;
-
- if (lock_pages(op, sizeof(dom0_op_t)) < 0)
- return -1;
-
- ret = ioctl(handle, xen_ioctl_hypercall_cmd, (unsigned long) &hc);
- if (ret < 0) {
- virReportSystemError(errno,
- _("Unable to issue hypervisor ioctl %d"),
- xen_ioctl_hypercall_cmd);
- }
-
- if (unlock_pages(op, sizeof(dom0_op_t)) < 0)
- ret = -1;
-
- if (ret < 0)
- return -1;
-
- return 0;
-}
-
-/**
- * xenHypervisorDoV2Sys:
- * @handle: the handle to the Xen hypervisor
- * @op: pointer to the hypervisor operation structure
- *
- * Do a hypervisor v2 system operation, this leads to a hypervisor
- * call through ioctl.
- *
- * Returns 0 in case of success and -1 in case of error.
- */
-static int
-xenHypervisorDoV2Sys(int handle, xen_op_v2_sys* op)
-{
- int ret;
- hypercall_t hc;
-
- memset(&hc, 0, sizeof(hc));
- op->interface_version = hv_versions.sys_interface;
- hc.op = __HYPERVISOR_sysctl;
- hc.arg[0] = (unsigned long) op;
-
- if (lock_pages(op, sizeof(dom0_op_t)) < 0)
- return -1;
-
- ret = ioctl(handle, xen_ioctl_hypercall_cmd, (unsigned long) &hc);
- if (ret < 0) {
- virReportSystemError(errno,
- _("Unable to issue hypervisor ioctl %d"),
- xen_ioctl_hypercall_cmd);
- }
-
- if (unlock_pages(op, sizeof(dom0_op_t)) < 0)
- ret = -1;
-
- if (ret < 0)
- return -1;
-
- return 0;
-}
-
-/**
- * xenHypervisorDoV2Dom:
- * @handle: the handle to the Xen hypervisor
- * @op: pointer to the hypervisor domain operation structure
- *
- * Do a hypervisor v2 domain operation, this leads to a hypervisor
- * call through ioctl.
- *
- * Returns 0 in case of success and -1 in case of error.
- */
-static int
-xenHypervisorDoV2Dom(int handle, xen_op_v2_dom* op)
-{
- int ret;
- hypercall_t hc;
-
- memset(&hc, 0, sizeof(hc));
- op->interface_version = hv_versions.dom_interface;
- hc.op = __HYPERVISOR_domctl;
- hc.arg[0] = (unsigned long) op;
-
- if (lock_pages(op, sizeof(dom0_op_t)) < 0)
- return -1;
-
- ret = ioctl(handle, xen_ioctl_hypercall_cmd, (unsigned long) &hc);
- if (ret < 0) {
- virReportSystemError(errno,
- _("Unable to issue hypervisor ioctl %d"),
- xen_ioctl_hypercall_cmd);
- }
-
- if (unlock_pages(op, sizeof(dom0_op_t)) < 0)
- ret = -1;
-
- if (ret < 0)
- return -1;
-
- return 0;
-}
-
-/**
- * virXen_getdomaininfolist:
- * @handle: the hypervisor handle
- * @first_domain: first domain in the range
- * @maxids: maximum number of domains to list
- * @dominfos: output structures
- *
- * Do a low level hypercall to list existing domains information
- *
- * Returns the number of domains or -1 in case of failure
- */
-static int
-virXen_getdomaininfolist(int handle,
- int first_domain,
- int maxids,
- xen_getdomaininfolist *dominfos)
-{
- int ret = -1;
-
- if (lock_pages(XEN_GETDOMAININFOLIST_DATA(dominfos),
- XEN_GETDOMAININFO_SIZE * maxids) < 0)
- return -1;
-
- if (hv_versions.hypervisor > 1) {
- xen_op_v2_sys op;
-
- memset(&op, 0, sizeof(op));
- op.cmd = XEN_V2_OP_GETDOMAININFOLIST;
-
- if (hv_versions.sys_interface < 3) {
- op.u.getdomaininfolist.first_domain = (domid_t) first_domain;
- op.u.getdomaininfolist.max_domains = maxids;
- op.u.getdomaininfolist.buffer = dominfos->v2;
- op.u.getdomaininfolist.num_domains = maxids;
- } else {
- op.u.getdomaininfolists3.first_domain = (domid_t) first_domain;
- op.u.getdomaininfolists3.max_domains = maxids;
- op.u.getdomaininfolists3.buffer.v = dominfos->v2d5;
- op.u.getdomaininfolists3.num_domains = maxids;
- }
- ret = xenHypervisorDoV2Sys(handle, &op);
-
- if (ret == 0) {
- if (hv_versions.sys_interface < 3)
- ret = op.u.getdomaininfolist.num_domains;
- else
- ret = op.u.getdomaininfolists3.num_domains;
- }
- } else if (hv_versions.hypervisor == 1) {
- xen_op_v1 op;
-
- memset(&op, 0, sizeof(op));
- op.cmd = XEN_V1_OP_GETDOMAININFOLIST;
- op.u.getdomaininfolist.first_domain = (domid_t) first_domain;
- op.u.getdomaininfolist.max_domains = maxids;
- op.u.getdomaininfolist.buffer = dominfos->v0;
- op.u.getdomaininfolist.num_domains = maxids;
- ret = xenHypervisorDoV1Op(handle, &op);
- if (ret == 0)
- ret = op.u.getdomaininfolist.num_domains;
- } else if (hv_versions.hypervisor == 0) {
- xen_op_v0 op;
-
- memset(&op, 0, sizeof(op));
- op.cmd = XEN_V0_OP_GETDOMAININFOLIST;
- op.u.getdomaininfolist.first_domain = (domid_t) first_domain;
- op.u.getdomaininfolist.max_domains = maxids;
- op.u.getdomaininfolist.buffer = dominfos->v0;
- op.u.getdomaininfolist.num_domains = maxids;
- ret = xenHypervisorDoV0Op(handle, &op);
- if (ret == 0)
- ret = op.u.getdomaininfolist.num_domains;
- }
- if (unlock_pages(XEN_GETDOMAININFOLIST_DATA(dominfos),
- XEN_GETDOMAININFO_SIZE * maxids) < 0)
- ret = -1;
-
- return ret;
-}
-
-static int
-virXen_getdomaininfo(int handle, int first_domain, xen_getdomaininfo *dominfo)
-{
- xen_getdomaininfolist dominfos;
-
- if (hv_versions.hypervisor < 2) {
- dominfos.v0 = &(dominfo->v0);
- } else {
- dominfos.v2 = &(dominfo->v2);
- }
-
- return virXen_getdomaininfolist(handle, first_domain, 1, &dominfos);
-}
-
-
-/**
- * xenHypervisorGetSchedulerType:
- * @conn: the hypervisor connection
- * @nparams:give a number of scheduler parameters.
- *
- * Do a low level hypercall to get scheduler type
- *
- * Returns scheduler name or NULL in case of failure
- */
-char *
-xenHypervisorGetSchedulerType(virConnectPtr conn,
- int *nparams)
-{
- char *schedulertype = NULL;
- xenUnifiedPrivatePtr priv = conn->privateData;
-
- /*
- * Support only hv_versions.dom_interface >=5
- * (Xen3.1.0 or later)
- * TODO: check on Xen 3.0.3
- */
- if (hv_versions.dom_interface < 5) {
- virReportError(VIR_ERR_NO_XEN, "%s",
- _("unsupported in dom interface < 5"));
- return NULL;
- }
-
- if (hv_versions.hypervisor > 1) {
- xen_op_v2_sys op;
- int ret;
-
- memset(&op, 0, sizeof(op));
- op.cmd = XEN_V2_OP_GETSCHEDULERID;
- ret = xenHypervisorDoV2Sys(priv->handle, &op);
- if (ret < 0)
- return NULL;
-
- switch (op.u.getschedulerid.sched_id) {
- case XEN_SCHEDULER_SEDF:
- ignore_value(VIR_STRDUP(schedulertype, "sedf"));
- if (nparams)
- *nparams = XEN_SCHED_SEDF_NPARAM;
- break;
- case XEN_SCHEDULER_CREDIT:
- ignore_value(VIR_STRDUP(schedulertype, "credit"));
- if (nparams)
- *nparams = XEN_SCHED_CRED_NPARAM;
- break;
- default:
- break;
- }
- }
-
- return schedulertype;
-}
-
-/**
- * xenHypervisorGetSchedulerParameters:
- * @conn: the hypervisor connection
- * @def: domain configuration
- * @params: pointer to scheduler parameters.
- * This memory area should be allocated before calling.
- * @nparams: this parameter must be at least as large as
- * the given number of scheduler parameters.
- * from xenHypervisorGetSchedulerType().
- *
- * Do a low level hypercall to get scheduler parameters
- *
- * Returns 0 or -1 in case of failure
- */
-int
-xenHypervisorGetSchedulerParameters(virConnectPtr conn,
- virDomainDefPtr def,
- virTypedParameterPtr params,
- int *nparams)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
-
- /*
- * Support only hv_versions.dom_interface >=5
- * (Xen3.1.0 or later)
- * TODO: check on Xen 3.0.3
- */
- if (hv_versions.dom_interface < 5) {
- virReportError(VIR_ERR_NO_XEN, "%s",
- _("unsupported in dom interface < 5"));
- return -1;
- }
-
- if (hv_versions.hypervisor > 1) {
- xen_op_v2_sys op_sys;
- xen_op_v2_dom op_dom;
- int ret;
-
- memset(&op_sys, 0, sizeof(op_sys));
- op_sys.cmd = XEN_V2_OP_GETSCHEDULERID;
- ret = xenHypervisorDoV2Sys(priv->handle, &op_sys);
- if (ret < 0)
- return -1;
-
- switch (op_sys.u.getschedulerid.sched_id) {
- case XEN_SCHEDULER_SEDF:
- if (*nparams < XEN_SCHED_SEDF_NPARAM) {
- virReportError(VIR_ERR_INVALID_ARG,
- "%s", _("Invalid parameter count"));
- return -1;
- }
-
- /* TODO: Implement for Xen/SEDF */
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("SEDF scheduler parameters not supported"));
- return -1;
- case XEN_SCHEDULER_CREDIT:
- memset(&op_dom, 0, sizeof(op_dom));
- op_dom.cmd = XEN_V2_OP_SCHEDULER;
- op_dom.domain = (domid_t) def->id;
- op_dom.u.getschedinfo.sched_id = XEN_SCHEDULER_CREDIT;
- op_dom.u.getschedinfo.cmd = XEN_DOMCTL_SCHEDOP_getinfo;
- ret = xenHypervisorDoV2Dom(priv->handle, &op_dom);
- if (ret < 0)
- return -1;
-
- if (virTypedParameterAssign(¶ms[0],
- VIR_DOMAIN_SCHEDULER_WEIGHT,
- VIR_TYPED_PARAM_UINT,
- op_dom.u.getschedinfo.u.credit.weight) < 0)
- return -1;
-
- if (*nparams > 1 &&
- virTypedParameterAssign(¶ms[1],
- VIR_DOMAIN_SCHEDULER_CAP,
- VIR_TYPED_PARAM_UINT,
- op_dom.u.getschedinfo.u.credit.cap) < 0)
- return -1;
-
- if (*nparams > XEN_SCHED_CRED_NPARAM)
- *nparams = XEN_SCHED_CRED_NPARAM;
- break;
- default:
- virReportError(VIR_ERR_INVALID_ARG,
- _("Unknown scheduler %d"),
- op_sys.u.getschedulerid.sched_id);
- return -1;
- }
- }
-
- return 0;
-}
-
-/**
- * xenHypervisorSetSchedulerParameters:
- * @conn: the hypervisor connection
- * @def: domain configuration
- * @nparams:give a number of scheduler setting parameters .
- *
- * Do a low level hypercall to set scheduler parameters
- *
- * Returns 0 or -1 in case of failure
- */
-int
-xenHypervisorSetSchedulerParameters(virConnectPtr conn,
- virDomainDefPtr def,
- virTypedParameterPtr params,
- int nparams)
-{
- size_t i;
- unsigned int val;
- xenUnifiedPrivatePtr priv = conn->privateData;
- char buf[256];
-
- if (nparams == 0) {
- /* nothing to do, exit early */
- return 0;
- }
-
- if (virTypedParamsValidate(params, nparams,
- VIR_DOMAIN_SCHEDULER_WEIGHT,
- VIR_TYPED_PARAM_UINT,
- VIR_DOMAIN_SCHEDULER_CAP,
- VIR_TYPED_PARAM_UINT,
- NULL) < 0)
- return -1;
-
- /*
- * Support only hv_versions.dom_interface >=5
- * (Xen3.1.0 or later)
- * TODO: check on Xen 3.0.3
- */
- if (hv_versions.dom_interface < 5) {
- virReportError(VIR_ERR_NO_XEN, "%s",
- _("unsupported in dom interface < 5"));
- return -1;
- }
-
- if (hv_versions.hypervisor > 1) {
- xen_op_v2_sys op_sys;
- xen_op_v2_dom op_dom;
- int ret;
-
- memset(&op_sys, 0, sizeof(op_sys));
- op_sys.cmd = XEN_V2_OP_GETSCHEDULERID;
- ret = xenHypervisorDoV2Sys(priv->handle, &op_sys);
- if (ret == -1) return -1;
-
- switch (op_sys.u.getschedulerid.sched_id) {
- case XEN_SCHEDULER_SEDF:
- /* TODO: Implement for Xen/SEDF */
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("SEDF scheduler parameters not supported"));
- return -1;
- case XEN_SCHEDULER_CREDIT: {
- memset(&op_dom, 0, sizeof(op_dom));
- op_dom.cmd = XEN_V2_OP_SCHEDULER;
- op_dom.domain = (domid_t) def->id;
- op_dom.u.getschedinfo.sched_id = XEN_SCHEDULER_CREDIT;
- op_dom.u.getschedinfo.cmd = XEN_DOMCTL_SCHEDOP_putinfo;
-
- /*
- * credit scheduler parameters
- * following values do not change the parameters
- */
- op_dom.u.getschedinfo.u.credit.weight = 0;
- op_dom.u.getschedinfo.u.credit.cap = (uint16_t)~0U;
-
- for (i = 0; i < nparams; i++) {
- memset(&buf, 0, sizeof(buf));
- if (STREQ(params[i].field, VIR_DOMAIN_SCHEDULER_WEIGHT)) {
- val = params[i].value.ui;
- if ((val < 1) || (val > USHRT_MAX)) {
- virReportError(VIR_ERR_INVALID_ARG,
- _("Credit scheduler weight parameter (%d) "
- "is out of range (1-65535)"), val);
- return -1;
- }
- op_dom.u.getschedinfo.u.credit.weight = val;
- } else if (STREQ(params[i].field, VIR_DOMAIN_SCHEDULER_CAP)) {
- val = params[i].value.ui;
- if (val >= USHRT_MAX) {
- virReportError(VIR_ERR_INVALID_ARG,
- _("Credit scheduler cap parameter (%d) is "
- "out of range (0-65534)"), val);
- return -1;
- }
- op_dom.u.getschedinfo.u.credit.cap = val;
- }
- }
-
- ret = xenHypervisorDoV2Dom(priv->handle, &op_dom);
- if (ret < 0)
- return -1;
- break;
- }
- default:
- virReportError(VIR_ERR_INVALID_ARG,
- _("Unknown scheduler %d"),
- op_sys.u.getschedulerid.sched_id);
- return -1;
- }
- }
-
- return 0;
-}
-
-
-int
-xenHypervisorDomainBlockStats(virConnectPtr conn,
- virDomainDefPtr def,
- const char *path,
- virDomainBlockStatsPtr stats)
-{
-#ifdef __linux__
- xenUnifiedPrivatePtr priv = conn->privateData;
- int ret;
-
- xenUnifiedLock(priv);
- /* Need to lock because it hits the xenstore handle :-( */
- ret = xenLinuxDomainBlockStats(priv, def, path, stats);
- xenUnifiedUnlock(priv);
- return ret;
-#else
- virReportError(VIR_ERR_OPERATION_INVALID, "%s",
- _("block statistics not supported on this platform"));
- return -1;
-#endif
-}
-
-/* Paths have the form vif<domid>.<n> (this interface checks that
- * <domid> is the real domain ID and returns an error if not).
- *
- * In future we may allow you to query bridge stats (virbrX or
- * xenbrX), but that will probably be through a separate
- * virNetwork interface, as yet not decided.
- */
-int
-xenHypervisorDomainInterfaceStats(virDomainDefPtr def,
- const char *path,
- virDomainInterfaceStatsPtr stats)
-{
-#ifdef __linux__
- int rqdomid, device;
-
- /* Verify that the vif requested is one belonging to the current
- * domain.
- */
- if (sscanf(path, "vif%d.%d", &rqdomid, &device) != 2) {
- virReportError(VIR_ERR_INVALID_ARG, "%s",
- _("invalid path, should be vif<domid>.<n>."));
- return -1;
- }
- if (rqdomid != def->id) {
- virReportError(VIR_ERR_INVALID_ARG, "%s",
- _("invalid path, vif<domid> should match this domain ID"));
- return -1;
- }
-
- return virNetDevTapInterfaceStats(path, stats, true);
-#else
- virReportError(VIR_ERR_OPERATION_INVALID, "%s",
- _("/proc/net/dev: Interface not found"));
- return -1;
-#endif
-}
-
-
-/**
- * virXen_setmaxmem:
- * @handle: the hypervisor handle
- * @id: the domain id
- * @memory: the amount of memory in kilobytes
- *
- * Do a low level hypercall to change the max memory amount
- *
- * Returns 0 or -1 in case of failure
- */
-static int
-virXen_setmaxmem(int handle, int id, unsigned long memory)
-{
- int ret = -1;
-
- if (hv_versions.hypervisor > 1) {
- xen_op_v2_dom op;
-
- memset(&op, 0, sizeof(op));
- op.cmd = XEN_V2_OP_SETMAXMEM;
- op.domain = (domid_t) id;
- if (hv_versions.dom_interface < 5)
- op.u.setmaxmem.maxmem = memory;
- else
- op.u.setmaxmemd5.maxmem = memory;
- ret = xenHypervisorDoV2Dom(handle, &op);
- } else if (hv_versions.hypervisor == 1) {
- xen_op_v1 op;
-
- memset(&op, 0, sizeof(op));
- op.cmd = XEN_V1_OP_SETMAXMEM;
- op.u.setmaxmem.domain = (domid_t) id;
- op.u.setmaxmem.maxmem = memory;
- ret = xenHypervisorDoV1Op(handle, &op);
- } else if (hv_versions.hypervisor == 0) {
- xen_op_v0 op;
-
- memset(&op, 0, sizeof(op));
- op.cmd = XEN_V0_OP_SETMAXMEM;
- op.u.setmaxmem.domain = (domid_t) id;
- op.u.setmaxmem.maxmem = memory;
- ret = xenHypervisorDoV0Op(handle, &op);
- }
- return ret;
-}
-
-
-/**
- * virXen_setvcpumap:
- * @handle: the hypervisor handle
- * @id: the domain id
- * @vcpu: the vcpu to map
- * @cpumap: the bitmap for this vcpu
- * @maplen: the size of the bitmap in bytes
- *
- * Do a low level hypercall to change the pinning for vcpu
- *
- * Returns 0 or -1 in case of failure
- */
-static int
-virXen_setvcpumap(int handle,
- int id,
- unsigned int vcpu,
- unsigned char * cpumap,
- int maplen)
-{
- int ret = -1;
- unsigned char *new = NULL;
- unsigned char *bitmap = NULL;
- uint32_t nr_cpus;
-
- if (hv_versions.hypervisor > 1) {
- xen_op_v2_dom op;
-
- if (lock_pages(cpumap, maplen) < 0)
- return -1;
-
- memset(&op, 0, sizeof(op));
- op.cmd = XEN_V2_OP_SETVCPUMAP;
- op.domain = (domid_t) id;
-
- /* The allocated memory to cpumap must be 'sizeof(uint64_t)' byte *
- * for Xen, and also nr_cpus must be 'sizeof(uint64_t) * 8' */
- if (maplen < 8) {
- if (VIR_ALLOC_N(new, sizeof(uint64_t)) < 0)
- return -1;
- memcpy(new, cpumap, maplen);
- bitmap = new;
- nr_cpus = sizeof(uint64_t) * 8;
- } else {
- bitmap = cpumap;
- nr_cpus = maplen * 8;
- }
-
- if (hv_versions.dom_interface < 5) {
- op.u.setvcpumap.vcpu = vcpu;
- op.u.setvcpumap.cpumap.bitmap = bitmap;
- op.u.setvcpumap.cpumap.nr_cpus = nr_cpus;
- } else {
- op.u.setvcpumapd5.vcpu = vcpu;
- op.u.setvcpumapd5.cpumap.bitmap.v = bitmap;
- op.u.setvcpumapd5.cpumap.nr_cpus = nr_cpus;
- }
- ret = xenHypervisorDoV2Dom(handle, &op);
- VIR_FREE(new);
-
- if (unlock_pages(cpumap, maplen) < 0)
- ret = -1;
- } else {
- cpumap_t xen_cpumap; /* limited to 64 CPUs in old hypervisors */
- char buf[8] = "";
-
- if (maplen > sizeof(cpumap_t) || sizeof(cpumap_t) != sizeof(uint64_t))
- return -1;
- /* Supply trailing 0s if user's input array was short */
- memcpy(buf, cpumap, maplen);
- xen_cpumap = virReadBufInt64LE(buf);
-
- if (hv_versions.hypervisor == 1) {
- xen_op_v1 op;
-
- memset(&op, 0, sizeof(op));
- op.cmd = XEN_V1_OP_SETVCPUMAP;
- op.u.setvcpumap.domain = (domid_t) id;
- op.u.setvcpumap.vcpu = vcpu;
- op.u.setvcpumap.cpumap = xen_cpumap;
- ret = xenHypervisorDoV1Op(handle, &op);
- } else if (hv_versions.hypervisor == 0) {
- xen_op_v0 op;
-
- memset(&op, 0, sizeof(op));
- op.cmd = XEN_V0_OP_SETVCPUMAP;
- op.u.setvcpumap.domain = (domid_t) id;
- op.u.setvcpumap.vcpu = vcpu;
- op.u.setvcpumap.cpumap = xen_cpumap;
- ret = xenHypervisorDoV0Op(handle, &op);
- }
- }
- return ret;
-}
-
-
-/**
- * virXen_getvcpusinfo:
- * @handle: the hypervisor handle
- * @id: the domain id
- * @vcpu: the vcpu to map
- * @cpumap: the bitmap for this vcpu
- * @maplen: the size of the bitmap in bytes
- *
- * Do a low level hypercall to change the pinning for vcpu
- *
- * Returns 0 or -1 in case of failure
- */
-static int
-virXen_getvcpusinfo(int handle,
- int id,
- unsigned int vcpu,
- virVcpuInfoPtr ipt,
- unsigned char *cpumap,
- int maplen)
-{
- int ret = -1;
-
- if (hv_versions.hypervisor > 1) {
- xen_op_v2_dom op;
-
- memset(&op, 0, sizeof(op));
- op.cmd = XEN_V2_OP_GETVCPUINFO;
- op.domain = (domid_t) id;
- if (hv_versions.dom_interface < 5)
- op.u.getvcpuinfo.vcpu = (uint16_t) vcpu;
- else
- op.u.getvcpuinfod5.vcpu = (uint16_t) vcpu;
- ret = xenHypervisorDoV2Dom(handle, &op);
-
- if (ret < 0)
- return -1;
- ipt->number = vcpu;
- if (hv_versions.dom_interface < 5) {
- if (op.u.getvcpuinfo.online) {
- if (op.u.getvcpuinfo.running)
- ipt->state = VIR_VCPU_RUNNING;
- if (op.u.getvcpuinfo.blocked)
- ipt->state = VIR_VCPU_BLOCKED;
- } else {
- ipt->state = VIR_VCPU_OFFLINE;
- }
-
- ipt->cpuTime = op.u.getvcpuinfo.cpu_time;
- ipt->cpu = op.u.getvcpuinfo.online ? (int)op.u.getvcpuinfo.cpu : -1;
- } else {
- if (op.u.getvcpuinfod5.online) {
- if (op.u.getvcpuinfod5.running)
- ipt->state = VIR_VCPU_RUNNING;
- if (op.u.getvcpuinfod5.blocked)
- ipt->state = VIR_VCPU_BLOCKED;
- } else {
- ipt->state = VIR_VCPU_OFFLINE;
- }
-
- ipt->cpuTime = op.u.getvcpuinfod5.cpu_time;
- ipt->cpu = op.u.getvcpuinfod5.online ? (int)op.u.getvcpuinfod5.cpu : -1;
- }
- if ((cpumap != NULL) && (maplen > 0)) {
- if (lock_pages(cpumap, maplen) < 0)
- return -1;
-
- memset(cpumap, 0, maplen);
- memset(&op, 0, sizeof(op));
- op.cmd = XEN_V2_OP_GETVCPUMAP;
- op.domain = (domid_t) id;
- if (hv_versions.dom_interface < 5) {
- op.u.getvcpumap.vcpu = vcpu;
- op.u.getvcpumap.cpumap.bitmap = cpumap;
- op.u.getvcpumap.cpumap.nr_cpus = maplen * 8;
- } else {
- op.u.getvcpumapd5.vcpu = vcpu;
- op.u.getvcpumapd5.cpumap.bitmap.v = cpumap;
- op.u.getvcpumapd5.cpumap.nr_cpus = maplen * 8;
- }
- ret = xenHypervisorDoV2Dom(handle, &op);
- if (unlock_pages(cpumap, maplen) < 0)
- ret = -1;
- }
- } else {
- int mapl = maplen;
- int cpu;
-
- if (maplen > (int)sizeof(cpumap_t))
- mapl = (int)sizeof(cpumap_t);
-
- if (hv_versions.hypervisor == 1) {
- xen_op_v1 op;
-
- memset(&op, 0, sizeof(op));
- op.cmd = XEN_V1_OP_GETVCPUINFO;
- op.u.getvcpuinfo.domain = (domid_t) id;
- op.u.getvcpuinfo.vcpu = vcpu;
- ret = xenHypervisorDoV1Op(handle, &op);
- if (ret < 0)
- return -1;
- ipt->number = vcpu;
- if (op.u.getvcpuinfo.online) {
- if (op.u.getvcpuinfo.running) ipt->state = VIR_VCPU_RUNNING;
- if (op.u.getvcpuinfo.blocked) ipt->state = VIR_VCPU_BLOCKED;
- }
- else ipt->state = VIR_VCPU_OFFLINE;
- ipt->cpuTime = op.u.getvcpuinfo.cpu_time;
- ipt->cpu = op.u.getvcpuinfo.online ? (int)op.u.getvcpuinfo.cpu : -1;
- if ((cpumap != NULL) && (maplen > 0)) {
- for (cpu = 0; cpu < (mapl * 8); cpu++) {
- if (op.u.getvcpuinfo.cpumap & ((uint64_t)1<<cpu))
- VIR_USE_CPU(cpumap, cpu);
- }
- }
- } else if (hv_versions.hypervisor == 0) {
- xen_op_v1 op;
-
- memset(&op, 0, sizeof(op));
- op.cmd = XEN_V0_OP_GETVCPUINFO;
- op.u.getvcpuinfo.domain = (domid_t) id;
- op.u.getvcpuinfo.vcpu = vcpu;
- ret = xenHypervisorDoV0Op(handle, &op);
- if (ret < 0)
- return -1;
- ipt->number = vcpu;
- if (op.u.getvcpuinfo.online) {
- if (op.u.getvcpuinfo.running) ipt->state = VIR_VCPU_RUNNING;
- if (op.u.getvcpuinfo.blocked) ipt->state = VIR_VCPU_BLOCKED;
- }
- else ipt->state = VIR_VCPU_OFFLINE;
- ipt->cpuTime = op.u.getvcpuinfo.cpu_time;
- ipt->cpu = op.u.getvcpuinfo.online ? (int)op.u.getvcpuinfo.cpu : -1;
- if ((cpumap != NULL) && (maplen > 0)) {
- for (cpu = 0; cpu < (mapl * 8); cpu++) {
- if (op.u.getvcpuinfo.cpumap & ((uint64_t)1<<cpu))
- VIR_USE_CPU(cpumap, cpu);
- }
- }
- }
- }
- return ret;
-}
-
-/**
- * xenHypervisorInit:
- * @override_versions: pointer to optional struct xenHypervisorVersions with
- * version information used instead of automatic version detection.
- *
- * Initialize the hypervisor layer. Try to detect the kind of interface
- * used i.e. pre or post changeset 10277
- *
- * Returns 0 or -1 in case of failure
- */
-int
-xenHypervisorInit(struct xenHypervisorVersions *override_versions)
-{
- int fd, ret, cmd, errcode;
- hypercall_t hc;
- v0_hypercall_t v0_hc;
- xen_getdomaininfo info;
- virVcpuInfoPtr ipt = NULL;
-
- /* Compile regular expressions used by xenHypervisorGetCapabilities.
- * Note that errors here are really internal errors since these
- * regexps should never fail to compile.
- */
- errcode = regcomp(&flags_hvm_rec, flags_hvm_re, REG_EXTENDED);
- if (errcode != 0) {
- char error[100];
- regerror(errcode, &flags_hvm_rec, error, sizeof(error));
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", error);
- return -1;
- }
- errcode = regcomp(&flags_pae_rec, flags_pae_re, REG_EXTENDED);
- if (errcode != 0) {
- char error[100];
- regerror(errcode, &flags_pae_rec, error, sizeof(error));
- regfree(&flags_hvm_rec);
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", error);
- return -1;
- }
- errcode = regcomp(&xen_cap_rec, xen_cap_re, REG_EXTENDED);
- if (errcode != 0) {
- char error[100];
- regerror(errcode, &xen_cap_rec, error, sizeof(error));
- regfree(&flags_pae_rec);
- regfree(&flags_hvm_rec);
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", error);
- return -1;
- }
-
- if (override_versions) {
- hv_versions = *override_versions;
- return 0;
- }
-
- /* Xen hypervisor version detection begins. */
- ret = open(XEN_HYPERVISOR_SOCKET, O_RDWR);
- if (ret < 0) {
- hv_versions.hypervisor = -1;
- return -1;
- }
- fd = ret;
-
- /*
- * The size of the hypervisor call block changed July 2006
- * this detect if we are using the new or old hypercall_t structure
- */
- hc.op = __HYPERVISOR_xen_version;
- hc.arg[0] = (unsigned long) XENVER_version;
- hc.arg[1] = 0;
-
- cmd = IOCTL_PRIVCMD_HYPERCALL;
- ret = ioctl(fd, cmd, (unsigned long) &hc);
-
- if ((ret != -1) && (ret != 0)) {
- VIR_DEBUG("Using new hypervisor call: %X", ret);
- hv_versions.hv = ret;
- xen_ioctl_hypercall_cmd = cmd;
- goto detect_v2;
- }
-
-#ifndef __sun
- /*
- * check if the old hypercall are actually working
- */
- v0_hc.op = __HYPERVISOR_xen_version;
- v0_hc.arg[0] = (unsigned long) XENVER_version;
- v0_hc.arg[1] = 0;
- cmd = _IOC(_IOC_NONE, 'P', 0, sizeof(v0_hypercall_t));
- ret = ioctl(fd, cmd, (unsigned long) &v0_hc);
- if ((ret != -1) && (ret != 0)) {
- VIR_DEBUG("Using old hypervisor call: %X", ret);
- hv_versions.hv = ret;
- xen_ioctl_hypercall_cmd = cmd;
- hv_versions.hypervisor = 0;
- goto done;
- }
-#endif
-
- /*
- * we failed to make any hypercall
- */
-
- hv_versions.hypervisor = -1;
- virReportSystemError(errno,
- _("Unable to issue hypervisor ioctl %lu"),
- (unsigned long)IOCTL_PRIVCMD_HYPERCALL);
- VIR_FORCE_CLOSE(fd);
- return -1;
-
- detect_v2:
- /*
- * The hypercalls were refactored into 3 different section in August 2006
- * Try to detect if we are running a version post 3.0.2 with the new ones
- * or the old ones
- */
- hv_versions.hypervisor = 2;
-
- if (VIR_ALLOC(ipt) < 0)
- return -1;
- /* Currently consider RHEL5.0 Fedora7, xen-3.1, and xen-unstable */
- hv_versions.sys_interface = 2; /* XEN_SYSCTL_INTERFACE_VERSION */
- if (virXen_getdomaininfo(fd, 0, &info) == 1) {
- /* RHEL 5.0 */
- hv_versions.dom_interface = 3; /* XEN_DOMCTL_INTERFACE_VERSION */
- if (virXen_getvcpusinfo(fd, 0, 0, ipt, NULL, 0) == 0) {
- VIR_DEBUG("Using hypervisor call v2, sys ver2 dom ver3");
- goto done;
- }
- /* Fedora 7 */
- hv_versions.dom_interface = 4; /* XEN_DOMCTL_INTERFACE_VERSION */
- if (virXen_getvcpusinfo(fd, 0, 0, ipt, NULL, 0) == 0) {
- VIR_DEBUG("Using hypervisor call v2, sys ver2 dom ver4");
- goto done;
- }
- }
-
- hv_versions.sys_interface = 3; /* XEN_SYSCTL_INTERFACE_VERSION */
- if (virXen_getdomaininfo(fd, 0, &info) == 1) {
- /* xen-3.1 */
- hv_versions.dom_interface = 5; /* XEN_DOMCTL_INTERFACE_VERSION */
- if (virXen_getvcpusinfo(fd, 0, 0, ipt, NULL, 0) == 0) {
- VIR_DEBUG("Using hypervisor call v2, sys ver3 dom ver5");
- goto done;
- }
- }
-
- hv_versions.sys_interface = 4; /* XEN_SYSCTL_INTERFACE_VERSION */
- if (virXen_getdomaininfo(fd, 0, &info) == 1) {
- /* Fedora 8 */
- hv_versions.dom_interface = 5; /* XEN_DOMCTL_INTERFACE_VERSION */
- if (virXen_getvcpusinfo(fd, 0, 0, ipt, NULL, 0) == 0) {
- VIR_DEBUG("Using hypervisor call v2, sys ver4 dom ver5");
- goto done;
- }
- }
-
- hv_versions.sys_interface = 6; /* XEN_SYSCTL_INTERFACE_VERSION */
- if (virXen_getdomaininfo(fd, 0, &info) == 1) {
- /* Xen 3.2, Fedora 9 */
- hv_versions.dom_interface = 5; /* XEN_DOMCTL_INTERFACE_VERSION */
- if (virXen_getvcpusinfo(fd, 0, 0, ipt, NULL, 0) == 0) {
- VIR_DEBUG("Using hypervisor call v2, sys ver6 dom ver5");
- goto done;
- }
- }
-
- /* Xen 4.0 */
- hv_versions.sys_interface = 7; /* XEN_SYSCTL_INTERFACE_VERSION */
- if (virXen_getdomaininfo(fd, 0, &info) == 1) {
- hv_versions.dom_interface = 6; /* XEN_DOMCTL_INTERFACE_VERSION */
- VIR_DEBUG("Using hypervisor call v2, sys ver7 dom ver6");
- goto done;
- }
-
- /* Xen 4.1
- * sysctl version 8 -> xen-unstable c/s 21118:28e5409e3fb3
- * domctl version 7 -> xen-unstable c/s 21212:de94884a669c
- * domctl version 8 -> xen-unstable c/s 23874:651aed73b39c
- */
- hv_versions.sys_interface = 8; /* XEN_SYSCTL_INTERFACE_VERSION */
- if (virXen_getdomaininfo(fd, 0, &info) == 1) {
- hv_versions.dom_interface = 7; /* XEN_DOMCTL_INTERFACE_VERSION */
- if (virXen_getvcpusinfo(fd, 0, 0, ipt, NULL, 0) == 0) {
- VIR_DEBUG("Using hypervisor call v2, sys ver8 dom ver7");
- goto done;
- }
- hv_versions.dom_interface = 8; /* XEN_DOMCTL_INTERFACE_VERSION */
- if (virXen_getvcpusinfo(fd, 0, 0, ipt, NULL, 0) == 0) {
- VIR_DEBUG("Using hypervisor call v2, sys ver8 dom ver8");
- goto done;
- }
- }
-
- /* Xen 4.2
- * sysctl version 9 -> xen-unstable c/s 24102:dc8e55c90604
- * domctl version 8 -> unchanged from Xen 4.1
- */
- hv_versions.sys_interface = 9; /* XEN_SYSCTL_INTERFACE_VERSION */
- if (virXen_getdomaininfo(fd, 0, &info) == 1) {
- hv_versions.dom_interface = 8; /* XEN_DOMCTL_INTERFACE_VERSION */
- if (virXen_getvcpusinfo(fd, 0, 0, ipt, NULL, 0) == 0) {
- VIR_DEBUG("Using hypervisor call v2, sys ver9 dom ver8");
- goto done;
- }
- }
-
- /* Xen 4.3
- * sysctl version 10 -> xen-unstable commit bec8f17e
- * domctl version 9 -> xen-unstable commit 65c9792d
- */
- hv_versions.sys_interface = 10; /* XEN_SYSCTL_INTERFACE_VERSION */
- if (virXen_getdomaininfo(fd, 0, &info) == 1) {
- hv_versions.dom_interface = 9; /* XEN_DOMCTL_INTERFACE_VERSION */
- if (virXen_getvcpusinfo(fd, 0, 0, ipt, NULL, 0) == 0) {
- VIR_DEBUG("Using hypervisor call v2, sys ver10 dom ver9");
- goto done;
- }
- }
-
- hv_versions.hypervisor = 1;
- hv_versions.sys_interface = -1;
- if (virXen_getdomaininfo(fd, 0, &info) == 1) {
- VIR_DEBUG("Using hypervisor call v1");
- goto done;
- }
-
- /*
- * we failed to make the getdomaininfolist hypercall
- */
- hv_versions.hypervisor = -1;
- virReportSystemError(errno,
- _("Unable to issue hypervisor ioctl %lu"),
- (unsigned long)IOCTL_PRIVCMD_HYPERCALL);
- VIR_DEBUG("Failed to find any Xen hypervisor method");
- VIR_FORCE_CLOSE(fd);
- VIR_FREE(ipt);
- return -1;
-
- done:
- VIR_FORCE_CLOSE(fd);
- VIR_FREE(ipt);
- return 0;
-}
-
-
-static int xenHypervisorOnceInit(void)
-{
- return xenHypervisorInit(NULL);
-}
-
-VIR_ONCE_GLOBAL_INIT(xenHypervisor)
-
-/**
- * xenHypervisorOpen:
- * @conn: pointer to the connection block
- * @name: URL for the target, NULL for local
- * @flags: combination of virDrvOpenFlag(s)
- *
- * Connects to the Xen hypervisor.
- *
- * Returns 0 or -1 in case of error.
- */
-int
-xenHypervisorOpen(virConnectPtr conn,
- virConnectAuthPtr auth ATTRIBUTE_UNUSED,
- unsigned int flags)
-{
- int ret;
- xenUnifiedPrivatePtr priv = conn->privateData;
-
- virCheckFlags(VIR_CONNECT_RO, -1);
-
- if (xenHypervisorInitialize() < 0)
- return -1;
-
- priv->handle = -1;
-
- ret = open(XEN_HYPERVISOR_SOCKET, O_RDWR);
- if (ret < 0) {
- virReportError(VIR_ERR_NO_XEN, "%s", XEN_HYPERVISOR_SOCKET);
- return -1;
- }
-
- priv->handle = ret;
-
- return 0;
-}
-
-/**
- * xenHypervisorClose:
- * @conn: pointer to the connection block
- *
- * Close the connection to the Xen hypervisor.
- *
- * Returns 0 in case of success or -1 in case of error.
- */
-int
-xenHypervisorClose(virConnectPtr conn)
-{
- int ret;
- xenUnifiedPrivatePtr priv = conn->privateData;
-
- ret = VIR_CLOSE(priv->handle);
- if (ret < 0)
- return -1;
-
- return 0;
-}
-
-
-/**
- * xenHypervisorGetVersion:
- * @conn: pointer to the connection block
- * @hvVer: where to store the version
- *
- * Call the hypervisor to extracts his own internal API version
- *
- * Returns 0 in case of success, -1 in case of error
- */
-int
-xenHypervisorGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED, unsigned long *hvVer)
-{
- *hvVer = (hv_versions.hv >> 16) * 1000000 + (hv_versions.hv & 0xFFFF) * 1000;
- return 0;
-}
-
-struct guest_arch {
- virArch arch;
- int hvm;
- int pae;
- int nonpae;
- int ia64_be;
-};
-
-
-static virCapsPtr
-xenHypervisorBuildCapabilities(virConnectPtr conn, virArch hostarch,
- int host_pae,
- const char *hvm_type,
- struct guest_arch *guest_archs,
- int nr_guest_archs)
-{
- virCapsPtr caps;
- size_t i;
- int hv_major = hv_versions.hv >> 16;
- int hv_minor = hv_versions.hv & 0xFFFF;
-
- if ((caps = virCapabilitiesNew(hostarch, true, true)) == NULL)
- goto no_memory;
-
- if (hvm_type && STRNEQ(hvm_type, "") &&
- virCapabilitiesAddHostFeature(caps, hvm_type) < 0)
- goto no_memory;
- if (host_pae &&
- virCapabilitiesAddHostFeature(caps, "pae") < 0)
- goto no_memory;
-
-
- if (virCapabilitiesAddHostMigrateTransport(caps,
- "xenmigr") < 0)
- goto no_memory;
-
-
- if (hv_versions.sys_interface >= SYS_IFACE_MIN_VERS_NUMA && conn != NULL) {
- if (xenDaemonNodeGetTopology(conn, caps) != 0) {
- virObjectUnref(caps);
- return NULL;
- }
- }
-
- for (i = 0; i < nr_guest_archs; ++i) {
- virCapsGuestPtr guest;
- char const *const xen_machines[] = {guest_archs[i].hvm ? "xenfv" : "xenpv"};
- virCapsGuestMachinePtr *machines;
-
- if ((machines = virCapabilitiesAllocMachines(xen_machines, 1)) == NULL)
- goto no_memory;
-
- if ((guest = virCapabilitiesAddGuest(caps,
- guest_archs[i].hvm ? VIR_DOMAIN_OSTYPE_HVM : VIR_DOMAIN_OSTYPE_XEN,
- guest_archs[i].arch,
- (hostarch == VIR_ARCH_X86_64 ?
- "/usr/lib64/xen/bin/qemu-dm" :
- "/usr/lib/xen/bin/qemu-dm"),
- (guest_archs[i].hvm ?
- "/usr/lib/xen/boot/hvmloader" :
- NULL),
- 1,
- machines)) == NULL) {
- virCapabilitiesFreeMachines(machines, 1);
- goto no_memory;
- }
- machines = NULL;
-
- if (virCapabilitiesAddGuestDomain(guest,
- VIR_DOMAIN_VIRT_XEN,
- NULL,
- NULL,
- 0,
- NULL) == NULL)
- goto no_memory;
-
- if (guest_archs[i].pae &&
- virCapabilitiesAddGuestFeature(guest,
- "pae",
- true,
- false) == NULL)
- goto no_memory;
-
- if (guest_archs[i].nonpae &&
- virCapabilitiesAddGuestFeature(guest,
- "nonpae",
- true,
- false) == NULL)
- goto no_memory;
-
- if (guest_archs[i].ia64_be &&
- virCapabilitiesAddGuestFeature(guest,
- "ia64_be",
- true,
- false) == NULL)
- goto no_memory;
-
- if (guest_archs[i].hvm) {
- if (virCapabilitiesAddGuestFeature(guest,
- "acpi",
- true, true) == NULL)
- goto no_memory;
-
- /* In Xen 3.1.0, APIC is always on and can't be toggled */
- if (virCapabilitiesAddGuestFeature(guest,
- "apic",
- true,
- !(hv_major > 3 &&
- hv_minor > 0)) == NULL)
- goto no_memory;
-
- /* Xen 3.3.x and beyond supports enabling/disabling
- * hardware assisted paging. Default is off.
- */
- if ((hv_major == 3 && hv_minor >= 3) || (hv_major > 3))
- if (virCapabilitiesAddGuestFeature(guest,
- "hap",
- true,
- true) == NULL)
- goto no_memory;
-
- /* Xen 3.4.x and beyond supports the Viridian (Hyper-V)
- * enlightenment interface. Default is off.
- */
- if ((hv_major == 3 && hv_minor >= 4) || (hv_major > 3))
- if (virCapabilitiesAddGuestFeature(guest,
- "viridian",
- false,
- true) == NULL)
- goto no_memory;
- }
-
- }
-
- return caps;
-
- no_memory:
- virObjectUnref(caps);
- return NULL;
-}
-
-#ifdef __sun
-
-static int
-get_cpu_flags(virConnectPtr conn, const char **hvm, int *pae, int *longmode)
-{
- struct {
- uint32_t r_eax, r_ebx, r_ecx, r_edx;
- } regs;
-
- char tmpbuf[20];
- int ret = 0;
- int fd;
-
- /* returns -1, errno 22 if in 32-bit mode */
- *longmode = (sysinfo(SI_ARCHITECTURE_64, tmpbuf, sizeof(tmpbuf)) != -1);
-
- if ((fd = open("/dev/cpu/self/cpuid", O_RDONLY)) == -1 ||
- pread(fd, ®s, sizeof(regs), 0) != sizeof(regs)) {
- virReportSystemError(errno, "%s", _("could not read CPU flags"));
- goto out;
- }
-
- *pae = 0;
- *hvm = "";
-
- if (STRPREFIX((const char *)®s.r_ebx, "AuthcAMDenti")) {
- if (pread(fd, ®s, sizeof(regs), 0x80000001) == sizeof(regs)) {
- /* Read secure virtual machine bit (bit 2 of ECX feature ID) */
- if ((regs.r_ecx >> 2) & 1)
- *hvm = "svm";
- if ((regs.r_edx >> 6) & 1)
- *pae = 1;
- }
- } else if (STRPREFIX((const char *)®s.r_ebx, "GenuntelineI")) {
- if (pread(fd, ®s, sizeof(regs), 0x00000001) == sizeof(regs)) {
- /* Read VMXE feature bit (bit 5 of ECX feature ID) */
- if ((regs.r_ecx >> 5) & 1)
- *hvm = "vmx";
- if ((regs.r_edx >> 6) & 1)
- *pae = 1;
- }
- }
-
- ret = 1;
-
- out:
- VIR_FORCE_CLOSE(fd);
- return ret;
-}
-
-static virCapsPtr
-xenHypervisorMakeCapabilitiesSunOS(virConnectPtr conn)
-{
- struct guest_arch guest_arches[32];
- size_t i = 0;
- virCapsPtr caps = NULL;
- int pae, longmode;
- const char *hvm;
-
- if (!get_cpu_flags(conn, &hvm, &pae, &longmode))
- return NULL;
-
- guest_arches[i].arch = VIR_ARCH_I686;
- guest_arches[i].hvm = 0;
- guest_arches[i].pae = pae;
- guest_arches[i].nonpae = !pae;
- guest_arches[i].ia64_be = 0;
- i++;
-
- if (longmode) {
- guest_arches[i].arch = VIR_ARCH_X86_64;
- guest_arches[i].hvm = 0;
- guest_arches[i].pae = 0;
- guest_arches[i].nonpae = 0;
- guest_arches[i].ia64_be = 0;
- i++;
- }
-
- if (hvm[0] != '\0') {
- guest_arches[i].arch = VIR_ARCH_I686;
- guest_arches[i].hvm = 1;
- guest_arches[i].pae = pae;
- guest_arches[i].nonpae = 1;
- guest_arches[i].ia64_be = 0;
- i++;
-
- if (longmode) {
- guest_arches[i].arch = VIR_ARCH_X86_64;
- guest_arches[i].hvm = 1;
- guest_arches[i].pae = 0;
- guest_arches[i].nonpae = 0;
- guest_arches[i].ia64_be = 0;
- i++;
- }
- }
-
- caps = xenHypervisorBuildCapabilities(conn,
- virArchFromHost(),
- pae, hvm,
- guest_arches, i);
-
- return caps;
-}
-
-#endif /* __sun */
-
-/**
- * xenHypervisorMakeCapabilitiesInternal:
- * @conn: pointer to the connection block
- * @cpuinfo: file handle containing /proc/cpuinfo data, or NULL
- * @capabilities: file handle containing /sys/hypervisor/properties/capabilities data, or NULL
- *
- * Return the capabilities of this hypervisor.
- */
-virCapsPtr
-xenHypervisorMakeCapabilitiesInternal(virConnectPtr conn,
- virArch hostarch,
- FILE *cpuinfo,
- FILE *capabilities)
-{
- char line[1024], *str, *token;
- regmatch_t subs[4];
- char *saveptr = NULL;
- size_t i;
-
- char hvm_type[4] = ""; /* "vmx" or "svm" (or "" if not in CPU). */
- int host_pae = 0;
- struct guest_arch guest_archs[32];
- int nr_guest_archs = 0;
- virCapsPtr caps = NULL;
-
- memset(guest_archs, 0, sizeof(guest_archs));
-
- /* /proc/cpuinfo: flags: Intel calls HVM "vmx", AMD calls it "svm".
- * It's not clear if this will work on IA64, let alone other
- * architectures and non-Linux. (XXX)
- */
- if (cpuinfo) {
- while (fgets(line, sizeof(line), cpuinfo)) {
- if (regexec(&flags_hvm_rec, line, sizeof(subs)/sizeof(regmatch_t), subs, 0) == 0
- && subs[0].rm_so != -1) {
- if (virStrncpy(hvm_type,
- &line[subs[1].rm_so],
- subs[1].rm_eo-subs[1].rm_so,
- sizeof(hvm_type)) == NULL)
- goto no_memory;
- } else if (regexec(&flags_pae_rec, line, 0, NULL, 0) == 0) {
- host_pae = 1;
- }
- }
- }
-
- /* Most of the useful info is in /sys/hypervisor/properties/capabilities
- * which is documented in the code in xen-unstable.hg/xen/arch/.../setup.c.
- *
- * It is a space-separated list of supported guest architectures.
- *
- * For x86:
- * TYP-VER-ARCH[p]
- * ^ ^ ^ ^
- * | | | +-- PAE supported
- * | | +------- x86_32 or x86_64
- * | +----------- the version of Xen, eg. "3.0"
- * +--------------- "xen" or "hvm" for para or full virt respectively
- *
- * For PPC this file appears to be always empty (?)
- *
- * For IA64:
- * TYP-VER-ARCH[be]
- * ^ ^ ^ ^
- * | | | +-- Big-endian supported
- * | | +------- always "ia64"
- * | +----------- the version of Xen, eg. "3.0"
- * +--------------- "xen" or "hvm" for para or full virt respectively
- */
-
- /* Expecting one line in this file - ignore any more. */
- if ((capabilities) && (fgets(line, sizeof(line), capabilities))) {
- /* Split the line into tokens. strtok_r is OK here because we "own"
- * this buffer. Parse out the features from each token.
- */
- for (str = line, nr_guest_archs = 0;
- nr_guest_archs < sizeof(guest_archs) / sizeof(guest_archs[0])
- && (token = strtok_r(str, " ", &saveptr)) != NULL;
- str = NULL) {
-
- if (regexec(&xen_cap_rec, token, sizeof(subs) / sizeof(subs[0]),
- subs, 0) == 0) {
- int hvm = STRPREFIX(&token[subs[1].rm_so], "hvm");
- int pae = 0, nonpae = 0, ia64_be = 0;
- virArch arch;
-
- if (STRPREFIX(&token[subs[2].rm_so], "x86_32")) {
- arch = VIR_ARCH_I686;
- if (subs[3].rm_so != -1 &&
- STRPREFIX(&token[subs[3].rm_so], "p"))
- pae = 1;
- else
- nonpae = 1;
- } else if (STRPREFIX(&token[subs[2].rm_so], "x86_64")) {
- arch = VIR_ARCH_X86_64;
- } else if (STRPREFIX(&token[subs[2].rm_so], "ia64")) {
- arch = VIR_ARCH_ITANIUM;
- if (subs[3].rm_so != -1 &&
- STRPREFIX(&token[subs[3].rm_so], "be"))
- ia64_be = 1;
- } else if (STRPREFIX(&token[subs[2].rm_so], "powerpc64")) {
- arch = VIR_ARCH_PPC64;
- } else {
- /* XXX surely no other Xen archs exist. Arrrrrrrrrm */
- continue;
- }
-
- /* Search for existing matching (model,hvm) tuple */
- for (i = 0; i < nr_guest_archs; i++) {
- if (guest_archs[i].arch == arch &&
- guest_archs[i].hvm == hvm) {
- break;
- }
- }
-
- /* Too many arch flavours - highly unlikely ! */
- if (i >= ARRAY_CARDINALITY(guest_archs))
- continue;
- /* Didn't find a match, so create a new one */
- if (i == nr_guest_archs)
- nr_guest_archs++;
-
- guest_archs[i].arch = arch;
- guest_archs[i].hvm = hvm;
-
- /* Careful not to overwrite a previous positive
- setting with a negative one here - some archs
- can do both pae & non-pae, but Xen reports
- separately capabilities so we're merging archs */
- if (pae)
- guest_archs[i].pae = pae;
- if (nonpae)
- guest_archs[i].nonpae = nonpae;
- if (ia64_be)
- guest_archs[i].ia64_be = ia64_be;
- }
- }
- }
-
- if ((caps = xenHypervisorBuildCapabilities(conn,
- hostarch,
- host_pae,
- hvm_type,
- guest_archs,
- nr_guest_archs)) == NULL)
- goto no_memory;
-
- return caps;
-
- no_memory:
- virObjectUnref(caps);
- return NULL;
-}
-
-/**
- * xenHypervisorMakeCapabilities:
- *
- * Return the capabilities of this hypervisor.
- */
-virCapsPtr
-xenHypervisorMakeCapabilities(virConnectPtr conn)
-{
-#ifdef __sun
- return xenHypervisorMakeCapabilitiesSunOS(conn);
-#else
- virCapsPtr caps = NULL;
- FILE *cpuinfo, *capabilities;
-
- cpuinfo = fopen("/proc/cpuinfo", "r");
- if (cpuinfo == NULL) {
- if (errno != ENOENT) {
- virReportSystemError(errno,
- _("cannot read file %s"),
- "/proc/cpuinfo");
- return NULL;
- }
- }
-
- capabilities = fopen("/sys/hypervisor/properties/capabilities", "r");
- if (capabilities == NULL) {
- if (errno != ENOENT) {
- VIR_FORCE_FCLOSE(cpuinfo);
- virReportSystemError(errno,
- _("cannot read file %s"),
- "/sys/hypervisor/properties/capabilities");
- return NULL;
- }
- }
-
- caps = xenHypervisorMakeCapabilitiesInternal(conn,
- virArchFromHost(),
- cpuinfo,
- capabilities);
- if (caps == NULL)
- goto cleanup;
-
- if (virNodeSuspendGetTargetMask(&caps->host.powerMgmt) < 0)
- VIR_WARN("Failed to get host power management capabilities");
-
- cleanup:
- VIR_FORCE_FCLOSE(cpuinfo);
- VIR_FORCE_FCLOSE(capabilities);
-
- return caps;
-#endif /* __sun */
-}
-
-
-
-/**
- * xenHypervisorGetCapabilities:
- * @conn: pointer to the connection block
- *
- * Return the capabilities of this hypervisor.
- */
-char *
-xenHypervisorGetCapabilities(virConnectPtr conn)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
-
- return virCapabilitiesFormatXML(priv->caps);
-}
-
-
-char *
-xenHypervisorDomainGetOSType(virConnectPtr conn,
- virDomainDefPtr def)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- xen_getdomaininfo dominfo;
- char *ostype = NULL;
-
- /* HV's earlier than 3.1.0 don't include the HVM flags in guests status*/
- if (hv_versions.hypervisor < 2 ||
- hv_versions.dom_interface < 4) {
- return xenDaemonDomainGetOSType(conn, def);
- }
-
- XEN_GETDOMAININFO_CLEAR(dominfo);
-
- if (virXen_getdomaininfo(priv->handle, def->id, &dominfo) < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("cannot get domain details"));
- return NULL;
- }
-
- if (XEN_GETDOMAININFO_DOMAIN(dominfo) != def->id) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("cannot get domain details"));
- return NULL;
- }
-
- ignore_value(VIR_STRDUP(ostype,
- XEN_GETDOMAININFO_FLAGS(dominfo) & DOMFLAGS_HVM ?
- "hvm" : "linux"));
- return ostype;
-}
-
-int
-xenHypervisorHasDomain(virConnectPtr conn, int id)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- xen_getdomaininfo dominfo;
-
- XEN_GETDOMAININFO_CLEAR(dominfo);
-
- if (virXen_getdomaininfo(priv->handle, id, &dominfo) < 0)
- return 0;
-
- if (XEN_GETDOMAININFO_DOMAIN(dominfo) != id)
- return 0;
-
- return 1;
-}
-
-
-virDomainDefPtr
-xenHypervisorLookupDomainByID(virConnectPtr conn, int id)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- xen_getdomaininfo dominfo;
- virDomainDefPtr ret;
- char *name;
-
- XEN_GETDOMAININFO_CLEAR(dominfo);
-
- if (virXen_getdomaininfo(priv->handle, id, &dominfo) < 0)
- return NULL;
-
- if (XEN_GETDOMAININFO_DOMAIN(dominfo) != id)
- return NULL;
-
- xenUnifiedLock(priv);
- name = xenStoreDomainGetName(conn, id);
- xenUnifiedUnlock(priv);
- if (!name)
- return NULL;
-
- ret = virDomainDefNewFull(name,
- XEN_GETDOMAININFO_UUID(dominfo),
- id);
- VIR_FREE(name);
- return ret;
-}
-
-
-virDomainDefPtr
-xenHypervisorLookupDomainByUUID(virConnectPtr conn, const unsigned char *uuid)
-{
- xen_getdomaininfolist dominfos;
- xenUnifiedPrivatePtr priv = conn->privateData;
- virDomainDefPtr ret;
- char *name;
- int maxids = 100, nids, id;
- size_t i;
-
- retry:
- if (!(XEN_GETDOMAININFOLIST_ALLOC(dominfos, maxids))) {
- virReportOOMError();
- return NULL;
- }
-
- XEN_GETDOMAININFOLIST_CLEAR(dominfos, maxids);
-
- nids = virXen_getdomaininfolist(priv->handle, 0, maxids, &dominfos);
-
- if (nids < 0) {
- XEN_GETDOMAININFOLIST_FREE(dominfos);
- return NULL;
- }
-
- /* Can't possibly have more than 65,000 concurrent guests
- * so limit how many times we try, to avoid increasing
- * without bound & thus allocating all of system memory !
- * XXX I'll regret this comment in a few years time ;-)
- */
- if (nids == maxids) {
- XEN_GETDOMAININFOLIST_FREE(dominfos);
- if (maxids < 65000) {
- maxids *= 2;
- goto retry;
- }
- return NULL;
- }
-
- id = -1;
- for (i = 0; i < nids; i++) {
- if (memcmp(XEN_GETDOMAININFOLIST_UUID(dominfos, i), uuid, VIR_UUID_BUFLEN) == 0) {
- id = XEN_GETDOMAININFOLIST_DOMAIN(dominfos, i);
- break;
- }
- }
- XEN_GETDOMAININFOLIST_FREE(dominfos);
-
- if (id == -1)
- return NULL;
-
- xenUnifiedLock(priv);
- name = xenStoreDomainGetName(conn, id);
- xenUnifiedUnlock(priv);
- if (!name)
- return NULL;
-
- ret = virDomainDefNewFull(name, uuid, id);
- if (ret)
- ret->id = id;
- VIR_FREE(name);
- return ret;
-}
-
-/**
- * xenHypervisorGetMaxVcpus:
- *
- * Returns the maximum of CPU defined by Xen.
- */
-int
-xenHypervisorGetMaxVcpus(virConnectPtr conn ATTRIBUTE_UNUSED,
- const char *type ATTRIBUTE_UNUSED)
-{
- return MAX_VIRT_CPUS;
-}
-
-/**
- * xenHypervisorDomMaxMemory:
- * @dom: domain
- *
- * Retrieve the maximum amount of physical memory allocated to a
- * domain.
- *
- * Returns the memory size in kilobytes or 0 in case of error.
- */
-unsigned long
-xenHypervisorGetMaxMemory(virConnectPtr conn,
- virDomainDefPtr def)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- xen_getdomaininfo dominfo;
- int ret;
-
- if (kb_per_pages == 0) {
- kb_per_pages = virGetSystemPageSizeKB();
- if (kb_per_pages <= 0)
- kb_per_pages = 4;
- }
-
- XEN_GETDOMAININFO_CLEAR(dominfo);
-
- ret = virXen_getdomaininfo(priv->handle, def->id, &dominfo);
-
- if ((ret < 0) || (XEN_GETDOMAININFO_DOMAIN(dominfo) != def->id))
- return 0;
-
- return (unsigned long) XEN_GETDOMAININFO_MAX_PAGES(dominfo) * kb_per_pages;
-}
-
-
-/**
- * xenHypervisorGetDomInfo:
- * @conn: connection data
- * @id: the domain ID
- * @info: the place where information should be stored
- *
- * Do a hypervisor call to get the related set of domain information.
- *
- * Returns 0 in case of success, -1 in case of error.
- */
-int
-xenHypervisorGetDomInfo(virConnectPtr conn, int id, virDomainInfoPtr info)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- xen_getdomaininfo dominfo;
- int ret;
- uint32_t domain_flags, domain_state, domain_shutdown_cause;
-
- if (kb_per_pages == 0) {
- kb_per_pages = virGetSystemPageSizeKB();
- if (kb_per_pages <= 0)
- kb_per_pages = 4;
- }
-
- memset(info, 0, sizeof(virDomainInfo));
- XEN_GETDOMAININFO_CLEAR(dominfo);
-
- ret = virXen_getdomaininfo(priv->handle, id, &dominfo);
-
- if ((ret < 0) || (XEN_GETDOMAININFO_DOMAIN(dominfo) != id))
- return -1;
-
- domain_flags = XEN_GETDOMAININFO_FLAGS(dominfo);
- domain_flags &= ~DOMFLAGS_HVM; /* Mask out HVM flags */
- domain_state = domain_flags & 0xFF; /* Mask out high bits */
- switch (domain_state) {
- case DOMFLAGS_DYING:
- info->state = VIR_DOMAIN_SHUTDOWN;
- break;
- case DOMFLAGS_SHUTDOWN:
- /* The domain is shutdown. Determine the cause. */
- domain_shutdown_cause = domain_flags >> DOMFLAGS_SHUTDOWNSHIFT;
- switch (domain_shutdown_cause) {
- case SHUTDOWN_crash:
- info->state = VIR_DOMAIN_CRASHED;
- break;
- default:
- info->state = VIR_DOMAIN_SHUTOFF;
- }
- break;
- case DOMFLAGS_PAUSED:
- info->state = VIR_DOMAIN_PAUSED;
- break;
- case DOMFLAGS_BLOCKED:
- info->state = VIR_DOMAIN_BLOCKED;
- break;
- case DOMFLAGS_RUNNING:
- info->state = VIR_DOMAIN_RUNNING;
- break;
- default:
- info->state = VIR_DOMAIN_NOSTATE;
- }
-
- /*
- * the API brings back the cpu time in nanoseconds,
- * convert to microseconds, same thing convert to
- * kilobytes from page counts
- */
- info->cpuTime = XEN_GETDOMAININFO_CPUTIME(dominfo);
- info->memory = XEN_GETDOMAININFO_TOT_PAGES(dominfo) * kb_per_pages;
- info->maxMem = XEN_GETDOMAININFO_MAX_PAGES(dominfo);
- if (info->maxMem != UINT_MAX)
- info->maxMem *= kb_per_pages;
- info->nrVirtCpu = XEN_GETDOMAININFO_CPUCOUNT(dominfo);
- return 0;
-}
-
-/**
- * xenHypervisorGetDomainInfo:
- * @domain: pointer to the domain block
- * @info: the place where information should be stored
- *
- * Do a hypervisor call to get the related set of domain information.
- *
- * Returns 0 in case of success, -1 in case of error.
- */
-int
-xenHypervisorGetDomainInfo(virConnectPtr conn,
- virDomainDefPtr def,
- virDomainInfoPtr info)
-{
- return xenHypervisorGetDomInfo(conn, def->id, info);
-}
-
-/**
- * xenHypervisorGetDomainState:
- * @domain: pointer to the domain block
- * @state: returned state of the domain
- * @reason: returned reason for the state
- *
- * Do a hypervisor call to get the related set of domain information.
- *
- * Returns 0 in case of success, -1 in case of error.
- */
-int
-xenHypervisorGetDomainState(virConnectPtr conn,
- virDomainDefPtr def,
- int *state,
- int *reason)
-{
- virDomainInfo info;
-
- if (xenHypervisorGetDomInfo(conn, def->id, &info) < 0)
- return -1;
-
- *state = info.state;
- if (reason)
- *reason = 0;
-
- return 0;
-}
-
-/**
- * xenHypervisorNodeGetCellsFreeMemory:
- * @conn: pointer to the hypervisor connection
- * @freeMems: pointer to the array of unsigned long long
- * @startCell: index of first cell to return freeMems info on.
- * @maxCells: Maximum number of cells for which freeMems information can
- * be returned.
- *
- * This call returns the amount of free memory in one or more NUMA cells.
- * The @freeMems array must be allocated by the caller and will be filled
- * with the amount of free memory in kilobytes for each cell requested,
- * starting with startCell (in freeMems[0]), up to either
- * (startCell + maxCells), or the number of additional cells in the node,
- * whichever is smaller.
- *
- * Returns the number of entries filled in freeMems, or -1 in case of error.
- */
-int
-xenHypervisorNodeGetCellsFreeMemory(virConnectPtr conn,
- unsigned long long *freeMems,
- int startCell,
- int maxCells)
-{
- xen_op_v2_sys op_sys;
- size_t i;
- int cell;
- int ret;
- xenUnifiedPrivatePtr priv = conn->privateData;
-
- if (priv->nbNodeCells < 0) {
- virReportError(VIR_ERR_XEN_CALL, "%s",
- _("cannot determine actual number of cells"));
- return -1;
- }
-
- if ((maxCells < 1) || (startCell >= priv->nbNodeCells)) {
- virReportError(VIR_ERR_INVALID_ARG, "%s",
- _("invalid argument"));
- return -1;
- }
-
- /*
- * Support only hv_versions.sys_interface >=4
- */
- if (hv_versions.sys_interface < SYS_IFACE_MIN_VERS_NUMA) {
- virReportError(VIR_ERR_XEN_CALL, "%s",
- _("unsupported in sys interface < 4"));
- return -1;
- }
-
- memset(&op_sys, 0, sizeof(op_sys));
- op_sys.cmd = XEN_V2_OP_GETAVAILHEAP;
-
- for (cell = startCell, i = 0;
- cell < priv->nbNodeCells && i < maxCells; cell++, i++) {
- if (hv_versions.sys_interface >= 5)
- op_sys.u.availheap5.node = cell;
- else
- op_sys.u.availheap.node = cell;
- ret = xenHypervisorDoV2Sys(priv->handle, &op_sys);
- if (ret < 0)
- return -1;
- if (hv_versions.sys_interface >= 5)
- freeMems[i] = op_sys.u.availheap5.avail_bytes;
- else
- freeMems[i] = op_sys.u.availheap.avail_bytes;
- }
- return i;
-}
-
-
-/**
- * xenHypervisorSetMaxMemory:
- * @domain: pointer to the domain block
- * @memory: the max memory size in kilobytes.
- *
- * Do a hypervisor call to change the maximum amount of memory used
- *
- * Returns 0 in case of success, -1 in case of error.
- */
-int
-xenHypervisorSetMaxMemory(virConnectPtr conn,
- virDomainDefPtr def,
- unsigned long memory)
-{
- int ret;
- xenUnifiedPrivatePtr priv = conn->privateData;
-
- ret = virXen_setmaxmem(priv->handle, def->id, memory);
- if (ret < 0)
- return -1;
- return 0;
-}
-
-
-/**
- * xenHypervisorPinVcpu:
- * @domain: pointer to domain object
- * @vcpu: virtual CPU number
- * @cpumap: pointer to a bit map of real CPUs (in 8-bit bytes)
- * @maplen: length of cpumap in bytes
- *
- * Dynamically change the real CPUs which can be allocated to a virtual CPU.
- *
- * Returns 0 in case of success, -1 in case of failure.
- */
-
-int
-xenHypervisorPinVcpu(virConnectPtr conn,
- virDomainDefPtr def,
- unsigned int vcpu,
- unsigned char *cpumap,
- int maplen)
-{
- int ret;
- xenUnifiedPrivatePtr priv = conn->privateData;
-
- ret = virXen_setvcpumap(priv->handle, def->id, vcpu,
- cpumap, maplen);
- if (ret < 0)
- return -1;
- return 0;
-}
-
-/**
- * virDomainGetVcpus:
- * @domain: pointer to domain object, or NULL for Domain0
- * @info: pointer to an array of virVcpuInfo structures (OUT)
- * @maxinfo: number of structures in info array
- * @cpumaps: pointer to a bit map of real CPUs for all vcpus of this domain (in 8-bit bytes) (OUT)
- * If cpumaps is NULL, then no cpumap information is returned by the API.
- * It's assumed there is <maxinfo> cpumap in cpumaps array.
- * The memory allocated to cpumaps must be (maxinfo * maplen) bytes
- * (ie: calloc(maxinfo, maplen)).
- * One cpumap inside cpumaps has the format described in virDomainPinVcpu() API.
- * @maplen: number of bytes in one cpumap, from 1 up to size of CPU map in
- * underlying virtualization system (Xen...).
- *
- * Extract information about virtual CPUs of domain, store it in info array
- * and also in cpumaps if this pointer isn't NULL.
- *
- * Returns the number of info filled in case of success, -1 in case of failure.
- */
-int
-xenHypervisorGetVcpus(virConnectPtr conn,
- virDomainDefPtr def,
- virVcpuInfoPtr info,
- int maxinfo,
- unsigned char *cpumaps,
- int maplen)
-{
- xen_getdomaininfo dominfo;
- int ret;
- xenUnifiedPrivatePtr priv = conn->privateData;
- virVcpuInfoPtr ipt;
- int nbinfo;
- size_t i;
-
- if (sizeof(cpumap_t) & 7) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("invalid cpumap_t size"));
- return -1;
- }
-
- /* first get the number of virtual CPUs in this domain */
- XEN_GETDOMAININFO_CLEAR(dominfo);
- ret = virXen_getdomaininfo(priv->handle, def->id,
- &dominfo);
-
- if ((ret < 0) || (XEN_GETDOMAININFO_DOMAIN(dominfo) != def->id)) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("cannot get domain details"));
- return -1;
- }
- nbinfo = XEN_GETDOMAININFO_CPUCOUNT(dominfo) + 1;
- if (nbinfo > maxinfo) nbinfo = maxinfo;
-
- if (cpumaps != NULL)
- memset(cpumaps, 0, maxinfo * maplen);
-
- for (i = 0, ipt = info; i < nbinfo; i++, ipt++) {
- if ((cpumaps != NULL) && (i < maxinfo)) {
- ret = virXen_getvcpusinfo(priv->handle, def->id, i,
- ipt,
- (unsigned char *)VIR_GET_CPUMAP(cpumaps, maplen, i),
- maplen);
- if (ret < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("cannot get VCPUs info"));
- return -1;
- }
- } else {
- ret = virXen_getvcpusinfo(priv->handle, def->id, i,
- ipt, NULL, 0);
- if (ret < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("cannot get VCPUs info"));
- return -1;
- }
- }
- }
- return nbinfo;
-}
-
-/**
- * xenHypervisorGetVcpuMax:
- *
- * Returns the maximum number of virtual CPUs supported for
- * the guest VM. If the guest is inactive, this is the maximum
- * of CPU defined by Xen. If the guest is running this reflect
- * the maximum number of virtual CPUs the guest was booted with.
- */
-int
-xenHypervisorGetVcpuMax(virConnectPtr conn,
- virDomainDefPtr def)
-{
- xen_getdomaininfo dominfo;
- int ret;
- int maxcpu;
- xenUnifiedPrivatePtr priv = conn->privateData;
-
- /* inactive domain */
- if (def->id < 0) {
- maxcpu = MAX_VIRT_CPUS;
- } else {
- XEN_GETDOMAININFO_CLEAR(dominfo);
- ret = virXen_getdomaininfo(priv->handle, def->id,
- &dominfo);
-
- if ((ret < 0) || (XEN_GETDOMAININFO_DOMAIN(dominfo) != def->id))
- return -1;
- maxcpu = XEN_GETDOMAININFO_MAXCPUID(dominfo) + 1;
- }
-
- return maxcpu;
-}
-
-/**
- * xenHavePrivilege()
- *
- * Return true if the current process should be able to connect to Xen.
- */
-int
-xenHavePrivilege(void)
-{
-#ifdef __sun
- return priv_ineffect(PRIV_XVM_CONTROL);
-#else
- return access(XEN_HYPERVISOR_SOCKET, R_OK) == 0;
-#endif
-}
+++ /dev/null
-/*
- * xen_hypervisor.h: internal API for direct access to Xen hypervisor level
- *
- * Copyright (C) 2005, 2010-2011 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/>.
- *
- * Daniel Veillard <veillard@redhat.com>
- */
-
-#ifndef __VIR_XEN_INTERNAL_H__
-# define __VIR_XEN_INTERNAL_H__
-
-# include "internal.h"
-# include "capabilities.h"
-# include "driver.h"
-# include "viruri.h"
-# include "domain_conf.h"
-
-/* See xenHypervisorInit() for details. */
-struct xenHypervisorVersions {
- int hv; /* u16 major,minor hypervisor version */
- int hypervisor; /* -1,0,1,2,3 */
- int sys_interface; /* -1,2,3,4,6,7,8 */
- int dom_interface; /* -1,3,4,5,6,7 */
-};
-
-int xenHypervisorInit(struct xenHypervisorVersions *override_versions);
-
-virCapsPtr xenHypervisorMakeCapabilities (virConnectPtr conn);
-
-int
- xenHypervisorHasDomain(virConnectPtr conn,
- int id);
-virDomainDefPtr
- xenHypervisorLookupDomainByID (virConnectPtr conn, int id);
-virDomainDefPtr
- xenHypervisorLookupDomainByUUID (virConnectPtr conn,
- const unsigned char *uuid);
-char *
- xenHypervisorDomainGetOSType (virConnectPtr conn,
- virDomainDefPtr def);
-
-int
- xenHypervisorOpen (virConnectPtr conn,
- virConnectAuthPtr auth,
- unsigned int flags);
-int xenHypervisorClose (virConnectPtr conn);
-int xenHypervisorGetVersion (virConnectPtr conn,
- unsigned long *hvVer);
-virCapsPtr
- xenHypervisorMakeCapabilitiesInternal(virConnectPtr conn,
- virArch hostarch,
- FILE *cpuinfo,
- FILE *capabilities);
-char * xenHypervisorGetCapabilities (virConnectPtr conn);
-unsigned long
- xenHypervisorGetMaxMemory(virConnectPtr conn,
- virDomainDefPtr def);
-int xenHypervisorGetMaxVcpus (virConnectPtr conn,
- const char *type);
-int xenHypervisorGetDomainInfo (virConnectPtr conn,
- virDomainDefPtr def,
- virDomainInfoPtr info)
- ATTRIBUTE_NONNULL (1);
-int xenHypervisorGetDomainState (virConnectPtr conn,
- virDomainDefPtr def,
- int *state,
- int *reason)
- ATTRIBUTE_NONNULL (1);
-int xenHypervisorGetDomInfo (virConnectPtr conn,
- int id,
- virDomainInfoPtr info);
-int xenHypervisorSetMaxMemory (virConnectPtr conn,
- virDomainDefPtr def,
- unsigned long memory)
- ATTRIBUTE_NONNULL (1);
-int xenHypervisorCheckID (virConnectPtr conn,
- int id);
-int xenHypervisorPinVcpu (virConnectPtr conn,
- virDomainDefPtr def,
- unsigned int vcpu,
- unsigned char *cpumap,
- int maplen)
- ATTRIBUTE_NONNULL (1);
-int xenHypervisorGetVcpus (virConnectPtr conn,
- virDomainDefPtr def,
- virVcpuInfoPtr info,
- int maxinfo,
- unsigned char *cpumaps,
- int maplen)
- ATTRIBUTE_NONNULL (1);
-int xenHypervisorGetVcpuMax (virConnectPtr conn,
- virDomainDefPtr def)
- ATTRIBUTE_NONNULL (1);
-
-char * xenHypervisorGetSchedulerType (virConnectPtr conn,
- int *nparams)
- ATTRIBUTE_NONNULL (1);
-
-int xenHypervisorGetSchedulerParameters(virConnectPtr conn,
- virDomainDefPtr def,
- virTypedParameterPtr params,
- int *nparams)
- ATTRIBUTE_NONNULL (1);
-
-int xenHypervisorSetSchedulerParameters(virConnectPtr conn,
- virDomainDefPtr def,
- virTypedParameterPtr params,
- int nparams)
- ATTRIBUTE_NONNULL (1);
-
-int xenHypervisorDomainBlockStats (virConnectPtr conn,
- virDomainDefPtr def,
- const char *path,
- virDomainBlockStatsPtr stats)
- ATTRIBUTE_NONNULL (1);
-int xenHypervisorDomainInterfaceStats (virDomainDefPtr def,
- const char *path,
- virDomainInterfaceStatsPtr stats)
- ATTRIBUTE_NONNULL (1);
-
-int xenHypervisorNodeGetCellsFreeMemory(virConnectPtr conn,
- unsigned long long *freeMems,
- int startCell,
- int maxCells);
-
-int xenHavePrivilege(void);
-
-#endif /* __VIR_XEN_INTERNAL_H__ */
+++ /dev/null
-/*
- * xen_inotify.c: Xen notification of xml file activity in the
- * following dirs:
- * /etc/xen
- * /var/lib/xend/domains
- *
- * Copyright (C) 2010-2014 Red Hat, Inc.
- * Copyright (C) 2008 VirtualIron
- *
- * 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/>.
- *
- * Author: Ben Guthro
- */
-#include <config.h>
-#include <dirent.h>
-#include <sys/inotify.h>
-
-#include "virerror.h"
-#include "datatypes.h"
-#include "driver.h"
-#include "viralloc.h"
-#include "xen_driver.h"
-#include "virconf.h"
-#include "domain_conf.h"
-#include "xen_inotify.h"
-#include "xend_internal.h"
-#include "virlog.h"
-#include "viruuid.h"
-#include "virfile.h"
-#include "virstring.h"
-#include "xm_internal.h" /* for xenXMDomainConfigParse */
-
-#define VIR_FROM_THIS VIR_FROM_XEN_INOTIFY
-
-VIR_LOG_INIT("xen.xen_inotify");
-
-static int
-xenInotifyXenCacheLookup(virConnectPtr conn,
- const char *filename,
- char **name,
- unsigned char *uuid)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- xenXMConfCachePtr entry;
-
- if (!(entry = virHashLookup(priv->configCache, filename))) {
- VIR_DEBUG("No config found for %s", filename);
- return -1;
- }
-
- memcpy(uuid, entry->def->uuid, VIR_UUID_BUFLEN);
- if (VIR_STRDUP(*name, entry->def->name) < 0) {
- VIR_DEBUG("Error getting dom from def");
- return -1;
- }
- return 0;
-}
-
-static int
-xenInotifyXendDomainsDirLookup(virConnectPtr conn,
- const char *filename,
- char **name,
- unsigned char *uuid)
-{
- size_t i;
- virDomainDefPtr def;
- const char *uuid_str;
- unsigned char rawuuid[VIR_UUID_BUFLEN];
- xenUnifiedPrivatePtr priv = conn->privateData;
-
- /* xend is managing domains. we will get
- * a filename in the manner:
- * /var/lib/xend/domains/<uuid>/
- */
- uuid_str = filename + strlen(XEND_DOMAINS_DIR) + 1;
-
- if (virUUIDParse(uuid_str, rawuuid) < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("parsing uuid %s"), uuid_str);
- return -1;
- }
- /* call directly into xend here, as driver may not yet
- be set during open while we are building our
- initial list of domains */
- VIR_DEBUG("Looking for dom with uuid: %s", uuid_str);
-
- if (!(def = xenDaemonLookupByUUID(conn, rawuuid))) {
- /* If we are here, the domain has gone away.
- search for, and create a domain from the stored
- list info */
- for (i = 0; i < priv->configInfoList->count; i++) {
- if (!memcmp(rawuuid, priv->configInfoList->doms[i]->uuid, VIR_UUID_BUFLEN)) {
- if (VIR_STRDUP(*name, priv->configInfoList->doms[i]->name) < 0)
- return -1;
- memcpy(uuid, priv->configInfoList->doms[i]->uuid, VIR_UUID_BUFLEN);
- VIR_DEBUG("Found dom on list");
- return 0;
- }
- }
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("finding dom on config list"));
- return -1;
- }
-
- if (VIR_STRDUP(*name, def->name) < 0) {
- virDomainDefFree(def);
- return -1;
- }
- memcpy(uuid, def->uuid, VIR_UUID_BUFLEN);
- virDomainDefFree(def);
- /* succeeded too find domain by uuid */
- return 0;
-}
-
-static int
-xenInotifyDomainLookup(virConnectPtr conn,
- const char *filename,
- char **name,
- unsigned char *uuid)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- if (priv->useXenConfigCache)
- return xenInotifyXenCacheLookup(conn, filename, name, uuid);
- else
- return xenInotifyXendDomainsDirLookup(conn, filename, name, uuid);
-}
-
-static virObjectEventPtr
-xenInotifyDomainEventFromFile(virConnectPtr conn,
- const char *filename,
- int type,
- int detail)
-{
- virObjectEventPtr event;
- char *name = NULL;
- unsigned char uuid[VIR_UUID_BUFLEN];
-
- if (xenInotifyDomainLookup(conn, filename, &name, uuid) < 0)
- return NULL;
-
- event = virDomainEventLifecycleNew(-1, name, uuid, type, detail);
- VIR_FREE(name);
- return event;
-}
-
-static int
-xenInotifyXendDomainsDirRemoveEntry(virConnectPtr conn, const char *fname)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- const char *uuidstr = fname + strlen(XEND_DOMAINS_DIR) + 1;
- unsigned char uuid[VIR_UUID_BUFLEN];
- size_t i;
-
- if (virUUIDParse(uuidstr, uuid) < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("parsing uuid %s"), uuidstr);
- return -1;
- }
-
- /* match and remove on uuid */
- for (i = 0; i < priv->configInfoList->count; i++) {
- if (!memcmp(uuid, priv->configInfoList->doms[i]->uuid, VIR_UUID_BUFLEN)) {
- VIR_FREE(priv->configInfoList->doms[i]->name);
- VIR_FREE(priv->configInfoList->doms[i]);
-
- VIR_DELETE_ELEMENT(priv->configInfoList->doms, i,
- priv->configInfoList->count);
- return 0;
- }
- }
- return -1;
-}
-
-static int
-xenInotifyXendDomainsDirAddEntry(virConnectPtr conn, const char *fname)
-{
- char *name = NULL;
- unsigned char uuid[VIR_UUID_BUFLEN];
- xenUnifiedPrivatePtr priv = conn->privateData;
-
- if (xenInotifyDomainLookup(conn, fname, &name, uuid) < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("Error looking up domain"));
- return -1;
- }
-
- if (xenUnifiedAddDomainInfo(priv->configInfoList,
- -1, name, uuid) < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("Error adding file to config cache"));
- VIR_FREE(name);
- return -1;
- }
- VIR_FREE(name);
- return 0;
-}
-
-static int
-xenInotifyRemoveDomainConfigInfo(virConnectPtr conn, const char *fname)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- return priv->useXenConfigCache ?
- xenXMConfigCacheRemoveFile(conn, fname) :
- xenInotifyXendDomainsDirRemoveEntry(conn, fname);
-}
-
-static int
-xenInotifyAddDomainConfigInfo(virConnectPtr conn, const char *fname, time_t now)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- return priv->useXenConfigCache ?
- xenXMConfigCacheAddFile(conn, fname, now) :
- xenInotifyXendDomainsDirAddEntry(conn, fname);
-}
-
-static void
-xenInotifyEvent(int watch ATTRIBUTE_UNUSED,
- int fd,
- int events ATTRIBUTE_UNUSED,
- void *data)
-{
- char buf[1024];
- char fname[1024];
- struct inotify_event *e;
- int got;
- char *tmp, *name;
- virConnectPtr conn = data;
- xenUnifiedPrivatePtr priv = NULL;
- time_t now = time(NULL);
-
- VIR_DEBUG("got inotify event");
-
- if (conn && conn->privateData) {
- priv = conn->privateData;
- } else {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("conn, or private data is NULL"));
- return;
- }
-
- xenUnifiedLock(priv);
-
- reread:
- got = read(fd, buf, sizeof(buf));
- if (got == -1) {
- if (errno == EINTR)
- goto reread;
- goto cleanup;
- }
-
- tmp = buf;
- while (got) {
- if (got < sizeof(struct inotify_event))
- goto cleanup; /* bad */
-
- VIR_WARNINGS_NO_CAST_ALIGN
- e = (struct inotify_event *)tmp;
- VIR_WARNINGS_RESET
-
- tmp += sizeof(struct inotify_event);
- got -= sizeof(struct inotify_event);
-
- if (got < e->len)
- goto cleanup;
-
- tmp += e->len;
- got -= e->len;
-
- name = (char *)&(e->name);
-
- snprintf(fname, 1024, "%s/%s",
- priv->configDir, name);
-
- if (e->mask & (IN_DELETE | IN_MOVED_FROM)) {
- virObjectEventPtr event =
- xenInotifyDomainEventFromFile(conn, fname,
- VIR_DOMAIN_EVENT_UNDEFINED,
- VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
- if (event)
- xenUnifiedDomainEventDispatch(conn->privateData, event);
- else
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("looking up dom"));
-
- if (xenInotifyRemoveDomainConfigInfo(conn, fname) < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("Error adding file to config cache"));
- goto cleanup;
- }
- } else if (e->mask & (IN_CREATE | IN_CLOSE_WRITE | IN_MOVED_TO)) {
- virObjectEventPtr event;
- if (xenInotifyAddDomainConfigInfo(conn, fname, now) < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("Error adding file to config cache"));
- goto cleanup;
- }
-
- event = xenInotifyDomainEventFromFile(conn, fname,
- VIR_DOMAIN_EVENT_DEFINED,
- VIR_DOMAIN_EVENT_DEFINED_ADDED);
-
- if (event)
- xenUnifiedDomainEventDispatch(conn->privateData, event);
- else
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("looking up dom"));
-
- }
-
- }
-
- cleanup:
- xenUnifiedUnlock(priv);
-}
-
-/**
- * xenInotifyOpen:
- * @conn: pointer to the connection block
- * @name: URL for the target, NULL for local
- * @flags: combination of virDrvOpenFlag(s)
- *
- * Connects and starts listening for inotify events
- *
- * Returns 0 or -1 in case of error.
- */
-int
-xenInotifyOpen(virConnectPtr conn,
- virConnectAuthPtr auth ATTRIBUTE_UNUSED,
- unsigned int flags)
-{
- DIR *dh;
- struct dirent *ent;
- char *path;
- xenUnifiedPrivatePtr priv = conn->privateData;
- int direrr;
- time_t now = time(NULL);
-
- virCheckFlags(VIR_CONNECT_RO, -1);
-
- if (priv->configDir) {
- priv->useXenConfigCache = 1;
- } else {
- /* /var/lib/xend/domains/<uuid>/config.sxp */
- priv->configDir = XEND_DOMAINS_DIR;
- priv->useXenConfigCache = 0;
-
- if (VIR_ALLOC(priv->configInfoList) < 0)
- return -1;
-
- /* populate initial list */
- if (virDirOpen(&dh, priv->configDir) < 0)
- return -1;
-
- while ((direrr = virDirRead(dh, &ent, priv->configDir)) > 0) {
- if (STRPREFIX(ent->d_name, "."))
- continue;
-
- /* Build the full file path */
- if (!(path = virFileBuildPath(priv->configDir, ent->d_name, NULL))) {
- VIR_DIR_CLOSE(dh);
- return -1;
- }
-
- if (xenInotifyAddDomainConfigInfo(conn, path, now) < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("Error adding file to config list"));
- VIR_DIR_CLOSE(dh);
- VIR_FREE(path);
- return -1;
- }
-
- VIR_FREE(path);
- }
- VIR_DIR_CLOSE(dh);
- if (direrr < 0)
- return -1;
- }
-
- if ((priv->inotifyFD = inotify_init()) < 0) {
- virReportSystemError(errno,
- "%s", _("initializing inotify"));
- return -1;
- }
-
- VIR_DEBUG("Adding a watch on %s", priv->configDir);
- if (inotify_add_watch(priv->inotifyFD,
- priv->configDir,
- IN_CREATE |
- IN_CLOSE_WRITE | IN_DELETE |
- IN_MOVED_TO | IN_MOVED_FROM) < 0) {
- virReportSystemError(errno,
- _("adding watch on %s"),
- priv->configDir);
- return -1;
- }
-
- VIR_DEBUG("Building initial config cache");
- if (priv->useXenConfigCache &&
- xenXMConfigCacheRefresh(conn) < 0) {
- VIR_DEBUG("Failed to enable XM config cache %s", conn->err.message);
- return -1;
- }
-
- VIR_DEBUG("Registering with event loop");
- /* Add the handle for monitoring */
- if ((priv->inotifyWatch = virEventAddHandle(priv->inotifyFD, VIR_EVENT_HANDLE_READABLE,
- xenInotifyEvent, conn, NULL)) < 0) {
- VIR_DEBUG("Failed to add inotify handle, disabling events");
- }
-
- return 0;
-}
-
-/**
- * xenInotifyClose:
- * @conn: pointer to the connection block
- *
- * Close and stop listening for inotify events
- *
- * Returns 0 in case of success or -1 in case of error.
- */
-int
-xenInotifyClose(virConnectPtr conn)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
-
- if (priv->configInfoList)
- xenUnifiedDomainInfoListFree(priv->configInfoList);
-
- if (priv->inotifyWatch != -1)
- virEventRemoveHandle(priv->inotifyWatch);
- VIR_FORCE_CLOSE(priv->inotifyFD);
-
- return 0;
-}
+++ /dev/null
-/*
- * xen_inotify.h: Xen notification of xml files
- *
- * Copyright (C) 2011 Red Hat, Inc.
- * Copyright (C) 2008 VirtualIron
- *
- * 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/>.
- *
- * Author: Ben Guthro
- */
-#ifndef __VIR_XEN_INOTIFY_H__
-# define __VIR_XEN_INOTIFY_H__
-
-# include "internal.h"
-
-int xenInotifyOpen(virConnectPtr conn,
- virConnectAuthPtr auth,
- unsigned int flags);
-int xenInotifyClose(virConnectPtr conn);
-
-#endif
+++ /dev/null
-/*
- * xend_internal.c: access to Xen though the Xen Daemon interface
- *
- * Copyright (C) 2010-2014 Red Hat, Inc.
- * Copyright (C) 2005 Anthony Liguori <aliguori@us.ibm.com>
- *
- * 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/>.
- */
-
-#include <config.h>
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/errno.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-#include <math.h>
-#include <stdarg.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <errno.h>
-
-#include "virerror.h"
-#include "virlog.h"
-#include "datatypes.h"
-#include "xend_internal.h"
-#include "driver.h"
-#include "virsexpr.h"
-#include "xen_sxpr.h"
-#include "virbuffer.h"
-#include "viruuid.h"
-#include "xen_driver.h"
-#include "xen_hypervisor.h"
-#include "xs_internal.h" /* To extract VNC port & Serial console TTY */
-#include "viralloc.h"
-#include "count-one-bits.h"
-#include "virfile.h"
-#include "viruri.h"
-#include "device_conf.h"
-#include "virstring.h"
-
-/* required for cpumap_t */
-#include <xen/dom0_ops.h>
-
-#define VIR_FROM_THIS VIR_FROM_XEND
-
-VIR_LOG_INIT("xen.xend_internal");
-
-/*
- * The number of Xen scheduler parameters
- */
-
-#define XEND_RCV_BUF_MAX_LEN (256 * 1024)
-
-static int
-virDomainXMLDevID(virConnectPtr conn, virDomainDefPtr domain,
- virDomainDeviceDefPtr dev, char *class,
- char *ref, int ref_len);
-
-/**
- * do_connect:
- * @xend: pointer to the Xen Daemon structure
- *
- * Internal routine to (re)connect to the daemon
- *
- * Returns the socket file descriptor or -1 in case of error
- */
-static int
-do_connect(virConnectPtr xend)
-{
- int s;
- int no_slow_start = 1;
- xenUnifiedPrivatePtr priv = xend->privateData;
-
- s = socket(priv->addrfamily, SOCK_STREAM, priv->addrprotocol);
- if (s == -1) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("failed to create a socket"));
- return -1;
- }
-
- /*
- * try to deactivate slow-start
- */
- ignore_value(setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (void *)&no_slow_start,
- sizeof(no_slow_start)));
-
- if (connect(s, (struct sockaddr *)&priv->addr, priv->addrlen) == -1) {
- VIR_FORCE_CLOSE(s); /* preserves errno */
-
- /*
- * Connecting to XenD when privileged is mandatory, so log this
- * error
- */
- if (xenHavePrivilege()) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("failed to connect to xend"));
- }
- }
-
- return s;
-}
-
-/**
- * wr_sync:
- * @xend: the xend connection object
- * @fd: the file descriptor
- * @buffer: the I/O buffer
- * @size: the size of the I/O
- * @do_read: write operation if 0, read operation otherwise
- *
- * Do a synchronous read or write on the file descriptor
- *
- * Returns the number of bytes exchanged, or -1 in case of error
- */
-static size_t
-wr_sync(int fd, void *buffer, size_t size, int do_read)
-{
- size_t offset = 0;
-
- while (offset < size) {
- ssize_t len;
-
- if (do_read) {
- len = read(fd, ((char *) buffer) + offset, size - offset);
- } else {
- len = write(fd, ((char *) buffer) + offset, size - offset);
- }
-
- /* recoverable error, retry */
- if ((len == -1) && ((errno == EAGAIN) || (errno == EINTR)))
- continue;
-
- /* eof */
- if (len == 0)
- break;
-
- /* unrecoverable error */
- if (len == -1) {
- if (do_read)
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("failed to read from Xen Daemon"));
- else
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("failed to write to Xen Daemon"));
-
- return -1;
- }
-
- offset += len;
- }
-
- return offset;
-}
-
-/**
- * sread:
- * @fd: the file descriptor
- * @buffer: the I/O buffer
- * @size: the size of the I/O
- *
- * Internal routine to do a synchronous read
- *
- * Returns the number of bytes read, or -1 in case of error
- */
-static ssize_t
-sread(int fd, void *buffer, size_t size)
-{
- return wr_sync(fd, buffer, size, 1);
-}
-
-/**
- * swrite:
- * @fd: the file descriptor
- * @buffer: the I/O buffer
- * @size: the size of the I/O
- *
- * Internal routine to do a synchronous write
- *
- * Returns the number of bytes written, or -1 in case of error
- */
-static ssize_t
-swrite(int fd, const void *buffer, size_t size)
-{
- return wr_sync(fd, (void *) buffer, size, 0);
-}
-
-/**
- * swrites:
- * @fd: the file descriptor
- * @string: the string to write
- *
- * Internal routine to do a synchronous write of a string
- *
- * Returns the number of bytes written, or -1 in case of error
- */
-static ssize_t
-swrites(int fd, const char *string)
-{
- return swrite(fd, string, strlen(string));
-}
-
-/**
- * sreads:
- * @fd: the file descriptor
- * @buffer: the I/O buffer
- * @n_buffer: the size of the I/O buffer
- *
- * Internal routine to do a synchronous read of a line
- *
- * Returns the number of bytes read, or -1 in case of error
- */
-static ssize_t
-sreads(int fd, char *buffer, size_t n_buffer)
-{
- size_t offset;
-
- if (n_buffer < 1)
- return -1;
-
- for (offset = 0; offset < (n_buffer - 1); offset++) {
- ssize_t ret;
-
- ret = sread(fd, buffer + offset, 1);
- if (ret == 0)
- break;
- else if (ret == -1)
- return ret;
-
- if (buffer[offset] == '\n') {
- offset++;
- break;
- }
- }
- buffer[offset] = 0;
-
- return offset;
-}
-
-static int
-istartswith(const char *haystack, const char *needle)
-{
- return STRCASEEQLEN(haystack, needle, strlen(needle));
-}
-
-
-/**
- * xend_req:
- * @fd: the file descriptor
- * @content: the buffer to store the content
- *
- * Read the HTTP response from a Xen Daemon request.
- * If the response contains content, memory is allocated to
- * hold the content.
- *
- * Returns the HTTP return code and @content is set to the
- * allocated memory containing HTTP content.
- */
-static int ATTRIBUTE_NONNULL(2)
-xend_req(int fd, char **content)
-{
- char *buffer;
- size_t buffer_size = 4096;
- int content_length = 0;
- int retcode = 0;
- char *end_ptr;
-
- if (VIR_ALLOC_N(buffer, buffer_size) < 0)
- return -1;
-
- while (sreads(fd, buffer, buffer_size) > 0) {
- if (STREQ(buffer, "\r\n"))
- break;
-
- if (istartswith(buffer, "Content-Length: ")) {
- if (virStrToLong_i(buffer + 16, &end_ptr, 10, &content_length) < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("failed to parse Xend response content length"));
- return -1;
- }
- } else if (istartswith(buffer, "HTTP/1.1 ")) {
- if (virStrToLong_i(buffer + 9, &end_ptr, 10, &retcode) < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("failed to parse Xend response return code"));
- return -1;
- }
- }
- }
-
- VIR_FREE(buffer);
-
- if (content_length > 0) {
- ssize_t ret;
-
- if (content_length > XEND_RCV_BUF_MAX_LEN) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Xend returned HTTP Content-Length of %d, "
- "which exceeds maximum of %d"),
- content_length,
- XEND_RCV_BUF_MAX_LEN);
- return -1;
- }
-
- /* Allocate one byte beyond the end of the largest buffer we will read.
- Combined with the fact that VIR_ALLOC_N zeros the returned buffer,
- this guarantees that "content" will always be NUL-terminated. */
- if (VIR_ALLOC_N(*content, content_length + 1) < 0)
- return -1;
-
- ret = sread(fd, *content, content_length);
- if (ret < 0)
- return -1;
- }
-
- return retcode;
-}
-
-/**
- * xend_get:
- * @xend: pointer to the Xen Daemon structure
- * @path: the path used for the HTTP request
- * @content: the buffer to store the content
- *
- * Do an HTTP GET RPC with the Xen Daemon
- *
- * Returns the HTTP return code or -1 in case or error.
- */
-static int ATTRIBUTE_NONNULL(3)
-xend_get(virConnectPtr xend, const char *path, char **content)
-{
- int ret;
- int s = do_connect(xend);
-
- if (s == -1)
- return s;
-
- swrites(s, "GET ");
- swrites(s, path);
- swrites(s, " HTTP/1.1\r\n");
-
- swrites(s,
- "Host: localhost:8000\r\n"
- "Accept-Encoding: identity\r\n"
- "Content-Type: application/x-www-form-urlencoded\r\n" "\r\n");
-
- ret = xend_req(s, content);
- VIR_FORCE_CLOSE(s);
-
- if (ret < 0)
- return ret;
-
- if ((ret >= 300) && ((ret != 404) || (!STRPREFIX(path, "/xend/domain/")))) {
- virReportError(VIR_ERR_GET_FAILED,
- _("%d status from xen daemon: %s:%s"),
- ret, path, NULLSTR(*content));
- }
-
- return ret;
-}
-
-/**
- * xend_post:
- * @xend: pointer to the Xen Daemon structure
- * @path: the path used for the HTTP request
- * @ops: the information sent for the POST
- *
- * Do an HTTP POST RPC with the Xen Daemon, this usually makes changes at the
- * Xen level.
- *
- * Returns the HTTP return code or -1 in case or error.
- */
-static int
-xend_post(virConnectPtr xend, const char *path, const char *ops)
-{
- char buffer[100];
- char *err_buf = NULL;
- int ret;
- int s = do_connect(xend);
-
- if (s == -1)
- return s;
-
- swrites(s, "POST ");
- swrites(s, path);
- swrites(s, " HTTP/1.1\r\n");
-
- swrites(s,
- "Host: localhost:8000\r\n"
- "Accept-Encoding: identity\r\n"
- "Content-Type: application/x-www-form-urlencoded\r\n"
- "Content-Length: ");
- snprintf(buffer, sizeof(buffer), "%d", (int) strlen(ops));
- swrites(s, buffer);
- swrites(s, "\r\n\r\n");
- swrites(s, ops);
-
- ret = xend_req(s, &err_buf);
- VIR_FORCE_CLOSE(s);
-
- if ((ret < 0) || (ret >= 300)) {
- virReportError(VIR_ERR_POST_FAILED,
- _("xend_post: error from xen daemon: %s"), err_buf);
- } else if ((ret == 202) && err_buf && (strstr(err_buf, "failed") != NULL)) {
- virReportError(VIR_ERR_POST_FAILED,
- _("xend_post: error from xen daemon: %s"), err_buf);
- ret = -1;
- } else if (((ret >= 200) && (ret <= 202)) && err_buf &&
- (strstr(err_buf, "xend.err") != NULL)) {
- /* This is to catch case of things like 'virsh dump Domain-0 foo'
- * which returns a success code, but the word 'xend.err'
- * in body to indicate error :-(
- */
- virReportError(VIR_ERR_POST_FAILED,
- _("xend_post: error from xen daemon: %s"), err_buf);
- ret = -1;
- }
-
- VIR_FREE(err_buf);
- return ret;
-}
-
-
-/**
- * http2unix:
- * @ret: the http return code
- *
- * Convert the HTTP return code to 0/-1 and set errno if needed
- *
- * Return -1 in case of error code 0 otherwise
- */
-static int
-http2unix(int ret)
-{
- switch (ret) {
- case -1:
- break;
- case 200:
- case 201:
- case 202:
- return 0;
- case 404:
- errno = ESRCH;
- break;
- case 500:
- errno = EIO;
- break;
- default:
- virReportError(VIR_ERR_HTTP_ERROR,
- _("Unexpected HTTP error code %d"), ret);
- errno = EINVAL;
- break;
- }
- return -1;
-}
-
-/**
- * xend_op_ext:
- * @xend: pointer to the Xen Daemon structure
- * @path: path for the object
- * @key: the key for the operation
- * @ap: input values to pass to the operation
- *
- * internal routine to run a POST RPC operation to the Xen Daemon
- *
- * Returns 0 in case of success, -1 in case of failure.
- */
-static int
-xend_op_ext(virConnectPtr xend, const char *path, const char *key, va_list ap)
-{
- const char *k = key, *v;
- virBuffer buf = VIR_BUFFER_INITIALIZER;
- int ret;
- char *content;
-
- while (k) {
- v = va_arg(ap, const char *);
-
- virBufferURIEncodeString(&buf, k);
- virBufferAddChar(&buf, '=');
- virBufferURIEncodeString(&buf, v);
- k = va_arg(ap, const char *);
-
- if (k)
- virBufferAddChar(&buf, '&');
- }
-
- if (virBufferCheckError(&buf) < 0)
- return -1;
-
- content = virBufferContentAndReset(&buf);
- VIR_DEBUG("xend op: %s", content);
- ret = http2unix(xend_post(xend, path, content));
- VIR_FREE(content);
-
- return ret;
-}
-
-
-/**
- * xend_op:
- * @xend: pointer to the Xen Daemon structure
- * @name: the domain name target of this operation
- * @key: the key for the operation
- * @ap: input values to pass to the operation
- * @...: input values to pass to the operation
- *
- * internal routine to run a POST RPC operation to the Xen Daemon targeting
- * a given domain.
- *
- * Returns 0 in case of success, -1 in case of failure.
- */
-static int ATTRIBUTE_SENTINEL
-xend_op(virConnectPtr xend, const char *name, const char *key, ...)
-{
- char buffer[1024];
- va_list ap;
- int ret;
-
- snprintf(buffer, sizeof(buffer), "/xend/domain/%s", name);
-
- va_start(ap, key);
- ret = xend_op_ext(xend, buffer, key, ap);
- va_end(ap);
-
- return ret;
-}
-
-
-/**
- * sexpr_get:
- * @xend: pointer to the Xen Daemon structure
- * @fmt: format string for the path of the operation
- * @...: extra data to build the path of the operation
- *
- * Internal routine to run a simple GET RPC operation to the Xen Daemon
- *
- * Returns a parsed S-Expression in case of success, NULL in case of failure
- */
-static struct sexpr *sexpr_get(virConnectPtr xend, const char *fmt, ...)
- ATTRIBUTE_FMT_PRINTF(2, 3);
-
-static struct sexpr *
-sexpr_get(virConnectPtr xend, const char *fmt, ...)
-{
- char *buffer = NULL;
- char path[1024];
- va_list ap;
- int ret;
- struct sexpr *res = NULL;
-
- va_start(ap, fmt);
- vsnprintf(path, sizeof(path), fmt, ap);
- va_end(ap);
-
- ret = xend_get(xend, path, &buffer);
- ret = http2unix(ret);
- if (ret == -1)
- goto cleanup;
-
- if (buffer == NULL)
- goto cleanup;
-
- res = string2sexpr(buffer);
-
- cleanup:
- VIR_FREE(buffer);
- return res;
-}
-
-/**
- * sexpr_uuid:
- * @ptr: where to store the UUID, incremented
- * @sexpr: an S-Expression
- * @name: the name for the value
- *
- * convenience function to lookup a UUID value from the S-Expression
- *
- * Returns a -1 on error, 0 on success
- */
-static int
-sexpr_uuid(unsigned char *ptr, const struct sexpr *node, const char *path)
-{
- const char *r = sexpr_node(node, path);
- if (!r)
- return -1;
- return virUUIDParse(r, ptr);
-}
-
-/* PUBLIC FUNCTIONS */
-
-/**
- * xenDaemonOpen_unix:
- * @conn: an existing virtual connection block
- * @path: the path for the Xen Daemon socket
- *
- * Creates a localhost Xen Daemon connection
- * Note: this doesn't try to check if the connection actually works
- *
- * Returns 0 in case of success, -1 in case of error.
- */
-int
-xenDaemonOpen_unix(virConnectPtr conn, const char *path)
-{
- struct sockaddr_un *addr;
- xenUnifiedPrivatePtr priv = conn->privateData;
-
- memset(&priv->addr, 0, sizeof(priv->addr));
- priv->addrfamily = AF_UNIX;
- /*
- * This must be zero on Solaris at least for AF_UNIX (which should
- * really be PF_UNIX, but doesn't matter).
- */
- priv->addrprotocol = 0;
- priv->addrlen = sizeof(struct sockaddr_un);
-
- addr = (struct sockaddr_un *)&priv->addr;
- addr->sun_family = AF_UNIX;
- memset(addr->sun_path, 0, sizeof(addr->sun_path));
- if (virStrcpyStatic(addr->sun_path, path) == NULL)
- return -1;
-
- return 0;
-}
-
-
-/**
- * xenDaemonOpen_tcp:
- * @conn: an existing virtual connection block
- * @host: the host name for the Xen Daemon
- * @port: the port
- *
- * Creates a possibly remote Xen Daemon connection
- * Note: this doesn't try to check if the connection actually works
- *
- * Returns 0 in case of success, -1 in case of error.
- */
-static int
-xenDaemonOpen_tcp(virConnectPtr conn, const char *host, const char *port)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- struct addrinfo *res, *r;
- struct addrinfo hints;
- int saved_errno = EINVAL;
- int ret;
-
- priv->addrlen = 0;
- memset(&priv->addr, 0, sizeof(priv->addr));
-
- /* http://people.redhat.com/drepper/userapi-ipv6.html */
- memset (&hints, 0, sizeof(hints));
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_flags = AI_ADDRCONFIG;
-
- ret = getaddrinfo (host, port, &hints, &res);
- if (ret != 0) {
- virReportError(VIR_ERR_UNKNOWN_HOST,
- _("unable to resolve hostname '%s': %s"),
- host, gai_strerror (ret));
- return -1;
- }
-
- /* Try to connect to each returned address in turn. */
- for (r = res; r; r = r->ai_next) {
- int sock;
-
- sock = socket(r->ai_family, SOCK_STREAM, r->ai_protocol);
- if (sock == -1) {
- saved_errno = errno;
- continue;
- }
-
- if (connect(sock, r->ai_addr, r->ai_addrlen) == -1) {
- saved_errno = errno;
- VIR_FORCE_CLOSE(sock);
- continue;
- }
-
- priv->addrlen = r->ai_addrlen;
- priv->addrfamily = r->ai_family;
- priv->addrprotocol = r->ai_protocol;
- memcpy(&priv->addr,
- r->ai_addr,
- r->ai_addrlen);
- VIR_FORCE_CLOSE(sock);
- break;
- }
-
- freeaddrinfo(res);
-
- if (!priv->addrlen) {
- /* Don't raise error when unprivileged, since proxy takes over */
- if (xenHavePrivilege())
- virReportSystemError(saved_errno,
- _("unable to connect to '%s:%s'"),
- host, port);
- return -1;
- }
-
- return 0;
-}
-
-
-/**
- * xend_wait_for_devices:
- * @xend: pointer to the Xen Daemon block
- * @name: name for the domain
- *
- * Block the domain until all the virtual devices are ready. This operation
- * is needed when creating a domain before resuming it.
- *
- * Returns 0 in case of success, -1 (with errno) in case of error.
- */
-int
-xend_wait_for_devices(virConnectPtr xend, const char *name)
-{
- return xend_op(xend, name, "op", "wait_for_devices", NULL);
-}
-
-
-/**
- * xenDaemonListDomainsOld:
- * @xend: pointer to the Xen Daemon block
- *
- * This method will return an array of names of currently running
- * domains. The memory should be released will a call to free().
- *
- * Returns a list of names or NULL in case of error.
- */
-char **
-xenDaemonListDomainsOld(virConnectPtr xend)
-{
- struct sexpr *root = NULL;
- char **ret = NULL;
- int count = 0;
- size_t i;
- struct sexpr *_for_i, *node;
-
- root = sexpr_get(xend, "/xend/domain");
- if (root == NULL)
- goto error;
-
- for (_for_i = root, node = root->u.s.car; _for_i->kind == SEXPR_CONS;
- _for_i = _for_i->u.s.cdr, node = _for_i->u.s.car) {
- if (node->kind != SEXPR_VALUE)
- continue;
- count++;
- }
-
- if (VIR_ALLOC_N(ret, count + 1) < 0)
- goto error;
-
- i = 0;
- for (_for_i = root, node = root->u.s.car; _for_i->kind == SEXPR_CONS;
- _for_i = _for_i->u.s.cdr, node = _for_i->u.s.car) {
- if (node->kind != SEXPR_VALUE)
- continue;
- if (VIR_STRDUP(ret[i], node->u.value) < 0)
- goto no_memory;
- i++;
- }
-
- ret[i] = NULL;
-
- error:
- sexpr_free(root);
- return ret;
-
- no_memory:
- for (i = 0; i < count; i++)
- VIR_FREE(ret[i]);
- VIR_FREE(ret);
- goto error;
-}
-
-
-/**
- * xenDaemonDomainCreateXML:
- * @xend: A xend instance
- * @sexpr: An S-Expr description of the domain.
- *
- * This method will create a domain based on the passed in description. The
- * domain will be paused after creation and must be unpaused with
- * xenDaemonResumeDomain() to begin execution.
- * This method may be deprecated once switching to XML-RPC based communcations
- * with xend.
- *
- * Returns 0 for success, -1 (with errno) on error
- */
-
-int
-xenDaemonDomainCreateXML(virConnectPtr xend, const char *sexpr)
-{
- int ret;
-
- ret = xend_op(xend, "", "op", "create", "config", sexpr, NULL);
-
- return ret;
-}
-
-
-/**
- * xenDaemonDomainLookupByName_ids:
- * @xend: A xend instance
- * @domname: The name of the domain
- * @uuid: return value for the UUID if not NULL
- *
- * This method looks up the id of a domain
- *
- * Returns the id on success; -1 (with errno) on error
- */
-int
-xenDaemonDomainLookupByName_ids(virConnectPtr xend,
- const char *domname,
- unsigned char *uuid)
-{
- struct sexpr *root;
- const char *value;
- int ret = -1;
-
- if (uuid != NULL)
- memset(uuid, 0, VIR_UUID_BUFLEN);
- root = sexpr_get(xend, "/xend/domain/%s?detail=1", domname);
- if (root == NULL)
- goto error;
-
- value = sexpr_node(root, "domain/domid");
- if (value == NULL) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("domain information incomplete, missing domid"));
- goto error;
- } else if (virStrToLong_i(value, NULL, 0, &ret) < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("domain information incorrect domid not numeric"));
- ret = -1;
- } else if (uuid != NULL) {
- if (sexpr_uuid(uuid, root, "domain/uuid") < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("domain information incomplete, missing uuid"));
- }
- }
-
- error:
- sexpr_free(root);
- return ret;
-}
-
-
-/**
- * sexpr_to_xend_domain_state:
- * @root: an S-Expression describing a domain
- *
- * Internal routine getting the domain's state from the domain root provided.
- *
- * Returns domain's state.
- */
-static int
-ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2)
-sexpr_to_xend_domain_state(virDomainDefPtr def, const struct sexpr *root)
-{
- const char *flags;
- int state = VIR_DOMAIN_NOSTATE;
-
- if ((flags = sexpr_node(root, "domain/state"))) {
- if (strchr(flags, 'c'))
- state = VIR_DOMAIN_CRASHED;
- else if (strchr(flags, 's'))
- state = VIR_DOMAIN_SHUTOFF;
- else if (strchr(flags, 'd'))
- state = VIR_DOMAIN_SHUTDOWN;
- else if (strchr(flags, 'p'))
- state = VIR_DOMAIN_PAUSED;
- else if (strchr(flags, 'b'))
- state = VIR_DOMAIN_BLOCKED;
- else if (strchr(flags, 'r'))
- state = VIR_DOMAIN_RUNNING;
- } else if (def->id < 0 || sexpr_int(root, "domain/status") == 0) {
- /* As far as I can see the domain->id is a bad sign for checking
- * inactive domains as this is inaccurate after the domain has
- * been running once. However domain/status from xend seems to
- * be always present and 0 for inactive domains.
- * (keeping the check for id < 0 to be extra safe about backward
- * compatibility)
- */
- state = VIR_DOMAIN_SHUTOFF;
- }
-
- return state;
-}
-
-/**
- * sexpr_to_xend_domain_info:
- * @root: an S-Expression describing a domain
- * @info: a info data structure to fill=up
- *
- * Internal routine filling up the info structure with the values from
- * the domain root provided.
- *
- * Returns 0 in case of success, -1 in case of error
- */
-static int
-sexpr_to_xend_domain_info(virDomainDefPtr def,
- const struct sexpr *root,
- virDomainInfoPtr info)
-{
- int vcpus;
-
- info->state = sexpr_to_xend_domain_state(def, root);
- info->memory = sexpr_u64(root, "domain/memory") << 10;
- info->maxMem = sexpr_u64(root, "domain/maxmem") << 10;
- info->cpuTime = sexpr_float(root, "domain/cpu_time") * 1000000000;
-
- vcpus = sexpr_int(root, "domain/vcpus");
- info->nrVirtCpu = count_one_bits_l(sexpr_u64(root, "domain/vcpu_avail"));
- if (!info->nrVirtCpu || vcpus < info->nrVirtCpu)
- info->nrVirtCpu = vcpus;
-
- return 0;
-}
-
-/**
- * sexpr_to_xend_node_info:
- * @root: an S-Expression describing a domain
- * @info: a info data structure to fill up
- *
- * Internal routine filling up the info structure with the values from
- * the node root provided.
- *
- * Returns 0 in case of success, -1 in case of error
- */
-static int
-sexpr_to_xend_node_info(const struct sexpr *root, virNodeInfoPtr info)
-{
- const char *machine;
-
- machine = sexpr_node(root, "node/machine");
- if (machine == NULL) {
- info->model[0] = 0;
- } else {
- snprintf(&info->model[0], sizeof(info->model) - 1, "%s", machine);
- info->model[sizeof(info->model) - 1] = 0;
- }
- info->memory = (unsigned long) sexpr_u64(root, "node/total_memory") << 10;
-
- info->cpus = sexpr_int(root, "node/nr_cpus");
- info->mhz = sexpr_int(root, "node/cpu_mhz");
- info->nodes = sexpr_int(root, "node/nr_nodes");
- info->sockets = sexpr_int(root, "node/sockets_per_node");
- info->cores = sexpr_int(root, "node/cores_per_socket");
- info->threads = sexpr_int(root, "node/threads_per_core");
-
- /* Xen 3.2.0 replaces sockets_per_node with 'nr_cpus'.
- * Old Xen calculated sockets_per_node using its internal
- * nr_cpus / (nodes*cores*threads), so fake it ourselves
- * in the same way
- */
- if (info->sockets == 0) {
- int nr_cpus = sexpr_int(root, "node/nr_cpus");
- int procs = info->nodes * info->cores * info->threads;
- if (procs == 0) /* Sanity check in case of Xen bugs in futures..*/
- return -1;
- info->sockets = nr_cpus / procs;
- }
-
- /* On systems where NUMA nodes are not composed of whole sockets either Xen
- * provided us wrong number of sockets per node or we computed the wrong
- * number in the compatibility code above. In such case, we compute the
- * correct number of sockets on the host, lie about the number of NUMA
- * nodes, and force apps to check capabilities XML for the actual NUMA
- * topology.
- */
- if (info->nodes * info->sockets * info->cores * info->threads
- != info->cpus) {
- info->nodes = 1;
- info->sockets = info->cpus / (info->cores * info->threads);
- }
-
- return 0;
-}
-
-
-/**
- * sexpr_to_xend_topology
- * @root: an S-Expression describing a node
- * @caps: capability info
- *
- * Internal routine populating capability info with
- * NUMA node mapping details
- *
- * Does nothing when the system doesn't support NUMA (not an error).
- *
- * Returns 0 in case of success, -1 in case of error
- */
-static int
-sexpr_to_xend_topology(const struct sexpr *root, virCapsPtr caps)
-{
- const char *nodeToCpu;
- const char *cur;
- virCapsHostNUMACellCPUPtr cpuInfo = NULL;
- int cell, cpu, nb_cpus = 0;
- int n = 0;
- int numCpus;
-
- nodeToCpu = sexpr_node(root, "node/node_to_cpu");
- if (nodeToCpu == NULL)
- return 0; /* no NUMA support */
-
- numCpus = sexpr_int(root, "node/nr_cpus");
-
-
- cur = nodeToCpu;
- while (*cur != 0) {
- virBitmapPtr cpuset = NULL;
- /*
- * Find the next NUMA cell described in the xend output
- */
- cur = strstr(cur, "node");
- if (cur == NULL)
- break;
- cur += 4;
- cell = virParseNumber(&cur);
- if (cell < 0)
- goto parse_error;
- virSkipSpacesAndBackslash(&cur);
- if (*cur != ':')
- goto parse_error;
- cur++;
- virSkipSpacesAndBackslash(&cur);
- if (STRPREFIX(cur, "no cpus")) {
- nb_cpus = 0;
- if (!(cpuset = virBitmapNew(numCpus)))
- goto error;
- } else {
- if (virBitmapParseSeparator(cur, 'n', &cpuset, numCpus) < 0)
- goto error;
-
- nb_cpus = virBitmapCountBits(cpuset);
- }
-
- if (VIR_ALLOC_N(cpuInfo, numCpus) < 0) {
- virBitmapFree(cpuset);
- goto error;
- }
-
- for (n = 0, cpu = 0; cpu < numCpus; cpu++) {
- if (virBitmapIsBitSet(cpuset, cpu))
- cpuInfo[n++].id = cpu;
- }
- virBitmapFree(cpuset);
-
- if (virCapabilitiesAddHostNUMACell(caps, cell, 0,
- nb_cpus, cpuInfo,
- 0, NULL,
- 0, NULL) < 0)
- goto error;
- cpuInfo = NULL;
- }
-
- return 0;
-
- parse_error:
- virReportError(VIR_ERR_XEN_CALL, "%s", _("topology syntax error"));
- error:
- if (nb_cpus > 0)
- virCapabilitiesClearHostNUMACellCPUTopology(cpuInfo, nb_cpus);
- VIR_FREE(cpuInfo);
- return -1;
-}
-
-
-/**
- * sexpr_to_domain:
- * @conn: an existing virtual connection block
- * @root: an S-Expression describing a domain
- *
- * Internal routine returning the associated virDomainPtr for this domain
- *
- * Returns the domain def pointer or NULL in case of error.
- */
-static virDomainDefPtr
-sexpr_to_domain(virConnectPtr conn ATTRIBUTE_UNUSED, const struct sexpr *root)
-{
- virDomainDefPtr ret = NULL;
- unsigned char uuid[VIR_UUID_BUFLEN];
- const char *name;
- int id = -1;
-
- if (sexpr_uuid(uuid, root, "domain/uuid") < 0)
- goto error;
- name = sexpr_node(root, "domain/name");
- if (name == NULL)
- goto error;
-
- if (sexpr_node(root, "domain/domid"))
- id = sexpr_int(root, "domain/domid");
-
- return virDomainDefNewFull(name, uuid, id);
-
- error:
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("failed to parse Xend domain information"));
- virObjectUnref(ret);
- return NULL;
-}
-
-
-/**
- * xenDaemonOpen:
- * @conn: an existing virtual connection block
- * @name: optional argument to select a connection type
- * @flags: combination of virDrvOpenFlag(s)
- *
- * Creates a localhost Xen Daemon connection
- *
- * Returns 0 in case of success, -1 in case of error.
- */
-int
-xenDaemonOpen(virConnectPtr conn,
- virConnectAuthPtr auth ATTRIBUTE_UNUSED,
- unsigned int flags)
-{
- char *port = NULL;
- int ret = -1;
-
- virCheckFlags(VIR_CONNECT_RO, -1);
-
- /* Switch on the scheme, which we expect to be NULL (file),
- * "http" or "xen".
- */
- if (conn->uri->scheme == NULL) {
- /* It should be a file access */
- if (conn->uri->path == NULL) {
- virReportError(VIR_ERR_NO_CONNECT, __FUNCTION__);
- goto failed;
- }
- if (xenDaemonOpen_unix(conn, conn->uri->path) < 0)
- goto failed;
- } else if (STRCASEEQ(conn->uri->scheme, "xen")) {
- /*
- * try first to open the unix socket
- */
- if (xenDaemonOpen_unix(conn, "/var/lib/xend/xend-socket") == 0)
- goto done;
-
- /*
- * try though http on port 8000
- */
- if (xenDaemonOpen_tcp(conn, "localhost", "8000") < 0)
- goto failed;
- } else if (STRCASEEQ(conn->uri->scheme, "http")) {
- if (conn->uri->port &&
- virAsprintf(&port, "%d", conn->uri->port) == -1)
- goto failed;
-
- if (xenDaemonOpen_tcp(conn,
- conn->uri->server ? conn->uri->server : "localhost",
- port ? port : "8000") < 0)
- goto failed;
- } else {
- virReportError(VIR_ERR_NO_CONNECT, __FUNCTION__);
- goto failed;
- }
-
- done:
- ret = 0;
-
- failed:
- VIR_FREE(port);
- return ret;
-}
-
-
-/**
- * xenDaemonClose:
- * @conn: an existing virtual connection block
- *
- * This method should be called when a connection to xend instance
- * initialized with xenDaemonOpen is no longer needed
- * to free the associated resources.
- *
- * Returns 0 in case of success, -1 in case of error
- */
-int
-xenDaemonClose(virConnectPtr conn ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-
-/**
- * xenDaemonDomainSuspend:
- * @conn: the connection object
- * @def: the domain to suspend
- *
- * Pause the domain, the domain is not scheduled anymore though its resources
- * are preserved. Use xenDaemonDomainResume() to resume execution.
- *
- * Returns 0 in case of success, -1 (with errno) in case of error.
- */
-int
-xenDaemonDomainSuspend(virConnectPtr conn, virDomainDefPtr def)
-{
- if (def->id < 0) {
- virReportError(VIR_ERR_OPERATION_INVALID,
- _("Domain %s isn't running."), def->name);
- return -1;
- }
-
- return xend_op(conn, def->name, "op", "pause", NULL);
-}
-
-/**
- * xenDaemonDomainResume:
- * @conn: the connection object
- * @def: the domain to resume
- *
- * Resume the domain after xenDaemonDomainSuspend() has been called
- *
- * Returns 0 in case of success, -1 (with errno) in case of error.
- */
-int
-xenDaemonDomainResume(virConnectPtr conn, virDomainDefPtr def)
-{
- if (def->id < 0) {
- virReportError(VIR_ERR_OPERATION_INVALID,
- _("Domain %s isn't running."), def->name);
- return -1;
- }
-
- return xend_op(conn, def->name, "op", "unpause", NULL);
-}
-
-/**
- * xenDaemonDomainShutdown:
- * @conn: the connection object
- * @def: the domain to shutdown
- *
- * Shutdown the domain, the OS is requested to properly shutdown
- * and the domain may ignore it. It will return immediately
- * after queuing the request.
- *
- * Returns 0 in case of success, -1 (with errno) in case of error.
- */
-int
-xenDaemonDomainShutdown(virConnectPtr conn, virDomainDefPtr def)
-{
- if (def->id < 0) {
- virReportError(VIR_ERR_OPERATION_INVALID,
- _("Domain %s isn't running."), def->name);
- return -1;
- }
-
- return xend_op(conn, def->name, "op", "shutdown", "reason", "poweroff", NULL);
-}
-
-/**
- * xenDaemonDomainReboot:
- * @conn: the connection object
- * @def: the domain to reboot
- *
- * Reboot the domain, the OS is requested to properly shutdown
- * and restart but the domain may ignore it. It will return immediately
- * after queuing the request.
- *
- * Returns 0 in case of success, -1 (with errno) in case of error.
- */
-int
-xenDaemonDomainReboot(virConnectPtr conn, virDomainDefPtr def)
-{
- if (def->id < 0) {
- virReportError(VIR_ERR_OPERATION_INVALID,
- _("Domain %s isn't running."), def->name);
- return -1;
- }
-
- return xend_op(conn, def->name, "op", "shutdown", "reason", "reboot", NULL);
-}
-
-/**
- * xenDaemonDomainDestroy:
- * @conn: the connection object
- * @def: the domain to destroy
- *
- * Abruptly halt the domain, the OS is not properly shutdown and the
- * resources allocated for the domain are immediately freed, mounted
- * filesystems will be marked as uncleanly shutdown.
- * After calling this function, the domain's status will change to
- * dying and will go away completely once all of the resources have been
- * unmapped (usually from the backend devices).
- *
- * Returns 0 in case of success, -1 (with errno) in case of error.
- */
-int
-xenDaemonDomainDestroy(virConnectPtr conn, virDomainDefPtr def)
-{
- if (def->id < 0) {
- virReportError(VIR_ERR_OPERATION_INVALID,
- _("Domain %s isn't running."), def->name);
- return -1;
- }
-
- return xend_op(conn, def->name, "op", "destroy", NULL);
-}
-
-/**
- * xenDaemonDomainGetOSType:
- * @domain: a domain object
- *
- * Get the type of domain operation system.
- *
- * Returns the new string or NULL in case of error, the string must be
- * freed by the caller.
- */
-char *
-xenDaemonDomainGetOSType(virConnectPtr conn,
- virDomainDefPtr def)
-{
- char *type;
- struct sexpr *root;
-
- /* can we ask for a subset ? worth it ? */
- root = sexpr_get(conn, "/xend/domain/%s?detail=1", def->name);
- if (root == NULL)
- return NULL;
-
- ignore_value(VIR_STRDUP(type,
- sexpr_lookup(root, "domain/image/hvm") ? "hvm" : "linux"));
-
- sexpr_free(root);
-
- return type;
-}
-
-/**
- * xenDaemonDomainSave:
- * @domain: pointer to the Domain block
- * @filename: path for the output file
- *
- * This method will suspend a domain and save its memory contents to
- * a file on disk. Use xenDaemonDomainRestore() to restore a domain after
- * saving.
- * Note that for remote Xen Daemon the file path will be interpreted in
- * the remote host.
- *
- * Returns 0 in case of success, -1 (with errno) in case of error.
- */
-int
-xenDaemonDomainSave(virConnectPtr conn,
- virDomainDefPtr def,
- const char *filename)
-{
- if (def->id < 0) {
- virReportError(VIR_ERR_OPERATION_INVALID,
- _("Domain %s isn't running."), def->name);
- return -1;
- }
-
- /* We can't save the state of Domain-0, that would mean stopping it too */
- if (def->id == 0) {
- virReportError(VIR_ERR_INVALID_ARG, "%s",
- _("Cannot save host domain"));
- return -1;
- }
-
- return xend_op(conn, def->name, "op", "save", "file", filename, NULL);
-}
-
-/**
- * xenDaemonDomainCoreDump:
- * @conn: the connection object
- * @def: domain configuration
- * @filename: path for the output file
- * @flags: extra flags, currently unused
- *
- * This method will dump the core of a domain on a given file for analysis.
- * Note that for remote Xen Daemon the file path will be interpreted in
- * the remote host.
- *
- * Returns 0 in case of success, -1 in case of error.
- */
-int
-xenDaemonDomainCoreDump(virConnectPtr conn,
- virDomainDefPtr def,
- const char *filename,
- unsigned int flags)
-{
- virCheckFlags(VIR_DUMP_LIVE | VIR_DUMP_CRASH, -1);
-
- if (def->id < 0) {
- virReportError(VIR_ERR_OPERATION_INVALID,
- _("Domain %s isn't running."), def->name);
- return -1;
- }
-
- return xend_op(conn, def->name,
- "op", "dump", "file", filename,
- "live", (flags & VIR_DUMP_LIVE ? "1" : "0"),
- "crash", (flags & VIR_DUMP_CRASH ? "1" : "0"),
- NULL);
-}
-
-/**
- * xenDaemonDomainRestore:
- * @conn: pointer to the Xen Daemon block
- * @filename: path for the output file
- *
- * This method will restore a domain saved to disk by xenDaemonDomainSave().
- * Note that for remote Xen Daemon the file path will be interpreted in
- * the remote host.
- *
- * Returns 0 in case of success, -1 (with errno) in case of error.
- */
-int
-xenDaemonDomainRestore(virConnectPtr conn, const char *filename)
-{
- return xend_op(conn, "", "op", "restore", "file", filename, NULL);
-}
-
-
-/**
- * xenDaemonDomainGetMaxMemory:
- * @domain: pointer to the domain block
- *
- * Ask the Xen Daemon for the maximum memory allowed for a domain
- *
- * Returns the memory size in kilobytes or 0 in case of error.
- */
-unsigned long long
-xenDaemonDomainGetMaxMemory(virConnectPtr conn, virDomainDefPtr def)
-{
- unsigned long long ret = 0;
- struct sexpr *root;
-
- /* can we ask for a subset ? worth it ? */
- root = sexpr_get(conn, "/xend/domain/%s?detail=1", def->name);
- if (root == NULL)
- return 0;
-
- ret = sexpr_u64(root, "domain/memory") << 10;
- sexpr_free(root);
-
- return ret;
-}
-
-
-/**
- * xenDaemonDomainSetMaxMemory:
- * @domain: pointer to the Domain block
- * @memory: The maximum memory in kilobytes
- *
- * This method will set the maximum amount of memory that can be allocated to
- * a domain. Please note that a domain is able to allocate up to this amount
- * on its own.
- *
- * Returns 0 for success; -1 (with errno) on error
- */
-int
-xenDaemonDomainSetMaxMemory(virConnectPtr conn,
- virDomainDefPtr def,
- unsigned long memory)
-{
- char buf[1024];
-
- snprintf(buf, sizeof(buf), "%lu", VIR_DIV_UP(memory, 1024));
- return xend_op(conn, def->name, "op", "maxmem_set", "memory",
- buf, NULL);
-}
-
-/**
- * xenDaemonDomainSetMemory:
- * @domain: pointer to the Domain block
- * @memory: The target memory in kilobytes
- *
- * This method will set a target memory allocation for a given domain and
- * request that the guest meet this target. The guest may or may not actually
- * achieve this target. When this function returns, it does not signify that
- * the domain has actually reached that target.
- *
- * Memory for a domain can only be allocated up to the maximum memory setting.
- * There is no safe guard for allocations that are too small so be careful
- * when using this function to reduce a domain's memory usage.
- *
- * Returns 0 for success; -1 (with errno) on error
- */
-int
-xenDaemonDomainSetMemory(virConnectPtr conn,
- virDomainDefPtr def,
- unsigned long memory)
-{
- char buf[1024];
-
- snprintf(buf, sizeof(buf), "%lu", VIR_DIV_UP(memory, 1024));
- return xend_op(conn, def->name, "op", "mem_target_set",
- "target", buf, NULL);
-}
-
-
-virDomainDefPtr
-xenDaemonDomainFetch(virConnectPtr conn, int domid, const char *name,
- const char *cpus)
-{
- struct sexpr *root;
- xenUnifiedPrivatePtr priv = conn->privateData;
- virDomainDefPtr def = NULL;
- int id;
- char * tty;
- int vncport;
-
- if (name)
- root = sexpr_get(conn, "/xend/domain/%s?detail=1", name);
- else
- root = sexpr_get(conn, "/xend/domain/%d?detail=1", domid);
- if (root == NULL)
- return NULL;
-
- if (xenGetDomIdFromSxpr(root, &id) < 0)
- goto cleanup;
- xenUnifiedLock(priv);
- if (sexpr_lookup(root, "domain/image/hvm"))
- tty = xenStoreDomainGetSerialConsolePath(conn, id);
- else
- tty = xenStoreDomainGetConsolePath(conn, id);
- vncport = xenStoreDomainGetVNCPort(conn, id);
- xenUnifiedUnlock(priv);
- if (!(def = xenParseSxpr(root,
- cpus,
- tty,
- vncport,
- priv->caps,
- priv->xmlopt)))
- goto cleanup;
-
- cleanup:
- sexpr_free(root);
-
- return def;
-}
-
-
-/**
- * xenDaemonDomainGetXMLDesc:
- * @domain: a domain object
- * @cpus: list of cpu the domain is pinned to.
- *
- * Get the XML description of the domain as a structure.
- *
- * Returns a virDomainDefPtr instance, or NULL in case of error.
- */
-virDomainDefPtr
-xenDaemonDomainGetXMLDesc(virConnectPtr conn,
- virDomainDefPtr minidef,
- const char *cpus)
-{
- return xenDaemonDomainFetch(conn,
- minidef->id,
- minidef->name,
- cpus);
-}
-
-
-/**
- * xenDaemonDomainGetInfo:
- * @domain: a domain object
- * @info: pointer to a virDomainInfo structure allocated by the user
- *
- * This method looks up information about a domain and update the
- * information block provided.
- *
- * Returns 0 in case of success, -1 in case of error
- */
-int
-xenDaemonDomainGetInfo(virConnectPtr conn,
- virDomainDefPtr def,
- virDomainInfoPtr info)
-{
- struct sexpr *root;
- int ret;
-
- root = sexpr_get(conn, "/xend/domain/%s?detail=1", def->name);
- if (root == NULL)
- return -1;
-
- ret = sexpr_to_xend_domain_info(def, root, info);
- sexpr_free(root);
- return ret;
-}
-
-
-/**
- * xenDaemonDomainGetState:
- * @domain: a domain object
- * @state: returned domain's state
- * @reason: returned reason for the state
- *
- * This method looks up domain state and reason.
- *
- * Returns 0 in case of success, -1 in case of error
- */
-int
-xenDaemonDomainGetState(virConnectPtr conn,
- virDomainDefPtr def,
- int *state,
- int *reason)
-{
- struct sexpr *root;
-
- root = sexpr_get(conn, "/xend/domain/%s?detail=1", def->name);
- if (!root)
- return -1;
-
- *state = sexpr_to_xend_domain_state(def, root);
- if (reason)
- *reason = 0;
-
- sexpr_free(root);
- return 0;
-}
-
-
-/**
- * xenDaemonLookupByName:
- * @conn: A xend instance
- * @name: The name of the domain
- *
- * This method looks up information about a domain and returns
- * it in the form of a struct xend_domain. This should be
- * free()'d when no longer needed.
- *
- * Returns domain def pointer on success; NULL on error
- */
-virDomainDefPtr
-xenDaemonLookupByName(virConnectPtr conn, const char *domname)
-{
- struct sexpr *root;
- virDomainDefPtr ret = NULL;
-
- root = sexpr_get(conn, "/xend/domain/%s?detail=1", domname);
- if (root == NULL)
- goto error;
-
- ret = sexpr_to_domain(conn, root);
-
- error:
- sexpr_free(root);
- return ret;
-}
-
-
-/**
- * xenDaemonNodeGetInfo:
- * @conn: pointer to the Xen Daemon block
- * @info: pointer to a virNodeInfo structure allocated by the user
- *
- * Extract hardware information about the node.
- *
- * Returns 0 in case of success and -1 in case of failure.
- */
-int
-xenDaemonNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info)
-{
- int ret = -1;
- struct sexpr *root;
-
- root = sexpr_get(conn, "/xend/node/");
- if (root == NULL)
- return -1;
-
- ret = sexpr_to_xend_node_info(root, info);
- sexpr_free(root);
- return ret;
-}
-
-/**
- * xenDaemonNodeGetTopology:
- * @conn: pointer to the Xen Daemon block
- * @caps: capabilities info
- *
- * This method retrieves a node's topology information.
- *
- * Returns -1 in case of error, 0 otherwise.
- */
-int
-xenDaemonNodeGetTopology(virConnectPtr conn, virCapsPtr caps)
-{
- int ret = -1;
- struct sexpr *root;
-
- root = sexpr_get(conn, "/xend/node/");
- if (root == NULL)
- return -1;
-
- ret = sexpr_to_xend_topology(root, caps);
- sexpr_free(root);
- return ret;
-}
-
-
-/**
- * xenDaemonDomainSetVcpusFlags:
- * @conn: the connection object
- * @def: domain configuration
- * @nvcpus: the new number of virtual CPUs for this domain
- * @flags: bitwise-ORd from virDomainVcpuFlags
- *
- * Change virtual CPUs allocation of domain according to flags.
- *
- * Returns 0 on success, -1 if an error message was issued
- */
-int
-xenDaemonDomainSetVcpusFlags(virConnectPtr conn,
- virDomainDefPtr def,
- unsigned int vcpus,
- unsigned int flags)
-{
- char buf[VIR_UUID_BUFLEN];
- int max;
-
- virCheckFlags(VIR_DOMAIN_VCPU_LIVE |
- VIR_DOMAIN_VCPU_CONFIG |
- VIR_DOMAIN_VCPU_MAXIMUM, -1);
-
- if (vcpus < 1) {
- virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
- return -1;
- }
-
- if (def->id < 0) {
- if (flags & VIR_DOMAIN_VCPU_LIVE) {
- virReportError(VIR_ERR_OPERATION_INVALID, "%s",
- _("domain not running"));
- return -1;
- }
- } else {
- if ((flags & (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) !=
- (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) {
- virReportError(VIR_ERR_OPERATION_INVALID, "%s",
- _("Xend only supports modifying both live and "
- "persistent config"));
- }
- }
-
- /* Unfortunately, xend_op does not validate whether this exceeds
- * the maximum. */
- flags |= VIR_DOMAIN_VCPU_MAXIMUM;
- if ((max = xenDaemonDomainGetVcpusFlags(conn, def, flags)) < 0) {
- virReportError(VIR_ERR_OPERATION_INVALID, "%s",
- _("could not determine max vcpus for the domain"));
- return -1;
- }
- if (vcpus > max) {
- virReportError(VIR_ERR_INVALID_ARG,
- _("requested vcpus is greater than max allowable"
- " vcpus for the domain: %d > %d"), vcpus, max);
- return -1;
- }
-
- snprintf(buf, sizeof(buf), "%d", vcpus);
- return xend_op(conn, def->name, "op", "set_vcpus", "vcpus",
- buf, NULL);
-}
-
-/**
- * xenDaemonDomainPinCpu:
- * @conn: the connection object
- * @minidef: minimal domain configuration
- * @vcpu: virtual CPU number
- * @cpumap: pointer to a bit map of real CPUs (in 8-bit bytes)
- * @maplen: length of cpumap in bytes
- *
- * Dynamically change the real CPUs which can be allocated to a virtual CPU.
- * NOTE: The XenD cpu affinity map format changed from "[0,1,2]" to
- * "0,1,2"
- * the XenD cpu affinity works only after cset 19579.
- * there is no fine grained xend version detection possible, so we
- * use the old format for anything before version 3
- *
- * Returns 0 for success; -1 (with errno) on error
- */
-int
-xenDaemonDomainPinVcpu(virConnectPtr conn,
- virDomainDefPtr minidef,
- unsigned int vcpu,
- unsigned char *cpumap,
- int maplen)
-{
- char buf[VIR_UUID_BUFLEN], mapstr[sizeof(cpumap_t) * 64];
- size_t i, j;
-
- if (maplen > (int)sizeof(cpumap_t)) {
- virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
- return -1;
- }
-
- mapstr[0] = 0;
- /* from bit map, build character string of mapped CPU numbers */
- for (i = 0; i < maplen; i++) for (j = 0; j < 8; j++)
- if (cpumap[i] & (1 << j)) {
- snprintf(buf, sizeof(buf), "%zu,", (8 * i) + j);
- strcat(mapstr, buf);
- }
- mapstr[strlen(mapstr) - 1] = 0;
-
- snprintf(buf, sizeof(buf), "%d", vcpu);
-
- return xend_op(conn, minidef->name, "op", "pincpu", "vcpu", buf,
- "cpumap", mapstr, NULL);
-
-}
-
-/**
- * xenDaemonDomainGetVcpusFlags:
- * @conn: the connection object
- * @def: domain configuration
- * @flags: bitwise-ORd from virDomainVcpuFlags
- *
- * Extract information about virtual CPUs of domain according to flags.
- *
- * Returns the number of vcpus on success, -1 if an error message was
- * issued
-
- */
-int
-xenDaemonDomainGetVcpusFlags(virConnectPtr conn,
- virDomainDefPtr def,
- unsigned int flags)
-{
- struct sexpr *root;
- int ret;
-
- virCheckFlags(VIR_DOMAIN_VCPU_LIVE |
- VIR_DOMAIN_VCPU_CONFIG |
- VIR_DOMAIN_VCPU_MAXIMUM, -1);
-
- if (def->id < 0 && (flags & VIR_DOMAIN_VCPU_LIVE)) {
- virReportError(VIR_ERR_OPERATION_INVALID, "%s",
- _("domain not active"));
- return -1;
- }
-
- root = sexpr_get(conn, "/xend/domain/%s?detail=1", def->name);
- if (root == NULL)
- return -1;
-
- ret = sexpr_int(root, "domain/vcpus");
- if (!(flags & VIR_DOMAIN_VCPU_MAXIMUM)) {
- int vcpus = count_one_bits_l(sexpr_u64(root, "domain/vcpu_avail"));
- if (vcpus)
- ret = MIN(vcpus, ret);
- }
- if (!ret)
- ret = -1;
- sexpr_free(root);
- return ret;
-}
-
-/**
- * virDomainGetVcpus:
- * @conn: the connection object
- * @def: domain configuration
- * @info: pointer to an array of virVcpuInfo structures (OUT)
- * @maxinfo: number of structures in info array
- * @cpumaps: pointer to a bit map of real CPUs for all vcpus of this domain (in 8-bit bytes) (OUT)
- * If cpumaps is NULL, then no cpumap information is returned by the API.
- * It's assumed there is <maxinfo> cpumap in cpumaps array.
- * The memory allocated to cpumaps must be (maxinfo * maplen) bytes
- * (ie: calloc(maxinfo, maplen)).
- * One cpumap inside cpumaps has the format described in virDomainPinVcpu() API.
- * @maplen: number of bytes in one cpumap, from 1 up to size of CPU map in
- * underlying virtualization system (Xen...).
- *
- * Extract information about virtual CPUs of domain, store it in info array
- * and also in cpumaps if this pointer isn't NULL.
- *
- * Returns the number of info filled in case of success, -1 in case of failure.
- */
-int
-xenDaemonDomainGetVcpus(virConnectPtr conn,
- virDomainDefPtr def,
- virVcpuInfoPtr info,
- int maxinfo,
- unsigned char *cpumaps,
- int maplen)
-{
- struct sexpr *root, *s, *t;
- virVcpuInfoPtr ipt = info;
- int nbinfo = 0, oln;
- unsigned char *cpumap;
- int vcpu, cpu;
-
- root = sexpr_get(conn, "/xend/domain/%s?op=vcpuinfo", def->name);
- if (root == NULL)
- return -1;
-
- if (cpumaps != NULL)
- memset(cpumaps, 0, maxinfo * maplen);
-
- /* scan the sexprs from "(vcpu (number x)...)" and get parameter values */
- for (s = root; s->kind == SEXPR_CONS; s = s->u.s.cdr) {
- if ((s->u.s.car->kind == SEXPR_CONS) &&
- (s->u.s.car->u.s.car->kind == SEXPR_VALUE) &&
- STREQ(s->u.s.car->u.s.car->u.value, "vcpu")) {
- t = s->u.s.car;
- vcpu = ipt->number = sexpr_int(t, "vcpu/number");
- if ((oln = sexpr_int(t, "vcpu/online")) != 0) {
- if (sexpr_int(t, "vcpu/running")) ipt->state = VIR_VCPU_RUNNING;
- if (sexpr_int(t, "vcpu/blocked")) ipt->state = VIR_VCPU_BLOCKED;
- }
- else
- ipt->state = VIR_VCPU_OFFLINE;
- ipt->cpuTime = sexpr_float(t, "vcpu/cpu_time") * 1000000000;
- ipt->cpu = oln ? sexpr_int(t, "vcpu/cpu") : -1;
-
- if (cpumaps != NULL && vcpu >= 0 && vcpu < maxinfo) {
- cpumap = (unsigned char *) VIR_GET_CPUMAP(cpumaps, maplen, vcpu);
- /*
- * get sexpr from "(cpumap (x y z...))" and convert values
- * to bitmap
- */
- for (t = t->u.s.cdr; t->kind == SEXPR_CONS; t = t->u.s.cdr)
- if ((t->u.s.car->kind == SEXPR_CONS) &&
- (t->u.s.car->u.s.car->kind == SEXPR_VALUE) &&
- STREQ(t->u.s.car->u.s.car->u.value, "cpumap") &&
- (t->u.s.car->u.s.cdr->kind == SEXPR_CONS)) {
- for (t = t->u.s.car->u.s.cdr->u.s.car; t->kind == SEXPR_CONS; t = t->u.s.cdr)
- if (t->u.s.car->kind == SEXPR_VALUE
- && virStrToLong_i(t->u.s.car->u.value, NULL, 10, &cpu) == 0
- && cpu >= 0
- && (VIR_CPU_MAPLEN(cpu+1) <= maplen)) {
- VIR_USE_CPU(cpumap, cpu);
- }
- break;
- }
- }
-
- if (++nbinfo == maxinfo) break;
- ipt++;
- }
- }
- sexpr_free(root);
- return nbinfo;
-}
-
-/**
- * xenDaemonLookupByUUID:
- * @conn: pointer to the hypervisor connection
- * @uuid: the raw UUID for the domain
- *
- * Try to lookup a domain on xend based on its UUID.
- *
- * Returns domain def pointer on success; NULL on error
- */
-virDomainDefPtr
-xenDaemonLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
-{
- virDomainDefPtr ret;
- char *name = NULL;
- int id = -1;
- char *domname = NULL;
- char uuidstr[VIR_UUID_STRING_BUFLEN];
- struct sexpr *root = NULL;
-
- virUUIDFormat(uuid, uuidstr);
- root = sexpr_get(conn, "/xend/domain/%s?detail=1", uuidstr);
- if (root == NULL)
- return NULL;
- domname = (char*)sexpr_node(root, "domain/name");
- if (sexpr_node(root, "domain/domid")) /* only active domains have domid */
- id = sexpr_int(root, "domain/domid");
- else
- id = -1;
-
- ignore_value(VIR_STRDUP(name, domname));
-
- sexpr_free(root);
-
- if (name == NULL)
- return NULL;
-
- ret = virDomainDefNewFull(name, uuid, id);
-
- VIR_FREE(name);
- return ret;
-}
-
-/**
- * xenDaemonCreateXML:
- * @conn: pointer to the hypervisor connection
- * @def: domain configuration
- * @flags: an optional set of virDomainFlags
- *
- * Launch a new Linux guest domain, based on an XML description similar
- * to the one returned by virDomainGetXMLDesc()
- * This function may requires privileged access to the hypervisor.
- *
- * Returns a new domain object or NULL in case of failure
- */
-int
-xenDaemonCreateXML(virConnectPtr conn, virDomainDefPtr def)
-{
- int ret;
- char *sexpr;
- const char *tmp;
- struct sexpr *root;
-
- if (def->id != -1) {
- virReportError(VIR_ERR_OPERATION_INVALID,
- _("Domain %s is already running"),
- def->name);
- return -1;
- }
-
- if (!(sexpr = xenFormatSxpr(conn, def)))
- return -1;
-
- ret = xenDaemonDomainCreateXML(conn, sexpr);
- VIR_FREE(sexpr);
- if (ret != 0)
- goto error;
-
- /* This comes before wait_for_devices, to ensure that latter
- cleanup will destroy the domain upon failure */
- root = sexpr_get(conn, "/xend/domain/%s?detail=1", def->name);
- if (root == NULL)
- goto error;
-
- tmp = sexpr_node(root, "domain/domid");
- if (!tmp) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Domain %s did not start"),
- def->name);
- goto error;
- }
- if (tmp)
- def->id = sexpr_int(root, "domain/domid");
-
- if (xend_wait_for_devices(conn, def->name) < 0)
- goto error;
-
- if (xenDaemonDomainResume(conn, def) < 0)
- goto error;
-
- return 0;
-
- error:
- /* Make sure we don't leave a still-born domain around */
- if (def->id != -1)
- xenDaemonDomainDestroy(conn, def);
- return -1;
-}
-
-/**
- * xenDaemonAttachDeviceFlags:
- * @conn: the connection object
- * @minidef: domain configuration
- * @xml: pointer to XML description of device
- * @flags: an OR'ed set of virDomainDeviceModifyFlags
- *
- * Create a virtual device attachment to backend.
- * XML description is translated into S-expression.
- *
- * Returns 0 in case of success, -1 in case of failure.
- */
-int
-xenDaemonAttachDeviceFlags(virConnectPtr conn,
- virDomainDefPtr minidef,
- const char *xml,
- unsigned int flags)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- char *sexpr = NULL;
- int ret = -1;
- virDomainDeviceDefPtr dev = NULL;
- virDomainDefPtr def = NULL;
- virBuffer buf = VIR_BUFFER_INITIALIZER;
- char class[8], ref[80];
- char *target = NULL;
-
- virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1);
-
- if (minidef->id < 0) {
- /* Cannot modify live config if domain is inactive */
- if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) {
- virReportError(VIR_ERR_OPERATION_INVALID, "%s",
- _("Cannot modify live config if domain is inactive"));
- return -1;
- }
- } else {
- /* Xen only supports modifying both live and persistent config */
- if (flags != (VIR_DOMAIN_DEVICE_MODIFY_LIVE |
- VIR_DOMAIN_DEVICE_MODIFY_CONFIG)) {
- virReportError(VIR_ERR_OPERATION_INVALID, "%s",
- _("Xend only supports modifying both live and "
- "persistent config"));
- return -1;
- }
- }
-
- if (!(def = xenDaemonDomainFetch(conn,
- minidef->id,
- minidef->name,
- NULL)))
- goto cleanup;
-
- if (!(dev = virDomainDeviceDefParse(xml, def, priv->caps, priv->xmlopt,
- VIR_DOMAIN_DEF_PARSE_INACTIVE)))
- goto cleanup;
-
-
- switch (dev->type) {
- case VIR_DOMAIN_DEVICE_DISK:
- if (xenFormatSxprDisk(dev->data.disk,
- &buf,
- def->os.type == VIR_DOMAIN_OSTYPE_HVM ? 1 : 0,
- 1) < 0)
- goto cleanup;
-
- if (dev->data.disk->device != VIR_DOMAIN_DISK_DEVICE_CDROM &&
- VIR_STRDUP(target, dev->data.disk->dst) < 0)
- goto cleanup;
- break;
-
- case VIR_DOMAIN_DEVICE_NET:
- if (xenFormatSxprNet(conn,
- dev->data.net,
- &buf,
- def->os.type == VIR_DOMAIN_OSTYPE_HVM ? 1 : 0,
- 1) < 0)
- goto cleanup;
-
- char macStr[VIR_MAC_STRING_BUFLEN];
- virMacAddrFormat(&dev->data.net->mac, macStr);
-
- if (VIR_STRDUP(target, macStr) < 0)
- goto cleanup;
- break;
-
- case VIR_DOMAIN_DEVICE_HOSTDEV:
- if (dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
- dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
- if (xenFormatSxprOnePCI(dev->data.hostdev, &buf, 0) < 0)
- goto cleanup;
-
- virPCIDeviceAddress PCIAddr;
-
- PCIAddr = dev->data.hostdev->source.subsys.u.pci.addr;
- if (virAsprintf(&target, "PCI device: %.4x:%.2x:%.2x",
- PCIAddr.domain, PCIAddr.bus, PCIAddr.slot) < 0)
- goto cleanup;
- } else {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("unsupported device type"));
- goto cleanup;
- }
- break;
-
- default:
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("unsupported device type"));
- goto cleanup;
- }
-
- sexpr = virBufferContentAndReset(&buf);
-
- if (virDomainXMLDevID(conn, minidef, dev, class, ref, sizeof(ref))) {
- /* device doesn't exist, define it */
- ret = xend_op(conn, def->name, "op", "device_create",
- "config", sexpr, NULL);
- } else {
- if (dev->data.disk->device != VIR_DOMAIN_DISK_DEVICE_CDROM) {
- virReportError(VIR_ERR_OPERATION_INVALID,
- _("target '%s' already exists"), target);
- } else {
- /* device exists, attempt to modify it */
- ret = xend_op(conn, minidef->name, "op", "device_configure",
- "config", sexpr, "dev", ref, NULL);
- }
- }
-
- cleanup:
- VIR_FREE(sexpr);
- virDomainDefFree(def);
- virDomainDeviceDefFree(dev);
- VIR_FREE(target);
- return ret;
-}
-
-/**
- * xenDaemonUpdateDeviceFlags:
- * @conn: the connection object
- * @minidef: domain configuration
- * @xml: pointer to XML description of device
- * @flags: an OR'ed set of virDomainDeviceModifyFlags
- *
- * Create a virtual device attachment to backend.
- * XML description is translated into S-expression.
- *
- * Returns 0 in case of success, -1 in case of failure.
- */
-int
-xenDaemonUpdateDeviceFlags(virConnectPtr conn,
- virDomainDefPtr minidef,
- const char *xml,
- unsigned int flags)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- char *sexpr = NULL;
- int ret = -1;
- virDomainDeviceDefPtr dev = NULL;
- virDomainDefPtr def = NULL;
- virBuffer buf = VIR_BUFFER_INITIALIZER;
- char class[8], ref[80];
-
- virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE |
- VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1);
-
- if (minidef->id < 0) {
- /* Cannot modify live config if domain is inactive */
- if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) {
- virReportError(VIR_ERR_OPERATION_INVALID, "%s",
- _("Cannot modify live config if domain is inactive"));
- return -1;
- }
- } else {
- /* Xen only supports modifying both live and persistent config */
- if (flags != (VIR_DOMAIN_DEVICE_MODIFY_LIVE |
- VIR_DOMAIN_DEVICE_MODIFY_CONFIG)) {
- virReportError(VIR_ERR_OPERATION_INVALID, "%s",
- _("Xend only supports modifying both live and "
- "persistent config"));
- return -1;
- }
- }
-
- if (!(def = xenDaemonDomainFetch(conn,
- minidef->id,
- minidef->name,
- NULL)))
- goto cleanup;
-
- if (!(dev = virDomainDeviceDefParse(xml, def, priv->caps, priv->xmlopt,
- VIR_DOMAIN_DEF_PARSE_INACTIVE)))
- goto cleanup;
-
-
- switch (dev->type) {
- case VIR_DOMAIN_DEVICE_DISK:
- if (xenFormatSxprDisk(dev->data.disk,
- &buf,
- def->os.type == VIR_DOMAIN_OSTYPE_HVM ? 1 : 0,
- 1) < 0)
- goto cleanup;
- break;
-
- default:
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("unsupported device type"));
- goto cleanup;
- }
-
- sexpr = virBufferContentAndReset(&buf);
-
- if (virDomainXMLDevID(conn, minidef, dev, class, ref, sizeof(ref))) {
- virReportError(VIR_ERR_OPERATION_INVALID, "%s",
- _("requested device does not exist"));
- goto cleanup;
- } else {
- /* device exists, attempt to modify it */
- ret = xend_op(conn, minidef->name, "op", "device_configure",
- "config", sexpr, "dev", ref, NULL);
- }
-
- cleanup:
- VIR_FREE(sexpr);
- virDomainDefFree(def);
- virDomainDeviceDefFree(dev);
- return ret;
-}
-
-/**
- * xenDaemonDetachDeviceFlags:
- * @conn: the connection object
- * @minidef: domain configuration
- * @xml: pointer to XML description of device
- * @flags: an OR'ed set of virDomainDeviceModifyFlags
- *
- * Destroy a virtual device attachment to backend.
- *
- * Returns 0 in case of success, -1 in case of failure.
- */
-int
-xenDaemonDetachDeviceFlags(virConnectPtr conn,
- virDomainDefPtr minidef,
- const char *xml,
- unsigned int flags)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- char class[8], ref[80];
- virDomainDeviceDefPtr dev = NULL;
- virDomainDefPtr def = NULL;
- int ret = -1;
- char *xendev = NULL;
- virBuffer buf = VIR_BUFFER_INITIALIZER;
-
- virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1);
-
- if (minidef->id < 0) {
- /* Cannot modify live config if domain is inactive */
- if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) {
- virReportError(VIR_ERR_OPERATION_INVALID, "%s",
- _("Cannot modify live config if domain is inactive"));
- return -1;
- }
- } else {
- /* Xen only supports modifying both live and persistent config */
- if (flags != (VIR_DOMAIN_DEVICE_MODIFY_LIVE |
- VIR_DOMAIN_DEVICE_MODIFY_CONFIG)) {
- virReportError(VIR_ERR_OPERATION_INVALID, "%s",
- _("Xend only supports modifying both live and "
- "persistent config"));
- return -1;
- }
- }
-
- if (!(def = xenDaemonDomainFetch(conn,
- minidef->id,
- minidef->name,
- NULL)))
- goto cleanup;
-
- if (!(dev = virDomainDeviceDefParse(xml, def, priv->caps, priv->xmlopt,
- VIR_DOMAIN_DEF_PARSE_INACTIVE |
- VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE)))
- goto cleanup;
-
- if (virDomainXMLDevID(conn, minidef, dev, class, ref, sizeof(ref)))
- goto cleanup;
-
- if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) {
- if (dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
- dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
- if (xenFormatSxprOnePCI(dev->data.hostdev, &buf, 1) < 0)
- goto cleanup;
- } else {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("unsupported device type"));
- goto cleanup;
- }
- xendev = virBufferContentAndReset(&buf);
- ret = xend_op(conn, minidef->name, "op", "device_configure",
- "config", xendev, "dev", ref, NULL);
- VIR_FREE(xendev);
- } else {
- ret = xend_op(conn, minidef->name, "op", "device_destroy",
- "type", class, "dev", ref, "force", "0", "rm_cfg", "1",
- NULL);
- }
-
- cleanup:
- virDomainDefFree(def);
- virDomainDeviceDefFree(dev);
-
- return ret;
-}
-
-int
-xenDaemonDomainGetAutostart(virConnectPtr conn,
- virDomainDefPtr def,
- int *autostart)
-{
- struct sexpr *root;
- const char *tmp;
-
- root = sexpr_get(conn, "/xend/domain/%s?detail=1", def->name);
- if (root == NULL) {
- virReportError(VIR_ERR_XEN_CALL,
- "%s", _("xenDaemonGetAutostart failed to find this domain"));
- return -1;
- }
-
- *autostart = 0;
-
- tmp = sexpr_node(root, "domain/on_xend_start");
- if (tmp && STREQ(tmp, "start"))
- *autostart = 1;
-
- sexpr_free(root);
- return 0;
-}
-
-int
-xenDaemonDomainSetAutostart(virConnectPtr conn,
- virDomainDefPtr def,
- int autostart)
-{
- struct sexpr *root, *autonode;
- virBuffer buffer = VIR_BUFFER_INITIALIZER;
- char *content = NULL;
- int ret = -1;
-
- root = sexpr_get(conn, "/xend/domain/%s?detail=1", def->name);
- if (root == NULL) {
- virReportError(VIR_ERR_XEN_CALL,
- "%s", _("xenDaemonSetAutostart failed to find this domain"));
- return -1;
- }
-
- autonode = sexpr_lookup(root, "domain/on_xend_start");
- if (autonode) {
- const char *val = (autonode->u.s.car->kind == SEXPR_VALUE
- ? autonode->u.s.car->u.value : NULL);
- if (!val || (STRNEQ(val, "ignore") && STRNEQ(val, "start"))) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("unexpected value from on_xend_start"));
- goto error;
- }
-
- /* Change the autostart value in place, then define the new sexpr */
- VIR_FREE(autonode->u.s.car->u.value);
- if (VIR_STRDUP(autonode->u.s.car->u.value,
- autostart ? "start" : "ignore") < 0)
- goto error;
-
- if (sexpr2string(root, &buffer) < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("sexpr2string failed"));
- goto error;
- }
-
- if (virBufferCheckError(&buffer) < 0)
- goto error;
-
- content = virBufferContentAndReset(&buffer);
-
- if (xend_op(conn, "", "op", "new", "config", content, NULL) != 0) {
- virReportError(VIR_ERR_XEN_CALL,
- "%s", _("Failed to redefine sexpr"));
- goto error;
- }
- } else {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("on_xend_start not present in sexpr"));
- goto error;
- }
-
- ret = 0;
- error:
- virBufferFreeAndReset(&buffer);
- VIR_FREE(content);
- sexpr_free(root);
- return ret;
-}
-
-int
-xenDaemonDomainMigratePrepare(virConnectPtr dconn ATTRIBUTE_UNUSED,
- char **cookie ATTRIBUTE_UNUSED,
- int *cookielen ATTRIBUTE_UNUSED,
- const char *uri_in,
- char **uri_out,
- unsigned long flags,
- const char *dname ATTRIBUTE_UNUSED,
- unsigned long resource ATTRIBUTE_UNUSED)
-{
- virCheckFlags(XEN_MIGRATION_FLAGS, -1);
-
- /* If uri_in is NULL, get the current hostname as a best guess
- * of how the source host should connect to us. Note that caller
- * deallocates this string.
- */
- if (uri_in == NULL) {
- *uri_out = virGetHostname();
- if (*uri_out == NULL)
- return -1;
- }
-
- return 0;
-}
-
-int
-xenDaemonDomainMigratePerform(virConnectPtr conn,
- virDomainDefPtr def,
- const char *cookie ATTRIBUTE_UNUSED,
- int cookielen ATTRIBUTE_UNUSED,
- const char *uri,
- unsigned long flags,
- const char *dname,
- unsigned long bandwidth)
-{
- /* Upper layers have already checked domain. */
- /* NB: Passing port=0 to xend means it ignores
- * the port. However this is somewhat specific to
- * the internals of the xend Python code. (XXX).
- */
- char port[16] = "0";
- char live[2] = "0";
- int ret;
- char *p, *hostname = NULL;
-
- int undefined_source = 0;
-
- virCheckFlags(XEN_MIGRATION_FLAGS, -1);
-
- /* Xen doesn't support renaming domains during migration. */
- if (dname) {
- virReportError(VIR_ERR_OPERATION_INVALID,
- "%s", _("xenDaemonDomainMigrate: Xen does not support"
- " renaming domains during migration"));
- return -1;
- }
-
- /* Xen (at least up to 3.1.0) takes a resource parameter but
- * ignores it.
- */
- if (bandwidth) {
- virReportError(VIR_ERR_OPERATION_INVALID,
- "%s", _("xenDaemonDomainMigrate: Xen does not support"
- " bandwidth limits during migration"));
- return -1;
- }
-
- /*
- * Check the flags.
- */
- if ((flags & VIR_MIGRATE_LIVE)) {
- strcpy(live, "1");
- flags &= ~VIR_MIGRATE_LIVE;
- }
-
- /* Undefine the VM on the source host after migration? */
- if (flags & VIR_MIGRATE_UNDEFINE_SOURCE) {
- undefined_source = 1;
- flags &= ~VIR_MIGRATE_UNDEFINE_SOURCE;
- }
-
- /* Ignore the persist_dest flag here */
- if (flags & VIR_MIGRATE_PERSIST_DEST)
- flags &= ~VIR_MIGRATE_PERSIST_DEST;
-
- /* This is buggy in Xend, but could be supported in principle. Give
- * a nice error message.
- */
- if (flags & VIR_MIGRATE_PAUSED) {
- virReportError(VIR_ERR_OPERATION_INVALID,
- "%s", _("xenDaemonDomainMigrate: xend cannot migrate paused domains"));
- return -1;
- }
-
- /* XXX we could easily do tunnelled & peer2peer migration too
- if we want to. support these... */
- if (flags != 0) {
- virReportError(VIR_ERR_OPERATION_INVALID,
- "%s", _("xenDaemonDomainMigrate: unsupported flag"));
- return -1;
- }
-
- /* Set hostname and port.
- *
- * URI is non-NULL (guaranteed by caller). We expect either
- * "hostname", "hostname:port" or "xenmigr://hostname[:port]/".
- */
- if (strstr(uri, "//")) { /* Full URI. */
- virURIPtr uriptr;
- if (!(uriptr = virURIParse(uri)))
- return -1;
-
- if (uriptr->scheme && STRCASENEQ(uriptr->scheme, "xenmigr")) {
- virReportError(VIR_ERR_INVALID_ARG,
- "%s", _("xenDaemonDomainMigrate: only xenmigr://"
- " migrations are supported by Xen"));
- virURIFree(uriptr);
- return -1;
- }
- if (!uriptr->server) {
- virReportError(VIR_ERR_INVALID_ARG,
- "%s", _("xenDaemonDomainMigrate: a hostname must be"
- " specified in the URI"));
- virURIFree(uriptr);
- return -1;
- }
- if (VIR_STRDUP(hostname, uriptr->server) < 0) {
- virURIFree(uriptr);
- return -1;
- }
- if (uriptr->port)
- snprintf(port, sizeof(port), "%d", uriptr->port);
- virURIFree(uriptr);
- } else if ((p = strrchr(uri, ':')) != NULL) { /* "hostname:port" */
- int port_nr, n;
-
- if (virStrToLong_i(p+1, NULL, 10, &port_nr) < 0) {
- virReportError(VIR_ERR_INVALID_ARG,
- "%s", _("xenDaemonDomainMigrate: invalid port number"));
- return -1;
- }
- snprintf(port, sizeof(port), "%d", port_nr);
-
- /* Get the hostname. */
- n = p - uri; /* n = Length of hostname in bytes. */
- if (VIR_STRDUP(hostname, uri) < 0)
- return -1;
- hostname[n] = '\0';
- } else { /* "hostname" (or IP address) */
- if (VIR_STRDUP(hostname, uri) < 0)
- return -1;
- }
-
- VIR_DEBUG("hostname = %s, port = %s", hostname, port);
-
- /* Make the call.
- * NB: xend will fail the operation if any parameters are
- * missing but happily accept unknown parameters. This works
- * to our advantage since all parameters supported and required
- * by current xend can be included without breaking older xend.
- */
- ret = xend_op(conn, def->name,
- "op", "migrate",
- "destination", hostname,
- "live", live,
- "port", port,
- "node", "-1", /* xen-unstable c/s 17753 */
- "ssl", "0", /* xen-unstable c/s 17709 */
- "change_home_server", "0", /* xen-unstable c/s 20326 */
- "resource", "0", /* removed by xen-unstable c/s 17553 */
- NULL);
- VIR_FREE(hostname);
-
- if (ret == 0 && undefined_source)
- xenDaemonDomainUndefine(conn, def);
-
- VIR_DEBUG("migration done");
-
- return ret;
-}
-
-int
-xenDaemonDomainDefineXML(virConnectPtr conn, virDomainDefPtr def)
-{
- int ret = -1;
- char *sexpr;
-
- if (!(sexpr = xenFormatSxpr(conn, def))) {
- virReportError(VIR_ERR_XML_ERROR,
- "%s", _("failed to build sexpr"));
- goto cleanup;
- }
-
- ret = xend_op(conn, "", "op", "new", "config", sexpr, NULL);
- VIR_FREE(sexpr);
- if (ret != 0) {
- virReportError(VIR_ERR_XEN_CALL,
- _("Failed to create inactive domain %s"), def->name);
- goto cleanup;
- }
-
- ret = 0;
-
- cleanup:
- return ret;
-}
-
-int
-xenDaemonDomainCreate(virConnectPtr conn,
- virDomainDefPtr def)
-{
- int ret;
-
- ret = xend_op(conn, def->name, "op", "start", NULL);
-
- if (ret == 0) {
- int id = xenDaemonDomainLookupByName_ids(conn, def->name,
- def->uuid);
- if (id > 0)
- def->id = id;
- }
-
- return ret;
-}
-
-int
-xenDaemonDomainUndefine(virConnectPtr conn, virDomainDefPtr def)
-{
- return xend_op(conn, def->name, "op", "delete", NULL);
-}
-
-/**
- * xenDaemonNumOfDomains:
- * @conn: pointer to the hypervisor connection
- *
- * Provides the number of active domains.
- *
- * Returns the number of domain found or -1 in case of error
- */
-int
-xenDaemonNumOfDefinedDomains(virConnectPtr conn)
-{
- struct sexpr *root = NULL;
- int ret = -1;
- struct sexpr *_for_i, *node;
-
- root = sexpr_get(conn, "/xend/domain?state=halted");
- if (root == NULL)
- goto error;
-
- ret = 0;
-
- /* coverity[copy_paste_error] */
- for (_for_i = root, node = root->u.s.car; _for_i->kind == SEXPR_CONS;
- _for_i = _for_i->u.s.cdr, node = _for_i->u.s.car) {
- if (node->kind != SEXPR_VALUE)
- continue;
- ret++;
- }
-
- error:
- sexpr_free(root);
- return ret;
-}
-
-int
-xenDaemonListDefinedDomains(virConnectPtr conn,
- char **const names,
- int maxnames)
-{
- struct sexpr *root = NULL;
- size_t i;
- int ret = 0;
- struct sexpr *_for_i, *node;
-
- if (maxnames == 0)
- return 0;
-
- root = sexpr_get(conn, "/xend/domain?state=halted");
- if (root == NULL)
- goto error;
-
- /* coverity[copy_paste_error] */
- for (_for_i = root, node = root->u.s.car; _for_i->kind == SEXPR_CONS;
- _for_i = _for_i->u.s.cdr, node = _for_i->u.s.car) {
- if (node->kind != SEXPR_VALUE)
- continue;
-
- if (VIR_STRDUP(names[ret++], node->u.value) < 0)
- goto error;
-
- if (ret >= maxnames)
- break;
- }
-
- cleanup:
- sexpr_free(root);
- return ret;
-
- error:
- for (i = 0; i < ret; ++i)
- VIR_FREE(names[i]);
-
- ret = -1;
- goto cleanup;
-}
-
-/**
- * xenDaemonGetSchedulerType:
- * @conn: the hypervisor connection
- * @nparams: give a number of scheduler parameters
- *
- * Get the scheduler type of Xen
- *
- * Returns a scheduler name (credit or sedf) which must be freed by the
- * caller or NULL in case of failure
- */
-char *
-xenDaemonGetSchedulerType(virConnectPtr conn,
- int *nparams)
-{
- struct sexpr *root;
- const char *ret = NULL;
- char *schedulertype = NULL;
-
- root = sexpr_get(conn, "/xend/node/");
- if (root == NULL)
- return NULL;
-
- /* get xen_scheduler from xend/node */
- ret = sexpr_node(root, "node/xen_scheduler");
- if (ret == NULL) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("node information incomplete, missing scheduler name"));
- goto error;
- }
- if (STREQ(ret, "credit")) {
- if (VIR_STRDUP(schedulertype, "credit") < 0)
- goto error;
- if (nparams)
- *nparams = XEN_SCHED_CRED_NPARAM;
- } else if (STREQ(ret, "sedf")) {
- if (VIR_STRDUP(schedulertype, "sedf") < 0)
- goto error;
- if (nparams)
- *nparams = XEN_SCHED_SEDF_NPARAM;
- } else {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Unknown scheduler"));
- goto error;
- }
-
- error:
- sexpr_free(root);
- return schedulertype;
-
-}
-
-/**
- * xenDaemonGetSchedulerParameters:
- * @conn: the hypervisor connection
- * @def: domain configuration
- * @params: pointer to scheduler parameters
- * This memory area must be allocated by the caller
- * @nparams: a number of scheduler parameters which should be same as a
- * given number from xenDaemonGetSchedulerType()
- *
- * Get the scheduler parameters
- *
- * Returns 0 or -1 in case of failure
- */
-int
-xenDaemonGetSchedulerParameters(virConnectPtr conn,
- virDomainDefPtr def,
- virTypedParameterPtr params,
- int *nparams)
-{
- struct sexpr *root;
- char *sched_type = NULL;
- int sched_nparam = 0;
- int ret = -1;
-
- /* look up the information by domain name */
- root = sexpr_get(conn, "/xend/domain/%s?detail=1", def->name);
- if (root == NULL)
- return -1;
-
- /* get the scheduler type */
- sched_type = xenDaemonGetSchedulerType(conn, &sched_nparam);
- if (sched_type == NULL) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("Failed to get a scheduler name"));
- goto error;
- }
-
- switch (sched_nparam) {
- case XEN_SCHED_SEDF_NPARAM:
- if (*nparams < XEN_SCHED_SEDF_NPARAM) {
- virReportError(VIR_ERR_INVALID_ARG,
- "%s", _("Invalid parameter count"));
- goto error;
- }
-
- /* TODO: Implement for Xen/SEDF */
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("SEDF scheduler parameters not supported"));
- goto error;
- case XEN_SCHED_CRED_NPARAM:
- /* get cpu_weight/cpu_cap from xend/domain */
- if (sexpr_node(root, "domain/cpu_weight") == NULL) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("domain information incomplete, missing cpu_weight"));
- goto error;
- }
- if (sexpr_node(root, "domain/cpu_cap") == NULL) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("domain information incomplete, missing cpu_cap"));
- goto error;
- }
-
- if (virStrcpyStatic(params[0].field,
- VIR_DOMAIN_SCHEDULER_WEIGHT) == NULL) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Weight %s too big for destination"),
- VIR_DOMAIN_SCHEDULER_WEIGHT);
- goto error;
- }
- params[0].type = VIR_TYPED_PARAM_UINT;
- params[0].value.ui = sexpr_int(root, "domain/cpu_weight");
-
- if (*nparams > 1) {
- if (virStrcpyStatic(params[1].field,
- VIR_DOMAIN_SCHEDULER_CAP) == NULL) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Cap %s too big for destination"),
- VIR_DOMAIN_SCHEDULER_CAP);
- goto error;
- }
- params[1].type = VIR_TYPED_PARAM_UINT;
- params[1].value.ui = sexpr_int(root, "domain/cpu_cap");
- }
-
- if (*nparams > XEN_SCHED_CRED_NPARAM)
- *nparams = XEN_SCHED_CRED_NPARAM;
- ret = 0;
- break;
- default:
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Unknown scheduler"));
- goto error;
- }
-
- error:
- sexpr_free(root);
- VIR_FREE(sched_type);
- return ret;
-}
-
-/**
- * xenDaemonSetSchedulerParameters:
- * @conn: the hypervisor connection
- * @def: domain configuration
- * @params: pointer to scheduler parameters
- * @nparams: a number of scheduler setting parameters
- *
- * Set the scheduler parameters
- *
- * Returns 0 or -1 in case of failure
- */
-int
-xenDaemonSetSchedulerParameters(virConnectPtr conn,
- virDomainDefPtr def,
- virTypedParameterPtr params,
- int nparams)
-{
- struct sexpr *root;
- char *sched_type = NULL;
- size_t i;
- int sched_nparam = 0;
- int ret = -1;
-
- /* look up the information by domain name */
- root = sexpr_get(conn, "/xend/domain/%s?detail=1", def->name);
- if (root == NULL)
- return -1;
-
- /* get the scheduler type */
- sched_type = xenDaemonGetSchedulerType(conn, &sched_nparam);
- if (sched_type == NULL) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("Failed to get a scheduler name"));
- goto error;
- }
-
- switch (sched_nparam) {
- case XEN_SCHED_SEDF_NPARAM:
- /* TODO: Implement for Xen/SEDF */
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("SEDF scheduler parameters not supported"));
- goto error;
- case XEN_SCHED_CRED_NPARAM: {
- char buf_weight[VIR_UUID_BUFLEN];
- char buf_cap[VIR_UUID_BUFLEN];
- const char *weight = NULL;
- const char *cap = NULL;
-
- /* get the scheduler parameters */
- memset(&buf_weight, 0, VIR_UUID_BUFLEN);
- memset(&buf_cap, 0, VIR_UUID_BUFLEN);
- for (i = 0; i < nparams; i++) {
- if (STREQ(params[i].field, VIR_DOMAIN_SCHEDULER_WEIGHT) &&
- params[i].type == VIR_TYPED_PARAM_UINT) {
- snprintf(buf_weight, sizeof(buf_weight), "%u", params[i].value.ui);
- } else if (STREQ(params[i].field, VIR_DOMAIN_SCHEDULER_CAP) &&
- params[i].type == VIR_TYPED_PARAM_UINT) {
- snprintf(buf_cap, sizeof(buf_cap), "%u", params[i].value.ui);
- } else {
- virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
- goto error;
- }
- }
-
- /* if not get the scheduler parameter, set the current setting */
- if (strlen(buf_weight) == 0) {
- weight = sexpr_node(root, "domain/cpu_weight");
- if (weight == NULL) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("domain information incomplete, missing cpu_weight"));
- goto error;
- }
- snprintf(buf_weight, sizeof(buf_weight), "%s", weight);
- }
- if (strlen(buf_cap) == 0) {
- cap = sexpr_node(root, "domain/cpu_cap");
- if (cap == NULL) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("domain information incomplete, missing cpu_cap"));
- goto error;
- }
- snprintf(buf_cap, sizeof(buf_cap), "%s", cap);
- }
-
- ret = xend_op(conn, def->name, "op",
- "domain_sched_credit_set", "weight", buf_weight,
- "cap", buf_cap, NULL);
- break;
- }
- default:
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Unknown scheduler"));
- goto error;
- }
-
- error:
- sexpr_free(root);
- VIR_FREE(sched_type);
- return ret;
-}
-
-/**
- * xenDaemonDomainBlockPeek:
- * @conn: the hypervisor connection
- * @minidef: minimal domain configuration
- * @path: path to the file or device
- * @offset: offset
- * @size: size
- * @buffer: return buffer
- *
- * Returns 0 if successful, -1 if error
- */
-int
-xenDaemonDomainBlockPeek(virConnectPtr conn,
- virDomainDefPtr minidef,
- const char *path,
- unsigned long long offset,
- size_t size,
- void *buffer)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- struct sexpr *root = NULL;
- int fd = -1, ret = -1;
- virDomainDefPtr def = NULL;
- int id;
- char * tty;
- int vncport;
- const char *actual;
-
- /* Security check: The path must correspond to a block device. */
- if (minidef->id > 0) {
- root = sexpr_get(conn, "/xend/domain/%d?detail=1",
- minidef->id);
- } else if (minidef->id < 0) {
- root = sexpr_get(conn, "/xend/domain/%s?detail=1",
- minidef->name);
- } else {
- /* This call always fails for dom0. */
- virReportError(VIR_ERR_OPERATION_INVALID,
- "%s", _("domainBlockPeek is not supported for dom0"));
- return -1;
- }
-
- if (!root) {
- virReportError(VIR_ERR_XEN_CALL, __FUNCTION__);
- return -1;
- }
-
- if (xenGetDomIdFromSxpr(root, &id) < 0)
- goto cleanup;
- xenUnifiedLock(priv);
- tty = xenStoreDomainGetConsolePath(conn, id);
- vncport = xenStoreDomainGetVNCPort(conn, id);
- xenUnifiedUnlock(priv);
-
- if (!(def = xenParseSxpr(root, NULL, tty, vncport,
- priv->caps, priv->xmlopt)))
- goto cleanup;
-
- if (!(actual = virDomainDiskPathByName(def, path))) {
- virReportError(VIR_ERR_INVALID_ARG,
- _("%s: invalid path"), path);
- goto cleanup;
- }
- path = actual;
-
- /* The path is correct, now try to open it and get its size. */
- fd = open(path, O_RDONLY);
- if (fd == -1) {
- virReportSystemError(errno,
- _("failed to open for reading: %s"),
- path);
- goto cleanup;
- }
-
- /* Seek and read. */
- /* NB. Because we configure with AC_SYS_LARGEFILE, off_t should
- * be 64 bits on all platforms.
- */
- if (lseek(fd, offset, SEEK_SET) == (off_t) -1 ||
- saferead(fd, buffer, size) == (ssize_t) -1) {
- virReportSystemError(errno,
- _("failed to lseek or read from file: %s"),
- path);
- goto cleanup;
- }
-
- ret = 0;
- cleanup:
- VIR_FORCE_CLOSE(fd);
- sexpr_free(root);
- virDomainDefFree(def);
- return ret;
-}
-
-
-/**
- * virDomainXMLDevID:
- * @conn: the hypervisor connection
- * @minidef: minimal domain configuration
- * @dev: pointer to device config object
- * @class: Xen device class "vbd" or "vif" (OUT)
- * @ref: Xen device reference (OUT)
- *
- * Set class according to XML root, and:
- * - if disk, copy in ref the target name from description
- * - if network, get MAC address from description, scan XenStore and
- * copy in ref the corresponding vif number.
- * - if pci, get BDF from description, scan XenStore and
- * copy in ref the corresponding dev number.
- *
- * Returns 0 in case of success, -1 in case of failure.
- */
-static int
-virDomainXMLDevID(virConnectPtr conn,
- virDomainDefPtr def,
- virDomainDeviceDefPtr dev,
- char *class,
- char *ref,
- int ref_len)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- char *xref;
- char *tmp;
-
- if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
- const char *driver = virDomainDiskGetDriver(dev->data.disk);
-
- if (STREQ_NULLABLE(driver, "tap") || STREQ_NULLABLE(driver, "tap2"))
- strcpy(class, driver);
- else
- strcpy(class, "vbd");
-
- if (dev->data.disk->dst == NULL)
- return -1;
- xenUnifiedLock(priv);
- xref = xenStoreDomainGetDiskID(conn, def->id,
- dev->data.disk->dst);
- xenUnifiedUnlock(priv);
- if (xref == NULL)
- return -1;
-
- tmp = virStrcpy(ref, xref, ref_len);
- VIR_FREE(xref);
- if (tmp == NULL)
- return -1;
- } else if (dev->type == VIR_DOMAIN_DEVICE_NET) {
- char mac[VIR_MAC_STRING_BUFLEN];
- virDomainNetDefPtr netdef = dev->data.net;
- virMacAddrFormat(&netdef->mac, mac);
-
- strcpy(class, "vif");
-
- xenUnifiedLock(priv);
- xref = xenStoreDomainGetNetworkID(conn, def->id, mac);
- xenUnifiedUnlock(priv);
- if (xref == NULL)
- return -1;
-
- tmp = virStrcpy(ref, xref, ref_len);
- VIR_FREE(xref);
- if (tmp == NULL)
- return -1;
- } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV &&
- dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
- dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
- char *bdf;
- virDomainHostdevDefPtr hostdef = dev->data.hostdev;
-
- if (virAsprintf(&bdf, "%04x:%02x:%02x.%0x",
- hostdef->source.subsys.u.pci.addr.domain,
- hostdef->source.subsys.u.pci.addr.bus,
- hostdef->source.subsys.u.pci.addr.slot,
- hostdef->source.subsys.u.pci.addr.function) < 0)
- return -1;
-
- strcpy(class, "pci");
-
- xenUnifiedLock(priv);
- xref = xenStoreDomainGetPCIID(conn, def->id, bdf);
- xenUnifiedUnlock(priv);
- VIR_FREE(bdf);
- if (xref == NULL)
- return -1;
-
- tmp = virStrcpy(ref, xref, ref_len);
- VIR_FREE(xref);
- if (tmp == NULL)
- return -1;
- } else {
- virReportError(VIR_ERR_OPERATION_INVALID,
- "%s", _("hotplug of device type not supported"));
- return -1;
- }
-
- return 0;
-}
+++ /dev/null
-/*
- * xend_internal.h
- *
- * Copyright (C) 2006-2008, 2010-2013 Red Hat, Inc.
- * Copyright (C) 2005,2006 Anthony Liguori <aliguori@us.ibm.com>
- * and Daniel Veillard <veillard@redhat.com>
- *
- * 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/>.
- */
-
-#ifndef __XEND_INTERNAL_H_
-# define __XEND_INTERNAL_H_
-
-# include <sys/types.h>
-# include <stdint.h>
-
-# include "internal.h"
-# include "capabilities.h"
-# include "domain_conf.h"
-# include "driver.h"
-# include "virbuffer.h"
-# include "viruri.h"
-
-int
-xenDaemonOpen_unix(virConnectPtr conn, const char *path);
-
-/**
- * \brief Blocks until a domain's devices are initialized
- * \param xend A xend instance
- * \param name The domain's name
- * \return 0 for success; -1 (with errno) on error
- *
- * xen_create() returns after a domain has been allocated including
- * its memory. This does not guarantee, though, that the devices
- * have come up properly. For instance, if you create a VBD with an
- * invalid filename, the error won't occur until after this function
- * returns.
- */
- int xend_wait_for_devices(virConnectPtr xend, const char *name);
-
-
-/**
- * \brief Create a new domain
- * \param xend A xend instance
- * \param sexpr An S-Expr defining the domain
- * \return 0 for success; -1 (with errno) on error
- *
- * This method will create a domain based the passed in description. The
- * domain will be paused after creation and must be unpaused with
- * xenDaemonResumeDomain() to begin execution.
- */
-int xenDaemonDomainCreateXML(virConnectPtr xend, const char *sexpr);
-
-/**
- * \brief Lookup the id of a domain
- * \param xend A xend instance
- * \param name The name of the domain
- * \param uuid pointer to store a copy of the uuid
- * \return the id number on success; -1 (with errno) on error
- *
- * This method looks up the ids of a domain
- */
-int xenDaemonDomainLookupByName_ids(virConnectPtr xend,
- const char *name, unsigned char *uuid);
-
-
-
-virDomainDefPtr
-xenDaemonDomainFetch(virConnectPtr xend,
- int domid,
- const char *name,
- const char *cpus);
-
-
-/* refactored ones */
-int xenDaemonOpen(virConnectPtr conn, virConnectAuthPtr auth,
- unsigned int flags);
-int xenDaemonClose(virConnectPtr conn);
-int xenDaemonNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info);
-int xenDaemonNodeGetTopology(virConnectPtr conn, virCapsPtr caps);
-int xenDaemonDomainSuspend(virConnectPtr conn, virDomainDefPtr def);
-int xenDaemonDomainResume(virConnectPtr conn, virDomainDefPtr def);
-int xenDaemonDomainShutdown(virConnectPtr conn, virDomainDefPtr def);
-int xenDaemonDomainReboot(virConnectPtr conn, virDomainDefPtr def);
-int xenDaemonDomainDestroy(virConnectPtr conn, virDomainDefPtr def);
-int xenDaemonDomainSave(virConnectPtr conn,
- virDomainDefPtr def,
- const char *filename);
-int xenDaemonDomainCoreDump(virConnectPtr conn,
- virDomainDefPtr def,
- const char *filename,
- unsigned int flags);
-int xenDaemonDomainRestore(virConnectPtr conn, const char *filename);
-int xenDaemonDomainSetMemory(virConnectPtr conn,
- virDomainDefPtr def,
- unsigned long memory);
-int xenDaemonDomainSetMaxMemory(virConnectPtr conn,
- virDomainDefPtr def,
- unsigned long memory);
-int xenDaemonDomainGetInfo(virConnectPtr conn,
- virDomainDefPtr def,
- virDomainInfoPtr info);
-int xenDaemonDomainGetState(virConnectPtr conn,
- virDomainDefPtr def,
- int *state,
- int *reason);
-virDomainDefPtr xenDaemonDomainGetXMLDesc(virConnectPtr conn,
- virDomainDefPtr def,
- const char *cpus);
-unsigned long long xenDaemonDomainGetMaxMemory(virConnectPtr conn,
- virDomainDefPtr def);
-char **xenDaemonListDomainsOld(virConnectPtr xend);
-
-char *xenDaemonDomainGetOSType(virConnectPtr conn,
- virDomainDefPtr def);
-
-int xenDaemonNumOfDefinedDomains(virConnectPtr conn);
-int xenDaemonListDefinedDomains(virConnectPtr conn,
- char **const names,
- int maxnames);
-
-int xenDaemonAttachDeviceFlags(virConnectPtr conn,
- virDomainDefPtr def,
- const char *xml,
- unsigned int flags);
-int xenDaemonDetachDeviceFlags(virConnectPtr conn,
- virDomainDefPtr def,
- const char *xml,
- unsigned int flags);
-
-int xenDaemonDomainDefineXML(virConnectPtr conn,
- virDomainDefPtr def);
-int xenDaemonDomainCreate(virConnectPtr conn,
- virDomainDefPtr def);
-int xenDaemonDomainUndefine(virConnectPtr conn,
- virDomainDefPtr def);
-
-int xenDaemonDomainSetVcpus (virConnectPtr conn,
- virDomainDefPtr def,
- unsigned int vcpus);
-int xenDaemonDomainSetVcpusFlags (virConnectPtr conn,
- virDomainDefPtr def,
- unsigned int vcpus,
- unsigned int flags);
-int xenDaemonDomainPinVcpu (virConnectPtr conn,
- virDomainDefPtr def,
- unsigned int vcpu,
- unsigned char *cpumap,
- int maplen);
-int xenDaemonDomainGetVcpusFlags (virConnectPtr conn,
- virDomainDefPtr def,
- unsigned int flags);
-int xenDaemonDomainGetVcpus (virConnectPtr conn,
- virDomainDefPtr def,
- virVcpuInfoPtr info,
- int maxinfo,
- unsigned char *cpumaps,
- int maplen);
-int xenDaemonUpdateDeviceFlags(virConnectPtr conn,
- virDomainDefPtr def,
- const char *xml,
- unsigned int flags);
-int xenDaemonDomainGetAutostart(virConnectPtr conn,
- virDomainDefPtr def,
- int *autostart);
-int xenDaemonDomainSetAutostart(virConnectPtr conn,
- virDomainDefPtr def,
- int autostart);
-
-int xenDaemonCreateXML(virConnectPtr conn, virDomainDefPtr def);
-virDomainDefPtr xenDaemonLookupByUUID(virConnectPtr conn, const unsigned char *uuid);
-virDomainDefPtr xenDaemonLookupByName(virConnectPtr conn, const char *domname);
-int xenDaemonDomainMigratePrepare (virConnectPtr dconn,
- char **cookie, int *cookielen,
- const char *uri_in, char **uri_out,
- unsigned long flags, const char *dname, unsigned long resource);
-int xenDaemonDomainMigratePerform (virConnectPtr conn,
- virDomainDefPtr def,
- const char *cookie, int cookielen,
- const char *uri, unsigned long flags,
- const char *dname, unsigned long resource);
-
-int xenDaemonDomainBlockPeek(virConnectPtr conn,
- virDomainDefPtr def,
- const char *path,
- unsigned long long offset,
- size_t size,
- void *buffer);
-
-char * xenDaemonGetSchedulerType(virConnectPtr conn,
- int *nparams);
-int xenDaemonGetSchedulerParameters(virConnectPtr conn,
- virDomainDefPtr def,
- virTypedParameterPtr params,
- int *nparams);
-int xenDaemonSetSchedulerParameters(virConnectPtr conn,
- virDomainDefPtr def,
- virTypedParameterPtr params,
- int nparams);
-
-#endif /* __XEND_INTERNAL_H_ */
+++ /dev/null
-/*
- * xm_internal.c: helper routines for dealing with inactive domains
- *
- * Copyright (C) 2006-2007, 2009-2014 Red Hat, Inc.
- * Copyright (C) 2006 Daniel P. Berrange
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * Author: Daniel P. Berrange <berrange@redhat.com>
- *
- */
-
-#include <config.h>
-
-#include <dirent.h>
-#include <time.h>
-#include <sys/stat.h>
-#include <limits.h>
-#include <string.h>
-#include <errno.h>
-
-#include <unistd.h>
-#include <stdint.h>
-#include <xen/dom0_ops.h>
-
-#include "virerror.h"
-#include "virfile.h"
-#include "datatypes.h"
-#include "xm_internal.h"
-#include "xen_driver.h"
-#include "xend_internal.h"
-#include "xen_sxpr.h"
-#include "xen_xm.h"
-#include "virhash.h"
-#include "virbuffer.h"
-#include "viruuid.h"
-#include "viralloc.h"
-#include "virlog.h"
-#include "count-one-bits.h"
-#include "virstring.h"
-
-#define VIR_FROM_THIS VIR_FROM_XENXM
-
-VIR_LOG_INIT("xen.xm_internal");
-
-#define XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU 3
-#define XEND_CONFIG_MIN_VERS_PVFB_NEWCONF 3
-
-/* The true Xen limit varies but so far is always way
- less than 1024, which is the Linux kernel limit according
- to sched.h, so we'll match that for now */
-#define XEN_MAX_PHYSICAL_CPU 1024
-
-char * xenXMAutoAssignMac(void);
-
-#define XM_REFRESH_INTERVAL 10
-
-#define XM_CONFIG_DIR "/etc/xen"
-#define XM_EXAMPLE_PREFIX "xmexample"
-#define XEND_CONFIG_FILE "xend-config.sxp"
-#define XEND_PCI_CONFIG_PREFIX "xend-pci-"
-#define QEMU_IF_SCRIPT "qemu-ifup"
-#define XM_XML_ERROR "Invalid xml"
-
-#ifndef WITH_XEN_INOTIFY
-static int xenInotifyActive(virConnectPtr conn ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-#else
-static int xenInotifyActive(virConnectPtr conn)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- return priv->inotifyWatch > 0;
-}
-#endif
-
-
-/* Release memory associated with a cached config object */
-static void xenXMConfigFree(void *payload, const void *key ATTRIBUTE_UNUSED)
-{
- xenXMConfCachePtr entry = (xenXMConfCachePtr)payload;
- virDomainDefFree(entry->def);
- VIR_FREE(entry->filename);
- VIR_FREE(entry);
-}
-
-struct xenXMConfigReaperData {
- xenUnifiedPrivatePtr priv;
- time_t now;
-};
-
-/* Remove any configs which were not refreshed recently */
-static int
-xenXMConfigReaper(const void *payload,
- const void *key ATTRIBUTE_UNUSED,
- const void *data)
-{
- const struct xenXMConfigReaperData *args = data;
- xenXMConfCachePtr entry = (xenXMConfCachePtr)payload;
-
- /* We're going to purge this config file, so check if it
- is currently mapped as owner of a named domain. */
- if (entry->refreshedAt != args->now) {
- const char *olddomname = entry->def->name;
- char *nameowner = (char *)virHashLookup(args->priv->nameConfigMap, olddomname);
- if (nameowner && STREQ(nameowner, key))
- virHashRemoveEntry(args->priv->nameConfigMap, olddomname);
- return 1;
- }
- return 0;
-}
-
-
-static virDomainDefPtr
-xenXMConfigReadFile(virConnectPtr conn, const char *filename)
-{
- virConfPtr conf;
- virDomainDefPtr def;
- xenUnifiedPrivatePtr priv = conn->privateData;
-
- if (!(conf = virConfReadFile(filename, 0)))
- return NULL;
-
- def = xenParseXM(conf, priv->caps, priv->xmlopt);
- virConfFree(conf);
-
- return def;
-}
-
-static int
-xenXMConfigSaveFile(virConnectPtr conn,
- const char *filename,
- virDomainDefPtr def)
-{
- virConfPtr conf;
- int ret;
-
- if (!(conf = xenFormatXM(conn, def)))
- return -1;
-
- ret = virConfWriteFile(filename, conf);
- virConfFree(conf);
- return ret;
-}
-
-
-/*
- * Caller must hold the lock on 'conn->privateData' before
- * calling this function
- */
-int
-xenXMConfigCacheRemoveFile(virConnectPtr conn, const char *filename)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- xenXMConfCachePtr entry;
-
- entry = virHashLookup(priv->configCache, filename);
- if (!entry) {
- VIR_DEBUG("No config entry for %s", filename);
- return 0;
- }
-
- virHashRemoveEntry(priv->nameConfigMap, entry->def->name);
- virHashRemoveEntry(priv->configCache, filename);
- VIR_DEBUG("Removed %s %s", entry->def->name, filename);
- return 0;
-}
-
-
-/*
- * Caller must hold the lock on 'conn->privateData' before
- * calling this function
- */
-int
-xenXMConfigCacheAddFile(virConnectPtr conn, const char *filename, time_t now)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- xenXMConfCachePtr entry;
- struct stat st;
- int newborn = 0;
-
- VIR_DEBUG("Adding file %s %lld", filename, (long long)now);
-
- /* Get modified time */
- if ((stat(filename, &st) < 0)) {
- virReportSystemError(errno,
- _("cannot stat: %s"),
- filename);
- return -1;
- }
-
- /* Ignore zero length files, because inotify fires before
- any content has actually been created */
- if (st.st_size == 0) {
- VIR_DEBUG("Ignoring zero length file %s", filename);
- return -1;
- }
-
- /* If we already have a matching entry and it is not
- modified, then carry on to next one*/
- if ((entry = virHashLookup(priv->configCache, filename))) {
- char *nameowner;
-
- if (entry->refreshedAt >= st.st_mtime) {
- entry->refreshedAt = now;
- /* return success if up-to-date */
- return 0;
- }
-
- /* If we currently own the name, then release it and
- re-acquire it later - just in case it was renamed */
- nameowner = (char *)virHashLookup(priv->nameConfigMap, entry->def->name);
- if (nameowner && STREQ(nameowner, filename))
- virHashRemoveEntry(priv->nameConfigMap, entry->def->name);
-
- /* Clear existing config entry which needs refresh */
- virDomainDefFree(entry->def);
- entry->def = NULL;
- } else { /* Completely new entry */
- newborn = 1;
- if (VIR_ALLOC(entry) < 0)
- return -1;
- if (VIR_STRDUP(entry->filename, filename) < 0) {
- VIR_FREE(entry);
- return -1;
- }
- }
- entry->refreshedAt = now;
-
- if (!(entry->def = xenXMConfigReadFile(conn, entry->filename))) {
- VIR_DEBUG("Failed to read %s", entry->filename);
- if (!newborn)
- virHashSteal(priv->configCache, filename);
- VIR_FREE(entry->filename);
- VIR_FREE(entry);
- return -1;
- }
-
- /* If its a completely new entry, it must be stuck into
- the cache (refresh'd entries are already registered) */
- if (newborn) {
- if (virHashAddEntry(priv->configCache, entry->filename, entry) < 0) {
- virDomainDefFree(entry->def);
- VIR_FREE(entry->filename);
- VIR_FREE(entry);
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("xenXMConfigCacheRefresh: virHashAddEntry"));
- return -1;
- }
- }
-
- /* See if we need to map this config file in as the primary owner
- * of the domain in question
- */
- if (!virHashLookup(priv->nameConfigMap, entry->def->name)) {
- if (virHashAddEntry(priv->nameConfigMap, entry->def->name,
- entry->filename) < 0) {
- virHashSteal(priv->configCache, filename);
- virDomainDefFree(entry->def);
- VIR_FREE(entry->filename);
- VIR_FREE(entry);
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("xenXMConfigCacheRefresh: virHashAddEntry name"));
- return -1;
- }
- }
- VIR_DEBUG("Added config %s %s", entry->def->name, filename);
-
- return 0;
-}
-
-/* This method is called by various methods to scan /etc/xen
- * (or whatever directory was set by LIBVIRT_XM_CONFIG_DIR
- * environment variable) and process any domain configs. It
- * has rate-limited so never rescans more frequently than
- * once every X seconds
- *
- * Caller must hold the lock on 'conn->privateData' before
- * calling this function
- */
-int
-xenXMConfigCacheRefresh(virConnectPtr conn)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- DIR *dh;
- struct dirent *ent;
- time_t now = time(NULL);
- int ret = -1;
- struct xenXMConfigReaperData args;
-
- if (now == ((time_t)-1)) {
- virReportSystemError(errno,
- "%s", _("cannot get time of day"));
- return -1;
- }
-
- /* Rate limit re-scans */
- if ((now - priv->lastRefresh) < XM_REFRESH_INTERVAL)
- return 0;
-
- priv->lastRefresh = now;
-
- /* Process the files in the config dir */
- if (virDirOpen(&dh, priv->configDir) < 0)
- return -1;
-
- while ((ret = virDirRead(dh, &ent, priv->configDir)) > 0) {
- struct stat st;
- char *path;
-
- /*
- * Skip a bunch of crufty files that clearly aren't config files
- */
-
- /* Like 'dot' files... */
- if (STRPREFIX(ent->d_name, "."))
- continue;
- /* ...and the XenD server config file */
- if (STRPREFIX(ent->d_name, XEND_CONFIG_FILE))
- continue;
- /* ...and random PCI config cruft */
- if (STRPREFIX(ent->d_name, XEND_PCI_CONFIG_PREFIX))
- continue;
- /* ...and the example domain configs */
- if (STRPREFIX(ent->d_name, XM_EXAMPLE_PREFIX))
- continue;
- /* ...and the QEMU networking script */
- if (STRPREFIX(ent->d_name, QEMU_IF_SCRIPT))
- continue;
-
- /* ...and editor backups */
- if (ent->d_name[0] == '#')
- continue;
- if (ent->d_name[strlen(ent->d_name)-1] == '~')
- continue;
-
- /* Build the full file path */
- if (!(path = virFileBuildPath(priv->configDir, ent->d_name, NULL))) {
- VIR_DIR_CLOSE(dh);
- return -1;
- }
-
- /* Skip anything which isn't a file (takes care of scripts/ subdir */
- if ((stat(path, &st) < 0) ||
- (!S_ISREG(st.st_mode))) {
- VIR_FREE(path);
- continue;
- }
-
- /* If we already have a matching entry and it is not
- modified, then carry on to next one*/
- if (xenXMConfigCacheAddFile(conn, path, now) < 0) {
- /* Ignoring errors, since a lot of stuff goes wrong in /etc/xen */
- }
-
- VIR_FREE(path);
- }
-
- /* Reap all entries which were not changed, by comparing
- their refresh timestamp - the timestamp should match
- 'now' if they were refreshed. If timestamp doesn't match
- then the config is no longer on disk */
- args.now = now;
- args.priv = priv;
- virHashRemoveSet(priv->configCache, xenXMConfigReaper, &args);
-
- VIR_DIR_CLOSE(dh);
-
- return ret;
-}
-
-
-/*
- * The XM driver keeps a cache of config files as virDomainDefPtr
- * objects in the xenUnifiedPrivatePtr. Optionally inotify lets
- * us watch for changes (see separate driver), otherwise we poll
- * every few seconds
- */
-int
-xenXMOpen(virConnectPtr conn,
- virConnectAuthPtr auth ATTRIBUTE_UNUSED,
- unsigned int flags)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
-
- virCheckFlags(VIR_CONNECT_RO, -1);
-
- priv->configDir = XM_CONFIG_DIR;
-
- priv->configCache = virHashCreate(50, xenXMConfigFree);
- if (!priv->configCache)
- return -1;
- priv->nameConfigMap = virHashCreate(50, NULL);
- if (!priv->nameConfigMap) {
- virHashFree(priv->configCache);
- priv->configCache = NULL;
- return -1;
- }
- /* Force the cache to be reloaded next time that
- * xenXMConfigCacheRefresh is called.
- */
- priv->lastRefresh = 0;
-
- return 0;
-}
-
-/*
- * Free the cached config files associated with this
- * connection
- */
-int
-xenXMClose(virConnectPtr conn)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
-
- virHashFree(priv->nameConfigMap);
- virHashFree(priv->configCache);
-
- return 0;
-}
-
-/*
- * Since these are all offline domains, the state is always SHUTOFF.
- */
-int
-xenXMDomainGetState(virConnectPtr conn ATTRIBUTE_UNUSED,
- virDomainDefPtr def ATTRIBUTE_UNUSED,
- int *state,
- int *reason)
-{
- *state = VIR_DOMAIN_SHUTOFF;
- if (reason)
- *reason = 0;
-
- return 0;
-}
-
-
-/*
- * Since these are all offline domains, we only return info about
- * VCPUs and memory.
- */
-int
-xenXMDomainGetInfo(virConnectPtr conn,
- virDomainDefPtr def,
- virDomainInfoPtr info)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- const char *filename;
- xenXMConfCachePtr entry;
-
- xenUnifiedLock(priv);
-
- if (!(filename = virHashLookup(priv->nameConfigMap, def->name)))
- goto error;
-
- if (!(entry = virHashLookup(priv->configCache, filename)))
- goto error;
-
- memset(info, 0, sizeof(virDomainInfo));
- info->maxMem = virDomainDefGetMemoryTotal(entry->def);
- info->memory = entry->def->mem.cur_balloon;
- info->nrVirtCpu = virDomainDefGetVcpus(entry->def);
- info->state = VIR_DOMAIN_SHUTOFF;
- info->cpuTime = 0;
-
- xenUnifiedUnlock(priv);
- return 0;
-
- error:
- xenUnifiedUnlock(priv);
- return -1;
-}
-
-
-/*
- * Turn a config record into a lump of XML describing the
- * domain, suitable for later feeding for virDomainCreateXML
- */
-virDomainDefPtr
-xenXMDomainGetXMLDesc(virConnectPtr conn,
- virDomainDefPtr def)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- const char *filename;
- xenXMConfCachePtr entry;
- virDomainDefPtr ret = NULL;
-
- /* Flags checked by virDomainDefFormat */
-
- xenUnifiedLock(priv);
-
- if (!(filename = virHashLookup(priv->nameConfigMap, def->name)))
- goto cleanup;
-
- if (!(entry = virHashLookup(priv->configCache, filename)))
- goto cleanup;
-
- ret = virDomainDefCopy(entry->def,
- priv->caps,
- priv->xmlopt,
- NULL,
- false);
-
- cleanup:
- xenUnifiedUnlock(priv);
- return ret;
-}
-
-
-/*
- * Update amount of memory in the config file
- */
-int
-xenXMDomainSetMemory(virConnectPtr conn,
- virDomainDefPtr def,
- unsigned long memory)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- const char *filename;
- xenXMConfCachePtr entry;
- int ret = -1;
-
- if (memory < 1024 * MIN_XEN_GUEST_SIZE) {
- virReportError(VIR_ERR_INVALID_ARG,
- _("Memory %lu too small, min %lu"),
- memory, (unsigned long)1024 * MIN_XEN_GUEST_SIZE);
- return -1;
- }
-
- xenUnifiedLock(priv);
-
- if (!(filename = virHashLookup(priv->nameConfigMap, def->name)))
- goto cleanup;
-
- if (!(entry = virHashLookup(priv->configCache, filename)))
- goto cleanup;
-
- entry->def->mem.cur_balloon = memory;
- if (entry->def->mem.cur_balloon > virDomainDefGetMemoryTotal(entry->def))
- entry->def->mem.cur_balloon = virDomainDefGetMemoryTotal(entry->def);
-
- /* If this fails, should we try to undo our changes to the
- * in-memory representation of the config file. I say not!
- */
- if (xenXMConfigSaveFile(conn, entry->filename, entry->def) < 0)
- goto cleanup;
- ret = 0;
-
- cleanup:
- xenUnifiedUnlock(priv);
- return ret;
-}
-
-/*
- * Update maximum memory limit in config
- */
-int
-xenXMDomainSetMaxMemory(virConnectPtr conn,
- virDomainDefPtr def,
- unsigned long memory)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- const char *filename;
- xenXMConfCachePtr entry;
- int ret = -1;
-
- if (memory < 1024 * MIN_XEN_GUEST_SIZE) {
- virReportError(VIR_ERR_INVALID_ARG,
- _("Memory %lu too small, min %lu"),
- memory, (unsigned long)1024 * MIN_XEN_GUEST_SIZE);
- return -1;
- }
-
- xenUnifiedLock(priv);
-
- if (!(filename = virHashLookup(priv->nameConfigMap, def->name)))
- goto cleanup;
-
- if (!(entry = virHashLookup(priv->configCache, filename)))
- goto cleanup;
-
- if (entry->def->mem.cur_balloon > memory)
- entry->def->mem.cur_balloon = memory;
-
- virDomainDefSetMemoryTotal(entry->def, memory);
- /* If this fails, should we try to undo our changes to the
- * in-memory representation of the config file. I say not!
- */
- if (xenXMConfigSaveFile(conn, entry->filename, entry->def) < 0)
- goto cleanup;
- ret = 0;
-
- cleanup:
- xenUnifiedUnlock(priv);
- return ret;
-}
-
-/*
- * Get max memory limit from config
- */
-unsigned long long
-xenXMDomainGetMaxMemory(virConnectPtr conn,
- virDomainDefPtr def)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- const char *filename;
- xenXMConfCachePtr entry;
- unsigned long long ret = 0;
-
- xenUnifiedLock(priv);
-
- if (!(filename = virHashLookup(priv->nameConfigMap, def->name)))
- goto cleanup;
-
- if (!(entry = virHashLookup(priv->configCache, filename)))
- goto cleanup;
-
- ret = virDomainDefGetMemoryTotal(entry->def);
-
- cleanup:
- xenUnifiedUnlock(priv);
- return ret;
-}
-
-/*
- * xenXMDomainSetVcpusFlags:
- * @conn: the connection object
- * @def: domain configuration
- * @nvcpus: number of vcpus
- * @flags: bitwise-ORd from virDomainVcpuFlags
- *
- * Change virtual CPUs allocation of domain according to flags.
- *
- * Returns 0 on success, -1 if an error message was issued
- */
-int
-xenXMDomainSetVcpusFlags(virConnectPtr conn,
- virDomainDefPtr def,
- unsigned int vcpus,
- unsigned int flags)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- const char *filename;
- xenXMConfCachePtr entry;
- int ret = -1;
- int max;
-
- virCheckFlags(VIR_DOMAIN_VCPU_LIVE |
- VIR_DOMAIN_VCPU_CONFIG |
- VIR_DOMAIN_VCPU_MAXIMUM, -1);
-
- if (flags & VIR_DOMAIN_VCPU_LIVE) {
- virReportError(VIR_ERR_OPERATION_INVALID, "%s",
- _("domain is not running"));
- return -1;
- }
-
- xenUnifiedLock(priv);
-
- if (!(filename = virHashLookup(priv->nameConfigMap, def->name)))
- goto cleanup;
-
- if (!(entry = virHashLookup(priv->configCache, filename)))
- goto cleanup;
-
- /* Hypervisor maximum. */
- if ((max = xenUnifiedConnectGetMaxVcpus(conn, NULL)) < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("could not determine max vcpus for the domain"));
- goto cleanup;
- }
- /* Can't specify a current larger than stored maximum; but
- * reducing maximum can silently reduce current. */
- if (!(flags & VIR_DOMAIN_VCPU_MAXIMUM))
- max = virDomainDefGetVcpusMax(entry->def);
-
- if (vcpus > max) {
- virReportError(VIR_ERR_INVALID_ARG,
- _("requested vcpus is greater than max allowable"
- " vcpus for the domain: %d > %d"), vcpus, max);
- goto cleanup;
- }
-
- if (flags & VIR_DOMAIN_VCPU_MAXIMUM) {
- if (virDomainDefSetVcpusMax(entry->def, vcpus, priv->xmlopt) < 0)
- goto cleanup;
- } else {
- if (virDomainDefSetVcpus(entry->def, vcpus) < 0)
- goto cleanup;
- }
-
- /* If this fails, should we try to undo our changes to the
- * in-memory representation of the config file. I say not!
- */
- if (xenXMConfigSaveFile(conn, entry->filename, entry->def) < 0)
- goto cleanup;
- ret = 0;
-
- cleanup:
- xenUnifiedUnlock(priv);
- return ret;
-}
-
-/**
- * xenXMDomainGetVcpusFlags:
- * @conn: the connection object
- * @def: domain configuration
- * @flags: bitwise-ORd from virDomainVcpuFlags
- *
- * Extract information about virtual CPUs of domain according to flags.
- *
- * Returns the number of vcpus on success, -1 if an error message was
- * issued
- */
-int
-xenXMDomainGetVcpusFlags(virConnectPtr conn,
- virDomainDefPtr def,
- unsigned int flags)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- const char *filename;
- xenXMConfCachePtr entry;
- int ret = -1;
-
- virCheckFlags(VIR_DOMAIN_VCPU_LIVE |
- VIR_DOMAIN_VCPU_CONFIG |
- VIR_DOMAIN_VCPU_MAXIMUM, -1);
-
- if (flags & VIR_DOMAIN_VCPU_LIVE) {
- virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("domain not active"));
- return -1;
- }
-
- xenUnifiedLock(priv);
-
- if (!(filename = virHashLookup(priv->nameConfigMap, def->name)))
- goto cleanup;
-
- if (!(entry = virHashLookup(priv->configCache, filename)))
- goto cleanup;
-
- if (flags & VIR_DOMAIN_VCPU_MAXIMUM)
- ret = virDomainDefGetVcpusMax(entry->def);
- else
- ret = virDomainDefGetVcpus(entry->def);
-
- cleanup:
- xenUnifiedUnlock(priv);
- return ret;
-}
-
-/**
- * xenXMDomainPinVcpu:
- * @conn: the connection object
- * @def: domain configuration
- * @vcpu: virtual CPU number (reserved)
- * @cpumap: pointer to a bit map of real CPUs (in 8-bit bytes)
- * @maplen: length of cpumap in bytes
- *
- * Set the vcpu affinity in config
- *
- * Returns 0 for success; -1 (with errno) on error
- */
-int
-xenXMDomainPinVcpu(virConnectPtr conn,
- virDomainDefPtr def,
- unsigned int vcpu ATTRIBUTE_UNUSED,
- unsigned char *cpumap,
- int maplen)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- const char *filename;
- xenXMConfCachePtr entry;
- int ret = -1;
-
- if (maplen > (int)sizeof(cpumap_t)) {
- virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
- return -1;
- }
-
- xenUnifiedLock(priv);
-
- if (!(filename = virHashLookup(priv->nameConfigMap, def->name))) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("virHashLookup"));
- goto cleanup;
- }
- if (!(entry = virHashLookup(priv->configCache, filename))) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("can't retrieve config file for domain"));
- goto cleanup;
- }
-
- virBitmapFree(entry->def->cpumask);
- entry->def->cpumask = virBitmapNewData(cpumap, maplen);
- if (!entry->def->cpumask)
- goto cleanup;
- if (xenXMConfigSaveFile(conn, entry->filename, entry->def) < 0)
- goto cleanup;
-
- ret = 0;
-
- cleanup:
- xenUnifiedUnlock(priv);
- return ret;
-}
-
-/*
- * Find an inactive domain based on its name
- */
-virDomainDefPtr
-xenXMDomainLookupByName(virConnectPtr conn, const char *domname)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- const char *filename;
- xenXMConfCachePtr entry;
- virDomainDefPtr ret = NULL;
-
- xenUnifiedLock(priv);
-
- if (!xenInotifyActive(conn) && xenXMConfigCacheRefresh(conn) < 0)
- goto cleanup;
-
- if (!(filename = virHashLookup(priv->nameConfigMap, domname)))
- goto cleanup;
-
- if (!(entry = virHashLookup(priv->configCache, filename)))
- goto cleanup;
-
- ret = virDomainDefNewFull(domname, entry->def->uuid, -1);
-
- cleanup:
- xenUnifiedUnlock(priv);
- return ret;
-}
-
-
-/*
- * Hash table iterator to search for a domain based on UUID
- */
-static int
-xenXMDomainSearchForUUID(const void *payload,
- const void *name ATTRIBUTE_UNUSED,
- const void *data)
-{
- const unsigned char *wantuuid = data;
- const xenXMConfCache *entry = payload;
-
- if (!memcmp(entry->def->uuid, wantuuid, VIR_UUID_BUFLEN))
- return 1;
-
- return 0;
-}
-
-/*
- * Find an inactive domain based on its UUID
- */
-virDomainDefPtr
-xenXMDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- xenXMConfCachePtr entry;
- virDomainDefPtr ret = NULL;
-
- xenUnifiedLock(priv);
-
- if (!xenInotifyActive(conn) && xenXMConfigCacheRefresh(conn) < 0)
- goto cleanup;
-
- if (!(entry = virHashSearch(priv->configCache, xenXMDomainSearchForUUID,
- (const void *)uuid, NULL)))
- goto cleanup;
-
- ret = virDomainDefNewFull(entry->def->name, uuid, -1);
-
- cleanup:
- xenUnifiedUnlock(priv);
- return ret;
-}
-
-
-/*
- * Start a domain from an existing defined config file
- */
-int
-xenXMDomainCreate(virConnectPtr conn,
- virDomainDefPtr def)
-{
- char *sexpr;
- int ret = -1;
- xenUnifiedPrivatePtr priv = conn->privateData;
- const char *filename;
- xenXMConfCachePtr entry = NULL;
-
- xenUnifiedLock(priv);
-
- if (!(filename = virHashLookup(priv->nameConfigMap, def->name)))
- goto error;
-
- if (!(entry = virHashLookup(priv->configCache, filename)))
- goto error;
-
- if (!(sexpr = xenFormatSxpr(conn, entry->def)))
- goto error;
-
- ret = xenDaemonDomainCreateXML(conn, sexpr);
- VIR_FREE(sexpr);
- if (ret != 0)
- goto error;
-
- if ((ret = xenDaemonDomainLookupByName_ids(conn, def->name,
- entry->def->uuid)) < 0)
- goto error;
- def->id = ret;
-
- if (xend_wait_for_devices(conn, def->name) < 0)
- goto error;
-
- if (xenDaemonDomainResume(conn, entry->def) < 0)
- goto error;
-
- xenUnifiedUnlock(priv);
- return 0;
-
- error:
- if (def->id != -1 && entry) {
- xenDaemonDomainDestroy(conn, entry->def);
- def->id = -1;
- }
- xenUnifiedUnlock(priv);
- return -1;
-}
-
-/*
- * Create a config file for a domain, based on an XML
- * document describing its config
- */
-int
-xenXMDomainDefineXML(virConnectPtr conn, virDomainDefPtr def)
-{
- char *filename = NULL;
- const char *oldfilename;
- virConfPtr conf = NULL;
- xenXMConfCachePtr entry = NULL;
- xenUnifiedPrivatePtr priv = conn->privateData;
-
- xenUnifiedLock(priv);
-
- if (!xenInotifyActive(conn) && xenXMConfigCacheRefresh(conn) < 0) {
- xenUnifiedUnlock(priv);
- return -1;
- }
-
- if (!(conf = xenFormatXM(conn, def)))
- goto error;
-
- /*
- * check that if there is another domain defined with the same uuid
- * it has the same name
- */
- if ((entry = virHashSearch(priv->configCache, xenXMDomainSearchForUUID,
- (const void *)&(def->uuid), NULL)) != NULL) {
- if ((entry->def != NULL) && (entry->def->name != NULL) &&
- (STRNEQ(def->name, entry->def->name))) {
- char uuidstr[VIR_UUID_STRING_BUFLEN];
-
- virUUIDFormat(entry->def->uuid, uuidstr);
- virReportError(VIR_ERR_OPERATION_FAILED,
- _("domain '%s' is already defined with uuid %s"),
- entry->def->name, uuidstr);
- entry = NULL;
- goto error;
- }
- entry = NULL;
- }
-
- if (virHashLookup(priv->nameConfigMap, def->name)) {
- /* domain exists, we will overwrite it */
-
- if (!(oldfilename = (char *)virHashLookup(priv->nameConfigMap, def->name))) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("can't retrieve config filename for domain to overwrite"));
- goto error;
- }
-
- if (!(entry = virHashLookup(priv->configCache, oldfilename))) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("can't retrieve config entry for domain to overwrite"));
- goto error;
- }
-
- /* Remove the name -> filename mapping */
- if (virHashRemoveEntry(priv->nameConfigMap, def->name) < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("failed to remove old domain from config map"));
- goto error;
- }
-
- /* Remove the config record itself */
- if (virHashRemoveEntry(priv->configCache, oldfilename) < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("failed to remove old domain from config map"));
- goto error;
- }
-
- entry = NULL;
- }
-
- if (!(filename = virFileBuildPath(priv->configDir, def->name, NULL)))
- goto error;
-
- if (virConfWriteFile(filename, conf) < 0)
- goto error;
-
- if (VIR_ALLOC(entry) < 0)
- goto error;
-
- if ((entry->refreshedAt = time(NULL)) == ((time_t)-1)) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("unable to get current time"));
- goto error;
- }
-
- if (VIR_STRDUP(entry->filename, filename) < 0)
- goto error;
- entry->def = def;
-
- if (virHashAddEntry(priv->configCache, filename, entry) < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("unable to store config file handle"));
- goto error;
- }
-
- if (virHashAddEntry(priv->nameConfigMap, def->name, entry->filename) < 0) {
- virHashSteal(priv->configCache, filename);
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("unable to store config file handle"));
- goto error;
- }
-
- xenUnifiedUnlock(priv);
- VIR_FREE(filename);
- return 0;
-
- error:
- VIR_FREE(filename);
- if (entry)
- VIR_FREE(entry->filename);
- VIR_FREE(entry);
- virConfFree(conf);
- xenUnifiedUnlock(priv);
- return -1;
-}
-
-/*
- * Delete a domain from disk
- */
-int
-xenXMDomainUndefine(virConnectPtr conn,
- virDomainDefPtr def)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- const char *filename;
- xenXMConfCachePtr entry;
- int ret = -1;
-
- xenUnifiedLock(priv);
-
- if (!(filename = virHashLookup(priv->nameConfigMap, def->name)))
- goto cleanup;
-
- if (!(entry = virHashLookup(priv->configCache, filename)))
- goto cleanup;
-
- if (unlink(entry->filename) < 0)
- goto cleanup;
-
- /* Remove the name -> filename mapping */
- if (virHashRemoveEntry(priv->nameConfigMap, def->name) < 0)
- goto cleanup;
-
- /* Remove the config record itself */
- if (virHashRemoveEntry(priv->configCache, entry->filename) < 0)
- goto cleanup;
-
- ret = 0;
-
- cleanup:
- xenUnifiedUnlock(priv);
- return ret;
-}
-
-struct xenXMListIteratorContext {
- virConnectPtr conn;
- int oom;
- int max;
- int count;
- char ** names;
-};
-
-static int
-xenXMListIterator(void *payload ATTRIBUTE_UNUSED,
- const void *name,
- void *data)
-{
- struct xenXMListIteratorContext *ctx = data;
- virDomainDefPtr def = NULL;
-
- if (ctx->oom)
- return 0;
-
- if (ctx->count == ctx->max)
- return 0;
-
- def = xenDaemonLookupByName(ctx->conn, name);
- if (!def) {
- if (VIR_STRDUP(ctx->names[ctx->count], name) < 0)
- ctx->oom = 1;
- else
- ctx->count++;
- } else {
- virDomainDefFree(def);
- }
- return 0;
-}
-
-
-/*
- * List all defined domains, filtered to remove any which
- * are currently running
- */
-int
-xenXMListDefinedDomains(virConnectPtr conn, char **const names, int maxnames)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- struct xenXMListIteratorContext ctx;
- size_t i;
- int ret = -1;
-
- xenUnifiedLock(priv);
-
- if (!xenInotifyActive(conn) && xenXMConfigCacheRefresh(conn) < 0)
- goto cleanup;
-
- if (maxnames > virHashSize(priv->configCache))
- maxnames = virHashSize(priv->configCache);
-
- ctx.conn = conn;
- ctx.oom = 0;
- ctx.count = 0;
- ctx.max = maxnames;
- ctx.names = names;
-
- virHashForEach(priv->nameConfigMap, xenXMListIterator, &ctx);
-
- if (ctx.oom) {
- for (i = 0; i < ctx.count; i++)
- VIR_FREE(ctx.names[i]);
- goto cleanup;
- }
-
- ret = ctx.count;
-
- cleanup:
- xenUnifiedUnlock(priv);
- return ret;
-}
-
-/*
- * Return the maximum number of defined domains - not filtered
- * based on number running
- */
-int
-xenXMNumOfDefinedDomains(virConnectPtr conn)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- int ret = -1;
-
- xenUnifiedLock(priv);
-
- if (!xenInotifyActive(conn) && xenXMConfigCacheRefresh(conn) < 0)
- goto cleanup;
-
- ret = virHashSize(priv->nameConfigMap);
-
- cleanup:
- xenUnifiedUnlock(priv);
- return ret;
-}
-
-
-/**
- * xenXMDomainAttachDeviceFlags:
- * @conn: the connection object
- * @minidef: domain configuration
- * @xml: pointer to XML description of device
- * @flags: an OR'ed set of virDomainDeviceModifyFlags
- *
- * Create a virtual device attachment to backend.
- * XML description is translated into config file.
- * This driver only supports device allocation to
- * persisted config.
- *
- * Returns 0 in case of success, -1 in case of failure.
- */
-int
-xenXMDomainAttachDeviceFlags(virConnectPtr conn,
- virDomainDefPtr minidef,
- const char *xml,
- unsigned int flags)
-{
- const char *filename = NULL;
- xenXMConfCachePtr entry = NULL;
- int ret = -1;
- virDomainDeviceDefPtr dev = NULL;
- virDomainDefPtr def;
- xenUnifiedPrivatePtr priv = conn->privateData;
-
- virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1);
-
- if ((flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) ||
- (minidef->id != -1 && flags == VIR_DOMAIN_DEVICE_MODIFY_CURRENT)) {
- virReportError(VIR_ERR_OPERATION_INVALID, "%s",
- _("Xm driver only supports modifying persistent config"));
- return -1;
- }
-
- xenUnifiedLock(priv);
-
- if (!(filename = virHashLookup(priv->nameConfigMap, minidef->name)))
- goto cleanup;
- if (!(entry = virHashLookup(priv->configCache, filename)))
- goto cleanup;
- def = entry->def;
-
- if (!(dev = virDomainDeviceDefParse(xml, entry->def,
- priv->caps,
- priv->xmlopt,
- VIR_DOMAIN_DEF_PARSE_INACTIVE)))
- goto cleanup;
-
- switch (dev->type) {
- case VIR_DOMAIN_DEVICE_DISK:
- {
- if (virDomainDiskInsert(def, dev->data.disk) < 0)
- goto cleanup;
- dev->data.disk = NULL;
- }
- break;
-
- case VIR_DOMAIN_DEVICE_NET:
- {
- if (VIR_APPEND_ELEMENT(def->nets, def->nnets, dev->data.net) < 0)
- goto cleanup;
- break;
- }
-
- default:
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("Xm driver only supports adding disk or network devices"));
- goto cleanup;
- }
-
- /* If this fails, should we try to undo our changes to the
- * in-memory representation of the config file. I say not!
- */
- if (xenXMConfigSaveFile(conn, entry->filename, entry->def) < 0)
- goto cleanup;
-
- ret = 0;
-
- cleanup:
- virDomainDeviceDefFree(dev);
- xenUnifiedUnlock(priv);
- return ret;
-}
-
-
-/**
- * xenXMDomainDetachDeviceFlags:
- * @conn: the connection object
- * @minidef: domain configuration
- * @xml: pointer to XML description of device
- * @flags: an OR'ed set of virDomainDeviceModifyFlags
- *
- * Destroy a virtual device attachment to backend.
- * This driver only supports device deallocation from
- * persisted config.
- *
- * Returns 0 in case of success, -1 in case of failure.
- */
-int
-xenXMDomainDetachDeviceFlags(virConnectPtr conn,
- virDomainDefPtr minidef,
- const char *xml,
- unsigned int flags)
-{
- const char *filename = NULL;
- xenXMConfCachePtr entry = NULL;
- virDomainDeviceDefPtr dev = NULL;
- virDomainDefPtr def;
- int ret = -1;
- size_t i;
- xenUnifiedPrivatePtr priv = conn->privateData;
-
- virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1);
-
- if ((flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) ||
- (minidef->id != -1 && flags == VIR_DOMAIN_DEVICE_MODIFY_CURRENT)) {
- virReportError(VIR_ERR_OPERATION_INVALID, "%s",
- _("Xm driver only supports modifying persistent config"));
- return -1;
- }
-
- xenUnifiedLock(priv);
-
- if (!(filename = virHashLookup(priv->nameConfigMap, minidef->name)))
- goto cleanup;
- if (!(entry = virHashLookup(priv->configCache, filename)))
- goto cleanup;
- def = entry->def;
-
- if (!(dev = virDomainDeviceDefParse(xml, entry->def,
- priv->caps,
- priv->xmlopt,
- VIR_DOMAIN_DEF_PARSE_INACTIVE |
- VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE)))
- goto cleanup;
-
- switch (dev->type) {
- case VIR_DOMAIN_DEVICE_DISK:
- {
- for (i = 0; i < def->ndisks; i++) {
- if (def->disks[i]->dst &&
- dev->data.disk->dst &&
- STREQ(def->disks[i]->dst, dev->data.disk->dst)) {
- virDomainDiskDefFree(def->disks[i]);
- VIR_DELETE_ELEMENT(def->disks, i, def->ndisks);
- break;
- }
- }
- break;
- }
-
- case VIR_DOMAIN_DEVICE_NET:
- {
- for (i = 0; i < def->nnets; i++) {
- if (!virMacAddrCmp(&def->nets[i]->mac, &dev->data.net->mac)) {
- virDomainNetDefFree(def->nets[i]);
- VIR_DELETE_ELEMENT(def->nets, i, def->nnets);
- break;
- }
- }
- break;
- }
- default:
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("device type '%s' cannot be detached"),
- virDomainDeviceTypeToString(dev->type));
- goto cleanup;
- }
-
- /* If this fails, should we try to undo our changes to the
- * in-memory representation of the config file. I say not!
- */
- if (xenXMConfigSaveFile(conn, entry->filename, entry->def) < 0)
- goto cleanup;
-
- ret = 0;
-
- cleanup:
- virDomainDeviceDefFree(dev);
- xenUnifiedUnlock(priv);
- return ret;
-}
-
-int
-xenXMDomainBlockPeek(virConnectPtr conn ATTRIBUTE_UNUSED,
- virDomainDefPtr def ATTRIBUTE_UNUSED,
- const char *path ATTRIBUTE_UNUSED,
- unsigned long long offset ATTRIBUTE_UNUSED,
- size_t size ATTRIBUTE_UNUSED,
- void *buffer ATTRIBUTE_UNUSED)
-{
- virReportError(VIR_ERR_OPERATION_INVALID, "%s",
- _("block peeking not implemented"));
- return -1;
-}
-
-
-static char *
-xenXMAutostartLinkName(virDomainDefPtr def)
-{
- char *ret;
- if (virAsprintf(&ret, "/etc/xen/auto/%s", def->name) < 0)
- return NULL;
- return ret;
-}
-
-static char *
-xenXMDomainConfigName(virDomainDefPtr def)
-{
- char *ret;
- if (virAsprintf(&ret, "/etc/xen/%s", def->name) < 0)
- return NULL;
- return ret;
-}
-
-int
-xenXMDomainGetAutostart(virDomainDefPtr def,
- int *autostart)
-{
- char *config = xenXMDomainConfigName(def);
- int ret = -1;
-
- if (!config)
- goto cleanup;
-
- *autostart = virFileRelLinkPointsTo("/etc/xen/auto/", def->name, config);
- if (*autostart < 0) {
- virReportSystemError(errno,
- _("cannot check link /etc/xen/auto/%s points "
- "to config %s"),
- def->name, config);
- goto cleanup;
- }
-
- ret = 0;
-
- cleanup:
- VIR_FREE(config);
- return ret;
-}
-
-
-int
-xenXMDomainSetAutostart(virDomainDefPtr def,
- int autostart)
-{
- char *linkname = xenXMAutostartLinkName(def);
- char *config = xenXMDomainConfigName(def);
- int ret = -1;
-
- if (!linkname || !config)
- goto cleanup;
-
- if (autostart) {
- if (symlink(config, linkname) < 0 &&
- errno != EEXIST) {
- virReportSystemError(errno,
- _("failed to create link %s to %s"),
- config, linkname);
- goto cleanup;
- }
- } else {
- if (unlink(linkname) < 0 &&
- errno != ENOENT) {
- virReportSystemError(errno,
- _("failed to remove link %s"),
- linkname);
- goto cleanup;
- }
- }
- ret = 0;
-
- cleanup:
- VIR_FREE(linkname);
- VIR_FREE(config);
-
- return ret;
-}
+++ /dev/null
-/*
- * xm_internal.h: helper routines for dealing with inactive domains
- *
- * Copyright (C) 2006-2007, 2010-2012 Red Hat, Inc.
- * Copyright (C) 2006 Daniel P. Berrange
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * Author: Daniel P. Berrange <berrange@redhat.com>
- *
- */
-
-#ifndef _LIBVIRT_XM_INTERNAL_H_
-# define _LIBVIRT_XM_INTERNAL_H_
-
-# include "internal.h"
-# include "driver.h"
-# include "virconf.h"
-# include "domain_conf.h"
-
-int xenXMConfigCacheRefresh (virConnectPtr conn);
-int xenXMConfigCacheAddFile(virConnectPtr conn, const char *filename, time_t now);
-int xenXMConfigCacheRemoveFile(virConnectPtr conn, const char *filename);
-
-int xenXMOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags);
-int xenXMClose(virConnectPtr conn);
-const char *xenXMGetType(virConnectPtr conn);
-int xenXMDomainGetInfo(virConnectPtr conn,
- virDomainDefPtr def,
- virDomainInfoPtr info);
-int xenXMDomainGetState(virConnectPtr conn,
- virDomainDefPtr def,
- int *state,
- int *reason);
-virDomainDefPtr xenXMDomainGetXMLDesc(virConnectPtr conn,
- virDomainDefPtr def);
-int xenXMDomainSetMemory(virConnectPtr conn,
- virDomainDefPtr def,
- unsigned long memory);
-int xenXMDomainSetMaxMemory(virConnectPtr conn,
- virDomainDefPtr def,
- unsigned long memory);
-unsigned long long xenXMDomainGetMaxMemory(virConnectPtr conn,
- virDomainDefPtr def);
-int xenXMDomainSetVcpus(virConnectPtr conn,
- virDomainDefPtr def,
- unsigned int vcpus);
-int xenXMDomainSetVcpusFlags(virConnectPtr conn,
- virDomainDefPtr def,
- unsigned int vcpus,
- unsigned int flags);
-int xenXMDomainGetVcpusFlags(virConnectPtr conn,
- virDomainDefPtr def,
- unsigned int flags);
-int xenXMDomainPinVcpu(virConnectPtr conn,
- virDomainDefPtr def,
- unsigned int vcpu,
- unsigned char *cpumap,
- int maplen);
-virDomainDefPtr xenXMDomainLookupByName(virConnectPtr conn, const char *domname);
-virDomainDefPtr xenXMDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid);
-
-int xenXMListDefinedDomains(virConnectPtr conn, char ** const names, int maxnames);
-int xenXMNumOfDefinedDomains(virConnectPtr conn);
-
-int xenXMDomainCreate(virConnectPtr conn,
- virDomainDefPtr def);
-int xenXMDomainDefineXML(virConnectPtr con, virDomainDefPtr def);
-int xenXMDomainUndefine(virConnectPtr conn, virDomainDefPtr def);
-
-int xenXMDomainBlockPeek(virConnectPtr conn,
- virDomainDefPtr def,
- const char *path,
- unsigned long long offset,
- size_t size,
- void *buffer);
-
-int xenXMDomainGetAutostart(virDomainDefPtr def,
- int *autostart);
-int xenXMDomainSetAutostart(virDomainDefPtr def,
- int autostart);
-
-int xenXMDomainAttachDeviceFlags(virConnectPtr conn,
- virDomainDefPtr def,
- const char *xml,
- unsigned int flags);
-
-int xenXMDomainDetachDeviceFlags(virConnectPtr conn,
- virDomainDefPtr def,
- const char *xml,
- unsigned int flags);
-
-#endif
+++ /dev/null
-/*
- * xs_internal.c: access to Xen Store
- *
- * Copyright (C) 2006, 2009-2013 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/>.
- *
- * Daniel Veillard <veillard@redhat.com>
- */
-
-#include <config.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <sys/ioctl.h>
-
-#include <stdint.h>
-
-#include <xen/dom0_ops.h>
-#include <xen/version.h>
-
-#if HAVE_XENSTORE_H
-# include <xenstore.h>
-#else
-# include <xs.h>
-#endif
-
-#include "virerror.h"
-#include "datatypes.h"
-#include "driver.h"
-#include "viralloc.h"
-#include "virlog.h"
-#include "viruuid.h"
-#include "xen_driver.h"
-#include "xs_internal.h"
-#include "xen_hypervisor.h"
-#include "virstring.h"
-
-#define VIR_FROM_THIS VIR_FROM_XENSTORE
-
-VIR_LOG_INIT("xen.xs_internal");
-
-static void xenStoreWatchEvent(int watch, int fd, int events, void *data);
-static void xenStoreWatchListFree(xenStoreWatchListPtr list);
-
-
-/**
- * virDomainDoStoreQuery:
- * @conn: pointer to the hypervisor connection
- * @domid: id of the domain
- * @path: the relative path of the data in the store to retrieve
- *
- * Internal API querying the Xenstore for a string value.
- *
- * Returns a string which must be freed by the caller or NULL in case of error
- */
-static char *
-virDomainDoStoreQuery(virConnectPtr conn, int domid, const char *path)
-{
- char s[256];
- unsigned int len = 0;
- xenUnifiedPrivatePtr priv = conn->privateData;
-
- if (priv->xshandle == NULL)
- return NULL;
-
- snprintf(s, 255, "/local/domain/%d/%s", domid, path);
- s[255] = 0;
-
- return xs_read(priv->xshandle, 0, &s[0], &len);
-}
-
-/**
- * xenStoreOpen:
- * @conn: pointer to the connection block
- * @name: URL for the target, NULL for local
- * @flags: combination of virDrvOpenFlag(s)
- *
- * Connects to the Xen hypervisor.
- *
- * Returns 0 or -1 in case of error.
- */
-int
-xenStoreOpen(virConnectPtr conn,
- virConnectAuthPtr auth ATTRIBUTE_UNUSED,
- unsigned int flags)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
-
- virCheckFlags(VIR_CONNECT_RO, -1);
-
- if (flags & VIR_CONNECT_RO)
- priv->xshandle = xs_daemon_open_readonly();
- else
- priv->xshandle = xs_daemon_open();
-
- if (priv->xshandle == NULL) {
- /*
- * not being able to connect via the socket as an unprivileged
- * user is rather normal, this should fallback to the proxy (or
- * remote) mechanism.
- */
- if (xenHavePrivilege()) {
- virReportError(VIR_ERR_NO_XEN,
- "%s", _("failed to connect to Xen Store"));
- }
- return -1;
- }
-
- /* Init activeDomainList */
- if (VIR_ALLOC(priv->activeDomainList) < 0)
- return -1;
-
- /* Init watch list before filling in domInfoList,
- so we can know if it is the first time through
- when the callback fires */
- if (VIR_ALLOC(priv->xsWatchList) < 0)
- return -1;
-
- /* This will get called once at start */
- if (xenStoreAddWatch(conn, "@releaseDomain",
- "releaseDomain", xenStoreDomainReleased, priv) < 0)
- {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("adding watch @releaseDomain"));
- return -1;
- }
-
- /* The initial call of this will fill domInfoList */
- if (xenStoreAddWatch(conn, "@introduceDomain",
- "introduceDomain", xenStoreDomainIntroduced, priv) < 0)
- {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("adding watch @introduceDomain"));
- return -1;
- }
-
- /* Add an event handle */
- if ((priv->xsWatch = virEventAddHandle(xs_fileno(priv->xshandle),
- VIR_EVENT_HANDLE_READABLE,
- xenStoreWatchEvent,
- conn,
- NULL)) < 0)
- VIR_DEBUG("Failed to add event handle, disabling events");
-
- return 0;
-}
-
-/**
- * xenStoreClose:
- * @conn: pointer to the connection block
- *
- * Close the connection to the Xen hypervisor.
- *
- * Returns 0 in case of success or -1 in case of error.
- */
-int
-xenStoreClose(virConnectPtr conn)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
-
- if (xenStoreRemoveWatch(conn, "@introduceDomain", "introduceDomain") < 0) {
- VIR_DEBUG("Warning, could not remove @introduceDomain watch");
- /* not fatal */
- }
-
- if (xenStoreRemoveWatch(conn, "@releaseDomain", "releaseDomain") < 0) {
- VIR_DEBUG("Warning, could not remove @releaseDomain watch");
- /* not fatal */
- }
-
- xenStoreWatchListFree(priv->xsWatchList);
- priv->xsWatchList = NULL;
- xenUnifiedDomainInfoListFree(priv->activeDomainList);
- priv->activeDomainList = NULL;
-
- if (priv->xshandle == NULL)
- return -1;
-
- if (priv->xsWatch != -1)
- virEventRemoveHandle(priv->xsWatch);
-
- xs_daemon_close(priv->xshandle);
- priv->xshandle = NULL;
-
- return 0;
-}
-
-/**
- * xenStoreNumOfDomains:
- * @conn: pointer to the hypervisor connection
- *
- * Provides the number of active domains.
- *
- * Returns the number of domain found or -1 in case of error
- */
-int
-xenStoreNumOfDomains(virConnectPtr conn)
-{
- unsigned int num;
- char **idlist = NULL;
- size_t i;
- int ret = -1, realnum = 0;
- long id;
- xenUnifiedPrivatePtr priv = conn->privateData;
-
- idlist = xs_directory(priv->xshandle, 0, "/local/domain", &num);
- if (idlist) {
- for (i = 0; i < num; i++) {
- if (virStrToLong_l(idlist[i], NULL, 10, &id) < 0)
- goto out;
-
- /* Sometimes xenstore has stale domain IDs, so filter
- against the hypervisor's info */
- if (xenHypervisorHasDomain(conn, (int)id))
- realnum++;
- }
- out:
- VIR_FREE(idlist);
- ret = realnum;
- }
- return ret;
-}
-
-/**
- * xenStoreDoListDomains:
- * @conn: pointer to the hypervisor connection
- * @ids: array to collect the list of IDs of active domains
- * @maxids: size of @ids
- *
- * Internal API: collect the list of active domains, and store
- * their ID in @maxids. The driver lock must be held.
- *
- * Returns the number of domain found or -1 in case of error
- */
-static int
-xenStoreDoListDomains(virConnectPtr conn,
- xenUnifiedPrivatePtr priv,
- int *ids,
- int maxids)
-{
- char **idlist = NULL;
- unsigned int num;
- size_t i;
- int ret = -1;
- long id;
-
- idlist = xs_directory(priv->xshandle, 0, "/local/domain", &num);
- if (idlist == NULL)
- goto out;
-
- for (ret = 0, i = 0; (i < num) && (ret < maxids); i++) {
- if (virStrToLong_l(idlist[i], NULL, 10, &id) < 0)
- goto out;
-
- /* Sometimes xenstore has stale domain IDs, so filter
- against the hypervisor's info */
- if (xenHypervisorHasDomain(conn, (int)id))
- ids[ret++] = (int) id;
- }
-
- out:
- VIR_FREE(idlist);
- return ret;
-}
-
-/**
- * xenStoreListDomains:
- * @conn: pointer to the hypervisor connection
- * @ids: array to collect the list of IDs of active domains
- * @maxids: size of @ids
- *
- * Collect the list of active domains, and store their ID in @maxids
- *
- * Returns the number of domain found or -1 in case of error
- */
-int
-xenStoreListDomains(virConnectPtr conn, int *ids, int maxids)
-{
- xenUnifiedPrivatePtr priv = conn->privateData;
- int ret;
-
- xenUnifiedLock(priv);
- ret = xenStoreDoListDomains(conn, priv, ids, maxids);
- xenUnifiedUnlock(priv);
-
- return ret;
-}
-
-
-/**
- * xenStoreDomainGetVNCPort:
- * @conn: the hypervisor connection
- * @domid: id of the domain
- *
- * Return the port number on which the domain is listening for VNC
- * connections.
- *
- * The caller must hold the lock on the privateData
- * associated with the 'conn' parameter.
- *
- * Returns the port number, -1 in case of error
- */
-int
-xenStoreDomainGetVNCPort(virConnectPtr conn, int domid)
-{
- char *tmp;
- int ret = -1;
-
- tmp = virDomainDoStoreQuery(conn, domid, "console/vnc-port");
- if (tmp != NULL) {
- ignore_value(virStrToLong_i(tmp, NULL, 10, &ret));
- VIR_FREE(tmp);
- }
- return ret;
-}
-
-/**
- * xenStoreDomainGetConsolePath:
- * @conn: the hypervisor connection
- * @domid: id of the domain
- *
- * Return the path to the pseudo TTY on which the guest domain's
- * serial console is attached.
- *
- * Returns the path to the serial console. It is the callers
- * responsibility to free() the return string. Returns NULL
- * on error
- *
- * The caller must hold the lock on the privateData
- * associated with the 'conn' parameter.
- */
-char *
-xenStoreDomainGetConsolePath(virConnectPtr conn, int domid)
-{
- return virDomainDoStoreQuery(conn, domid, "console/tty");
-}
-
-/**
- * xenStoreDomainGetSerailConsolePath:
- * @conn: the hypervisor connection
- * @domid: id of the domain
- *
- * Return the path to the pseudo TTY on which the guest domain's
- * serial console is attached.
- *
- * Returns the path to the serial console. It is the callers
- * responsibility to free() the return string. Returns NULL
- * on error
- *
- * The caller must hold the lock on the privateData
- * associated with the 'conn' parameter.
- */
-char *
-xenStoreDomainGetSerialConsolePath(virConnectPtr conn, int domid)
-{
- return virDomainDoStoreQuery(conn, domid, "serial/0/tty");
-}
-
-
-/*
- * xenStoreDomainGetNetworkID:
- * @conn: pointer to the connection.
- * @id: the domain id
- * @mac: the mac address
- *
- * Get the reference (i.e. the string number) for the device on that domain
- * which uses the given mac address
- *
- * The caller must hold the lock on the privateData
- * associated with the 'conn' parameter.
- *
- * Returns the new string or NULL in case of error, the string must be
- * freed by the caller.
- */
-char *
-xenStoreDomainGetNetworkID(virConnectPtr conn, int id, const char *mac)
-{
- char dir[80], path[128], **list = NULL, *val = NULL;
- unsigned int len, num;
- size_t i;
- char *ret = NULL;
- xenUnifiedPrivatePtr priv = conn->privateData;
-
- if (id < 0 || priv->xshandle == NULL || mac == NULL)
- return NULL;
-
- snprintf(dir, sizeof(dir), "/local/domain/0/backend/vif/%d", id);
- list = xs_directory(priv->xshandle, 0, dir, &num);
- if (list == NULL)
- return NULL;
- for (i = 0; i < num; i++) {
- snprintf(path, sizeof(path), "%s/%s/%s", dir, list[i], "mac");
- if ((val = xs_read(priv->xshandle, 0, path, &len)) == NULL)
- break;
-
- bool match = (virMacAddrCompare(val, mac) == 0);
-
- VIR_FREE(val);
-
- if (match) {
- ignore_value(VIR_STRDUP(ret, list[i]));
- break;
- }
- }
-
- VIR_FREE(list);
- return ret;
-}
-
-/*
- * xenStoreDomainGetDiskID:
- * @conn: pointer to the connection.
- * @id: the domain id
- * @dev: the virtual block device name
- *
- * Get the reference (i.e. the string number) for the device on that domain
- * which uses the given virtual block device name
- *
- * The caller must hold the lock on the privateData
- * associated with the 'conn' parameter.
- *
- * Returns the new string or NULL in case of error, the string must be
- * freed by the caller.
- */
-char *
-xenStoreDomainGetDiskID(virConnectPtr conn, int id, const char *dev)
-{
- char dir[80], path[128], **list = NULL, *val = NULL;
- unsigned int devlen, len, num;
- size_t i;
- char *ret = NULL;
- xenUnifiedPrivatePtr priv = conn->privateData;
-
- if (id < 0 || priv->xshandle == NULL || dev == NULL)
- return NULL;
- devlen = strlen(dev);
- if (devlen <= 0)
- return NULL;
-
- snprintf(dir, sizeof(dir), "/local/domain/0/backend/vbd/%d", id);
- list = xs_directory(priv->xshandle, 0, dir, &num);
- if (list != NULL) {
- for (i = 0; i < num; i++) {
- snprintf(path, sizeof(path), "%s/%s/%s", dir, list[i], "dev");
- val = xs_read(priv->xshandle, 0, path, &len);
- if (val == NULL)
- break;
- if ((devlen != len) || memcmp(val, dev, len)) {
- VIR_FREE(val);
- } else {
- ignore_value(VIR_STRDUP(ret, list[i]));
-
- VIR_FREE(val);
- VIR_FREE(list);
- return ret;
- }
- }
- VIR_FREE(list);
- }
- snprintf(dir, sizeof(dir), "/local/domain/0/backend/tap/%d", id);
- list = xs_directory(priv->xshandle, 0, dir, &num);
- if (list != NULL) {
- for (i = 0; i < num; i++) {
- snprintf(path, sizeof(path), "%s/%s/%s", dir, list[i], "dev");
- val = xs_read(priv->xshandle, 0, path, &len);
- if (val == NULL)
- break;
- if ((devlen != len) || memcmp(val, dev, len)) {
- VIR_FREE(val);
- } else {
- ignore_value(VIR_STRDUP(ret, list[i]));
-
- VIR_FREE(val);
- VIR_FREE(list);
- return ret;
- }
- }
- VIR_FREE(list);
- }
- return NULL;
-}
-
-/*
- * xenStoreDomainGetPCIID:
- * @conn: pointer to the connection.
- * @id: the domain id
- * @bdf: the PCI BDF
- *
- * Get the reference (i.e. the string number) for the device on that domain
- * which uses the given PCI address
- *
- * The caller must hold the lock on the privateData
- * associated with the 'conn' parameter.
- *
- * Returns the new string or NULL in case of error, the string must be
- * freed by the caller.
- */
-char *
-xenStoreDomainGetPCIID(virConnectPtr conn, int id, const char *bdf)
-{
- char dir[80], path[128], **list = NULL, *val = NULL;
- unsigned int len, num;
- size_t i;
- char *ret = NULL;
- xenUnifiedPrivatePtr priv = conn->privateData;
-
- if (id < 0 || priv->xshandle == NULL || bdf == NULL)
- return NULL;
-
- snprintf(dir, sizeof(dir), "/local/domain/0/backend/pci/%d", id);
- list = xs_directory(priv->xshandle, 0, dir, &num);
- if (list == NULL)
- return NULL;
- for (i = 0; i < num; i++) {
- snprintf(path, sizeof(path), "%s/%s/%s", dir, list[i], "dev-0");
- if ((val = xs_read(priv->xshandle, 0, path, &len)) == NULL)
- break;
-
- bool match = STREQ(val, bdf);
-
- VIR_FREE(val);
-
- if (match) {
- ignore_value(VIR_STRDUP(ret, list[i]));
- break;
- }
- }
-
- VIR_FREE(list);
- return ret;
-}
-
-/*
- * The caller must hold the lock on the privateData
- * associated with the 'conn' parameter.
- */
-char *
-xenStoreDomainGetName(virConnectPtr conn, int id)
-{
- char prop[200];
- xenUnifiedPrivatePtr priv = conn->privateData;
- unsigned int len;
-
- if (priv->xshandle == NULL)
- return NULL;
-
- snprintf(prop, 199, "/local/domain/%d/name", id);
- prop[199] = 0;
- return xs_read(priv->xshandle, 0, prop, &len);
-}
-
-/*
- * The caller must hold the lock on the privateData
- * associated with the 'conn' parameter.
- */
-int
-xenStoreDomainGetUUID(virConnectPtr conn, int id, unsigned char *uuid)
-{
- char prop[200];
- xenUnifiedPrivatePtr priv = conn->privateData;
- unsigned int len;
- char *uuidstr;
- int ret = 0;
-
- if (priv->xshandle == NULL)
- return -1;
-
- snprintf(prop, 199, "/local/domain/%d/vm", id);
- prop[199] = 0;
- /* This will return something like
- * /vm/00000000-0000-0000-0000-000000000000[-*] */
- uuidstr = xs_read(priv->xshandle, 0, prop, &len);
- /* Strip optional version suffix when VM was renamed */
- if (len > 40) /* strlen('/vm/') + VIR_UUID_STRING_BUFLEN - sizeof('\0') */
- uuidstr[40] = '\0';
-
- /* remove "/vm/" */
- ret = virUUIDParse(uuidstr + 4, uuid);
-
- VIR_FREE(uuidstr);
-
- return ret;
-}
-
-static void
-xenStoreWatchListFree(xenStoreWatchListPtr list)
-{
- size_t i;
- for (i = 0; i < list->count; i++) {
- VIR_FREE(list->watches[i]->path);
- VIR_FREE(list->watches[i]->token);
- VIR_FREE(list->watches[i]);
- }
- VIR_FREE(list);
-}
-
-/*
- * The caller must hold the lock on the privateData
- * associated with the 'conn' parameter.
- */
-int
-xenStoreAddWatch(virConnectPtr conn,
- const char *path,
- const char *token,
- xenStoreWatchCallback cb,
- void *opaque)
-{
- xenStoreWatchPtr watch = NULL;
- int n;
- xenStoreWatchListPtr list;
- xenUnifiedPrivatePtr priv = conn->privateData;
-
- if (priv->xshandle == NULL)
- return -1;
-
- list = priv->xsWatchList;
- if (!list)
- return -1;
-
- /* check if we already have this callback on our list */
- for (n = 0; n < list->count; n++) {
- if (STREQ(list->watches[n]->path, path) &&
- STREQ(list->watches[n]->token, token)) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("watch already tracked"));
- return -1;
- }
- }
-
- if (VIR_ALLOC(watch) < 0)
- goto error;
-
- watch->cb = cb;
- watch->opaque = opaque;
- if (VIR_STRDUP(watch->path, path) < 0 ||
- VIR_STRDUP(watch->token, token) < 0)
- goto error;
-
- if (VIR_APPEND_ELEMENT_COPY(list->watches, list->count, watch) < 0)
- goto error;
-
- return xs_watch(priv->xshandle, watch->path, watch->token);
-
- error:
- if (watch) {
- VIR_FREE(watch->path);
- VIR_FREE(watch->token);
- VIR_FREE(watch);
- }
- return -1;
-}
-
-/*
- * The caller must hold the lock on the privateData
- * associated with the 'conn' parameter.
- */
-int
-xenStoreRemoveWatch(virConnectPtr conn, const char *path, const char *token)
-{
- size_t i;
- xenStoreWatchListPtr list;
- xenUnifiedPrivatePtr priv = conn->privateData;
-
- if (priv->xshandle == NULL)
- return -1;
-
- list = priv->xsWatchList;
- if (!list)
- return -1;
-
- for (i = 0; i < list->count; i++) {
- if (STREQ(list->watches[i]->path, path) &&
- STREQ(list->watches[i]->token, token)) {
-
- if (!xs_unwatch(priv->xshandle,
- list->watches[i]->path,
- list->watches[i]->token))
- {
- VIR_DEBUG("WARNING: Could not remove watch");
- /* Not fatal, continue */
- }
-
- VIR_FREE(list->watches[i]->path);
- VIR_FREE(list->watches[i]->token);
- VIR_FREE(list->watches[i]);
-
- VIR_DELETE_ELEMENT(list->watches, i, list->count);
- return 0;
- }
- }
- return -1;
-}
-
-static xenStoreWatchPtr
-xenStoreFindWatch(xenStoreWatchListPtr list,
- const char *path,
- const char *token)
-{
- size_t i;
- for (i = 0; i < list->count; i++)
- if (STREQ(path, list->watches[i]->path) &&
- STREQ(token, list->watches[i]->token))
- return list->watches[i];
-
- return NULL;
-}
-
-static void
-xenStoreWatchEvent(int watch ATTRIBUTE_UNUSED,
- int fd ATTRIBUTE_UNUSED,
- int events, void *data)
-{
- char **event;
- char *path;
- char *token;
- unsigned int stringCount;
- xenStoreWatchPtr sw;
-
- virConnectPtr conn = data;
- xenUnifiedPrivatePtr priv = conn->privateData;
-
- if (!priv) return;
-
- /* only set a watch on read and write events */
- if (events & (VIR_EVENT_HANDLE_ERROR | VIR_EVENT_HANDLE_HANGUP)) return;
-
- xenUnifiedLock(priv);
-
- if (!priv->xshandle)
- goto cleanup;
-
- event = xs_read_watch(priv->xshandle, &stringCount);
- if (!event)
- goto cleanup;
-
- path = event[XS_WATCH_PATH];
- token = event[XS_WATCH_TOKEN];
-
- sw = xenStoreFindWatch(priv->xsWatchList, path, token);
- if (sw)
- sw->cb(conn, path, token, sw->opaque);
- VIR_FREE(event);
-
- cleanup:
- xenUnifiedUnlock(priv);
-}
-
-
-/*
- * The domain callback for the @introduceDomain watch
- *
- * The lock on 'priv' is held when calling this
- */
-int
-xenStoreDomainIntroduced(virConnectPtr conn,
- const char *path ATTRIBUTE_UNUSED,
- const char *token ATTRIBUTE_UNUSED,
- void *opaque)
-{
- size_t i, j;
- int found, missing = 0, retries = 20;
- int new_domain_cnt;
- int *new_domids;
- int nread;
-
- xenUnifiedPrivatePtr priv = opaque;
-
- retry:
- new_domain_cnt = xenStoreNumOfDomains(conn);
- if (new_domain_cnt < 0)
- return -1;
-
- if (VIR_ALLOC_N(new_domids, new_domain_cnt) < 0)
- return -1;
- nread = xenStoreDoListDomains(conn, priv, new_domids, new_domain_cnt);
- if (nread != new_domain_cnt) {
- /* mismatch. retry this read */
- VIR_FREE(new_domids);
- goto retry;
- }
-
- missing = 0;
- for (i = 0; i < new_domain_cnt; i++) {
- found = 0;
- for (j = 0; j < priv->activeDomainList->count; j++) {
- if (priv->activeDomainList->doms[j]->id == new_domids[i]) {
- found = 1;
- break;
- }
- }
-
- if (!found) {
- virObjectEventPtr event;
- char *name;
- unsigned char uuid[VIR_UUID_BUFLEN];
-
- if (!(name = xenStoreDomainGetName(conn, new_domids[i]))) {
- missing = 1;
- continue;
- }
- if (xenStoreDomainGetUUID(conn, new_domids[i], uuid) < 0) {
- missing = 1;
- VIR_FREE(name);
- continue;
- }
-
- event = virDomainEventLifecycleNew(new_domids[i], name, uuid,
- VIR_DOMAIN_EVENT_STARTED,
- VIR_DOMAIN_EVENT_STARTED_BOOTED);
- if (event)
- xenUnifiedDomainEventDispatch(priv, event);
-
- /* Add to the list */
- xenUnifiedAddDomainInfo(priv->activeDomainList,
- new_domids[i], name, uuid);
-
- VIR_FREE(name);
- }
- }
- VIR_FREE(new_domids);
-
- if (missing && retries--) {
- VIR_DEBUG("Some domains were missing, trying again");
- usleep(100 * 1000);
- goto retry;
- }
- return 0;
-}
-
-/*
- * The domain callback for the @destroyDomain watch
- *
- * The lock on 'priv' is held when calling this
- */
-int
-xenStoreDomainReleased(virConnectPtr conn,
- const char *path ATTRIBUTE_UNUSED,
- const char *token ATTRIBUTE_UNUSED,
- void *opaque)
-{
- size_t i, j;
- int found, removed, retries = 20;
- int new_domain_cnt;
- int *new_domids;
- int nread;
-
- xenUnifiedPrivatePtr priv = opaque;
-
- if (!priv->activeDomainList->count) return 0;
-
- retry:
- new_domain_cnt = xenStoreNumOfDomains(conn);
- if (new_domain_cnt < 0)
- return -1;
-
- if (VIR_ALLOC_N(new_domids, new_domain_cnt) < 0)
- return -1;
- nread = xenStoreDoListDomains(conn, priv, new_domids, new_domain_cnt);
- if (nread != new_domain_cnt) {
- /* mismatch. retry this read */
- VIR_FREE(new_domids);
- goto retry;
- }
-
- removed = 0;
- for (j = 0; j < priv->activeDomainList->count; j++) {
- found = 0;
- for (i = 0; i < new_domain_cnt; i++) {
- if (priv->activeDomainList->doms[j]->id == new_domids[i]) {
- found = 1;
- break;
- }
- }
-
- if (!found) {
- virObjectEventPtr event =
- virDomainEventLifecycleNew(-1,
- priv->activeDomainList->doms[j]->name,
- priv->activeDomainList->doms[j]->uuid,
- VIR_DOMAIN_EVENT_STOPPED,
- VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN);
- if (event)
- xenUnifiedDomainEventDispatch(priv, event);
-
- /* Remove from the list */
- xenUnifiedRemoveDomainInfo(priv->activeDomainList,
- priv->activeDomainList->doms[j]->id,
- priv->activeDomainList->doms[j]->name,
- priv->activeDomainList->doms[j]->uuid);
-
- removed = 1;
- }
- }
-
- VIR_FREE(new_domids);
-
- if (!removed && retries--) {
- VIR_DEBUG("No domains removed, retrying");
- usleep(100 * 1000);
- goto retry;
- }
- return 0;
-}
+++ /dev/null
-/*
- * xs_internal.h: internal API for access to XenStore
- *
- * Copyright (C) 2006, 2010-2012 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/>.
- *
- * Daniel Veillard <veillard@redhat.com>
- */
-
-#ifndef __VIR_XS_INTERNAL_H__
-# define __VIR_XS_INTERNAL_H__
-
-# include "internal.h"
-# include "driver.h"
-
-int xenStoreOpen (virConnectPtr conn,
- virConnectAuthPtr auth,
- unsigned int flags);
-int xenStoreClose (virConnectPtr conn);
-int xenStoreNumOfDomains (virConnectPtr conn);
-int xenStoreListDomains (virConnectPtr conn,
- int *ids,
- int maxids);
-
-int xenStoreDomainGetVNCPort(virConnectPtr conn,
- int domid);
-char * xenStoreDomainGetConsolePath(virConnectPtr conn,
- int domid);
-char * xenStoreDomainGetSerialConsolePath(virConnectPtr conn,
- int domid);
-char * xenStoreDomainGetNetworkID(virConnectPtr conn,
- int id,
- const char *mac);
-char * xenStoreDomainGetDiskID(virConnectPtr conn,
- int id,
- const char *dev);
-char * xenStoreDomainGetPCIID(virConnectPtr conn,
- int domid,
- const char *bdf);
-char * xenStoreDomainGetName(virConnectPtr conn,
- int id);
-int xenStoreDomainGetUUID(virConnectPtr conn,
- int id,
- unsigned char *uuid);
-
-typedef int (*xenStoreWatchCallback)(virConnectPtr conn,
- const char *path,
- const char *token,
- void *opaque);
-
-struct _xenStoreWatch {
- char *path;
- char *token;
- xenStoreWatchCallback cb;
- void *opaque;
-};
-typedef struct _xenStoreWatch xenStoreWatch;
-typedef xenStoreWatch *xenStoreWatchPtr;
-
-struct _xenStoreWatchList {
- size_t count;
- xenStoreWatchPtr *watches;
-};
-typedef struct _xenStoreWatchList xenStoreWatchList;
-typedef xenStoreWatchList *xenStoreWatchListPtr;
-
-
-int xenStoreAddWatch(virConnectPtr conn,
- const char *path,
- const char *token,
- xenStoreWatchCallback cb,
- void *opaque);
-int xenStoreRemoveWatch(virConnectPtr conn,
- const char *path,
- const char *token);
-
-/* domain events */
-int xenStoreDomainIntroduced(virConnectPtr conn,
- const char *path,
- const char *token,
- void *opaque);
-int xenStoreDomainReleased(virConnectPtr conn,
- const char *path,
- const char *token,
- void *opaque);
-
-int xenStoreDomainEventEmitted(virDomainEventType evt);
-#endif /* __VIR_XS_INTERNAL_H__ */