[libvirt] [PATCH V4 0/3] Parser for xen-xl config format

It's been a long, twisting road to V4 of the Xen xl parser. V3 [1] was based on a flex-based parser that was copied from the Xen project and proved to be a bit challenging to integrate properly with autotools. But as it turns out, Xen provides an interface to the parser via libxlutil. I hadn't realized this interface was available for external consumption since the corresponding header file was never installed. Patch sent to xen-devel [2] to install the header, but in the meantime need to declare gthe imported libxlutil functions as extern (see patch 1). V4 uses libxlutil, which has simplified the series quite a bit and eliminates the potential of the copied flex parser diverging from the canonical source in xen.git. [1] https://www.redhat.com/archives/libvir-list/2014-December/msg00765.html [2] http://lists.xen.org/archives/html/xen-devel/2015-01/msg00690.html Jim Fehlig (1): Introduce support for parsing/formatting Xen xl config format Kiarie Kahurani (2): tests: Tests for the xen-xl parser libxl: Add support for parsing/formating Xen XL config configure.ac | 3 + po/POTFILES.in | 1 + src/Makefile.am | 11 + src/libvirt_xenxlconfig.syms | 12 + src/libxl/libxl_driver.c | 32 ++- src/xenconfig/xen_common.c | 3 +- src/xenconfig/xen_xl.c | 515 +++++++++++++++++++++++++++++++++++ src/xenconfig/xen_xl.h | 35 +++ tests/Makefile.am | 11 + tests/testutilsxen.c | 50 ++++ tests/testutilsxen.h | 9 +- tests/xlconfigdata/test-new-disk.cfg | 26 ++ tests/xlconfigdata/test-new-disk.xml | 51 ++++ tests/xlconfigdata/test-spice.cfg | 32 +++ tests/xlconfigdata/test-spice.xml | 45 +++ tests/xlconfigtest.c | 225 +++++++++++++++ tools/virsh.pod | 8 +- 17 files changed, 1055 insertions(+), 14 deletions(-) create mode 100644 src/libvirt_xenxlconfig.syms create mode 100644 src/xenconfig/xen_xl.c create mode 100644 src/xenconfig/xen_xl.h create mode 100644 tests/xlconfigdata/test-new-disk.cfg create mode 100644 tests/xlconfigdata/test-new-disk.xml create mode 100644 tests/xlconfigdata/test-spice.cfg create mode 100644 tests/xlconfigdata/test-spice.xml create mode 100644 tests/xlconfigtest.c -- 1.8.4.5

