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__ */