From 1dac5fbbbb06a0341e8087dc33af75c8352d77a4 Mon Sep 17 00:00:00 2001 From: Jim Fehlig Date: Wed, 28 Mar 2018 16:50:04 -0600 Subject: [PATCH] Remove the xend driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit xend was deprecated in Xen 4.2 and removed from the Xen sources before the Xen 4.5 release. The last Xen release to contain xend was Xen 4.4, which was retired upstream in March 2017. Remove xend support from libvirt since it is unrealistic to use modern libvirt with ancient Xen. Signed-off-by: Jim Fehlig Reviewed-by: Daniel P. BerrangĂ© --- configure.ac | 7 +- m4/virt-driver-xen.m4 | 142 -- po/POTFILES.in | 7 - src/Makefile.am | 1 - src/xen/Makefile.inc.am | 67 - src/xen/block_stats.c | 355 ----- src/xen/block_stats.h | 38 - src/xen/xen_driver.c | 2845 --------------------------------- src/xen/xen_driver.h | 204 --- src/xen/xen_hypervisor.c | 3125 ------------------------------------ src/xen/xen_hypervisor.h | 142 -- src/xen/xen_inotify.c | 447 ------ src/xen/xen_inotify.h | 33 - src/xen/xend_internal.c | 3221 -------------------------------------- src/xen/xend_internal.h | 213 --- src/xen/xm_internal.c | 1484 ------------------ src/xen/xm_internal.h | 105 -- src/xen/xs_internal.c | 920 ----------- src/xen/xs_internal.h | 101 -- 19 files changed, 1 insertion(+), 13456 deletions(-) delete mode 100644 m4/virt-driver-xen.m4 delete mode 100644 src/xen/Makefile.inc.am delete mode 100644 src/xen/block_stats.c delete mode 100644 src/xen/block_stats.h delete mode 100644 src/xen/xen_driver.c delete mode 100644 src/xen/xen_driver.h delete mode 100644 src/xen/xen_hypervisor.c delete mode 100644 src/xen/xen_hypervisor.h delete mode 100644 src/xen/xen_inotify.c delete mode 100644 src/xen/xen_inotify.h delete mode 100644 src/xen/xend_internal.c delete mode 100644 src/xen/xend_internal.h delete mode 100644 src/xen/xm_internal.c delete mode 100644 src/xen/xm_internal.h delete mode 100644 src/xen/xs_internal.c delete mode 100644 src/xen/xs_internal.h diff --git a/configure.ac b/configure.ac index 18587270e6..ae798faa54 100644 --- a/configure.ac +++ b/configure.ac @@ -224,7 +224,6 @@ fi # 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 @@ -402,7 +401,6 @@ dnl dnl Virtualization drivers check dnl -LIBVIRT_DRIVER_ARG_XEN LIBVIRT_DRIVER_ARG_QEMU LIBVIRT_DRIVER_ARG_OPENVZ LIBVIRT_DRIVER_ARG_VMWARE @@ -422,7 +420,6 @@ LIBVIRT_DRIVER_ARG_LIBVIRTD LIBVIRT_DRIVER_ARG_NETWORK LIBVIRT_DRIVER_ARG_INTERFACE -LIBVIRT_DRIVER_CHECK_XEN LIBVIRT_DRIVER_CHECK_QEMU LIBVIRT_DRIVER_CHECK_OPENVZ LIBVIRT_DRIVER_CHECK_VMWARE @@ -442,7 +439,7 @@ LIBVIRT_DRIVER_CHECK_LIBVIRTD 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 @@ -925,7 +922,6 @@ AC_MSG_NOTICE([=====================]) 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 @@ -1009,7 +1005,6 @@ LIBVIRT_RESULT_SSH2 LIBVIRT_RESULT_UDEV LIBVIRT_RESULT_VIRTUALPORT LIBVIRT_RESULT_XDR -LIBVIRT_RESULT_XEN LIBVIRT_RESULT_XENAPI LIBVIRT_RESULT_YAJL AC_MSG_NOTICE([]) diff --git a/m4/virt-driver-xen.m4 b/m4/virt-driver-xen.m4 deleted file mode 100644 index 1d0acfa363..0000000000 --- a/m4/virt-driver-xen.m4 +++ /dev/null @@ -1,142 +0,0 @@ -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 . -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 -#include -]) - fi - - if test "$with_xen" != "no" ; then - dnl Search for the location of . - found= - AC_CHECK_HEADERS([xen/sys/privcmd.h xen/linux/privcmd.h], [found=yes; break;], [], - [#include - #include - #include - ]) - 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 is required for Xen Inotify support, disabling it]) - else - AC_MSG_ERROR([Header file 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]) -]) diff --git a/po/POTFILES.in b/po/POTFILES.in index d84859a4e3..0dcd1cab28 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -291,13 +291,6 @@ src/vz/vz_driver.c 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 diff --git a/src/Makefile.am b/src/Makefile.am index 8b1e4c8a4e..a6667228b6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -115,7 +115,6 @@ include qemu/Makefile.inc.am 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 diff --git a/src/xen/Makefile.inc.am b/src/xen/Makefile.inc.am deleted file mode 100644 index 85260251ec..0000000000 --- a/src/xen/Makefile.inc.am +++ /dev/null @@ -1,67 +0,0 @@ -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) diff --git a/src/xen/block_stats.c b/src/xen/block_stats.c deleted file mode 100644 index a1ffc21243..0000000000 --- a/src/xen/block_stats.c +++ /dev/null @@ -1,355 +0,0 @@ -/* - * 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 - * . - * - * Richard W.M. Jones - */ - -#include - -/* This file only applies on Linux. */ -#ifdef __linux__ - -# include -# include -# include -# include -# include -# include - -# if HAVE_XENSTORE_H -# include -# else -# include -# 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 - -/* This is normally defined in 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///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__ */ diff --git a/src/xen/block_stats.h b/src/xen/block_stats.h deleted file mode 100644 index c8a61ab2e0..0000000000 --- a/src/xen/block_stats.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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 - * . - * - * Richard W.M. Jones - */ - -#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__ */ diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c deleted file mode 100644 index 85c3424b11..0000000000 --- a/src/xen/xen_driver.c +++ /dev/null @@ -1,2845 +0,0 @@ -/* - * 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 - * . - * - * Richard W.M. Jones - */ - -#include - -/* 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 -#include -#include -#include -#include -#include -#include - -#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); -} diff --git a/src/xen/xen_driver.h b/src/xen/xen_driver.h deleted file mode 100644 index f95b5e7053..0000000000 --- a/src/xen/xen_driver.h +++ /dev/null @@ -1,204 +0,0 @@ -/* - * 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 - * . - * - * Richard W.M. Jones - */ - -#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 -# include -# else -# include -# endif - -# include - -/* 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__ */ diff --git a/src/xen/xen_hypervisor.c b/src/xen/xen_hypervisor.c deleted file mode 100644 index 4621507eb0..0000000000 --- a/src/xen/xen_hypervisor.c +++ /dev/null @@ -1,3125 +0,0 @@ -/* - * 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 - * . - * - * Daniel Veillard - */ - -#include - -#include -#include -/* required for uint8_t, uint32_t, etc ... */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __sun -# include - -# include - -# ifndef PRIV_XVM_CONTROL -# define PRIV_XVM_CONTROL ((const char *)"xvm_control") -# endif - -#endif /* __sun */ - -/* required for dom0_getdomaininfo_t */ -#include -#include -#ifdef HAVE_XEN_LINUX_PRIVCMD_H -# include -#else -# ifdef HAVE_XEN_SYS_PRIVCMD_H -# include -# endif -#endif - -/* required for shutdown flags */ -#include - -#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. (this interface checks that - * 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..")); - return -1; - } - if (rqdomid != def->id) { - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("invalid path, vif 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<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< 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 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 -} diff --git a/src/xen/xen_hypervisor.h b/src/xen/xen_hypervisor.h deleted file mode 100644 index 5a964690fa..0000000000 --- a/src/xen/xen_hypervisor.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * 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 - * . - * - * Daniel Veillard - */ - -#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__ */ diff --git a/src/xen/xen_inotify.c b/src/xen/xen_inotify.c deleted file mode 100644 index ac4070c917..0000000000 --- a/src/xen/xen_inotify.c +++ /dev/null @@ -1,447 +0,0 @@ -/* - * 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 - * . - * - * Author: Ben Guthro - */ -#include -#include -#include - -#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_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//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; -} diff --git a/src/xen/xen_inotify.h b/src/xen/xen_inotify.h deleted file mode 100644 index 8a9370deab..0000000000 --- a/src/xen/xen_inotify.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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 - * . - * - * 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 diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c deleted file mode 100644 index b3178b7bea..0000000000 --- a/src/xen/xend_internal.c +++ /dev/null @@ -1,3221 +0,0 @@ -/* - * xend_internal.c: access to Xen though the Xen Daemon interface - * - * Copyright (C) 2010-2014 Red Hat, Inc. - * Copyright (C) 2005 Anthony Liguori - * - * 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 - * . - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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 - -#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 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; -} diff --git a/src/xen/xend_internal.h b/src/xen/xend_internal.h deleted file mode 100644 index 7e947ff6e5..0000000000 --- a/src/xen/xend_internal.h +++ /dev/null @@ -1,213 +0,0 @@ -/* - * xend_internal.h - * - * Copyright (C) 2006-2008, 2010-2013 Red Hat, Inc. - * Copyright (C) 2005,2006 Anthony Liguori - * and Daniel Veillard - * - * 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 - * . - */ - -#ifndef __XEND_INTERNAL_H_ -# define __XEND_INTERNAL_H_ - -# include -# include - -# 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_ */ diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c deleted file mode 100644 index 123f379572..0000000000 --- a/src/xen/xm_internal.c +++ /dev/null @@ -1,1484 +0,0 @@ -/* - * 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 - * . - * - * Author: Daniel P. Berrange - * - */ - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#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; -} diff --git a/src/xen/xm_internal.h b/src/xen/xm_internal.h deleted file mode 100644 index 0246895d89..0000000000 --- a/src/xen/xm_internal.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * 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 - * . - * - * Author: Daniel P. Berrange - * - */ - -#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 diff --git a/src/xen/xs_internal.c b/src/xen/xs_internal.c deleted file mode 100644 index 353169da05..0000000000 --- a/src/xen/xs_internal.c +++ /dev/null @@ -1,920 +0,0 @@ -/* - * 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 - * . - * - * Daniel Veillard - */ - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#if HAVE_XENSTORE_H -# include -#else -# include -#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; -} diff --git a/src/xen/xs_internal.h b/src/xen/xs_internal.h deleted file mode 100644 index 69cca585c2..0000000000 --- a/src/xen/xs_internal.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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 - * . - * - * Daniel Veillard - */ - -#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__ */