Introduce a parser/formatter for the xl config format. Since the deprecation of xm/xend, the VM config file format has diverged as new features are added to libxl. This patch adds support for parsing and formating the xl config format. It supports the existing xm config format, plus adds support for spice graphics and xl disk config syntax. Disk config is specified a bit differently in xl as compared to xm. In xl, disk config consists of comma-separated positional parameters and keyword/value pairs separated by commas. Positional parameters are specified as follows target, format, vdev, access Supported keys for key=value options are devtype, backendtype The positional paramters can also be specified in key/value form. For example the following xl disk config are equivalent /dev/vg/guest-volume,,hda /dev/vg/guest-volume,raw,hda,rw format=raw, vdev=hda, access=rw, target=/dev/vg/guest-volume See $xen_sources/docs/misc/xl-disk-configuration.txt for more details. xl disk config is parsed with the help of xlu_disk_parse() from libxlutil, libxl's utility library. Although the library exists in all Xen versions supported by the libxl virt driver, only recently has the corresponding header file been included. A check for the header is done in configure.ac. If not found, xlu_disk_parse() is declared externally. Signed-off-by: Kiarie Kahurani <davidkiarie4@gmail.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- V4: Use Xen's libxlutil to parse disk strings instead of copying the flex-based parser. Only build support for parsing xen-xl when libxl is available. Address several comments from previous review. configure.ac | 3 + po/POTFILES.in | 1 + src/Makefile.am | 11 + src/libvirt_xenxlconfig.syms | 12 + src/xenconfig/xen_common.c | 3 +- src/xenconfig/xen_xl.c | 515 +++++++++++++++++++++++++++++++++++++++++++ src/xenconfig/xen_xl.h | 35 +++ 7 files changed, 579 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 9d12079..f370475 100644 --- a/configure.ac +++ b/configure.ac @@ -891,6 +891,9 @@ if test $fail = 1; then fi if test "$with_libxl" = "yes"; then + dnl If building with libxl, use the libxl utility header and lib too + AC_CHECK_HEADERS([libxlutil.h]) + LIBXL_LIBS="$LIBXL_LIBS -lxlutil" AC_DEFINE_UNQUOTED([WITH_LIBXL], 1, [whether libxenlight driver is enabled]) fi AM_CONDITIONAL([WITH_LIBXL], [test "$with_libxl" = "yes"]) diff --git a/po/POTFILES.in b/po/POTFILES.in index e7cb2cc..094c8e3 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -247,6 +247,7 @@ src/xenapi/xenapi_driver.c src/xenapi/xenapi_utils.c src/xenconfig/xen_common.c src/xenconfig/xen_sxpr.c +src/xenconfig/xen_xl.c src/xenconfig/xen_xm.c tests/virpolkittest.c tools/libvirt-guests.sh.in diff --git a/src/Makefile.am b/src/Makefile.am index e0e47d0..216abac 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1005,6 +1005,10 @@ XENCONFIG_SOURCES = \ xenconfig/xen_common.c xenconfig/xen_common.h \ xenconfig/xen_sxpr.c xenconfig/xen_sxpr.h \ xenconfig/xen_xm.c xenconfig/xen_xm.h +if WITH_LIBXL +XENCONFIG_SOURCES += \ + xenconfig/xen_xl.c xenconfig/xen_xl.h +endif WITH_LIBXL pkgdata_DATA = cpu/cpu_map.xml @@ -1061,6 +1065,7 @@ endif WITH_VMX if WITH_XENCONFIG noinst_LTLIBRARIES += libvirt_xenconfig.la libvirt_la_BUILT_LIBADD += libvirt_xenconfig.la +libvirt_la_LIBADD += $(LIBXL_LIBS) libvirt_xenconfig_la_CFLAGS = \ -I$(srcdir)/conf $(AM_CFLAGS) libvirt_xenconfig_la_SOURCES = $(XENCONFIG_SOURCES) @@ -1979,6 +1984,12 @@ else ! WITH_XENCONFIG SYM_FILES += $(srcdir)/libvirt_xenconfig.syms endif ! WITH_XENCONFIG +if WITH_LIBXL +USED_SYM_FILES += $(srcdir)/libvirt_xenxlconfig.syms +else ! WITH_LIBXL +SYM_FILES += $(srcdir)/libvirt_xenxlconfig.syms +endif ! WITH_LIBXL + if WITH_SASL USED_SYM_FILES += $(srcdir)/libvirt_sasl.syms else ! WITH_SASL diff --git a/src/libvirt_xenxlconfig.syms b/src/libvirt_xenxlconfig.syms new file mode 100644 index 0000000..dbe43aa --- /dev/null +++ b/src/libvirt_xenxlconfig.syms @@ -0,0 +1,12 @@ +# +# These symbols are dependent upon --with-libxl via WITH_LIBXL. +# + +#xenconfig/xen_xl.h +xenFormatXL; +xenParseXL; + +# Let emacs know we want case-insensitive sorting +# Local Variables: +# sort-fold-case: t +# End: diff --git a/src/xenconfig/xen_common.c b/src/xenconfig/xen_common.c index b40a722..a2a1474 100644 --- a/src/xenconfig/xen_common.c +++ b/src/xenconfig/xen_common.c @@ -1812,7 +1812,8 @@ xenFormatVfb(virConfPtr conf, virDomainDefPtr def, int xendConfigVersion) { int hvm = STREQ(def->os.type, "hvm") ? 1 : 0; - if (def->ngraphics == 1) { + if (def->ngraphics == 1 && + def->graphics[0]->type != VIR_DOMAIN_GRAPHICS_TYPE_SPICE) { if (hvm || (xendConfigVersion < XEND_CONFIG_MIN_VERS_PVFB_NEWCONF)) { if (def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) { if (xenConfigSetInt(conf, "sdl", 1) < 0) diff --git a/src/xenconfig/xen_xl.c b/src/xenconfig/xen_xl.c new file mode 100644 index 0000000..b09c0e3 --- /dev/null +++ b/src/xenconfig/xen_xl.c @@ -0,0 +1,515 @@ +/* + * xen_xl.c: Xen XL parsing functions + * + * Copyright (c) 2015 SUSE LINUX Products GmbH, Nuernberg, Germany. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + * Author: Kiarie Kahurani <davidkiarie4@gmail.com> + * Author: Jim Fehlig <jfehlig@suse.com> + */ + +#include <config.h> + +#include <libxl.h> + +#include "virconf.h" +#include "virerror.h" +#include "domain_conf.h" +#include "viralloc.h" +#include "virstring.h" +#include "virstoragefile.h" +#include "xen_xl.h" + +#define VIR_FROM_THIS VIR_FROM_NONE + +/* + * Xen provides a libxl utility library, with several useful functions, + * specifically xlu_disk_parse for parsing xl disk config strings. + * Although the libxlutil library is installed, until recently the + * corresponding header file wasn't. Use the header file if detected during + * configure, otherwise provide extern declarations for any functions used. + */ +#ifdef HAVE_LIBXLUTIL_H +# include <libxlutil.h> +#else +typedef struct XLU_Config XLU_Config; + +extern XLU_Config *xlu_cfg_init(FILE *report, + const char *report_filename); + +extern void xlu_cfg_destroy(XLU_Config*); + +extern int xlu_disk_parse(XLU_Config *cfg, + int nspecs, + const char *const *specs, + libxl_device_disk *disk); +#endif + +static int +xenParseXLSpice(virConfPtr conf, virDomainDefPtr def) +{ + virDomainGraphicsDefPtr graphics = NULL; + unsigned long port; + char *listenAddr = NULL; + int val; + + if (STREQ(def->os.type, "hvm")) { + if (xenConfigGetBool(conf, "spice", &val, 0) < 0) + return -1; + + if (val) { + if (VIR_ALLOC(graphics) < 0) + return -1; + + graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_SPICE; + if (xenConfigCopyStringOpt(conf, "spicehost", &listenAddr) < 0) + goto cleanup; + if (listenAddr && + virDomainGraphicsListenSetAddress(graphics, 0, listenAddr, + -1, true) < 0) { + goto cleanup; + } + VIR_FREE(listenAddr); + + if (xenConfigGetULong(conf, "spicetls_port", &port, 0) < 0) + goto cleanup; + graphics->data.spice.tlsPort = (int)port; + + if (xenConfigGetULong(conf, "spiceport", &port, 0) < 0) + goto cleanup; + + graphics->data.spice.port = (int)port; + + if (!graphics->data.spice.tlsPort && + !graphics->data.spice.port) + graphics->data.spice.autoport = 1; + + if (xenConfigGetBool(conf, "spicedisable_ticketing", &val, 0) < 0) + goto cleanup; + if (val) { + if (xenConfigCopyStringOpt(conf, "spicepasswd", + &graphics->data.spice.auth.passwd) < 0) + goto cleanup; + } + + if (xenConfigGetBool(conf, "spiceagent_mouse", + &graphics->data.spice.mousemode, 0) < 0) + goto cleanup; + if (xenConfigGetBool(conf, "spicedvagent", &val, 0) < 0) + goto cleanup; + if (val) { + if (xenConfigGetBool(conf, "spice_clipboard_sharing", + &graphics->data.spice.copypaste, + 0) < 0) + goto cleanup; + } + + if (VIR_ALLOC_N(def->graphics, 1) < 0) + goto cleanup; + def->graphics[0] = graphics; + def->ngraphics = 1; + } + } + + return 0; + + cleanup: + virDomainGraphicsDefFree(graphics); + return -1; +} + +/* + * For details on xl disk config syntax, see + * docs/misc/xl-disk-configuration.txt in the Xen sources. The important + * section of text is: + * + * More formally, the string is a series of comma-separated keyword/value + * pairs, flags and positional parameters. Parameters which are not bare + * keywords and which do not contain "=" symbols are assigned to the + * so-far-unspecified positional parameters, in the order below. The + * positional parameters may also be specified explicitly by name. + * + * Each parameter may be specified at most once, either as a positional + * parameter or a named parameter. Default values apply if the parameter + * is not specified, or if it is specified with an empty value (whether + * positionally or explicitly). + * + * Whitespace may appear before each parameter and will be ignored. + * + * The order of the positional parameters mentioned in the quoted text is: + * + * target,format,vdev,access + * + * The following options must be specified by key=value: + * + * devtype=<devtype> + * backendtype=<backend-type> + * + * The following options are currently not supported: + * + * backend=<domain-name> + * script=<script> + * direct-io-safe + * + */ +static int +xenParseXLDisk(virConfPtr conf, virDomainDefPtr def) +{ + int ret = -1; + virConfValuePtr list = virConfGetValue(conf, "disk"); + XLU_Config *xluconf; + libxl_device_disk *libxldisk; + virDomainDiskDefPtr disk = NULL; + + if (VIR_ALLOC(libxldisk) < 0) + return -1; + + if (!(xluconf = xlu_cfg_init(stderr, "command line"))) + goto cleanup; + + if (list && list->type == VIR_CONF_LIST) { + list = list->list; + while (list) { + const char *disk_spec = list->str; + + if ((list->type != VIR_CONF_STRING) || (list->str == NULL)) + goto skipdisk; + + libxl_device_disk_init(libxldisk); + + if (xlu_disk_parse(xluconf, 1, &disk_spec, libxldisk)) + goto fail; + + if (!(disk = virDomainDiskDefNew())) + goto fail; + + if (VIR_STRDUP(disk->dst, libxldisk->vdev) < 0) + goto fail; + + if (virDomainDiskSetSource(disk, libxldisk->pdev_path) < 0) + goto fail; + + disk->src->readonly = libxldisk->readwrite ? 0 : 1; + disk->removable = libxldisk->removable; + + if (libxldisk->is_cdrom) { + if (virDomainDiskSetDriver(disk, "qemu") < 0) + goto fail; + + virDomainDiskSetType(disk, VIR_STORAGE_TYPE_FILE); + disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM; + if (!disk->src->path || STREQ(disk->src->path, "")) + disk->src->format = VIR_STORAGE_FILE_NONE; + else + disk->src->format = VIR_STORAGE_FILE_RAW; + } else { + switch (libxldisk->format) { + case LIBXL_DISK_FORMAT_QCOW: + disk->src->format = VIR_STORAGE_FILE_QCOW; + break; + + case LIBXL_DISK_FORMAT_QCOW2: + disk->src->format = VIR_STORAGE_FILE_QCOW2; + break; + + case LIBXL_DISK_FORMAT_VHD: + disk->src->format = VIR_STORAGE_FILE_VHD; + break; + + case LIBXL_DISK_FORMAT_RAW: + case LIBXL_DISK_FORMAT_UNKNOWN: + disk->src->format = VIR_STORAGE_FILE_RAW; + break; + + case LIBXL_DISK_FORMAT_EMPTY: + break; + } + + switch (libxldisk->backend) { + case LIBXL_DISK_BACKEND_QDISK: + case LIBXL_DISK_BACKEND_UNKNOWN: + if (virDomainDiskSetDriver(disk, "qemu") < 0) + goto fail; + virDomainDiskSetType(disk, VIR_STORAGE_TYPE_FILE); + break; + + case LIBXL_DISK_BACKEND_TAP: + if (virDomainDiskSetDriver(disk, "tap") < 0) + goto fail; + virDomainDiskSetType(disk, VIR_STORAGE_TYPE_FILE); + break; + + case LIBXL_DISK_BACKEND_PHY: + if (virDomainDiskSetDriver(disk, "phy") < 0) + goto fail; + virDomainDiskSetType(disk, VIR_STORAGE_TYPE_BLOCK); + break; + } + } + + if (STRPREFIX(libxldisk->vdev, "xvd") || !STREQ(def->os.type, "hvm")) + disk->bus = VIR_DOMAIN_DISK_BUS_XEN; + else if (STRPREFIX(libxldisk->vdev, "sd")) + disk->bus = VIR_DOMAIN_DISK_BUS_SCSI; + else + disk->bus = VIR_DOMAIN_DISK_BUS_IDE; + + if (VIR_APPEND_ELEMENT(def->disks, def->ndisks, disk) < 0) + goto fail; + + libxl_device_disk_dispose(libxldisk); + + skipdisk: + list = list->next; + } + } + ret = 0; + + cleanup: + virDomainDiskDefFree(disk); + xlu_cfg_destroy(xluconf); + VIR_FREE(libxldisk); + return ret; + + fail: + libxl_device_disk_dispose(libxldisk); + goto cleanup; +} + + +virDomainDefPtr +xenParseXL(virConfPtr conf, virCapsPtr caps, int xendConfigVersion) +{ + virDomainDefPtr def = NULL; + + if (VIR_ALLOC(def) < 0) + return NULL; + + def->virtType = VIR_DOMAIN_VIRT_XEN; + def->id = -1; + + if (xenParseConfigCommon(conf, def, caps, xendConfigVersion) < 0) + goto cleanup; + + if (xenParseXLDisk(conf, def) < 0) + goto cleanup; + + if (xenParseXLSpice(conf, def) < 0) + goto cleanup; + + return def; + + cleanup: + virDomainDefFree(def); + return NULL; +} + + +static int +xenFormatXLDisk(virConfValuePtr list, virDomainDiskDefPtr disk) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + virConfValuePtr val, tmp; + const char *src = virDomainDiskGetSource(disk); + int format = virDomainDiskGetFormat(disk); + const char *driver = virDomainDiskGetDriver(disk); + + /* target */ + virBufferAsprintf(&buf, "%s,", src); + /* format */ + switch (format) { + case VIR_STORAGE_FILE_RAW: + virBufferAddLit(&buf, "raw,"); + break; + case VIR_STORAGE_FILE_VHD: + virBufferAddLit(&buf, "xvhd,"); + break; + case VIR_STORAGE_FILE_QCOW: + virBufferAddLit(&buf, "qcow,"); + break; + case VIR_STORAGE_FILE_QCOW2: + virBufferAddLit(&buf, "qcow2,"); + break; + /* set default */ + default: + virBufferAddLit(&buf, "raw,"); + } + + /* device */ + virBufferAdd(&buf, disk->dst, -1); + + virBufferAddLit(&buf, ","); + + if (disk->src->readonly) + virBufferAddLit(&buf, "r,"); + else if (disk->src->shared) + virBufferAddLit(&buf, "!,"); + else + virBufferAddLit(&buf, "w,"); + if (disk->transient) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("transient disks not supported yet")); + goto cleanup; + } + + if (STREQ_NULLABLE(driver, "qemu")) + virBufferAddLit(&buf, "backendtype=qdisk"); + else if (STREQ_NULLABLE(driver, "tap")) + virBufferAddLit(&buf, "backendtype=tap"); + else if (STREQ_NULLABLE(driver, "phy")) + virBufferAddLit(&buf, "backendtype=phy"); + + if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) + virBufferAddLit(&buf, ",devtype=cdrom"); + + if (virBufferCheckError(&buf) < 0) + goto cleanup; + + if (VIR_ALLOC(val) < 0) + goto cleanup; + + val->type = VIR_CONF_STRING; + val->str = virBufferContentAndReset(&buf); + tmp = list->list; + while (tmp && tmp->next) + tmp = tmp->next; + if (tmp) + tmp->next = val; + else + list->list = val; + return 0; + + cleanup: + virBufferFreeAndReset(&buf); + return -1; +} + + +static int +xenFormatXLDomainDisks(virConfPtr conf, virDomainDefPtr def) +{ + int ret = -1; + virConfValuePtr diskVal; + size_t i; + + if (VIR_ALLOC(diskVal) < 0) + return -1; + + diskVal->type = VIR_CONF_LIST; + diskVal->list = NULL; + + for (i = 0; i < def->ndisks; i++) { + if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) + continue; + + if (xenFormatXLDisk(diskVal, def->disks[i]) < 0) + goto cleanup; + } + + if (diskVal->list != NULL) + if (virConfSetValue(conf, "disk", diskVal) == 0) + diskVal = NULL; + + ret = 0; + + cleanup: + virConfFreeValue(diskVal); + return ret; +} + + +static int +xenFormatXLSpice(virConfPtr conf, virDomainDefPtr def) +{ + const char *listenAddr = NULL; + + if (STREQ(def->os.type, "hvm")) { + if (def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) { + /* set others to false but may not be necessary */ + if (xenConfigSetInt(conf, "sdl", 0) < 0) + return -1; + + if (xenConfigSetInt(conf, "vnc", 0) < 0) + return -1; + + if (xenConfigSetInt(conf, "spice", 1) < 0) + return -1; + + if (xenConfigSetInt(conf, "spiceport", + def->graphics[0]->data.spice.port) < 0) + return -1; + + if (xenConfigSetInt(conf, "spicetls_port", + def->graphics[0]->data.spice.tlsPort) < 0) + return -1; + + if (def->graphics[0]->data.spice.auth.passwd) { + if (xenConfigSetInt(conf, "spicedisable_ticketing", 1) < 0) + return -1; + + if (def->graphics[0]->data.spice.auth.passwd && + xenConfigSetString(conf, "spicepasswd", + def->graphics[0]->data.spice.auth.passwd) < 0) + return -1; + } + + listenAddr = virDomainGraphicsListenGetAddress(def->graphics[0], 0); + if (listenAddr && + xenConfigSetString(conf, "spicehost", listenAddr) < 0) + return -1; + + if (xenConfigSetInt(conf, "spicemouse_mouse", + def->graphics[0]->data.spice.mousemode) < 0) + return -1; + + if (def->graphics[0]->data.spice.copypaste) { + if (xenConfigSetInt(conf, "spicedvagent", 1) < 0) + return -1; + if (xenConfigSetInt(conf, "spice_clipboard_sharing", + def->graphics[0]->data.spice.copypaste) < 0) + return -1; + } + } + } + + return 0; +} + + +virConfPtr +xenFormatXL(virDomainDefPtr def, virConnectPtr conn, int xendConfigVersion) +{ + virConfPtr conf = NULL; + + if (!(conf = virConfNew())) + goto cleanup; + + if (xenFormatConfigCommon(conf, def, conn, xendConfigVersion) < 0) + goto cleanup; + + if (xenFormatXLDomainDisks(conf, def) < 0) + goto cleanup; + + if (xenFormatXLSpice(conf, def) < 0) + goto cleanup; + + return conf; + + cleanup: + if (conf) + virConfFree(conf); + return NULL; +} diff --git a/src/xenconfig/xen_xl.h b/src/xenconfig/xen_xl.h new file mode 100644 index 0000000..9838297 --- /dev/null +++ b/src/xenconfig/xen_xl.h @@ -0,0 +1,35 @@ +/* + * xen_xl.h: Xen XL parsing functions + * + * Copyright (c) 2015 SUSE LINUX Products GmbH, Nuernberg, Germany. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + * Author: Kiarie Kahurani<davidkiarie4@gmail.com> + */ + +#ifndef __VIR_XEN_XL_H__ +# define __VIR_XEN_XL_H__ + +# include "virconf.h" +# include "domain_conf.h" +# include "xen_common.h" + +virDomainDefPtr xenParseXL(virConfPtr conn, virCapsPtr caps, + int xendConfigVersion); +virConfPtr xenFormatXL(virDomainDefPtr def, + virConnectPtr, int xendConfigVersion); + +#endif /* __VIR_XEN_XL_H__ */ -- 1.8.4.5

On 01/13/2015 08:53 AM, Jim Fehlig wrote:
Introduce a parser/formatter for the xl config format. Since the deprecation of xm/xend, the VM config file format has diverged as new features are added to libxl. This patch adds support for parsing and formating the xl config format. It supports the existing xm config format, plus adds support for spice graphics and xl disk config syntax.
xl disk config is parsed with the help of xlu_disk_parse() from libxlutil, libxl's utility library. Although the library exists in all Xen versions supported by the libxl virt driver, only recently has the corresponding header file been included. A check for the header is done in configure.ac. If not found, xlu_disk_parse() is declared externally.
Signed-off-by: Kiarie Kahurani <davidkiarie4@gmail.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- +++ b/src/Makefile.am @@ -1005,6 +1005,10 @@ XENCONFIG_SOURCES = \ xenconfig/xen_common.c xenconfig/xen_common.h \ xenconfig/xen_sxpr.c xenconfig/xen_sxpr.h \ xenconfig/xen_xm.c xenconfig/xen_xm.h +if WITH_LIBXL +XENCONFIG_SOURCES += \ + xenconfig/xen_xl.c xenconfig/xen_xl.h +endif WITH_LIBXL
Missing an EXTRA_DIST listing to ensure these two files are part of a tarball even when configure does not build libxl sources (that is, make sure 'make distcheck' will not fail if configured on a machine without libxl support).
+xenParseXLDisk(virConfPtr conf, virDomainDefPtr def)
+ while (list) { + const char *disk_spec = list->str; + + if ((list->type != VIR_CONF_STRING) || (list->str == NULL))
Over-parenthesized.
+ goto skipdisk; + + libxl_device_disk_init(libxldisk); + + if (xlu_disk_parse(xluconf, 1, &disk_spec, libxldisk)) + goto fail; + + if (!(disk = virDomainDiskDefNew())) + goto fail; + + if (VIR_STRDUP(disk->dst, libxldisk->vdev) < 0) + goto fail; + + if (virDomainDiskSetSource(disk, libxldisk->pdev_path) < 0) + goto fail; + + disk->src->readonly = libxldisk->readwrite ? 0 : 1;
Isn't disk->src->readonly a bool? In which case, this should be: disk->src->readonly = !libxldisk->readwrite; for correct typing. I'd wait for John to confirm that Coverity is happy, but ACK if you fix the spots I pointed out. -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

Eric Blake wrote:
On 01/13/2015 08:53 AM, Jim Fehlig wrote:
Introduce a parser/formatter for the xl config format. Since the deprecation of xm/xend, the VM config file format has diverged as new features are added to libxl. This patch adds support for parsing and formating the xl config format. It supports the existing xm config format, plus adds support for spice graphics and xl disk config syntax.
xl disk config is parsed with the help of xlu_disk_parse() from libxlutil, libxl's utility library. Although the library exists in all Xen versions supported by the libxl virt driver, only recently has the corresponding header file been included. A check for the header is done in configure.ac. If not found, xlu_disk_parse() is declared externally.
Signed-off-by: Kiarie Kahurani <davidkiarie4@gmail.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- +++ b/src/Makefile.am @@ -1005,6 +1005,10 @@ XENCONFIG_SOURCES = \ xenconfig/xen_common.c xenconfig/xen_common.h \ xenconfig/xen_sxpr.c xenconfig/xen_sxpr.h \ xenconfig/xen_xm.c xenconfig/xen_xm.h +if WITH_LIBXL +XENCONFIG_SOURCES += \ + xenconfig/xen_xl.c xenconfig/xen_xl.h +endif WITH_LIBXL
Missing an EXTRA_DIST listing to ensure these two files are part of a tarball even when configure does not build libxl sources (that is, make sure 'make distcheck' will not fail if configured on a machine without libxl support).
Several of the tests fail on the old distro I'm testing on, which causes 'make distcheck' to fail. But I assumed I could simulate it on a newer distro with 'configure --without-libxl', yet 'make distcheck' succeeds and the files are included in the tarball. Are you seeing a failure on RHEL5? Regards, Jim

On 01/13/2015 04:47 PM, Jim Fehlig wrote:
+++ b/src/Makefile.am @@ -1005,6 +1005,10 @@ XENCONFIG_SOURCES = \ xenconfig/xen_common.c xenconfig/xen_common.h \ xenconfig/xen_sxpr.c xenconfig/xen_sxpr.h \ xenconfig/xen_xm.c xenconfig/xen_xm.h +if WITH_LIBXL +XENCONFIG_SOURCES += \ + xenconfig/xen_xl.c xenconfig/xen_xl.h +endif WITH_LIBXL
Missing an EXTRA_DIST listing to ensure these two files are part of a tarball even when configure does not build libxl sources (that is, make sure 'make distcheck' will not fail if configured on a machine without libxl support).
Several of the tests fail on the old distro I'm testing on, which causes 'make distcheck' to fail. But I assumed I could simulate it on a newer distro with 'configure --without-libxl', yet 'make distcheck' succeeds and the files are included in the tarball. Are you seeing a failure on RHEL5?
I haven't yet tested a 'make distcheck' on that particular VM of mine; I'll fire one off and see what happens. It might be simpler to just to check that if 'make dist' is run when configured --without-libxl, then it still includes both files in the tarball. -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

Eric Blake wrote:
On 01/13/2015 04:47 PM, Jim Fehlig wrote:
+++ b/src/Makefile.am @@ -1005,6 +1005,10 @@ XENCONFIG_SOURCES = \ xenconfig/xen_common.c xenconfig/xen_common.h \ xenconfig/xen_sxpr.c xenconfig/xen_sxpr.h \ xenconfig/xen_xm.c xenconfig/xen_xm.h +if WITH_LIBXL +XENCONFIG_SOURCES += \ + xenconfig/xen_xl.c xenconfig/xen_xl.h +endif WITH_LIBXL
Missing an EXTRA_DIST listing to ensure these two files are part of a tarball even when configure does not build libxl sources (that is, make sure 'make distcheck' will not fail if configured on a machine without libxl support).
Several of the tests fail on the old distro I'm testing on, which causes 'make distcheck' to fail. But I assumed I could simulate it on a newer distro with 'configure --without-libxl', yet 'make distcheck' succeeds and the files are included in the tarball. Are you seeing a failure on RHEL5?
I haven't yet tested a 'make distcheck' on that particular VM of mine; I'll fire one off and see what happens. It might be simpler to just to check that if 'make dist' is run when configured --without-libxl, then it still includes both files in the tarball.
I've verified src/xenconfig/xen_xl.[ch] are included in the tarball when configured --without-libxl. I've sent a V5 which addresses all of your V4 comments https://www.redhat.com/archives/libvir-list/2015-January/msg00494.html Regards, Jim

From: Kiarie Kahurani <davidkiarie4@gmail.com> add tests for the xen_xl config parser Signed-off-by: Kiarie Kahurani <davidkiarie4@gmail.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- V4: Only build xlconfigtest when libxl is available. tests/Makefile.am | 11 ++ tests/testutilsxen.c | 50 ++++++++ tests/testutilsxen.h | 9 +- tests/xlconfigdata/test-new-disk.cfg | 26 ++++ tests/xlconfigdata/test-new-disk.xml | 51 ++++++++ tests/xlconfigdata/test-spice.cfg | 32 +++++ tests/xlconfigdata/test-spice.xml | 45 +++++++ tests/xlconfigtest.c | 225 +++++++++++++++++++++++++++++++++++ 8 files changed, 448 insertions(+), 1 deletion(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index e9418ea..b16d3d5 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -138,6 +138,7 @@ EXTRA_DIST = \ vmx2xmldata \ xencapsdata \ xmconfigdata \ + xlconfigdata \ xml2sexprdata \ xml2vmxdata \ vmwareverdata \ @@ -227,6 +228,11 @@ if WITH_XEN test_programs += xml2sexprtest sexpr2xmltest \ xmconfigtest xencapstest statstest reconnect endif WITH_XEN + +if WITH_LIBXL +test_programs += xlconfigtest +endif WITH_LIBXL + if WITH_QEMU test_programs += qemuxml2argvtest qemuxml2xmltest qemuxmlnstest \ qemuargv2xmltest qemuhelptest domainsnapshotxml2xmltest \ @@ -477,6 +483,11 @@ sexpr2xmltest_SOURCES = \ testutils.c testutils.h sexpr2xmltest_LDADD = $(xen_LDADDS) +xlconfigtest_SOURCES = \ + xlconfigtest.c testutilsxen.c testutilsxen.h \ + testutils.c testutils.h +xlconfigtest_LDADD =$(xen_LDADDS) + xmconfigtest_SOURCES = \ xmconfigtest.c testutilsxen.c testutilsxen.h \ testutils.c testutils.h diff --git a/tests/testutilsxen.c b/tests/testutilsxen.c index a50a8a2..df1d124 100644 --- a/tests/testutilsxen.c +++ b/tests/testutilsxen.c @@ -69,3 +69,53 @@ virCapsPtr testXenCapsInit(void) virObjectUnref(caps); return NULL; } + + +virCapsPtr +testXLInitCaps(void) +{ + virCapsPtr caps; + virCapsGuestPtr guest; + virCapsGuestMachinePtr *machines; + int nmachines; + static const char *const x86_machines[] = { + "xenfv" + }; + static const char *const xen_machines[] = { + "xenpv" + }; + + if ((caps = virCapabilitiesNew(virArchFromHost(), + false, false)) == NULL) + return NULL; + nmachines = ARRAY_CARDINALITY(x86_machines); + if ((machines = virCapabilitiesAllocMachines(x86_machines, nmachines)) == NULL) + goto cleanup; + if ((guest = virCapabilitiesAddGuest(caps, "hvm", VIR_ARCH_X86_64, + "/usr/lib/xen/bin/qemu-dm", NULL, + nmachines, machines)) == NULL) + goto cleanup; + machines = NULL; + if (virCapabilitiesAddGuestDomain(guest, "xen", NULL, + NULL, 0, NULL) == NULL) + goto cleanup; + nmachines = ARRAY_CARDINALITY(xen_machines); + if ((machines = virCapabilitiesAllocMachines(xen_machines, nmachines)) == NULL) + goto cleanup; + + if ((guest = virCapabilitiesAddGuest(caps, "xen", VIR_ARCH_X86_64, + "/usr/lib/xen/bin/qemu-dm", NULL, + nmachines, machines)) == NULL) + goto cleanup; + machines = NULL; + + if (virCapabilitiesAddGuestDomain(guest, "xen", NULL, + NULL, 0, NULL) == NULL) + goto cleanup; + return caps; + + cleanup: + virCapabilitiesFreeMachines(machines, nmachines); + virObjectUnref(caps); + return NULL; +} diff --git a/tests/testutilsxen.h b/tests/testutilsxen.h index 54155e5..c78350d 100644 --- a/tests/testutilsxen.h +++ b/tests/testutilsxen.h @@ -1,3 +1,10 @@ -#include "capabilities.h" +#ifndef _TESTUTILSXEN_H_ +# define _TESTUTILSXEN_H_ + +# include "capabilities.h" virCapsPtr testXenCapsInit(void); + +virCapsPtr testXLInitCaps(void); + +#endif /* _TESTUTILSXEN_H_ */ diff --git a/tests/xlconfigdata/test-new-disk.cfg b/tests/xlconfigdata/test-new-disk.cfg new file mode 100644 index 0000000..b672b4a --- /dev/null +++ b/tests/xlconfigdata/test-new-disk.cfg @@ -0,0 +1,26 @@ +name = "XenGuest2" +uuid = "c7a5fdb2-cdaf-9455-926a-d65c16db1809" +maxmem = 579 +memory = 394 +vcpus = 1 +builder = "hvm" +kernel = "/usr/lib/xen/boot/hvmloader" +boot = "d" +pae = 1 +acpi = 1 +apic = 1 +hap = 0 +viridian = 0 +localtime = 0 +on_poweroff = "destroy" +on_reboot = "restart" +on_crash = "restart" +device_model = "/usr/lib/xen/bin/qemu-dm" +sdl = 0 +vnc = 1 +vncunused = 1 +vnclisten = "127.0.0.1" +vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr1,script=vif-bridge,model=e1000,type=ioemu" ] +parallel = "none" +serial = "none" +disk = [ "/dev/HostVG/XenGuest2,raw,hda,w,backendtype=phy", "/var/lib/libvirt/images/XenGuest2-home,qcow2,hdb,w,backendtype=qdisk", "/root/boot.iso,raw,hdc,r,backendtype=qdisk,devtype=cdrom" ] diff --git a/tests/xlconfigdata/test-new-disk.xml b/tests/xlconfigdata/test-new-disk.xml new file mode 100644 index 0000000..1c96a62 --- /dev/null +++ b/tests/xlconfigdata/test-new-disk.xml @@ -0,0 +1,51 @@ +<domain type='xen'> + <name>XenGuest2</name> + <uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>592896</memory> + <currentMemory unit='KiB'>403456</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='xenfv'>hvm</type> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> + <boot dev='cdrom'/> + </os> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='utc' adjustment='reset'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <devices> + <emulator>/usr/lib/xen/bin/qemu-dm</emulator> + <disk type='block' device='disk'> + <driver name='phy' type='raw'/> + <source dev='/dev/HostVG/XenGuest2'/> + <target dev='hda' bus='ide'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='qcow2'/> + <source file='/var/lib/libvirt/images/XenGuest2-home'/> + <target dev='hdb' bus='ide'/> + </disk> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/root/boot.iso'/> + <target dev='hdc' bus='ide'/> + <readonly/> + </disk> + <interface type='bridge'> + <mac address='00:16:3e:66:92:9c'/> + <source bridge='xenbr1'/> + <script path='vif-bridge'/> + <model type='e1000'/> + </interface> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1'> + <listen type='address' address='127.0.0.1'/> + </graphics> + </devices> +</domain> diff --git a/tests/xlconfigdata/test-spice.cfg b/tests/xlconfigdata/test-spice.cfg new file mode 100644 index 0000000..f7aa55c --- /dev/null +++ b/tests/xlconfigdata/test-spice.cfg @@ -0,0 +1,32 @@ +name = "XenGuest2" +uuid = "c7a5fdb2-cdaf-9455-926a-d65c16db1809" +maxmem = 579 +memory = 394 +vcpus = 1 +builder = "hvm" +kernel = "/usr/lib/xen/boot/hvmloader" +boot = "d" +pae = 1 +acpi = 1 +apic = 1 +hap = 0 +viridian = 0 +rtc_timeoffset = 0 +localtime = 1 +on_poweroff = "destroy" +on_reboot = "restart" +on_crash = "restart" +device_model = "/usr/lib/xen/bin/qemu-dm" +vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr1,script=vif-bridge,model=e1000" ] +parallel = "none" +serial = "none" +disk = [ "/dev/HostVG/XenGuest2,raw,hda,w,", "/root/boot.iso,raw,hdc,w," ] +sdl = 0 +vnc = 0 +spice = 1 +spicehost = "127.0.0.1" +spiceport = 590 +spicetls_port = 500 +spicedisable_ticketing = 1 +spicepasswd = "thebeast" +spiceagent_mouse = 0 diff --git a/tests/xlconfigdata/test-spice.xml b/tests/xlconfigdata/test-spice.xml new file mode 100644 index 0000000..1e3f78d --- /dev/null +++ b/tests/xlconfigdata/test-spice.xml @@ -0,0 +1,45 @@ +<domain type='xen'> + <name>XenGuest2</name> + <uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>592896</memory> + <currentMemory unit='KiB'>403456</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='xenfv'>hvm</type> + <loader>/usr/lib/xen/boot/hvmloader</loader> + <boot dev='cdrom'/> + </os> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='variable' adjustment='0' basis='localtime'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <devices> + <emulator>/usr/lib/xen/bin/qemu-dm</emulator> + <disk type='block' device='disk'> + <driver name='phy' type='raw'/> + <source dev='/dev/HostVG/XenGuest2'/> + <target dev='hda' bus='ide'/> + </disk> + <disk type='block' device='disk'> + <driver name='phy' type='raw'/> + <source dev='/root/boot.iso'/> + <target dev='hdc' bus='ide'/> + </disk> + <interface type='bridge'> + <mac address='00:16:3e:66:92:9c'/> + <source bridge='xenbr1'/> + <script path='vif-bridge'/> + <model type='e1000'/> + </interface> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <graphics type='spice' port='590' tlsPort='500' autoport='no' listen='127.0.0.1' passwd='thebeast'> + <listen type='address' address='127.0.0.1'/> + </graphics> + </devices> +</domain> diff --git a/tests/xlconfigtest.c b/tests/xlconfigtest.c new file mode 100644 index 0000000..d61d294 --- /dev/null +++ b/tests/xlconfigtest.c @@ -0,0 +1,225 @@ +/* + * xlconfigtest.c: Test backend for xl_internal config file handling + * + * Copyright (C) 2007, 2010-2011, 2014 Red Hat, Inc. + * Copyright (c) 2015 SUSE LINUX Products GmbH, Nuernberg, Germany. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + * Author: Daniel P. Berrange <berrange@redhat.com> + * Author: Kiarie Kahurani <davidkiarie4@gmail.com> + * + */ + +#include <config.h> + +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include "internal.h" +#include "datatypes.h" +#include "xenconfig/xen_xl.h" +#include "viralloc.h" +#include "virstring.h" +#include "testutils.h" +#include "testutilsxen.h" +#include "xen/xen_driver.h" + +#define VIR_FROM_THIS VIR_FROM_NONE + +static virCapsPtr caps; +static virDomainXMLOptionPtr xmlopt; +/* + * parses the xml, creates a domain def and compare with equivalent xm config + */ +static int +testCompareParseXML(const char *xmcfg, const char *xml, int xendConfigVersion) +{ + char *xmlData = NULL; + char *xmcfgData = NULL; + char *gotxmcfgData = NULL; + virConfPtr conf = NULL; + virConnectPtr conn = NULL; + int wrote = 4096; + int ret = -1; + virDomainDefPtr def = NULL; + + if (VIR_ALLOC_N(gotxmcfgData, wrote) < 0) + goto fail; + + conn = virGetConnect(); + if (!conn) goto fail; + + if (virtTestLoadFile(xml, &xmlData) < 0) + goto fail; + + if (virtTestLoadFile(xmcfg, &xmcfgData) < 0) + goto fail; + + if (!(def = virDomainDefParseString(xmlData, caps, xmlopt, + 1 << VIR_DOMAIN_VIRT_XEN, + VIR_DOMAIN_XML_INACTIVE))) + goto fail; + + if (!virDomainDefCheckABIStability(def, def)) { + fprintf(stderr, "ABI stability check failed on %s", xml); + goto fail; + } + + if (!(conf = xenFormatXL(def, conn, xendConfigVersion))) + goto fail; + + if (virConfWriteMem(gotxmcfgData, &wrote, conf) < 0) + goto fail; + gotxmcfgData[wrote] = '\0'; + + if (STRNEQ(xmcfgData, gotxmcfgData)) { + virtTestDifference(stderr, xmcfgData, gotxmcfgData); + goto fail; + } + + ret = 0; + + fail: + VIR_FREE(xmlData); + VIR_FREE(xmcfgData); + VIR_FREE(gotxmcfgData); + if (conf) + virConfFree(conf); + virDomainDefFree(def); + virObjectUnref(conn); + + return ret; +} +/* + * parses the xl config, develops domain def and compares with equivalent xm config + */ +static int +testCompareFormatXML(const char *xmcfg, const char *xml, int xendConfigVersion) +{ + char *xmlData = NULL; + char *xmcfgData = NULL; + char *gotxml = NULL; + virConfPtr conf = NULL; + int ret = -1; + virConnectPtr conn; + virDomainDefPtr def = NULL; + + conn = virGetConnect(); + if (!conn) goto fail; + + if (virtTestLoadFile(xml, &xmlData) < 0) + goto fail; + + if (virtTestLoadFile(xmcfg, &xmcfgData) < 0) + goto fail; + + if (!(conf = virConfReadMem(xmcfgData, strlen(xmcfgData), 0))) + goto fail; + + if (!(def = xenParseXL(conf, caps, xendConfigVersion))) + goto fail; + + if (!(gotxml = virDomainDefFormat(def, VIR_DOMAIN_XML_INACTIVE | + VIR_DOMAIN_XML_SECURE))) + goto fail; + + if (STRNEQ(xmlData, gotxml)) { + virtTestDifference(stderr, xmlData, gotxml); + goto fail; + } + + ret = 0; + + fail: + if (conf) + virConfFree(conf); + VIR_FREE(xmlData); + VIR_FREE(xmcfgData); + VIR_FREE(gotxml); + virDomainDefFree(def); + virObjectUnref(conn); + + return ret; +} + + +struct testInfo { + const char *name; + int version; + int mode; +}; + +static int +testCompareHelper(const void *data) +{ + int result = -1; + const struct testInfo *info = data; + char *xml = NULL; + char *cfg = NULL; + + if (virAsprintf(&xml, "%s/xlconfigdata/test-%s.xml", + abs_srcdir, info->name) < 0 || + virAsprintf(&cfg, "%s/xlconfigdata/test-%s.cfg", + abs_srcdir, info->name) < 0) + goto cleanup; + + if (info->mode == 0) + result = testCompareParseXML(cfg, xml, info->version); + else + result = testCompareFormatXML(cfg, xml, info->version); + + cleanup: + VIR_FREE(xml); + VIR_FREE(cfg); + + return result; +} + + +static int +mymain(void) +{ + int ret = 0; + + if (!(caps = testXLInitCaps())) + return EXIT_FAILURE; + + if (!(xmlopt = xenDomainXMLConfInit())) + return EXIT_FAILURE; + +#define DO_TEST(name, version) \ + do { \ + struct testInfo info0 = { name, version, 0 }; \ + struct testInfo info1 = { name, version, 1 }; \ + if (virtTestRun("Xen XM-2-XML Parse " name, \ + testCompareHelper, &info0) < 0) \ + ret = -1; \ + if (virtTestRun("Xen XM-2-XML Format " name, \ + testCompareHelper, &info1) < 0) \ + ret = -1; \ + } while (0) + + DO_TEST("new-disk", 3); +// DO_TEST("spice", 3); + + virObjectUnref(caps); + virObjectUnref(xmlopt); + + return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; +} + +VIRT_TEST_MAIN(mymain) -- 1.8.4.5

On 01/13/2015 08:53 AM, Jim Fehlig wrote:
From: Kiarie Kahurani <davidkiarie4@gmail.com>
add tests for the xen_xl config parser
Signed-off-by: Kiarie Kahurani <davidkiarie4@gmail.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com> ---
V4: Only build xlconfigtest when libxl is available.
@@ -227,6 +228,11 @@ if WITH_XEN test_programs += xml2sexprtest sexpr2xmltest \ xmconfigtest xencapstest statstest reconnect endif WITH_XEN + +if WITH_LIBXL +test_programs += xlconfigtest +endif WITH_LIBXL
Nice.
+ + DO_TEST("new-disk", 3); +// DO_TEST("spice", 3); +
Do we still need this comment? ACK with that resolved. -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

Eric Blake wrote:
On 01/13/2015 08:53 AM, Jim Fehlig wrote:
From: Kiarie Kahurani <davidkiarie4@gmail.com>
add tests for the xen_xl config parser
Signed-off-by: Kiarie Kahurani <davidkiarie4@gmail.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com> ---
V4: Only build xlconfigtest when libxl is available.
@@ -227,6 +228,11 @@ if WITH_XEN test_programs += xml2sexprtest sexpr2xmltest \ xmconfigtest xencapstest statstest reconnect endif WITH_XEN + +if WITH_LIBXL +test_programs += xlconfigtest +endif WITH_LIBXL
Nice.
+ + DO_TEST("new-disk", 3); +// DO_TEST("spice", 3); +
Do we still need this comment?
Wow, I can't believe I missed that. Thanks for catching it. This series is quite old and I forgot about this todo item. Enabling the spice test not only exposed problems with the xlconfigdata test files, but caught a bug in the xen-xl parser too! I'll fix those in V5 after seeing your answer to my question in 1/3. Regards, Jim

From: Kiarie Kahurani <davidkiarie4@gmail.com> Now that xenconfig supports parsing and formatting Xen's XL config format, integrate it into the libxl driver's connectDomainXML{From,To}Native functions. Signed-off-by: Kiarie Kahurani <davidkiarie4@gmail.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- V4: Note support for new 'xen-xl' format in virsh man page. src/libxl/libxl_driver.c | 32 ++++++++++++++++++++++++-------- tools/virsh.pod | 8 ++++---- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 53c87ce..4135670 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -48,6 +48,7 @@ #include "libxl_migration.h" #include "xen_xm.h" #include "xen_sxpr.h" +#include "xen_xl.h" #include "virtypedparam.h" #include "viruri.h" #include "virstring.h" @@ -67,6 +68,7 @@ VIR_LOG_INIT("libxl.libxl_driver"); #define LIBXL_DOM_REQ_CRASH 3 #define LIBXL_DOM_REQ_HALT 4 +#define LIBXL_CONFIG_FORMAT_XL "xen-xl" #define LIBXL_CONFIG_FORMAT_XM "xen-xm" #define LIBXL_CONFIG_FORMAT_SEXPR "xen-sxpr" @@ -2214,7 +2216,17 @@ libxlConnectDomainXMLFromNative(virConnectPtr conn, if (virConnectDomainXMLFromNativeEnsureACL(conn) < 0) goto cleanup; - if (STREQ(nativeFormat, LIBXL_CONFIG_FORMAT_XM)) { + if (STREQ(nativeFormat, LIBXL_CONFIG_FORMAT_XL)) { + if (!(conf = virConfReadMem(nativeConfig, strlen(nativeConfig), 0))) + goto cleanup; + if (!(def = xenParseXL(conf, + cfg->caps, + cfg->verInfo->xen_version_major))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("parsing xl config failed")); + goto cleanup; + } + } else if (STREQ(nativeFormat, LIBXL_CONFIG_FORMAT_XM)) { if (!(conf = virConfReadMem(nativeConfig, strlen(nativeConfig), 0))) goto cleanup; @@ -2269,20 +2281,24 @@ libxlConnectDomainXMLToNative(virConnectPtr conn, const char * nativeFormat, if (virConnectDomainXMLToNativeEnsureACL(conn) < 0) goto cleanup; - if (STRNEQ(nativeFormat, LIBXL_CONFIG_FORMAT_XM)) { - virReportError(VIR_ERR_INVALID_ARG, - _("unsupported config type %s"), nativeFormat); - goto cleanup; - } - if (!(def = virDomainDefParseString(domainXml, cfg->caps, driver->xmlopt, 1 << VIR_DOMAIN_VIRT_XEN, VIR_DOMAIN_XML_INACTIVE))) goto cleanup; - if (!(conf = xenFormatXM(conn, def, cfg->verInfo->xen_version_major))) + if (STREQ(nativeFormat, LIBXL_CONFIG_FORMAT_XL)) { + if (!(conf = xenFormatXL(def, conn, cfg->verInfo->xen_version_major))) + goto cleanup; + } else if (STREQ(nativeFormat, LIBXL_CONFIG_FORMAT_XM)) { + if (!(conf = xenFormatXM(conn, def, cfg->verInfo->xen_version_major))) + goto cleanup; + } else { + + virReportError(VIR_ERR_INVALID_ARG, + _("unsupported config type %s"), nativeFormat); goto cleanup; + } if (VIR_ALLOC_N(ret, len) < 0) goto cleanup; diff --git a/tools/virsh.pod b/tools/virsh.pod index 56fe896..abe80c2 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -1272,16 +1272,16 @@ in order to get or set the guest time. Convert the file I<config> in the native guest configuration format named by I<format> to a domain XML format. For QEMU/KVM hypervisor, the I<format> argument must be B<qemu-argv>. For Xen hypervisor, the -I<format> argument may be B<xen-xm> or B<xen-sxpr>. For LXC hypervisor, -the I<format> argument must be B<lxc-tools>. +I<format> argument may be B<xen-xm>, B<xen-xl>, or B<xen-sxpr>. For +LXC hypervisor, the I<format> argument must be B<lxc-tools>. =item B<domxml-to-native> I<format> I<xml> Convert the file I<xml> in domain XML format to the native guest configuration format named by I<format>. For QEMU/KVM hypervisor, the I<format> argument must be B<qemu-argv>. For Xen hypervisor, the -I<format> argument may be B<xen-xm> or B<xen-sxpr>. For LXC hypervisor, -the I<format> argument must be B<lxc-tools>. +I<format> argument may be B<xen-xm>, B<xen-xl>, or B<xen-sxpr>. For +LXC hypervisor, the I<format> argument must be B<lxc-tools>. =item B<dump> I<domain> I<corefilepath> [I<--bypass-cache>] { [I<--live>] | [I<--crash>] | [I<--reset>] } [I<--verbose>] [I<--memory-only>] -- 1.8.4.5

On 01/13/2015 08:53 AM, Jim Fehlig wrote:
From: Kiarie Kahurani <davidkiarie4@gmail.com>
Now that xenconfig supports parsing and formatting Xen's XL config format, integrate it into the libxl driver's connectDomainXML{From,To}Native functions.
Signed-off-by: Kiarie Kahurani <davidkiarie4@gmail.com> Signed-off-by: Jim Fehlig <jfehlig@suse.com> ---
V4: Note support for new 'xen-xl' format in virsh man page.
src/libxl/libxl_driver.c | 32 ++++++++++++++++++++++++-------- tools/virsh.pod | 8 ++++---- 2 files changed, 28 insertions(+), 12 deletions(-)
Thanks for the man page docs. [Someday, I'd like to add an API or modify an existing capability API that returns XML to make it possible to query at runtime what formats are supported by the format-{to,from}-native calls - but that doesn't have to hold up this series] -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

On 01/13/2015 08:53 AM, Jim Fehlig wrote:
It's been a long, twisting road to V4 of the Xen xl parser. V3 [1] was based on a flex-based parser that was copied from the Xen project and proved to be a bit challenging to integrate properly with autotools. But as it turns out, Xen provides an interface to the parser via libxlutil. I hadn't realized this interface was available for external consumption since the corresponding header file was never installed. Patch sent to xen-devel [2] to install the header, but in the meantime need to declare gthe imported libxlutil functions as extern (see patch 1).
V4 uses libxlutil, which has simplified the series quite a bit and eliminates the potential of the copied flex parser diverging from the canonical source in xen.git.
[1] https://www.redhat.com/archives/libvir-list/2014-December/msg00765.html [2] http://lists.xen.org/archives/html/xen-devel/2015-01/msg00690.html
Yay - this series compiled on RHEL 5, with no extra efforts on my part. I'll review the individual patches as well, but we're already looking better. -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

On 01/13/2015 10:53 AM, Jim Fehlig wrote:
It's been a long, twisting road to V4 of the Xen xl parser. V3 [1] was based on a flex-based parser that was copied from the Xen project and proved to be a bit challenging to integrate properly with autotools. But as it turns out, Xen provides an interface to the parser via libxlutil. I hadn't realized this interface was available for external consumption since the corresponding header file was never installed. Patch sent to xen-devel [2] to install the header, but in the meantime need to declare gthe imported libxlutil functions as extern (see patch 1).
V4 uses libxlutil, which has simplified the series quite a bit and eliminates the potential of the copied flex parser diverging from the canonical source in xen.git.
[1] https://www.redhat.com/archives/libvir-list/2014-December/msg00765.html [2] http://lists.xen.org/archives/html/xen-devel/2015-01/msg00690.html
Jim Fehlig (1): Introduce support for parsing/formatting Xen xl config format
Kiarie Kahurani (2): tests: Tests for the xen-xl parser libxl: Add support for parsing/formating Xen XL config
configure.ac | 3 + po/POTFILES.in | 1 + src/Makefile.am | 11 + src/libvirt_xenxlconfig.syms | 12 + src/libxl/libxl_driver.c | 32 ++- src/xenconfig/xen_common.c | 3 +- src/xenconfig/xen_xl.c | 515 +++++++++++++++++++++++++++++++++++ src/xenconfig/xen_xl.h | 35 +++ tests/Makefile.am | 11 + tests/testutilsxen.c | 50 ++++ tests/testutilsxen.h | 9 +- tests/xlconfigdata/test-new-disk.cfg | 26 ++ tests/xlconfigdata/test-new-disk.xml | 51 ++++ tests/xlconfigdata/test-spice.cfg | 32 +++ tests/xlconfigdata/test-spice.xml | 45 +++ tests/xlconfigtest.c | 225 +++++++++++++++ tools/virsh.pod | 8 +- 17 files changed, 1055 insertions(+), 14 deletions(-) create mode 100644 src/libvirt_xenxlconfig.syms create mode 100644 src/xenconfig/xen_xl.c create mode 100644 src/xenconfig/xen_xl.h create mode 100644 tests/xlconfigdata/test-new-disk.cfg create mode 100644 tests/xlconfigdata/test-new-disk.xml create mode 100644 tests/xlconfigdata/test-spice.cfg create mode 100644 tests/xlconfigdata/test-spice.xml create mode 100644 tests/xlconfigtest.c
My Coverity run was happy with the changes. John
participants (3)
-
Eric Blake
-
Jim Fehlig
-
John Ferlan